Merge branch 'master' of https://github.com/FlaxEngine/FlaxEngine into pxupvector

This commit is contained in:
Jean-Baptiste Perrier
2021-04-07 17:01:52 +02:00
20 changed files with 297 additions and 30 deletions

View File

@@ -10,7 +10,7 @@ jobs:
steps: steps:
- name: Install dependencies - name: Install dependencies
run: | run: |
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext curl libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libcurl4-gnutls-dev sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext curl libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libcurl4
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Checkout LFS - name: Checkout LFS

View File

@@ -32,3 +32,19 @@ Go check out our [Trello](https://trello.com/b/NQjLXRCP/flax-roadmap).
Thank you for taking interest in contributing to Flax! Thank you for taking interest in contributing to Flax!
## **Common issues**
Below are some common issues that someone working with the FlaxEngine source code might run into. Hopefully some of those issues will get fixed in the future. If you know how, please contribute!
* Missing MSVC toolset
* Install it through the Visual Studio Installer
* Building or attaching fails
* Run `GenerateProjectFiles.bat`
* Rebuild `Flax.Build`
* Make sure that there isn't a stray FlaxEngine process running in the background
* First start Flax and then attach the C# debugger
* Configure the C# FlaxEngine project by going into the project properties, then the debug tab and selecting "Start external program" `Flax\FlaxEngine\Binaries\Editor\Win64\Debug\FlaxEditor.exe`
* Then you can also set command line arguments such as `-project "C:\Users\PROFILE\Documents\Flax Projects\FlaxSamples\BasicTemplate"`
* Git LFS
* Push with `git push --no-verify`

View File

@@ -47,7 +47,7 @@ Flax Visual Studio extension provides better programming workflow, C# scripts de
* Install Visual Studio Code * Install Visual Studio Code
* Install Mono ([https://www.mono-project.com/download/stable](https://www.mono-project.com/download/stable)) * Install Mono ([https://www.mono-project.com/download/stable](https://www.mono-project.com/download/stable))
* Install Git with LFS * Install Git with LFS
* Install requried packages: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev nuget autoconf libogg-dev automake build-essential gettext cmake python curl libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libcurl4-gnutls-dev` * Install requried packages: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev nuget autoconf libogg-dev automake build-essential gettext cmake python curl libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev libcurl4`
* Install compiler `sudo apt-get install clang lldb lld` (Clang 6 or newer) * Install compiler `sudo apt-get install clang lldb lld` (Clang 6 or newer)
* Clone repo (with LFS) * Clone repo (with LFS)
* Run `./GenerateProjectFiles.sh` * Run `./GenerateProjectFiles.sh`

View File

@@ -59,7 +59,10 @@ namespace FlaxEditor.GUI.Docking
/// <summary> /// <summary>
/// Gets the default window size. /// Gets the default window size.
/// </summary> /// </summary>
public virtual Vector2 DefaultSize => new Vector2(900, 580); /// <remarks>
/// Scaled by the DPI, because the window should be large enough for its content on every monitor
/// </remarks>
public virtual Vector2 DefaultSize => new Vector2(900, 580) * DpiScale;
/// <summary> /// <summary>
/// Gets the serialization typename. /// Gets the serialization typename.

View File

@@ -367,6 +367,15 @@ namespace FlaxEditor.SceneGraph.Actors
} }
} }
/// <inheritdoc />
public override bool RayCastSelf(ref RayCastData ray, out float distance, out Vector3 normal)
{
// Select only spline points
normal = Vector3.Up;
distance = float.MaxValue;
return false;
}
/// <inheritdoc /> /// <inheritdoc />
public override void OnDispose() public override void OnDispose()
{ {

View File

@@ -341,7 +341,21 @@ void ScriptsBuilder::GetBinariesConfiguration(const Char*& target, const Char*&
target = platform = architecture = configuration = nullptr; target = platform = architecture = configuration = nullptr;
return; return;
} }
target = Editor::Project->EditorTarget.GetText();
// Pick game target
if (Editor::Project->EditorTarget.HasChars())
{
target = Editor::Project->EditorTarget.Get();
}
else if (Editor::Project->GameTarget.HasChars())
{
target = Editor::Project->GameTarget.Get();
}
else
{
target = TEXT("");
LOG(Error, "Missing editor/game targets in project. Please specify EditorTarget and GameTarget properties in .flaxproj file.");
}
#if PLATFORM_WINDOWS #if PLATFORM_WINDOWS
platform = TEXT("Windows"); platform = TEXT("Windows");
@@ -551,19 +565,13 @@ bool ScriptsBuilderService::Init()
} }
// Verify project // Verify project
if (project->EditorTarget.IsEmpty() || project->GameTarget.IsEmpty()) if (project->EditorTarget.IsEmpty())
{ {
const String& name = project->Name; LOG(Warning, "Missing {0} property in opened project", TEXT("EditorTarget"));
String codeName; }
for (int32 i = 0; i < name.Length(); i++) if (project->GameTarget.IsEmpty())
{ {
Char c = name[i]; LOG(Warning, "Missing {0} property in opened project", TEXT("GameTarget"));
if (StringUtils::IsAlnum(c) && c != ' ' && c != '.')
codeName += c;
}
project->GameTarget = codeName + TEXT("Target");
project->EditorTarget = codeName + TEXT("EditorTarget");
LOG(Warning, "Missing EditorTarget property in opened project, using deducted target name {0}", Editor::Project->EditorTarget);
} }
// Remove any remaining files from previous Editor run hot-reloads // Remove any remaining files from previous Editor run hot-reloads

View File

@@ -399,9 +399,18 @@ namespace FlaxEditor.Windows.Assets
ShadowsCastingMode[] shadowsModes = new ShadowsCastingMode[value.Length]; ShadowsCastingMode[] shadowsModes = new ShadowsCastingMode[value.Length];
for (int i = 0; i < value.Length; i++) for (int i = 0; i < value.Length; i++)
{ {
materials[i] = value[i].Material; if (value[i] != null)
names[i] = value[i].Name; {
shadowsModes[i] = value[i].ShadowsMode; materials[i] = value[i].Material;
names[i] = value[i].Name;
shadowsModes[i] = value[i].ShadowsMode;
}
else
{
materials[i] = null;
names[i] = "Material " + i;
shadowsModes[i] = ShadowsCastingMode.All;
}
} }
Asset.SetupMaterialSlots(value.Length); Asset.SetupMaterialSlots(value.Length);

View File

@@ -511,9 +511,18 @@ namespace FlaxEditor.Windows.Assets
ShadowsCastingMode[] shadowsModes = new ShadowsCastingMode[value.Length]; ShadowsCastingMode[] shadowsModes = new ShadowsCastingMode[value.Length];
for (int i = 0; i < value.Length; i++) for (int i = 0; i < value.Length; i++)
{ {
materials[i] = value[i].Material; if (value[i] != null)
names[i] = value[i].Name; {
shadowsModes[i] = value[i].ShadowsMode; materials[i] = value[i].Material;
names[i] = value[i].Name;
shadowsModes[i] = value[i].ShadowsMode;
}
else
{
materials[i] = null;
names[i] = "Material " + i;
shadowsModes[i] = ShadowsCastingMode.All;
}
} }
Asset.SetupMaterialSlots(value.Length); Asset.SetupMaterialSlots(value.Length);

View File

@@ -209,9 +209,11 @@ namespace FlaxEditor.Windows
public override void Draw() public override void Draw()
{ {
var style = Style.Current; var style = Style.Current;
// Draw overlay // Draw overlay
string overlayText = null; string overlayText = null;
var state = Editor.StateMachine.CurrentState; var state = Editor.StateMachine.CurrentState;
var textWrap = TextWrapping.NoWrap;
if (state is LoadingState) if (state is LoadingState)
{ {
overlayText = "Loading..."; overlayText = "Loading...";
@@ -223,10 +225,11 @@ namespace FlaxEditor.Windows
else if (((ContainerControl)_tree.GetChild(0)).ChildrenCount == 0) else if (((ContainerControl)_tree.GetChild(0)).ChildrenCount == 0)
{ {
overlayText = "No scene\nOpen one from the content window"; overlayText = "No scene\nOpen one from the content window";
textWrap = TextWrapping.WrapWords;
} }
if (overlayText != null) if (overlayText != null)
{ {
Render2D.DrawText(Style.Current.FontLarge, overlayText, GetClientArea(), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center); Render2D.DrawText(style.FontLarge, overlayText, GetClientArea(), style.ForegroundDisabled, TextAlignment.Center, TextAlignment.Center, textWrap);
} }
base.Draw(); base.Draw();

View File

@@ -358,6 +358,51 @@ bool Physics::SphereCastAll(const Vector3& center, const float radius, const Vec
return true; return true;
} }
bool Physics::CapsuleCast(const Vector3& center, const float radius, const float height, const Vector3& direction, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform sweep test
return GetScene()->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, GetQueryFilterCallback());
}
bool Physics::CapsuleCast(const Vector3& center, const float radius, const float height, const Vector3& direction, RayCastHit& hitInfo, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_SWEEP_1();
const PxTransform pose(C2P(center), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform sweep test
if (!GetScene()->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, GetQueryFilterCallback()))
return false;
// Collect results
SCENE_QUERY_COLLECT_SINGLE();
return true;
}
bool Physics::CapsuleCastAll(const Vector3& center, const float radius, const float height, const Vector3& direction, Array<RayCastHit>& results, const Quaternion& rotation, const float maxDistance, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_SWEEP();
const PxTransform pose(C2P(center), C2P(rotation));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform sweep test
if (!GetScene()->sweep(geometry, pose, C2P(direction), maxDistance, buffer, hitFlags, filterData, GetQueryFilterCallback()))
return false;
// Collect results
SCENE_QUERY_COLLECT_ALL();
return true;
}
bool Physics::CheckBox(const Vector3& center, const Vector3& halfExtents, const Quaternion& rotation, uint32 layerMask, bool hitTriggers) bool Physics::CheckBox(const Vector3& center, const Vector3& halfExtents, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{ {
// Prepare data // Prepare data
@@ -380,6 +425,17 @@ bool Physics::CheckSphere(const Vector3& center, const float radius, uint32 laye
return GetScene()->overlap(geometry, pose, buffer, filterData, GetQueryFilterCallback()); return GetScene()->overlap(geometry, pose, buffer, filterData, GetQueryFilterCallback());
} }
bool Physics::CheckCapsule(const Vector3& center, const float radius, const float height, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_OVERLAP_1();
const PxTransform pose(C2P(center));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform overlap test
return GetScene()->overlap(geometry, pose, buffer, filterData, GetQueryFilterCallback());
}
bool Physics::OverlapBox(const Vector3& center, const Vector3& halfExtents, Array<Collider*>& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers) bool Physics::OverlapBox(const Vector3& center, const Vector3& halfExtents, Array<Collider*>& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{ {
// Prepare data // Prepare data
@@ -414,6 +470,23 @@ bool Physics::OverlapSphere(const Vector3& center, const float radius, Array<Col
return true; return true;
} }
bool Physics::OverlapCapsule(const Vector3& center, const float radius, const float height, Array<Collider*>& results, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform overlap test
if (!GetScene()->overlap(geometry, pose, buffer, filterData, GetQueryFilterCallback()))
return false;
// Collect results
SCENE_QUERY_COLLECT_OVERLAP_COLLIDER();
return true;
}
bool Physics::OverlapBox(const Vector3& center, const Vector3& halfExtents, Array<PhysicsColliderActor*>& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers) bool Physics::OverlapBox(const Vector3& center, const Vector3& halfExtents, Array<PhysicsColliderActor*>& results, const Quaternion& rotation, uint32 layerMask, bool hitTriggers)
{ {
// Prepare data // Prepare data
@@ -447,3 +520,20 @@ bool Physics::OverlapSphere(const Vector3& center, const float radius, Array<Phy
return true; return true;
} }
bool Physics::OverlapCapsule(const Vector3& center, const float radius, const float height, Array<PhysicsColliderActor*>& results, uint32 layerMask, bool hitTriggers)
{
// Prepare data
SCENE_QUERY_SETUP_OVERLAP();
const PxTransform pose(C2P(center));
const PxCapsuleGeometry geometry(radius, height * 0.5f);
// Perform overlap test
if (!GetScene()->overlap(geometry, pose, buffer, filterData, GetQueryFilterCallback()))
return false;
// Collect results
SCENE_QUERY_COLLECT_OVERLAP();
return true;
}

View File

@@ -276,6 +276,50 @@ public:
/// <returns>True if sphere hits an matching object, otherwise false.</returns> /// <returns>True if sphere hits an matching object, otherwise false.</returns>
API_FUNCTION() static bool SphereCastAll(const Vector3& center, float radius, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true); API_FUNCTION() static bool SphereCastAll(const Vector3& center, float radius, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Performs a sweep test against objects in the scene using a capsule geometry.
/// </summary>
/// <param name="center">The box center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="direction">The normalized direction in which cast a box.</param>
/// <param name="rotation">The capsule rotation.</param>
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
API_FUNCTION() static bool CapsuleCast(const Vector3& center, float radius, float height, const Vector3& direction, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Performs a sweep test against objects in the scene using a capsule geometry.
/// </summary>
/// <param name="center">The box center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="direction">The normalized direction in which cast a box.</param>
/// <param name="hitInfo">The result hit information. Valid only when method returns true.</param>
/// <param name="rotation">The capsule rotation.</param>
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
API_FUNCTION() static bool CapsuleCast(const Vector3& center, float radius, float height, const Vector3& direction, API_PARAM(Out) RayCastHit& hitInfo, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Performs a sweep test against objects in the scene using a capsule geometry.
/// </summary>
/// <param name="center">The box center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="direction">The normalized direction in which cast a box.</param>
/// <param name="results">The result hits. Valid only when method returns true.</param>
/// <param name="rotation">The capsule rotation.</param>
/// <param name="maxDistance">The maximum distance the ray should check for collisions.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule hits an matching object, otherwise false.</returns>
API_FUNCTION() static bool CapsuleCastAll(const Vector3& center, float radius, float height, const Vector3& direction, API_PARAM(Out) Array<RayCastHit, HeapAllocation>& results, const Quaternion& rotation = Quaternion::Identity, float maxDistance = MAX_float, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary> /// <summary>
/// Checks whether the given box overlaps with other colliders or not. /// Checks whether the given box overlaps with other colliders or not.
/// </summary> /// </summary>
@@ -297,6 +341,17 @@ public:
/// <returns>True if sphere overlaps any matching object, otherwise false.</returns> /// <returns>True if sphere overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool CheckSphere(const Vector3& center, float radius, uint32 layerMask = MAX_uint32, bool hitTriggers = true); API_FUNCTION() static bool CheckSphere(const Vector3& center, float radius, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Checks whether the given capsule overlaps with other colliders or not.
/// </summary>
/// <param name="center">The capsule center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool CheckCapsule(const Vector3& center, float radius, float height, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary> /// <summary>
/// Finds all colliders touching or inside of the given box. /// Finds all colliders touching or inside of the given box.
/// </summary> /// </summary>
@@ -320,6 +375,18 @@ public:
/// <returns>True if sphere overlaps any matching object, otherwise false.</returns> /// <returns>True if sphere overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool OverlapSphere(const Vector3& center, float radius, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true); API_FUNCTION() static bool OverlapSphere(const Vector3& center, float radius, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Finds all colliders touching or inside of the given sphere.
/// </summary>
/// <param name="center">The sphere center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="results">The result colliders that overlap with the given sphere. Valid only when method returns true.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array<Collider*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary> /// <summary>
/// Finds all colliders touching or inside of the given box. /// Finds all colliders touching or inside of the given box.
/// </summary> /// </summary>
@@ -343,6 +410,18 @@ public:
/// <returns>True if sphere overlaps any matching object, otherwise false.</returns> /// <returns>True if sphere overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool OverlapSphere(const Vector3& center, float radius, API_PARAM(Out) Array<PhysicsColliderActor*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true); API_FUNCTION() static bool OverlapSphere(const Vector3& center, float radius, API_PARAM(Out) Array<PhysicsColliderActor*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
/// <summary>
/// Finds all colliders touching or inside of the given sphere.
/// </summary>
/// <param name="center">The capsule center.</param>
/// <param name="radius">The radius of the capsule.</param>
/// <param name="height">The height of the capsule, excluding the top and bottom spheres.</param>
/// <param name="results">The result colliders that overlap with the given sphere. Valid only when method returns true.</param>
/// <param name="layerMask">The layer mask used to filter the results.</param>
/// <param name="hitTriggers">If set to <c>true</c> triggers will be hit, otherwise will skip them.</param>
/// <returns>True if capsule overlaps any matching object, otherwise false.</returns>
API_FUNCTION() static bool OverlapCapsule(const Vector3& center, float radius, float height, API_PARAM(Out) Array<PhysicsColliderActor*, HeapAllocation>& results, uint32 layerMask = MAX_uint32, bool hitTriggers = true);
public: public:
/// <summary> /// <summary>

View File

@@ -260,7 +260,7 @@ bool WindowsFileSystem::ShowSaveFileDialog(Window* parentWindow, const StringVie
of.lpstrFilter = filter.HasChars() ? filter.Get() : nullptr; of.lpstrFilter = filter.HasChars() ? filter.Get() : nullptr;
of.lpstrFile = fileNamesBuffer.Get(); of.lpstrFile = fileNamesBuffer.Get();
of.nMaxFile = maxFilenamesSize; of.nMaxFile = maxFilenamesSize;
of.Flags = OFN_EXPLORER | OFN_ENABLESIZING; of.Flags = OFN_EXPLORER | OFN_ENABLESIZING | OFN_OVERWRITEPROMPT;
of.lpstrTitle = title.HasChars() ? title.Get() : nullptr; of.lpstrTitle = title.HasChars() ? title.Get() : nullptr;
of.lpstrInitialDir = initialDirectory.HasChars() ? initialDirectory.Get() : nullptr; of.lpstrInitialDir = initialDirectory.HasChars() ? initialDirectory.Get() : nullptr;
if (parentWindow) if (parentWindow)

View File

@@ -313,7 +313,7 @@ namespace FlaxEngine.GUI
/// <summary> /// <summary>
/// Gets the control DPI scale factor (1 is default). Includes custom DPI scale. /// Gets the control DPI scale factor (1 is default). Includes custom DPI scale.
/// </summary> /// </summary>
public float DpiScale => _root?.RootWindow?.Window.DpiScale ?? Platform.DpiScale; public float DpiScale => RootWindow?.Window.DpiScale ?? Platform.DpiScale;
/// <summary> /// <summary>
/// Gets screen position of the control (upper left corner). /// Gets screen position of the control (upper left corner).

View File

@@ -3172,6 +3172,8 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
node->bone_link_property = con.property; node->bone_link_property = con.property;
} }
break; break;
default:
break;
} }
switch (parent->getType()) switch (parent->getType())
@@ -3190,6 +3192,8 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
mesh->geometry = (Geometry*)child; mesh->geometry = (Geometry*)child;
break; break;
case Object::Type::MATERIAL: mesh->materials.push_back((Material*)child); break; case Object::Type::MATERIAL: mesh->materials.push_back((Material*)child); break;
default:
break;
} }
break; break;
} }
@@ -3323,6 +3327,8 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
} }
break; break;
} }
default:
break;
} }
} }
@@ -3350,6 +3356,8 @@ static bool parseObjects(const Element& root, Scene* scene, u64 flags, Allocator
return false; return false;
} }
break; break;
default:
break;
} }
} }
} }

View File

@@ -246,7 +246,7 @@ namespace Flax.Build
// Get all modules aggregated into all binary modules used in all configurations of this target // Get all modules aggregated into all binary modules used in all configurations of this target
foreach (var configurationData in mainProject.Configurations) foreach (var configurationData in mainProject.Configurations)
{ {
var configurationBinaryModules = GetBinaryModules(rootProject, configurationData.Target, configurationData.Modules); var configurationBinaryModules = GetBinaryModules(projectInfo, configurationData.Target, configurationData.Modules);
foreach (var configurationBinaryModule in configurationBinaryModules) foreach (var configurationBinaryModule in configurationBinaryModules)
{ {
// Skip if none of the included binary modules is inside the project workspace (eg. merged external binary modules from engine to game project) // Skip if none of the included binary modules is inside the project workspace (eg. merged external binary modules from engine to game project)
@@ -272,7 +272,7 @@ namespace Flax.Build
{ {
var referenceBuildOptions = GetBuildOptions(referenceTarget, configurationData.TargetBuildOptions.Platform, configurationData.TargetBuildOptions.Toolchain, configurationData.Architecture, configurationData.Configuration, reference.Project.ProjectFolderPath); var referenceBuildOptions = GetBuildOptions(referenceTarget, configurationData.TargetBuildOptions.Platform, configurationData.TargetBuildOptions.Toolchain, configurationData.Architecture, configurationData.Configuration, reference.Project.ProjectFolderPath);
var referenceModules = CollectModules(rules, referenceBuildOptions.Platform, referenceTarget, referenceBuildOptions, referenceBuildOptions.Toolchain, referenceBuildOptions.Architecture, referenceBuildOptions.Configuration); var referenceModules = CollectModules(rules, referenceBuildOptions.Platform, referenceTarget, referenceBuildOptions, referenceBuildOptions.Toolchain, referenceBuildOptions.Architecture, referenceBuildOptions.Configuration);
var referenceBinaryModules = GetBinaryModules(rootProject, referenceTarget, referenceModules); var referenceBinaryModules = GetBinaryModules(projectInfo, referenceTarget, referenceModules);
foreach (var binaryModule in referenceBinaryModules) foreach (var binaryModule in referenceBinaryModules)
{ {
project.Defines.Add(binaryModule.Key.ToUpperInvariant() + "_API="); project.Defines.Add(binaryModule.Key.ToUpperInvariant() + "_API=");

View File

@@ -82,6 +82,17 @@ namespace Flax.Build
return GetModuleProject(module, buildData.Project); return GetModuleProject(module, buildData.Project);
} }
/// <summary>
/// Checks if the project that contains a given module (checks for modules located in the given project Source folder).
/// </summary>
/// <param name="module">The module.</param>
/// <param name="project">The project to check.</param>
/// <returns>True if project contains that module inside, otherwise it's external or referenced.</returns>
public static bool IsModuleFromProject(Module module, ProjectInfo project)
{
return GetModuleProject(module, project) == project;
}
/// <summary> /// <summary>
/// Builds the targets. /// Builds the targets.
/// </summary> /// </summary>

View File

@@ -101,7 +101,7 @@ namespace Flax.Build
} }
// Mono on Linux is using dynamic linking and needs additional link files // Mono on Linux is using dynamic linking and needs additional link files
if (buildOptions.Platform.Target == TargetPlatform.Linux && Platform.BuildTargetPlatform == TargetPlatform.Linux) if (buildOptions.Platform.Target == TargetPlatform.Linux && Platform.BuildTargetPlatform == TargetPlatform.Linux && !IsPreBuilt)
{ {
var task = graph.Add<Task>(); var task = graph.Add<Task>();
task.PrerequisiteFiles.Add(Path.Combine(buildOptions.OutputFolder, "libmonosgen-2.0.so")); task.PrerequisiteFiles.Add(Path.Combine(buildOptions.OutputFolder, "libmonosgen-2.0.so"));
@@ -141,7 +141,7 @@ namespace Flax.Build
// Build Main module // Build Main module
var mainModule = rules.GetModule("Main"); var mainModule = rules.GetModule("Main");
var mainModuleOutputPath = Path.Combine(exeBuildOptions.IntermediateFolder, mainModule.Name); var mainModuleOutputPath = Path.Combine(exeBuildOptions.IntermediateFolder, mainModule.Name);
if (!IsPreBuilt && !Directory.Exists(mainModuleOutputPath)) if (!Directory.Exists(mainModuleOutputPath))
Directory.CreateDirectory(mainModuleOutputPath); Directory.CreateDirectory(mainModuleOutputPath);
var mainModuleOptions = new BuildOptions var mainModuleOptions = new BuildOptions
{ {

View File

@@ -696,6 +696,26 @@ namespace Flax.Build
{ {
// Export symbols from binary module // Export symbols from binary module
moduleOptions.CompileEnv.PreprocessorDefinitions.Add(binaryModuleNameUpper + (target.UseSymbolsExports ? "_API=" + toolchain.DllExport : "_API=")); moduleOptions.CompileEnv.PreprocessorDefinitions.Add(binaryModuleNameUpper + (target.UseSymbolsExports ? "_API=" + toolchain.DllExport : "_API="));
// Import symbols from binary modules containing the referenced modules (from this project only, external ones are handled via ReferenceBuilds below)
foreach (var moduleName in moduleOptions.PrivateDependencies)
{
var dependencyModule = buildData.Rules.GetModule(moduleName);
if (dependencyModule != null && !string.IsNullOrEmpty(dependencyModule.BinaryModuleName) && dependencyModule.BinaryModuleName != binaryModule.Key && IsModuleFromProject(dependencyModule, project) && buildData.Modules.TryGetValue(dependencyModule, out var dependencyOptions))
{
// Import symbols from referenced binary module
moduleOptions.CompileEnv.PreprocessorDefinitions.Add(dependencyModule.BinaryModuleName.ToUpperInvariant() + "_API=" + toolchain.DllImport);
}
}
foreach (var moduleName in moduleOptions.PublicDependencies)
{
var dependencyModule = buildData.Rules.GetModule(moduleName);
if (dependencyModule != null && !string.IsNullOrEmpty(dependencyModule.BinaryModuleName) && dependencyModule.BinaryModuleName != binaryModule.Key && IsModuleFromProject(dependencyModule, project) && buildData.Modules.TryGetValue(dependencyModule, out var dependencyOptions))
{
// Import symbols from referenced binary module
moduleOptions.CompileEnv.PreprocessorDefinitions.Add(dependencyModule.BinaryModuleName.ToUpperInvariant() + "_API=" + toolchain.DllImport);
}
}
} }
else else
{ {

View File

@@ -45,7 +45,7 @@ namespace Flax.Build
throw new Exception($"Invalid or missing editor target {project.EditorTarget} specified in project {project.Name} (referenced by project {Project.Name})."); throw new Exception($"Invalid or missing editor target {project.EditorTarget} specified in project {project.Name} (referenced by project {Project.Name}).");
return result; return result;
} }
if (!IsEditor && !string.IsNullOrEmpty(project.GameTarget)) if (!string.IsNullOrEmpty(project.GameTarget))
{ {
var result = projectTargets.FirstOrDefault(x => x.Name == project.GameTarget); var result = projectTargets.FirstOrDefault(x => x.Name == project.GameTarget);
if (result == null) if (result == null)

View File

@@ -119,6 +119,8 @@ namespace Flax.Build
private bool IsTargetCSharpOnly(string name) private bool IsTargetCSharpOnly(string name)
{ {
if (string.IsNullOrWhiteSpace(name))
return true;
var rules = Builder.GenerateRulesAssembly(); var rules = Builder.GenerateRulesAssembly();
var target = rules.GetTarget(name); var target = rules.GetTarget(name);
return target == null || target.Modules.TrueForAll(x => !rules.GetModule(x).BuildNativeCode); return target == null || target.Modules.TrueForAll(x => !rules.GetModule(x).BuildNativeCode);