Merge remote-tracking branch 'origin/1.7' into 1.8
# Conflicts: # Flax.flaxproj
This commit is contained in:
@@ -33,4 +33,4 @@ jobs:
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -arch=ARM64 -platform=Android -configuration=Release -buildtargets=FlaxGame
|
||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -dotnet=7 -arch=ARM64 -platform=Android -configuration=Release -buildtargets=FlaxGame
|
||||
|
||||
@@ -33,4 +33,4 @@ jobs:
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
./Development/Scripts/Mac/CallBuildTool.sh -build -log -arch=ARM64 -platform=iOS -configuration=Release -buildtargets=FlaxGame
|
||||
./Development/Scripts/Mac/CallBuildTool.sh -build -log -dotnet=7 -arch=ARM64 -platform=iOS -configuration=Release -buildtargets=FlaxGame
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -printSDKs -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxEditor
|
||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -printSDKs -dotnet=7 -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxEditor
|
||||
|
||||
# Game
|
||||
game-linux:
|
||||
@@ -64,4 +64,4 @@ jobs:
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -printSDKs -arch=x64 -platform=Linux -configuration=Release -buildtargets=FlaxGame
|
||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -printSDKs -dotnet=7 -arch=x64 -platform=Linux -configuration=Release -buildtargets=FlaxGame
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
./Development/Scripts/Mac/CallBuildTool.sh -build -log -printSDKs -arch=x64 -platform=Mac -configuration=Development -buildtargets=FlaxEditor
|
||||
./Development/Scripts/Mac/CallBuildTool.sh -build -log -printSDKs -dotnet=7 -arch=x64 -platform=Mac -configuration=Development -buildtargets=FlaxEditor
|
||||
|
||||
# Game
|
||||
game-mac:
|
||||
@@ -55,4 +55,4 @@ jobs:
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
./Development/Scripts/Mac/CallBuildTool.sh -build -log -printSDKs -arch=x64 -platform=Mac -configuration=Release -buildtargets=FlaxGame
|
||||
./Development/Scripts/Mac/CallBuildTool.sh -build -log -printSDKs -dotnet=7 -arch=x64 -platform=Mac -configuration=Release -buildtargets=FlaxGame
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxEditor
|
||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -dotnet=7 -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxEditor
|
||||
|
||||
# Game
|
||||
game-windows:
|
||||
@@ -55,4 +55,4 @@ jobs:
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -arch=x64 -platform=Windows -configuration=Release -buildtargets=FlaxGame
|
||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -printSDKs -dotnet=7 -arch=x64 -platform=Windows -configuration=Release -buildtargets=FlaxGame
|
||||
|
||||
@@ -34,8 +34,8 @@ jobs:
|
||||
sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev build-essential gettext libtool libtool-bin libpulse-dev libasound2-dev libjack-dev portaudio19-dev
|
||||
- name: Build
|
||||
run: |
|
||||
./GenerateProjectFiles.sh -vs2022 -log -verbose -printSDKs
|
||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxTestsTarget
|
||||
./GenerateProjectFiles.sh -vs2022 -log -verbose -printSDKs -dotnet=7
|
||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -dotnet=7 -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxTestsTarget
|
||||
dotnet msbuild Source/Tools/Flax.Build.Tests/Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo
|
||||
dotnet msbuild Source/Tools/Flax.Build.Tests/Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo
|
||||
- name: Test
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
dotnet test -f net7.0 Binaries/Tests/FlaxEngine.CSharp.dll
|
||||
- name: Test UseLargeWorlds
|
||||
run: |
|
||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxTestsTarget -UseLargeWorlds=true
|
||||
./Development/Scripts/Linux/CallBuildTool.sh -build -log -dotnet=7 -arch=x64 -platform=Linux -configuration=Development -buildtargets=FlaxTestsTarget -UseLargeWorlds=true
|
||||
${GITHUB_WORKSPACE}/Binaries/Editor/Linux/Development/FlaxTests
|
||||
|
||||
# Tests on Windows
|
||||
@@ -72,8 +72,8 @@ jobs:
|
||||
git lfs pull
|
||||
- name: Build
|
||||
run: |
|
||||
.\GenerateProjectFiles.bat -vs2022 -log -verbose -printSDKs
|
||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxTestsTarget
|
||||
.\GenerateProjectFiles.bat -vs2022 -log -verbose -printSDKs -dotnet=7
|
||||
.\Development\Scripts\Windows\CallBuildTool.bat -build -log -dotnet=7 -arch=x64 -platform=Windows -configuration=Development -buildtargets=FlaxTestsTarget
|
||||
dotnet msbuild Source\Tools\Flax.Build.Tests\Flax.Build.Tests.csproj /m /t:Restore,Build /p:Configuration=Debug /p:Platform=AnyCPU /nologo
|
||||
- name: Test
|
||||
run: |
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
-1
@@ -4,7 +4,7 @@
|
||||
"Major": 1,
|
||||
"Minor": 8,
|
||||
"Revision": 0,
|
||||
"Build": 6502
|
||||
"Build": 6503
|
||||
},
|
||||
"Company": "Flax",
|
||||
"Copyright": "Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.",
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ pushd
|
||||
echo Performing the full package...
|
||||
|
||||
rem Run the build tool.
|
||||
call "Development\Scripts\Windows\CallBuildTool.bat" -deploy -deployEditor -deployPlatforms -verbose -log -logFile="Cache\Intermediate\PackageLog.txt" %*
|
||||
call "Development\Scripts\Windows\CallBuildTool.bat" -deploy -deployEditor -deployPlatforms -dotnet=7 -verbose -log -logFile="Cache\Intermediate\PackageLog.txt" %*
|
||||
if errorlevel 1 goto BuildToolFailed
|
||||
|
||||
popd
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ pushd
|
||||
echo Building and packaging Flax Editor...
|
||||
|
||||
rem Run the build tool.
|
||||
call "Development\Scripts\Windows\CallBuildTool.bat" -deploy -deployEditor -verbose -log -logFile="Cache\Intermediate\PackageLog.txt" %*
|
||||
call "Development\Scripts\Windows\CallBuildTool.bat" -deploy -deployEditor -dotnet=7 -verbose -log -logFile="Cache\Intermediate\PackageLog.txt" %*
|
||||
if errorlevel 1 goto BuildToolFailed
|
||||
|
||||
popd
|
||||
|
||||
@@ -9,4 +9,4 @@ echo Building and packaging Flax Editor...
|
||||
cd "`dirname "$0"`"
|
||||
|
||||
# Run Flax.Build (also pass the arguments)
|
||||
bash ./Development/Scripts/Mac/CallBuildTool.sh --deploy --deployEditor --verbose --log --logFile="Cache/Intermediate/PackageLog.txt" "$@"
|
||||
bash ./Development/Scripts/Mac/CallBuildTool.sh --deploy --deployEditor --dotnet=7 --verbose --log --logFile="Cache/Intermediate/PackageLog.txt" "$@"
|
||||
|
||||
+1
-1
@@ -9,4 +9,4 @@ echo Building and packaging Flax Editor...
|
||||
cd "`dirname "$0"`"
|
||||
|
||||
# Run Flax.Build (also pass the arguments)
|
||||
bash ./Development/Scripts/Linux/CallBuildTool.sh --deploy --deployEditor --verbose --log --logFile="Cache/Intermediate/PackageLog.txt" "$@"
|
||||
bash ./Development/Scripts/Linux/CallBuildTool.sh --deploy --deployEditor --dotnet=7 --verbose --log --logFile="Cache/Intermediate/PackageLog.txt" "$@"
|
||||
|
||||
@@ -7,7 +7,7 @@ pushd
|
||||
echo Building and packaging platforms data...
|
||||
|
||||
rem Run the build tool.
|
||||
call "Development\Scripts\Windows\CallBuildTool.bat" -deploy -deployPlatforms -verbose -log -logFile="Cache\Intermediate\PackageLog.txt" %*
|
||||
call "Development\Scripts\Windows\CallBuildTool.bat" -deploy -deployPlatforms -dotnet=7 -verbose -log -logFile="Cache\Intermediate\PackageLog.txt" %*
|
||||
if errorlevel 1 goto BuildToolFailed
|
||||
|
||||
popd
|
||||
|
||||
@@ -9,4 +9,4 @@ echo Building and packaging platforms data...
|
||||
cd "`dirname "$0"`"
|
||||
|
||||
# Run Flax.Build (also pass the arguments)
|
||||
bash ./Development/Scripts/Mac/CallBuildTool.sh --deploy --deployPlatforms --verbose --log --logFile="Cache/Intermediate/PackageLog.txt" "$@"
|
||||
bash ./Development/Scripts/Mac/CallBuildTool.sh --deploy --deployPlatforms --dotnet=7 --verbose --log --logFile="Cache/Intermediate/PackageLog.txt" "$@"
|
||||
|
||||
+1
-1
@@ -9,4 +9,4 @@ echo Building and packaging platforms data...
|
||||
cd "`dirname "$0"`"
|
||||
|
||||
# Run Flax.Build (also pass the arguments)
|
||||
bash ./Development/Scripts/Linux/CallBuildTool.sh --deploy --deployPlatforms --verbose --log --logFile="Cache/Intermediate/PackageLog.txt" "$@"
|
||||
bash ./Development/Scripts/Linux/CallBuildTool.sh --deploy --deployPlatforms --dotnet=7 --verbose --log --logFile="Cache/Intermediate/PackageLog.txt" "$@"
|
||||
|
||||
@@ -12,6 +12,13 @@
|
||||
class GameCooker;
|
||||
class PlatformTools;
|
||||
|
||||
#if OFFICIAL_BUILD
|
||||
// Use the fixed .NET SDK version in packaged builds for compatibility (FlaxGame is precompiled with it)
|
||||
#define GAME_BUILD_DOTNET_VER TEXT("-dotnet=7")
|
||||
#else
|
||||
#define GAME_BUILD_DOTNET_VER TEXT("")
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Game building options. Used as flags.
|
||||
/// </summary>
|
||||
|
||||
@@ -188,8 +188,8 @@ bool CompileScriptsStep::Perform(CookingData& data)
|
||||
LOG(Info, "Starting scripts compilation for game...");
|
||||
const String logFile = data.CacheDirectory / TEXT("CompileLog.txt");
|
||||
auto args = String::Format(
|
||||
TEXT("-log -logfile=\"{4}\" -build -mutex -buildtargets={0} -platform={1} -arch={2} -configuration={3} -aotMode={5}"),
|
||||
target, platform, architecture, configuration, logFile, ToString(data.Tools->UseAOT()));
|
||||
TEXT("-log -logfile=\"{4}\" -build -mutex -buildtargets={0} -platform={1} -arch={2} -configuration={3} -aotMode={5} {6}"),
|
||||
target, platform, architecture, configuration, logFile, ToString(data.Tools->UseAOT()), GAME_BUILD_DOTNET_VER);
|
||||
#if PLATFORM_WINDOWS
|
||||
if (data.Platform == BuildPlatform::LinuxX64)
|
||||
#elif PLATFORM_LINUX
|
||||
|
||||
@@ -87,7 +87,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
{
|
||||
// Ask Flax.Build to provide .Net SDK location for the current platform
|
||||
String sdks;
|
||||
bool failed = ScriptsBuilder::RunBuildTool(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printSDKs"), data.CacheDirectory);
|
||||
bool failed = ScriptsBuilder::RunBuildTool(String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printSDKs {}"), GAME_BUILD_DOTNET_VER), data.CacheDirectory);
|
||||
failed |= File::ReadAllText(data.CacheDirectory / TEXT("SDKs.txt"), sdks);
|
||||
int32 idx = sdks.Find(TEXT("DotNetSdk, "), StringSearchCase::CaseSensitive);
|
||||
if (idx != -1)
|
||||
@@ -168,7 +168,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
String sdks;
|
||||
const Char *platformName, *archName;
|
||||
data.GetBuildPlatformName(platformName, archName);
|
||||
String args = String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printDotNetRuntime -platform={} -arch={}"), platformName, archName);
|
||||
String args = String::Format(TEXT("-log -logMessagesOnly -logFileWithConsole -logfile=SDKs.txt -printDotNetRuntime -platform={} -arch={} {}"), platformName, archName, GAME_BUILD_DOTNET_VER);
|
||||
bool failed = ScriptsBuilder::RunBuildTool(args, data.CacheDirectory);
|
||||
failed |= File::ReadAllText(data.CacheDirectory / TEXT("SDKs.txt"), sdks);
|
||||
Array<String> parts;
|
||||
@@ -269,8 +269,8 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
LOG(Info, "Optimizing .NET class library size to include only used assemblies");
|
||||
const String logFile = data.CacheDirectory / TEXT("StripDotnetLibs.txt");
|
||||
String args = String::Format(
|
||||
TEXT("-log -logfile=\"{}\" -runDotNetClassLibStripping -mutex -binaries=\"{}\""),
|
||||
logFile, data.DataOutputPath);
|
||||
TEXT("-log -logfile=\"{}\" -runDotNetClassLibStripping -mutex -binaries=\"{}\" {}"),
|
||||
logFile, data.DataOutputPath, GAME_BUILD_DOTNET_VER);
|
||||
for (const String& define : data.CustomDefines)
|
||||
{
|
||||
args += TEXT(" -D");
|
||||
|
||||
@@ -67,8 +67,8 @@ bool PrecompileAssembliesStep::Perform(CookingData& data)
|
||||
data.GetBuildPlatformName(platform, architecture);
|
||||
const String logFile = data.CacheDirectory / TEXT("AOTLog.txt");
|
||||
String args = String::Format(
|
||||
TEXT("-log -logfile=\"{}\" -runDotNetAOT -mutex -platform={} -arch={} -configuration={} -aotMode={} -binaries=\"{}\" -intermediate=\"{}\""),
|
||||
logFile, platform, architecture, configuration, ToString(aotMode), data.DataOutputPath, data.ManagedCodeOutputPath);
|
||||
TEXT("-log -logfile=\"{}\" -runDotNetAOT -mutex -platform={} -arch={} -configuration={} -aotMode={} -binaries=\"{}\" -intermediate=\"{}\" {}"),
|
||||
logFile, platform, architecture, configuration, ToString(aotMode), data.DataOutputPath, data.ManagedCodeOutputPath, GAME_BUILD_DOTNET_VER);
|
||||
if (!buildSettings.SkipUnusedDotnetLibsPackaging)
|
||||
args += TEXT(" -skipUnusedDotnetLibs=false"); // Run AOT on whole class library (not just used libs)
|
||||
for (const String& define : data.CustomDefines)
|
||||
|
||||
@@ -171,11 +171,13 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
tree.Select(typeNode);
|
||||
if (addItems)
|
||||
{
|
||||
var items = GenericEditor.GetItemsForType(type, type.IsClass, true);
|
||||
var items = GenericEditor.GetItemsForType(type, type.IsClass, true, true);
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (typed && !typed.IsAssignableFrom(item.Info.ValueType))
|
||||
continue;
|
||||
if (item.Info.DeclaringType.Type == typeof(FlaxEngine.Object))
|
||||
continue; // Skip engine internals
|
||||
var itemPath = typePath + item.Info.Name;
|
||||
var node = new TreeNode
|
||||
{
|
||||
|
||||
@@ -247,8 +247,9 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="useProperties">True if use type properties.</param>
|
||||
/// <param name="useFields">True if use type fields.</param>
|
||||
/// <param name="usePropertiesWithoutSetter">True if use type properties that have only getter method without setter method (aka read-only).</param>
|
||||
/// <returns>The items.</returns>
|
||||
public static List<ItemInfo> GetItemsForType(ScriptType type, bool useProperties, bool useFields)
|
||||
public static List<ItemInfo> GetItemsForType(ScriptType type, bool useProperties, bool useFields, bool usePropertiesWithoutSetter = false)
|
||||
{
|
||||
var items = new List<ItemInfo>();
|
||||
|
||||
@@ -264,7 +265,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
var showInEditor = attributes.Any(x => x is ShowInEditorAttribute);
|
||||
|
||||
// Skip properties without getter or setter
|
||||
if (!p.HasGet || (!p.HasSet && !showInEditor))
|
||||
if (!p.HasGet || (!p.HasSet && !showInEditor && !usePropertiesWithoutSetter))
|
||||
continue;
|
||||
|
||||
// Skip hidden fields, handle special attributes
|
||||
|
||||
@@ -111,7 +111,8 @@ namespace FlaxEditor.Gizmo
|
||||
if (isSelected)
|
||||
{
|
||||
GetSelectedObjectsBounds(out var selectionBounds, out _);
|
||||
ray.Position = ray.GetPoint(selectionBounds.Size.Y * 0.5f);
|
||||
var offset = Mathf.Max(selectionBounds.Size.Y * 0.5f, 1.0f);
|
||||
ray.Position = ray.GetPoint(offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -288,6 +288,9 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
}
|
||||
}
|
||||
SetValue(2, ids);
|
||||
|
||||
// Force refresh UI
|
||||
ResizeAuto();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -371,7 +371,10 @@ namespace FlaxEditor.Windows.Assets
|
||||
private void OnTreeSelectedChanged(List<TreeNode> before, List<TreeNode> after)
|
||||
{
|
||||
if (after.Count != 0)
|
||||
((SkeletonPropertiesProxy)Values[0]).Window._preview.ShowDebugDraw = true;
|
||||
{
|
||||
var proxy = (SkeletonPropertiesProxy)Values[0];
|
||||
proxy.Window._preview.ShowDebugDraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTreeNodeCopyName(ContextMenuButton b)
|
||||
@@ -1045,6 +1048,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
{
|
||||
Proxy = new SkeletonPropertiesProxy();
|
||||
Presenter.Select(Proxy);
|
||||
// Draw highlight on selected node
|
||||
window._preview.CustomDebugDraw += OnDebugDraw;
|
||||
}
|
||||
|
||||
@@ -1146,6 +1150,15 @@ namespace FlaxEditor.Windows.Assets
|
||||
_tabs.AddTab(new RetargetTab(this));
|
||||
_tabs.AddTab(new ImportTab(this));
|
||||
|
||||
// Automatically show nodes when switching to skeleton page
|
||||
_tabs.SelectedTabChanged += (tabs) =>
|
||||
{
|
||||
if (tabs.SelectedTab is SkeletonTab)
|
||||
{
|
||||
_preview.ShowNodes = true;
|
||||
}
|
||||
};
|
||||
|
||||
// Highlight actor (used to highlight selected material slot, see UpdateEffectsOnAsset)
|
||||
_highlightActor = new AnimatedModel
|
||||
{
|
||||
|
||||
@@ -386,6 +386,7 @@ namespace FlaxEditor.Windows
|
||||
{
|
||||
_viewport.Bounds = new Rectangle(Width * (1 - scaleWidth) / 2, 0, Width * scaleWidth, Height);
|
||||
}
|
||||
_viewport.SyncBackbufferSize();
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
|
||||
@@ -391,6 +391,25 @@ namespace FlaxEditor.Windows
|
||||
}
|
||||
|
||||
Editor.Log("Plugin project has been cloned.");
|
||||
|
||||
try
|
||||
{
|
||||
// Start git submodule clone
|
||||
var settings = new CreateProcessSettings
|
||||
{
|
||||
FileName = "git",
|
||||
WorkingDirectory = clonePath,
|
||||
Arguments = "submodule update --init",
|
||||
ShellExecute = false,
|
||||
LogOutput = true,
|
||||
};
|
||||
Platform.CreateProcess(ref settings);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Editor.LogError($"Failed Git submodule process. {e}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Find project config file. Could be different then what the user named the folder.
|
||||
var files = Directory.GetFiles(clonePath);
|
||||
|
||||
@@ -114,14 +114,19 @@ void Behavior::UpdateAsync()
|
||||
|
||||
void Behavior::StartLogic()
|
||||
{
|
||||
if (_result == BehaviorUpdateResult::Running)
|
||||
return;
|
||||
PROFILE_CPU();
|
||||
|
||||
// Ensure to have tree loaded on begin play
|
||||
// Ensure to have tree loaded on play
|
||||
CHECK(Tree && !Tree->WaitForLoaded());
|
||||
BehaviorTree* tree = Tree.Get();
|
||||
CHECK(tree->Graph.Root);
|
||||
|
||||
// Setup state
|
||||
_result = BehaviorUpdateResult::Running;
|
||||
_accumulatedTime = 0.0f;
|
||||
_totalTime = 0;
|
||||
|
||||
// Init knowledge
|
||||
_knowledge.InitMemory(tree);
|
||||
@@ -135,6 +140,7 @@ void Behavior::StopLogic(BehaviorUpdateResult result)
|
||||
_accumulatedTime = 0.0f;
|
||||
_totalTime = 0;
|
||||
_result = result;
|
||||
_knowledge.FreeMemory();
|
||||
}
|
||||
|
||||
void Behavior::ResetLogic()
|
||||
@@ -170,7 +176,11 @@ void Behavior::OnDisable()
|
||||
|
||||
bool Behavior::GetNodeDebugRelevancy(const BehaviorTreeNode* node, const Behavior* behavior)
|
||||
{
|
||||
return node && behavior && node->_executionIndex != -1 && behavior->_knowledge.RelevantNodes.Get(node->_executionIndex);
|
||||
return node &&
|
||||
behavior &&
|
||||
node->_executionIndex >= 0 &&
|
||||
node->_executionIndex < behavior->_knowledge.RelevantNodes.Count() &&
|
||||
behavior->_knowledge.RelevantNodes.Get(node->_executionIndex);
|
||||
}
|
||||
|
||||
String Behavior::GetNodeDebugInfo(const BehaviorTreeNode* node, Behavior* behavior)
|
||||
@@ -179,7 +189,7 @@ String Behavior::GetNodeDebugInfo(const BehaviorTreeNode* node, Behavior* behavi
|
||||
return String::Empty;
|
||||
BehaviorUpdateContext context;
|
||||
Platform::MemoryClear(&context, sizeof(context));
|
||||
if (behavior && node->_executionIndex != -1 && behavior->_knowledge.RelevantNodes.Get(node->_executionIndex))
|
||||
if (GetNodeDebugRelevancy(node, behavior))
|
||||
{
|
||||
// Pass behavior and knowledge data only for relevant nodes to properly access it
|
||||
context.Behavior = behavior;
|
||||
|
||||
@@ -83,7 +83,7 @@ bool AccessVariant(Variant& instance, const StringAnsiView& member, Variant& val
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
else if (typeName.HasChars())
|
||||
{
|
||||
LOG(Warning, "Missing scripting type \'{0}\'", String(typeName));
|
||||
}
|
||||
|
||||
@@ -1342,7 +1342,12 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
{
|
||||
const bool xAxis = Math::IsZero(v0.X) && Math::IsZero(v1.X);
|
||||
const bool yAxis = Math::IsZero(v0.Y) && Math::IsZero(v1.Y);
|
||||
if (xAxis || yAxis)
|
||||
if (xAxis && yAxis)
|
||||
{
|
||||
// Single animation
|
||||
value = SampleAnimation(node, loop, data.Length, startTimePos, bucket.TimePosition, newTimePos, aAnim, aData.W);
|
||||
}
|
||||
else if (xAxis || yAxis)
|
||||
{
|
||||
if (yAxis)
|
||||
{
|
||||
|
||||
@@ -323,26 +323,29 @@ bool BinaryAsset::SaveToAsset(const StringView& path, AssetInitData& data, bool
|
||||
{
|
||||
// Ensure path is in a valid format
|
||||
String pathNorm(path);
|
||||
FileSystem::NormalizePath(pathNorm);
|
||||
ContentStorageManager::FormatPath(pathNorm);
|
||||
const StringView filePath = pathNorm;
|
||||
|
||||
// Find target storage container and the asset
|
||||
auto storage = ContentStorageManager::TryGetStorage(pathNorm);
|
||||
auto asset = Content::GetAsset(pathNorm);
|
||||
auto storage = ContentStorageManager::TryGetStorage(filePath);
|
||||
auto asset = Content::GetAsset(filePath);
|
||||
auto binaryAsset = dynamic_cast<BinaryAsset*>(asset);
|
||||
if (asset && !binaryAsset)
|
||||
{
|
||||
LOG(Warning, "Cannot write to the non-binary asset location.");
|
||||
return true;
|
||||
}
|
||||
if (!binaryAsset && !storage && FileSystem::FileExists(filePath))
|
||||
{
|
||||
// Force-resolve storage (asset at that path could be not yet loaded into registry)
|
||||
storage = ContentStorageManager::GetStorage(filePath);
|
||||
}
|
||||
|
||||
// Check if can perform write operation to the asset container
|
||||
if (storage)
|
||||
if (storage && !storage->AllowDataModifications())
|
||||
{
|
||||
if (!storage->AllowDataModifications())
|
||||
{
|
||||
LOG(Warning, "Cannot write to the asset storage container.");
|
||||
return true;
|
||||
}
|
||||
LOG(Warning, "Cannot write to the asset storage container.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize data container
|
||||
@@ -352,6 +355,11 @@ bool BinaryAsset::SaveToAsset(const StringView& path, AssetInitData& data, bool
|
||||
// Use the same asset ID
|
||||
data.Header.ID = binaryAsset->GetID();
|
||||
}
|
||||
else if (storage && storage->GetEntriesCount())
|
||||
{
|
||||
// Use the same file ID
|
||||
data.Header.ID = storage->GetEntry(0).ID;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Randomize ID
|
||||
@@ -373,8 +381,8 @@ bool BinaryAsset::SaveToAsset(const StringView& path, AssetInitData& data, bool
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(pathNorm.HasChars());
|
||||
result = FlaxStorage::Create(pathNorm, data, silentMode);
|
||||
ASSERT(filePath.HasChars());
|
||||
result = FlaxStorage::Create(filePath, data, silentMode);
|
||||
}
|
||||
if (binaryAsset)
|
||||
binaryAsset->_isSaving = false;
|
||||
|
||||
@@ -54,8 +54,7 @@ namespace
|
||||
// Assets
|
||||
CriticalSection AssetsLocker;
|
||||
Dictionary<Guid, Asset*> Assets(2048);
|
||||
CriticalSection LoadCallAssetsLocker;
|
||||
Array<Guid> LoadCallAssets(64);
|
||||
Array<Guid> LoadCallAssets(PLATFORM_THREADS_LIMIT);
|
||||
CriticalSection LoadedAssetsToInvokeLocker;
|
||||
Array<Asset*> LoadedAssetsToInvoke(64);
|
||||
Array<Asset*> ToUnload;
|
||||
@@ -449,18 +448,19 @@ Asset* Content::LoadAsync(const StringView& path, const ScriptingTypeHandle& typ
|
||||
{
|
||||
// Ensure path is in a valid format
|
||||
String pathNorm(path);
|
||||
StringUtils::PathRemoveRelativeParts(pathNorm);
|
||||
ContentStorageManager::FormatPath(pathNorm);
|
||||
const StringView filePath = pathNorm;
|
||||
|
||||
#if USE_EDITOR
|
||||
if (!FileSystem::FileExists(pathNorm))
|
||||
if (!FileSystem::FileExists(filePath))
|
||||
{
|
||||
LOG(Error, "Missing file \'{0}\'", pathNorm);
|
||||
LOG(Error, "Missing file \'{0}\'", filePath);
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
AssetInfo assetInfo;
|
||||
if (GetAssetInfo(pathNorm, assetInfo))
|
||||
if (GetAssetInfo(filePath, assetInfo))
|
||||
{
|
||||
return LoadAsync(assetInfo.ID, type);
|
||||
}
|
||||
@@ -910,9 +910,13 @@ Asset* Content::LoadAsync(const Guid& id, const ScriptingTypeHandle& type)
|
||||
return nullptr;
|
||||
|
||||
// Check if asset has been already loaded
|
||||
Asset* result = GetAsset(id);
|
||||
Asset* result = nullptr;
|
||||
AssetsLocker.Lock();
|
||||
Assets.TryGet(id, result);
|
||||
if (result)
|
||||
{
|
||||
AssetsLocker.Unlock();
|
||||
|
||||
// Validate type
|
||||
if (IsAssetTypeIdInvalid(type, result->GetTypeHandle()) && !result->Is(type))
|
||||
{
|
||||
@@ -923,57 +927,41 @@ Asset* Content::LoadAsync(const Guid& id, const ScriptingTypeHandle& type)
|
||||
}
|
||||
|
||||
// Check if that asset is during loading
|
||||
LoadCallAssetsLocker.Lock();
|
||||
if (LoadCallAssets.Contains(id))
|
||||
{
|
||||
LoadCallAssetsLocker.Unlock();
|
||||
AssetsLocker.Unlock();
|
||||
|
||||
// Wait for load end
|
||||
// TODO: dont use active waiting and prevent deadlocks if running on a main thread
|
||||
//while (!Engine::ShouldExit())
|
||||
while (true)
|
||||
// Wait for loading end by other thread
|
||||
bool contains = true;
|
||||
while (contains)
|
||||
{
|
||||
LoadCallAssetsLocker.Lock();
|
||||
const bool contains = LoadCallAssets.Contains(id);
|
||||
LoadCallAssetsLocker.Unlock();
|
||||
if (!contains)
|
||||
return GetAsset(id);
|
||||
Platform::Sleep(1);
|
||||
AssetsLocker.Lock();
|
||||
contains = LoadCallAssets.Contains(id);
|
||||
AssetsLocker.Unlock();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mark asset as loading
|
||||
LoadCallAssets.Add(id);
|
||||
LoadCallAssetsLocker.Unlock();
|
||||
Assets.TryGet(id, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Load asset
|
||||
AssetInfo assetInfo;
|
||||
result = load(id, type, assetInfo);
|
||||
// Mark asset as loading and release lock so other threads can load other assets
|
||||
LoadCallAssets.Add(id);
|
||||
AssetsLocker.Unlock();
|
||||
|
||||
// End loading
|
||||
LoadCallAssetsLocker.Lock();
|
||||
LoadCallAssets.Remove(id);
|
||||
LoadCallAssetsLocker.Unlock();
|
||||
#define LOAD_FAILED() AssetsLocker.Lock(); LoadCallAssets.Remove(id); AssetsLocker.Unlock(); return nullptr
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Asset* Content::load(const Guid& id, const ScriptingTypeHandle& type, AssetInfo& assetInfo)
|
||||
{
|
||||
// Get cached asset info (from registry)
|
||||
AssetInfo assetInfo;
|
||||
if (!GetAssetInfo(id, assetInfo))
|
||||
{
|
||||
LOG(Warning, "Invalid or missing asset ({0}, {1}).", id, type.ToString());
|
||||
return nullptr;
|
||||
LOAD_FAILED();
|
||||
}
|
||||
|
||||
#if ASSETS_LOADING_EXTRA_VERIFICATION
|
||||
if (!FileSystem::FileExists(assetInfo.Path))
|
||||
{
|
||||
LOG(Error, "Cannot find file '{0}'", assetInfo.Path);
|
||||
return nullptr;
|
||||
LOAD_FAILED();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -982,28 +970,27 @@ Asset* Content::load(const Guid& id, const ScriptingTypeHandle& type, AssetInfo&
|
||||
if (factory == nullptr)
|
||||
{
|
||||
LOG(Error, "Cannot find asset factory. Info: {0}", assetInfo.ToString());
|
||||
return nullptr;
|
||||
LOAD_FAILED();
|
||||
}
|
||||
|
||||
// Create asset object
|
||||
auto result = factory->New(assetInfo);
|
||||
result = factory->New(assetInfo);
|
||||
if (result == nullptr)
|
||||
{
|
||||
LOG(Error, "Cannot create asset object. Info: {0}", assetInfo.ToString());
|
||||
return nullptr;
|
||||
LOAD_FAILED();
|
||||
}
|
||||
|
||||
ASSERT(result->GetID() == id);
|
||||
#if ASSETS_LOADING_EXTRA_VERIFICATION
|
||||
if (IsAssetTypeIdInvalid(type, result->GetTypeHandle()) && !result->Is(type))
|
||||
{
|
||||
LOG(Error, "Different loaded asset type! Asset: '{0}'. Expected type: {1}", assetInfo.ToString(), type.ToString());
|
||||
LOG(Warning, "Different loaded asset type! Asset: '{0}'. Expected type: {1}", assetInfo.ToString(), type.ToString());
|
||||
result->DeleteObject();
|
||||
return nullptr;
|
||||
LOAD_FAILED();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Register asset
|
||||
ASSERT(result->GetID() == id);
|
||||
AssetsLocker.Lock();
|
||||
#if ASSETS_LOADING_EXTRA_VERIFICATION
|
||||
ASSERT(!Assets.ContainsKey(id));
|
||||
@@ -1011,11 +998,14 @@ Asset* Content::load(const Guid& id, const ScriptingTypeHandle& type, AssetInfo&
|
||||
Assets.Add(id, result);
|
||||
|
||||
// Start asset loading
|
||||
// TODO: refactor this to create asset loading task-chain before AssetsLocker.Lock() to allow better parallelization
|
||||
result->startLoading();
|
||||
|
||||
// Remove from the loading queue and release lock
|
||||
LoadCallAssets.Remove(id);
|
||||
AssetsLocker.Unlock();
|
||||
|
||||
#undef LOAD_FAILED
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -366,7 +366,6 @@ private:
|
||||
static void onAssetLoaded(Asset* asset);
|
||||
static void onAssetUnload(Asset* asset);
|
||||
static void onAssetChangeId(Asset* asset, const Guid& oldId, const Guid& newId);
|
||||
static Asset* load(const Guid& id, const ScriptingTypeHandle& type, AssetInfo& assetInfo);
|
||||
|
||||
private:
|
||||
static void deleteFileSafety(const StringView& path, const Guid& id);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Engine/Engine.h"
|
||||
#include "Engine/Engine/EngineService.h"
|
||||
#include "Engine/Engine/Globals.h"
|
||||
#include "Engine/Platform/FileSystem.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Threading/TaskGraph.h"
|
||||
@@ -185,6 +186,16 @@ void ContentStorageManager::EnsureUnlocked()
|
||||
Locker.Unlock();
|
||||
}
|
||||
|
||||
void ContentStorageManager::FormatPath(String& path)
|
||||
{
|
||||
StringUtils::PathRemoveRelativeParts(path);
|
||||
if (FileSystem::IsRelative(path))
|
||||
{
|
||||
// Convert local-project paths into absolute format which is used by Content Storage system
|
||||
path = Globals::ProjectFolder / path;
|
||||
}
|
||||
}
|
||||
|
||||
bool ContentStorageManager::IsFlaxStoragePath(const String& path)
|
||||
{
|
||||
auto extension = FileSystem::GetExtension(path).ToLower();
|
||||
|
||||
@@ -75,6 +75,9 @@ public:
|
||||
/// </summary>
|
||||
static void EnsureUnlocked();
|
||||
|
||||
// Formats path into valid format used by the storage system (normalized and absolute).
|
||||
static void FormatPath(String& path);
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Determines whether the specified path can be a binary asset file (based on it's extension).
|
||||
|
||||
@@ -8,11 +8,12 @@
|
||||
#include "Engine/Core/Collections/Sorting.h"
|
||||
#include "Engine/Debug/DebugLog.h"
|
||||
#include "Engine/Level/Level.h"
|
||||
#include "Engine/Level/Scene/Scene.h"
|
||||
#include "Engine/Level/Actors/Camera.h"
|
||||
#include "Engine/Level/Actors/PostFxVolume.h"
|
||||
#include "Engine/Renderer/Renderer.h"
|
||||
#include "Engine/Render2D/Render2D.h"
|
||||
#include "Engine/Engine/Engine.h"
|
||||
#include "Engine/Level/Actors/PostFxVolume.h"
|
||||
#include "Engine/Profiler/Profiler.h"
|
||||
#include "Engine/Renderer/RenderList.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
@@ -202,15 +203,21 @@ void SceneRenderTask::CollectPostFxVolumes(RenderContext& renderContext)
|
||||
{
|
||||
Level::CollectPostFxVolumes(renderContext);
|
||||
}
|
||||
if (EnumHasAllFlags(ActorsSource , ActorsSources::CustomActors))
|
||||
if (EnumHasAllFlags(ActorsSource, ActorsSources::CustomActors))
|
||||
{
|
||||
for (Actor* a : CustomActors)
|
||||
{
|
||||
auto* postFxVolume = dynamic_cast<PostFxVolume*>(a);
|
||||
if (postFxVolume && a->GetIsActive())
|
||||
{
|
||||
postFxVolume->Collect(renderContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (EnumHasAllFlags(ActorsSource, ActorsSources::CustomScenes))
|
||||
{
|
||||
for (Scene* scene : CustomScenes)
|
||||
{
|
||||
if (scene && scene->IsActiveInHierarchy())
|
||||
scene->Rendering.CollectPostFxVolumes(renderContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,6 +289,14 @@ void SceneRenderTask::OnCollectDrawCalls(RenderContextBatch& renderContextBatch,
|
||||
ASSERT_LOW_LAYER(_customActorsScene);
|
||||
_customActorsScene->Draw(renderContextBatch, (SceneRendering::DrawCategory)category);
|
||||
}
|
||||
if (EnumHasAllFlags(ActorsSource, ActorsSources::CustomScenes))
|
||||
{
|
||||
for (Scene* scene : CustomScenes)
|
||||
{
|
||||
if (scene && scene->IsActiveInHierarchy())
|
||||
scene->Rendering.Draw(renderContextBatch, (SceneRendering::DrawCategory)category);
|
||||
}
|
||||
}
|
||||
if (EnumHasAllFlags(ActorsSource, ActorsSources::Scenes))
|
||||
{
|
||||
Level::DrawActors(renderContextBatch, category);
|
||||
|
||||
@@ -21,6 +21,7 @@ class PostProcessEffect;
|
||||
struct RenderContext;
|
||||
class Camera;
|
||||
class Actor;
|
||||
class Scene;
|
||||
|
||||
/// <summary>
|
||||
/// Allows to perform custom rendering using graphics pipeline.
|
||||
@@ -174,6 +175,11 @@ API_ENUM(Attributes="Flags") enum class ActorsSources
|
||||
/// </summary>
|
||||
CustomActors = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The scenes from the custom collection.
|
||||
/// </summary>
|
||||
CustomScenes = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The actors from the loaded scenes and custom collection.
|
||||
/// </summary>
|
||||
@@ -267,9 +273,14 @@ public:
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// The custom set of actors to render.
|
||||
/// The custom set of actors to render. Used when ActorsSources::CustomActors flag is active.
|
||||
/// </summary>
|
||||
Array<Actor*> CustomActors;
|
||||
API_FIELD() Array<Actor*> CustomActors;
|
||||
|
||||
/// <summary>
|
||||
/// The custom set of scenes to render. Used when ActorsSources::CustomScenes flag is active.
|
||||
/// </summary>
|
||||
API_FIELD() Array<Scene*> CustomScenes;
|
||||
|
||||
/// <summary>
|
||||
/// Adds the custom actor to the rendering.
|
||||
|
||||
@@ -172,6 +172,28 @@ void AnimatedModel::GetNodeTransformation(const StringView& nodeName, Matrix& no
|
||||
GetNodeTransformation(SkinnedModel ? SkinnedModel->FindNode(nodeName) : -1, nodeTransformation, worldSpace);
|
||||
}
|
||||
|
||||
void AnimatedModel::SetNodeTransformation(int32 nodeIndex, const Matrix& nodeTransformation, bool worldSpace)
|
||||
{
|
||||
if (GraphInstance.NodesPose.IsEmpty())
|
||||
const_cast<AnimatedModel*>(this)->PreInitSkinningData(); // Ensure to have valid nodes pose to return
|
||||
CHECK(nodeIndex >= 0 && nodeIndex < GraphInstance.NodesPose.Count());
|
||||
GraphInstance.NodesPose[nodeIndex] = nodeTransformation;
|
||||
if (worldSpace)
|
||||
{
|
||||
Matrix world;
|
||||
_transform.GetWorld(world);
|
||||
Matrix invWorld;
|
||||
Matrix::Invert(world, invWorld);
|
||||
GraphInstance.NodesPose[nodeIndex] = GraphInstance.NodesPose[nodeIndex] * invWorld;
|
||||
}
|
||||
OnAnimationUpdated();
|
||||
}
|
||||
|
||||
void AnimatedModel::SetNodeTransformation(const StringView& nodeName, const Matrix& nodeTransformation, bool worldSpace)
|
||||
{
|
||||
SetNodeTransformation(SkinnedModel ? SkinnedModel->FindNode(nodeName) : -1, nodeTransformation, worldSpace);
|
||||
}
|
||||
|
||||
int32 AnimatedModel::FindClosestNode(const Vector3& location, bool worldSpace) const
|
||||
{
|
||||
if (GraphInstance.NodesPose.IsEmpty())
|
||||
|
||||
@@ -229,6 +229,22 @@ public:
|
||||
/// <param name="worldSpace">True if convert matrices into world-space, otherwise returned values will be in local-space of the actor.</param>
|
||||
API_FUNCTION() void GetNodeTransformation(const StringView& nodeName, API_PARAM(Out) Matrix& nodeTransformation, bool worldSpace = false) const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the node final transformation. If multiple nodes are to be set within a frame, do not use set worldSpace to true, and do the conversion yourself to avoid recalculation of inv matrices.
|
||||
/// </summary>
|
||||
/// <param name="nodeIndex">The index of the skinned model skeleton node.</param>
|
||||
/// <param name="nodeTransformation">The final node transformation matrix.</param>
|
||||
/// <param name="worldSpace">True if convert matrices from world-space, otherwise values will be in local-space of the actor.</param>
|
||||
API_FUNCTION() void SetNodeTransformation(int32 nodeIndex, const Matrix& nodeTransformation, bool worldSpace = false);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the node final transformation. If multiple nodes are to be set within a frame, do not use set worldSpace to true, and do the conversion yourself to avoid recalculation of inv matrices.
|
||||
/// </summary>
|
||||
/// <param name="nodeName">The name of the skinned model skeleton node.</param>
|
||||
/// <param name="nodeTransformation">The final node transformation matrix.</param>
|
||||
/// <param name="worldSpace">True if convert matrices from world-space, otherwise values will be in local-space of the actor.</param>
|
||||
API_FUNCTION() void SetNodeTransformation(const StringView& nodeName, const Matrix& nodeTransformation, bool worldSpace = false);
|
||||
|
||||
/// <summary>
|
||||
/// Finds the closest node to a given location.
|
||||
/// </summary>
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
/// </summary>
|
||||
Win32CriticalSection()
|
||||
{
|
||||
Windows::InitializeCriticalSectionEx(&_criticalSection, 100, 0x01000000);
|
||||
Windows::InitializeCriticalSectionEx(&_criticalSection, 4000, 0x01000000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1812,7 +1812,7 @@ void* GetStaticMethodPointer(const String& methodName)
|
||||
PROFILE_CPU();
|
||||
const int rc = get_function_pointer(NativeInteropTypeName, FLAX_CORECLR_STRING(methodName).Get(), UNMANAGEDCALLERSONLY_METHOD, nullptr, nullptr, &fun);
|
||||
if (rc != 0)
|
||||
LOG(Fatal, "Failed to get unmanaged function pointer for method {0}: 0x{1:x}", methodName.Get(), (unsigned int)rc);
|
||||
LOG(Fatal, "Failed to get unmanaged function pointer for method '{0}': 0x{1:x}", methodName, (unsigned int)rc);
|
||||
CachedFunctions.Add(methodName, fun);
|
||||
return fun;
|
||||
}
|
||||
@@ -2211,7 +2211,7 @@ void* GetStaticMethodPointer(const String& methodName)
|
||||
{
|
||||
const unsigned short errorCode = mono_error_get_error_code(&error);
|
||||
const char* errorMessage = mono_error_get_message(&error);
|
||||
LOG(Fatal, "mono_method_get_unmanaged_callers_only_ftnptr failed with error code 0x{0:x}, {1}", errorCode, String(errorMessage));
|
||||
LOG(Fatal, "Failed to get unmanaged function pointer for method '{0}': 0x{1:x}, {2}", methodName, errorCode, String(errorMessage));
|
||||
}
|
||||
mono_error_cleanup(&error);
|
||||
|
||||
|
||||
@@ -180,6 +180,8 @@ namespace FlaxEngine
|
||||
|
||||
private static void OnLocalizationChanged()
|
||||
{
|
||||
// iOS uses globalization-invariant mode so ignore it
|
||||
#if !PLATFORM_IOS
|
||||
var currentThread = Thread.CurrentThread;
|
||||
var language = Localization.CurrentLanguage;
|
||||
if (language != null)
|
||||
@@ -187,6 +189,7 @@ namespace FlaxEngine
|
||||
var culture = Localization.CurrentCulture;
|
||||
if (culture != null)
|
||||
currentThread.CurrentCulture = culture;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace FlaxEngine.Utilities
|
||||
where T : new()
|
||||
{
|
||||
var json = Json.JsonSerializer.Serialize(instance);
|
||||
return Json.JsonSerializer.Deserialize<T>(json);
|
||||
return (T)Json.JsonSerializer.Deserialize(json, instance.GetType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ public class nethost : ThirdPartyModule
|
||||
// Get .NET SDK runtime host
|
||||
var dotnetSdk = DotNetSdk.Instance;
|
||||
if (!dotnetSdk.IsValid)
|
||||
throw new Exception($"Missing NET SDK {DotNetSdk.MinimumVersion}.");
|
||||
throw new DotNetSdk.MissingException();
|
||||
if (!dotnetSdk.GetHostRuntime(options.Platform.Target, options.Architecture, out var hostRuntime))
|
||||
{
|
||||
if (options.Target.IsPreBuilt)
|
||||
|
||||
@@ -145,6 +145,20 @@ namespace Flax.Build.Bindings
|
||||
return $"(void*){result}";
|
||||
}
|
||||
|
||||
|
||||
private static void GenerateCppAddFileReference(BuildData buildData, ApiTypeInfo caller, TypeInfo typeInfo, ApiTypeInfo apiType)
|
||||
{
|
||||
CppReferencesFiles.Add(apiType?.File);
|
||||
if (typeInfo.GenericArgs != null)
|
||||
{
|
||||
for (int i = 0; i < typeInfo.GenericArgs.Count; i++)
|
||||
{
|
||||
var g = typeInfo.GenericArgs[i];
|
||||
GenerateCppAddFileReference(buildData, caller, g, FindApiTypeInfo(buildData, g, caller));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string GenerateCppWrapperNativeToVariant(BuildData buildData, TypeInfo typeInfo, ApiTypeInfo caller, string value)
|
||||
{
|
||||
if (typeInfo.Type == "Variant")
|
||||
@@ -640,15 +654,7 @@ namespace Flax.Build.Bindings
|
||||
|
||||
// Register any API types usage
|
||||
apiType = FindApiTypeInfo(buildData, typeInfo, caller);
|
||||
CppReferencesFiles.Add(apiType?.File);
|
||||
if (typeInfo.GenericArgs != null)
|
||||
{
|
||||
for (int i = 0; i < typeInfo.GenericArgs.Count; i++)
|
||||
{
|
||||
var t = FindApiTypeInfo(buildData, typeInfo.GenericArgs[i], caller);
|
||||
CppReferencesFiles.Add(t?.File);
|
||||
}
|
||||
}
|
||||
GenerateCppAddFileReference(buildData, caller, typeInfo, apiType);
|
||||
|
||||
// Use dynamic array as wrapper container for fixed-size native arrays
|
||||
if (typeInfo.IsArray)
|
||||
@@ -1795,15 +1801,7 @@ namespace Flax.Build.Bindings
|
||||
return true;
|
||||
|
||||
// Add includes to properly compile bindings (eg. SoftObjectReference<class Texture>)
|
||||
CppReferencesFiles.Add(apiTypeInfo?.File);
|
||||
if (typeInfo.GenericArgs != null)
|
||||
{
|
||||
for (int i = 0; i < typeInfo.GenericArgs.Count; i++)
|
||||
{
|
||||
var t = FindApiTypeInfo(buildData, typeInfo.GenericArgs[i], caller);
|
||||
CppReferencesFiles.Add(t?.File);
|
||||
}
|
||||
}
|
||||
GenerateCppAddFileReference(buildData, caller, typeInfo, apiTypeInfo);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace Flax.Build
|
||||
#if USE_NETCORE
|
||||
var dotnetSdk = DotNetSdk.Instance;
|
||||
if (!dotnetSdk.IsValid)
|
||||
throw new Exception("Cannot compile C# without .NET SDK");
|
||||
throw new DotNetSdk.MissingException();
|
||||
string dotnetPath = "dotnet", referenceAnalyzers;
|
||||
string[] runtimeVersionNameParts = dotnetSdk.RuntimeVersionName.Split('.');
|
||||
string runtimeVersionShort = runtimeVersionNameParts[0] + '.' + runtimeVersionNameParts[1];
|
||||
|
||||
@@ -106,6 +106,20 @@ namespace Flax.Build
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exception when .NET SDK is missing.
|
||||
/// </summary>
|
||||
public sealed class MissingException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Init with a proper message.
|
||||
/// </summary>
|
||||
public MissingException()
|
||||
: base(string.IsNullOrEmpty(Configuration.Dotnet) ? $"Missing .NET SDK {MinimumVersion} (or higher)." : $"Missing .NET SDK {Configuration.Dotnet}.")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<KeyValuePair<TargetPlatform, TargetArchitecture>, HostRuntime> _hostRuntimes = new();
|
||||
|
||||
/// <summary>
|
||||
@@ -223,7 +237,7 @@ namespace Flax.Build
|
||||
// We need to support two paths here:
|
||||
// 1. We are running an x64 binary and we are running on an arm64 host machine
|
||||
// 2. We are running an Arm64 binary and we are targeting an x64 host machine
|
||||
if (Flax.Build.Platforms.MacPlatform.GetProcessIsTranslated() || isRunningOnArm64Targetx64)
|
||||
if (Flax.Build.Platforms.MacPlatform.GetProcessIsTranslated() || isRunningOnArm64Targetx64)
|
||||
{
|
||||
rid = "osx-x64";
|
||||
dotnetPath = Path.Combine(dotnetPath, "x64");
|
||||
@@ -246,10 +260,9 @@ namespace Flax.Build
|
||||
Log.Warning($"Missing .NET SDK ({dotnetPath})");
|
||||
return;
|
||||
}
|
||||
if (dotnetSdkVersions == null)
|
||||
dotnetSdkVersions = GetVersions(Path.Combine(dotnetPath, "sdk"));
|
||||
if (dotnetRuntimeVersions == null)
|
||||
dotnetRuntimeVersions = GetVersions(Path.Combine(dotnetPath, "shared", "Microsoft.NETCore.App"));
|
||||
|
||||
dotnetSdkVersions = MergeVersions(dotnetSdkVersions, GetVersions(Path.Combine(dotnetPath, "sdk")));
|
||||
dotnetRuntimeVersions = MergeVersions(dotnetRuntimeVersions, GetVersions(Path.Combine(dotnetPath, "shared", "Microsoft.NETCore.App")));
|
||||
|
||||
dotnetSdkVersions = dotnetSdkVersions.Where(x => IsValidVersion(Path.Combine(dotnetPath, "sdk", x)));
|
||||
dotnetRuntimeVersions = dotnetRuntimeVersions.Where(x => IsValidVersion(Path.Combine(dotnetPath, "shared", "Microsoft.NETCore.App", x)));
|
||||
@@ -260,18 +273,23 @@ namespace Flax.Build
|
||||
Log.Verbose($"Found the following .NET SDK versions: {string.Join(", ", dotnetSdkVersions)}");
|
||||
Log.Verbose($"Found the following .NET runtime versions: {string.Join(", ", dotnetRuntimeVersions)}");
|
||||
|
||||
string dotnetSdkVersion = dotnetSdkVersions.FirstOrDefault(x => ParseVersion(x).Major >= MinimumVersion.Major && ParseVersion(x).Major <= MaximumVersion.Major);
|
||||
string dotnetRuntimeVersion = dotnetRuntimeVersions.FirstOrDefault(x => ParseVersion(x).Major >= MinimumVersion.Major && ParseVersion(x).Major <= MaximumVersion.Major);
|
||||
var dotnetSdkVersion = GetVersion(dotnetSdkVersions);
|
||||
var dotnetRuntimeVersion = GetVersion(dotnetRuntimeVersions);
|
||||
var minVer = string.IsNullOrEmpty(Configuration.Dotnet) ? MinimumVersion.ToString() : Configuration.Dotnet;
|
||||
if (string.IsNullOrEmpty(dotnetSdkVersion))
|
||||
dotnetSdkVersion = dotnetPath;
|
||||
if (dotnetSdkVersion == null && dotnetSdkVersions.Count() > 0)
|
||||
{
|
||||
Log.Warning($"Unsupported .NET SDK {dotnetSdkVersions.First()} version found. Minimum version required is .NET {MinimumVersion}.");
|
||||
if (dotnetSdkVersions.Any())
|
||||
Log.Warning($"Unsupported .NET SDK versions found: {string.Join(", ", dotnetSdkVersions)}. Minimum version required is .NET {minVer}.");
|
||||
else
|
||||
Log.Warning($"Missing .NET SDK. Minimum version required is .NET {minVer}.");
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrEmpty(dotnetSdkVersion) || string.IsNullOrEmpty(dotnetRuntimeVersion))
|
||||
if (string.IsNullOrEmpty(dotnetRuntimeVersion))
|
||||
{
|
||||
Log.Warning("Missing .NET SDK");
|
||||
if (dotnetRuntimeVersions.Any())
|
||||
Log.Warning($"Unsupported .NET runtime versions found: {string.Join(", ", dotnetRuntimeVersions)}. Minimum version required is .NET {minVer}.");
|
||||
else
|
||||
Log.Warning($"Missing .NET runtime. Minimum version required is .NET {minVer}.");
|
||||
return;
|
||||
}
|
||||
RootPath = dotnetPath;
|
||||
@@ -434,7 +452,7 @@ namespace Flax.Build
|
||||
exists = Directory.Exists(path);
|
||||
|
||||
if (exists)
|
||||
_hostRuntimes[new KeyValuePair<TargetPlatform, TargetArchitecture>(platform, arch)] = new HostRuntime(platform, path);
|
||||
_hostRuntimes[new KeyValuePair<TargetPlatform, TargetArchitecture>(platform, arch)] = new HostRuntime(platform, Utilities.NormalizePath(path));
|
||||
return exists;
|
||||
}
|
||||
|
||||
@@ -445,6 +463,18 @@ namespace Flax.Build
|
||||
return Path.Combine(root, version);
|
||||
}
|
||||
|
||||
private static IEnumerable<string> MergeVersions(IEnumerable<string> a, IEnumerable<string> b)
|
||||
{
|
||||
if (a == null || !a.Any())
|
||||
return b;
|
||||
if (b == null || !b.Any())
|
||||
return a;
|
||||
var result = new HashSet<string>();
|
||||
result.AddRange(a);
|
||||
result.AddRange(b);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Version ParseVersion(string version)
|
||||
{
|
||||
// Give precedence to final releases over release candidate / beta releases
|
||||
@@ -456,6 +486,8 @@ namespace Flax.Build
|
||||
}
|
||||
if (!Version.TryParse(version, out var ver))
|
||||
return null;
|
||||
if (ver.Build == -1)
|
||||
return new Version(ver.Major, ver.Minor);
|
||||
return new Version(ver.Major, ver.Minor, ver.Build, rev);
|
||||
}
|
||||
|
||||
@@ -466,9 +498,42 @@ namespace Flax.Build
|
||||
|
||||
private static string GetVersion(IEnumerable<string> versions)
|
||||
{
|
||||
return versions.OrderByDescending(ParseVersion)
|
||||
.Where(x => ParseVersion(x).Major >= MinimumVersion.Major && ParseVersion(x).Major <= MaximumVersion.Major)
|
||||
.FirstOrDefault();
|
||||
Version dotnetVer = null;
|
||||
int dotnetVerNum = -1;
|
||||
if (!string.IsNullOrEmpty(Configuration.Dotnet))
|
||||
{
|
||||
dotnetVer = ParseVersion(Configuration.Dotnet);
|
||||
if (int.TryParse(Configuration.Dotnet, out var tmp) && tmp >= MinimumVersion.Major)
|
||||
dotnetVerNum = tmp;
|
||||
}
|
||||
var sorted = versions.OrderByDescending(ParseVersion);
|
||||
foreach (var version in sorted)
|
||||
{
|
||||
var v = ParseVersion(version);
|
||||
|
||||
// Filter by version specified in command line
|
||||
if (dotnetVer != null)
|
||||
{
|
||||
if (dotnetVer.Major != v.Major)
|
||||
continue;
|
||||
if (dotnetVer.Minor != v.Minor)
|
||||
continue;
|
||||
if (dotnetVer.Revision != -1 && dotnetVer.Revision != v.Revision)
|
||||
continue;
|
||||
if (dotnetVer.Build != -1 && dotnetVer.Build != v.Build)
|
||||
continue;
|
||||
}
|
||||
else if (dotnetVerNum != -1)
|
||||
{
|
||||
if (dotnetVerNum != v.Major)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filter by min/max versions supported by Flax.Build
|
||||
if (v.Major >= MinimumVersion.Major && v.Major <= MaximumVersion.Major)
|
||||
return version;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool IsValidVersion(string versionPath)
|
||||
|
||||
@@ -225,10 +225,24 @@ namespace Flax.Build
|
||||
[CommandLine("compiler", "<name>", "Overrides the compiler to use for building. Eg. v140 overrides the toolset when building for Windows.")]
|
||||
public static string Compiler = null;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the dotnet SDK version to use for the build. Eg. set to '7' to use .NET 7 even if .NET 8 is installed.
|
||||
/// </summary>
|
||||
[CommandLine("dotnet", "<ver>", "Specifies the dotnet SDK version to use for the build. Eg. set to '7' to use .NET 7 even if .NET 8 is installed.")]
|
||||
public static string Dotnet = null;
|
||||
|
||||
/// <summary>
|
||||
/// Custom configuration defines provided via command line for the build tool.
|
||||
/// </summary>
|
||||
public static List<string> CustomDefines = new List<string>();
|
||||
|
||||
internal static void PassArgs(ref string cmdLine)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Compiler))
|
||||
cmdLine += " -compiler=" + Compiler;
|
||||
if (!string.IsNullOrEmpty(Dotnet))
|
||||
cmdLine += " -dotnet=" + Dotnet;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -17,8 +17,7 @@ namespace Flax.Deploy
|
||||
var flaxBuildTool = Path.Combine(Globals.EngineRoot, buildPlatform == TargetPlatform.Windows ? "Binaries/Tools/Flax.Build.exe" : "Binaries/Tools/Flax.Build");
|
||||
var format = "-build -buildtargets={0} -log -logfile= -platform={1} -arch={2} -configuration={3}";
|
||||
var cmdLine = string.Format(format, target, platform, architecture, configuration);
|
||||
if (!string.IsNullOrEmpty(Configuration.Compiler))
|
||||
cmdLine += " -compiler=" + Configuration.Compiler;
|
||||
Configuration.PassArgs(ref cmdLine);
|
||||
|
||||
Log.Info($"Building {target} for {platform} {architecture} {configuration}...");
|
||||
int result = Utilities.Run(flaxBuildTool, cmdLine, null, root);
|
||||
|
||||
@@ -82,7 +82,10 @@ namespace Flax.Build
|
||||
{
|
||||
var engineProject = EngineTarget.EngineProject;
|
||||
if (engineProject != null && engineProject.Configuration != null && engineProject.Configuration.Count != 0)
|
||||
{
|
||||
CommandLine.Configure(typeof(EngineConfiguration), engineProject.Configuration);
|
||||
CommandLine.Configure(typeof(Configuration), engineProject.Configuration);
|
||||
}
|
||||
CommandLine.Configure(typeof(EngineConfiguration));
|
||||
}
|
||||
|
||||
@@ -90,7 +93,6 @@ namespace Flax.Build
|
||||
if (Configuration.Mutex)
|
||||
{
|
||||
singleInstanceMutex = new Mutex(true, "Flax.Build", out var oneInstanceMutexCreated);
|
||||
|
||||
if (!oneInstanceMutexCreated)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -172,8 +172,7 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
configuration.Configuration,
|
||||
configuration.Platform,
|
||||
target.Name);
|
||||
if (!string.IsNullOrEmpty(Configuration.Compiler))
|
||||
cmdLine += " -compiler=" + Configuration.Compiler;
|
||||
Configuration.PassArgs(ref cmdLine);
|
||||
|
||||
vcProjectFileContent.AppendLine(string.Format(" <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='{0}'\">", configuration.Name));
|
||||
if (platform is IVisualStudioProjectCustomizer customizer)
|
||||
|
||||
@@ -731,8 +731,7 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
configuration.Configuration,
|
||||
configuration.Platform,
|
||||
configuration.Target);
|
||||
if (!string.IsNullOrEmpty(Configuration.Compiler))
|
||||
cmdLine += " -compiler=" + Configuration.Compiler;
|
||||
Configuration.PassArgs(ref cmdLine);
|
||||
|
||||
str.AppendLine(string.Format(" <Exec Command=\"{0} {1}\" Condition=\"'$(Configuration)|$(Platform)'=='{2}'\"/>", cmdLine, extraArgs, configuration.Name));
|
||||
}
|
||||
|
||||
@@ -201,6 +201,8 @@ namespace Flax.Build.Projects.VisualStudioCode
|
||||
json.AddUnnamedField(string.Format("-buildTargets={0}", target.Name));
|
||||
if (!string.IsNullOrEmpty(Configuration.Compiler))
|
||||
json.AddUnnamedField(string.Format("-compiler={0}", Configuration.Compiler));
|
||||
if (!string.IsNullOrEmpty(Configuration.Dotnet))
|
||||
json.AddUnnamedField(string.Format("-dotnet={0}", Configuration.Dotnet));
|
||||
}
|
||||
json.EndArray();
|
||||
|
||||
@@ -228,6 +230,8 @@ namespace Flax.Build.Projects.VisualStudioCode
|
||||
json.AddUnnamedField(string.Format("--buildTargets={0}", target.Name));
|
||||
if (!string.IsNullOrEmpty(Configuration.Compiler))
|
||||
json.AddUnnamedField(string.Format("--compiler={0}", Configuration.Compiler));
|
||||
if (!string.IsNullOrEmpty(Configuration.Dotnet))
|
||||
json.AddUnnamedField(string.Format("-dotnet={0}", Configuration.Dotnet));
|
||||
}
|
||||
json.EndArray();
|
||||
|
||||
@@ -255,6 +259,8 @@ namespace Flax.Build.Projects.VisualStudioCode
|
||||
json.AddUnnamedField(string.Format("--buildTargets={0}", target.Name));
|
||||
if (!string.IsNullOrEmpty(Configuration.Compiler))
|
||||
json.AddUnnamedField(string.Format("--compiler={0}", Configuration.Compiler));
|
||||
if (!string.IsNullOrEmpty(Configuration.Dotnet))
|
||||
json.AddUnnamedField(string.Format("-dotnet={0}", Configuration.Dotnet));
|
||||
}
|
||||
json.EndArray();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user