Merge remote-tracking branch 'upstream/master' into Statusbar-Imrpovements
This commit is contained in:
@@ -11,16 +11,6 @@ for %%I in (Source\Logo.png) do if %%~zI LSS 2000 (
|
||||
call "Development\Scripts\Windows\GetMSBuildPath.bat"
|
||||
if errorlevel 1 goto Error_NoVisualStudioEnvironment
|
||||
|
||||
if not exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" goto Compile
|
||||
for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -products * -requires Microsoft.Component.MSBuild -property installationPath') do (
|
||||
for %%j in (15.0, Current) do (
|
||||
if exist "%%i\MSBuild\%%j\Bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%%i\MSBuild\%%j\Bin\MSBuild.exe"
|
||||
goto Compile
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
:Compile
|
||||
md Cache\Intermediate >nul 2>nul
|
||||
dir /s /b Source\Tools\Flax.Build\*.cs >Cache\Intermediate\Flax.Build.Files.txt
|
||||
@@ -44,7 +34,7 @@ goto Exit
|
||||
echo CallBuildTool ERROR: The script is in invalid directory.
|
||||
goto Exit
|
||||
:Error_NoVisualStudioEnvironment
|
||||
echo CallBuildTool ERROR: Missing Visual Studio 2015 or newer.
|
||||
echo CallBuildTool ERROR: Missing Visual Studio 2022 or newer.
|
||||
goto Exit
|
||||
:Error_CompilationFailed
|
||||
echo CallBuildTool ERROR: Failed to compile Flax.Build project.
|
||||
|
||||
@@ -4,66 +4,26 @@ rem Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
set MSBUILD_PATH=
|
||||
|
||||
rem Look for MSBuild version 17.0 or later
|
||||
if not exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" goto VsWhereNotFound
|
||||
for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -products * -requires Microsoft.Component.MSBuild -property installationPath') do (
|
||||
if exist "%%i\MSBuild\15.0\Bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%%i\MSBuild\15.0\Bin\MSBuild.exe"
|
||||
goto End
|
||||
)
|
||||
)
|
||||
for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -prerelease -products * -requires Microsoft.Component.MSBuild -property installationPath') do (
|
||||
if exist "%%i\MSBuild\15.0\Bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%%i\MSBuild\15.0\Bin\MSBuild.exe"
|
||||
goto End
|
||||
)
|
||||
for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -version 17.0 -latest -products * -requires Microsoft.Component.MSBuild -property installationPath') do (
|
||||
if exist "%%i\MSBuild\Current\Bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%%i\MSBuild\Current\Bin\MSBuild.exe"
|
||||
goto End
|
||||
)
|
||||
)
|
||||
:VsWhereNotFound
|
||||
|
||||
if exist "%ProgramFiles(x86)%\MSBuild\14.0\bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%ProgramFiles(x86)%\MSBuild\14.0\bin\MSBuild.exe"
|
||||
goto End
|
||||
rem Look for MSBuild version 17.0 or later in pre-release versions
|
||||
for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -version 17.0 -latest -prerelease -products * -requires Microsoft.Component.MSBuild -property installationPath') do (
|
||||
if exist "%%i\MSBuild\Current\Bin\MSBuild.exe" (
|
||||
set MSBUILD_PATH="%%i\MSBuild\Current\Bin\MSBuild.exe"
|
||||
goto End
|
||||
)
|
||||
)
|
||||
|
||||
call :GetInstallPath Microsoft\VisualStudio\SxS\VS7 15.0 MSBuild\15.0\bin\MSBuild.exe
|
||||
if not errorlevel 1 goto End
|
||||
call :GetInstallPath Microsoft\MSBuild\ToolsVersions\14.0 MSBuildToolsPath MSBuild.exe
|
||||
if not errorlevel 1 goto End
|
||||
call :GetInstallPath Microsoft\MSBuild\ToolsVersions\12.0 MSBuildToolsPath MSBuild.exe
|
||||
if not errorlevel 1 goto End
|
||||
call :GetInstallPath Microsoft\MSBuild\ToolsVersions\4.0 MSBuildToolsPath MSBuild.exe
|
||||
if not errorlevel 1 goto End
|
||||
|
||||
echo GetMSBuildPath ERROR: Could not find MSBuild version 17.0 or later.
|
||||
exit /B 1
|
||||
:VsWhereNotFound
|
||||
echo GetMSBuildPath ERROR: vswhere.exe was not found.
|
||||
exit /B 1
|
||||
:End
|
||||
exit /B 0
|
||||
|
||||
:GetInstallPath
|
||||
for /f "tokens=2,*" %%A in ('REG.exe query HKCU\SOFTWARE\%1 /v %2 2^>Nul') do (
|
||||
if exist "%%B%%3" (
|
||||
set MSBUILD_PATH="%%B%3"
|
||||
exit /B 0
|
||||
)
|
||||
)
|
||||
for /f "tokens=2,*" %%A in ('REG.exe query HKLM\SOFTWARE\%1 /v %2 2^>Nul') do (
|
||||
if exist "%%B%3" (
|
||||
set MSBUILD_PATH="%%B%3"
|
||||
exit /B 0
|
||||
)
|
||||
)
|
||||
for /f "tokens=2,*" %%A in ('REG.exe query HKCU\SOFTWARE\Wow6432Node\%1 /v %2 2^>Nul') do (
|
||||
if exist "%%B%%3" (
|
||||
set MSBUILD_PATH="%%B%3"
|
||||
exit /B 0
|
||||
)
|
||||
)
|
||||
for /f "tokens=2,*" %%A in ('REG.exe query HKLM\SOFTWARE\Wow6432Node\%1 /v %2 2^>Nul') do (
|
||||
if exist "%%B%3" (
|
||||
set MSBUILD_PATH="%%B%3"
|
||||
exit /B 0
|
||||
)
|
||||
)
|
||||
exit /B 1
|
||||
exit /B 0
|
||||
@@ -3,7 +3,7 @@
|
||||
"Version": {
|
||||
"Major": 1,
|
||||
"Minor": 6,
|
||||
"Build": 6344
|
||||
"Build": 6345
|
||||
},
|
||||
"Company": "Flax",
|
||||
"Copyright": "Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.",
|
||||
|
||||
@@ -31,19 +31,20 @@ Follow the instructions below to compile and run the engine from source.
|
||||
* Install Visual Studio 2022 or newer
|
||||
* Install Windows 8.1 SDK or newer (via Visual Studio Installer)
|
||||
* Install Microsoft Visual C++ 2015 v140 toolset or newer (via Visual Studio Installer)
|
||||
* Install .Net 7 SDK (via Visual Studio Installer or [from web](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Install .NET 7 SDK for **Windows x64** (via Visual Studio Installer or [from web](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Install Git with LFS
|
||||
* Clone repo (with LFS)
|
||||
* Run **GenerateProjectFiles.bat**
|
||||
* Open `Flax.sln` and set solution configuration to **Editor.Development** and solution platform to **Win64**
|
||||
* Set Flax (C++) or FlaxEngine (C#) as startup project
|
||||
* Compile Flax project (hit F7 or CTRL+Shift+B)
|
||||
* Optionally set Debug Type to **Managed Only (.NET Core)** to debug C#-only, or **Mixed (.NET Core)** to debug both C++ and C#
|
||||
* Run Flax (hit F5 key)
|
||||
|
||||
## Linux
|
||||
|
||||
* Install Visual Studio Code
|
||||
* Install .Net 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Install .NET 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Ubuntu: `sudo apt install dotnet-sdk-7.0`
|
||||
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
||||
* Ubuntu: `sudo apt install vulkan-sdk`
|
||||
@@ -66,7 +67,7 @@ Follow the instructions below to compile and run the engine from source.
|
||||
## Mac
|
||||
|
||||
* Install XCode
|
||||
* Install .Net 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Install .NET 7 SDK ([https://dotnet.microsoft.com/en-us/download/dotnet/7.0](https://dotnet.microsoft.com/en-us/download/dotnet/7.0))
|
||||
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
|
||||
* Clone repo (with LFS)
|
||||
* Run `GenerateProjectFiles.command`
|
||||
|
||||
@@ -260,15 +260,20 @@ bool iOSPlatformTools::OnPostProcess(CookingData& data)
|
||||
{
|
||||
LOG(Info, "Building app package...");
|
||||
const Char* configuration = data.Configuration == BuildConfiguration::Release ? TEXT("Release") : TEXT("Debug");
|
||||
String command = String::Format(TEXT("xcodebuild -project FlaxGame.xcodeproj -configuration {} -scheme FlaxGame -archivePath FlaxGame.xcarchive archive"), configuration);
|
||||
int32 result = Platform::RunProcess(command, data.OriginalOutputPath);
|
||||
CreateProcessSettings procSettings;
|
||||
procSettings.HiddenWindow = true;
|
||||
procSettings.WorkingDirectory = data.OriginalOutputPath;
|
||||
procSettings.FileName = TEXT("/usr/bin/xcodebuild");
|
||||
procSettings.Arguments = String::Format(TEXT("-project FlaxGame.xcodeproj -configuration {} -scheme FlaxGame -archivePath FlaxGame.xcarchive archive"), configuration);
|
||||
int32 result = Platform::CreateProcess(procSettings);
|
||||
if (result != 0)
|
||||
{
|
||||
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
|
||||
return true;
|
||||
}
|
||||
command = TEXT("xcodebuild -exportArchive -archivePath FlaxGame.xcarchive -allowProvisioningUpdates -exportPath . -exportOptionsPlist ExportOptions.plist");
|
||||
result = Platform::RunProcess(command, data.OriginalOutputPath);
|
||||
procSettings.FileName = TEXT("/usr/bin/xcodebuild");
|
||||
procSettings.Arguments = TEXT("-exportArchive -archivePath FlaxGame.xcarchive -allowProvisioningUpdates -exportPath . -exportOptionsPlist ExportOptions.plist");
|
||||
result = Platform::CreateProcess(procSettings);
|
||||
if (result != 0)
|
||||
{
|
||||
data.Error(String::Format(TEXT("Failed to package app (result code: {0}). See log for more info."), result));
|
||||
|
||||
@@ -476,6 +476,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
settings.ShowInTaskbar = false;
|
||||
settings.ActivateWhenFirstShown = false;
|
||||
settings.IsTopmost = true;
|
||||
settings.ShowAfterFirstPaint = false;
|
||||
|
||||
win = Platform.CreateWindow(ref settings);
|
||||
|
||||
|
||||
@@ -268,8 +268,16 @@ void RiderCodeEditor::OpenFile(const String& path, int32 line)
|
||||
// Open file
|
||||
line = line > 0 ? line : 1;
|
||||
CreateProcessSettings procSettings;
|
||||
|
||||
#if !PLATFORM_MAC
|
||||
procSettings.FileName = _execPath;
|
||||
procSettings.Arguments = String::Format(TEXT("\"{0}\" --line {2} \"{1}\""), _solutionPath, path, line);
|
||||
#else
|
||||
// This follows pretty much how all the other engines open rider which deals with cross architecture issues
|
||||
procSettings.FileName = "/usr/bin/open";
|
||||
procSettings.Arguments = String::Format(TEXT("-n -a \"{0}\" --args \"{1}\" --line {3} \"{2}\""), _execPath, _solutionPath, path, line);
|
||||
#endif
|
||||
|
||||
procSettings.HiddenWindow = false;
|
||||
procSettings.WaitForEnd = false;
|
||||
procSettings.LogOutput = false;
|
||||
@@ -287,8 +295,14 @@ void RiderCodeEditor::OpenSolution()
|
||||
|
||||
// Open solution
|
||||
CreateProcessSettings procSettings;
|
||||
#if !PLATFORM_MAC
|
||||
procSettings.FileName = _execPath;
|
||||
procSettings.Arguments = String::Format(TEXT("\"{0}\""), _solutionPath);
|
||||
#else
|
||||
// This follows pretty much how all the other engines open rider which deals with cross architecture issues
|
||||
procSettings.FileName = "/usr/bin/open";
|
||||
procSettings.Arguments = String::Format(TEXT("-n -a \"{0}\" \"{1}\""), _execPath, _solutionPath);
|
||||
#endif
|
||||
procSettings.HiddenWindow = false;
|
||||
procSettings.WaitForEnd = false;
|
||||
procSettings.LogOutput = false;
|
||||
|
||||
@@ -544,7 +544,7 @@ namespace FlaxEditor.Windows
|
||||
if (noLocation)
|
||||
{
|
||||
desc.LocationFile = match.Groups[2].Value;
|
||||
int.TryParse(match.Groups[5].Value, out desc.LocationLine);
|
||||
int.TryParse(match.Groups[4].Value, out desc.LocationLine);
|
||||
noLocation = false;
|
||||
}
|
||||
fineStackTrace.AppendLine(match.Groups[0].Value);
|
||||
|
||||
@@ -559,6 +559,19 @@ namespace FlaxEngine.Interop
|
||||
return managedArray.Pointer;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static IntPtr GetArray(ManagedHandle handle)
|
||||
{
|
||||
if (!handle.IsAllocated)
|
||||
return IntPtr.Zero;
|
||||
object value = handle.Target;
|
||||
if (value is ManagedArray)
|
||||
return (IntPtr)handle;
|
||||
if (value is Array)
|
||||
return Invoker.MarshalReturnValueGeneric(value.GetType(), value);
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static int GetArrayLength(ManagedHandle arrayHandle)
|
||||
{
|
||||
|
||||
@@ -24,7 +24,8 @@ namespace FlaxEngine.Interop
|
||||
/// <summary>
|
||||
/// Provides a Mono-like API for native code to access managed runtime.
|
||||
/// </summary>
|
||||
internal static unsafe partial class NativeInterop
|
||||
[HideInEditor]
|
||||
public static unsafe partial class NativeInterop
|
||||
{
|
||||
internal static Dictionary<string, string> AssemblyLocations = new();
|
||||
|
||||
@@ -147,7 +148,27 @@ namespace FlaxEngine.Interop
|
||||
NativeMemory.AlignedFree(ptr);
|
||||
}
|
||||
|
||||
internal static T[] GCHandleArrayToManagedArray<T>(ManagedArray ptrArray) where T : class
|
||||
/// <summary>
|
||||
/// Converts a delegate into a function pointer that is callable from unmanaged code via <see cref="Marshal.GetFunctionPointerForDelegate{TDelegate}"/> but cached <paramref name="d"/> delegate to prevent collecting it by GC.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDelegate">The type of delegate to convert.</typeparam>
|
||||
/// <param name="d">The delegate to be passed to unmanaged code.</param>
|
||||
/// <returns>A value that can be passed to unmanaged code, which, in turn, can use it to call the underlying managed delegate.</returns>
|
||||
public static IntPtr GetFunctionPointerForDelegate<TDelegate>(TDelegate d) where TDelegate : notnull
|
||||
{
|
||||
// Example use-case: C# script runs actions via JobSystem.Dispatch which causes crash due to GC collecting Delegate object
|
||||
ManagedHandle.Alloc(d, GCHandleType.Weak);
|
||||
|
||||
return Marshal.GetFunctionPointerForDelegate<TDelegate>(d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts array of GC Handles from native runtime to managed array.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Array element type.</typeparam>
|
||||
/// <param name="ptrArray">Input array.</param>
|
||||
/// <returns>Output array.</returns>
|
||||
public static T[] GCHandleArrayToManagedArray<T>(ManagedArray ptrArray) where T : class
|
||||
{
|
||||
Span<IntPtr> span = ptrArray.ToSpan<IntPtr>();
|
||||
T[] managedArray = new T[ptrArray.Length];
|
||||
@@ -156,7 +177,12 @@ namespace FlaxEngine.Interop
|
||||
return managedArray;
|
||||
}
|
||||
|
||||
internal static IntPtr[] ManagedArrayToGCHandleArray(Array array)
|
||||
/// <summary>
|
||||
/// Converts managed array wrapper into array of GC Handles for native runtime.
|
||||
/// </summary>
|
||||
/// <param name="array">Input array.</param>
|
||||
/// <returns>Output array.</returns>
|
||||
public static IntPtr[] ManagedArrayToGCHandleArray(Array array)
|
||||
{
|
||||
if (array.Length == 0)
|
||||
return Array.Empty<IntPtr>();
|
||||
@@ -170,13 +196,26 @@ namespace FlaxEngine.Interop
|
||||
return pointerArray;
|
||||
}
|
||||
|
||||
internal static ManagedArray ManagedArrayToGCHandleWrappedArray(Array array)
|
||||
/// <summary>
|
||||
/// Converts managed array wrapper into array of GC Handles for native runtime.
|
||||
/// </summary>
|
||||
/// <param name="array">Input array.</param>
|
||||
/// <returns>Output array.</returns>
|
||||
public static ManagedArray ManagedArrayToGCHandleWrappedArray(Array array)
|
||||
{
|
||||
IntPtr[] pointerArray = ManagedArrayToGCHandleArray(array);
|
||||
return ManagedArray.WrapNewArray(pointerArray, array.GetType());
|
||||
}
|
||||
|
||||
internal static TDst[] ConvertArray<TSrc, TDst>(Span<TSrc> src, Func<TSrc, TDst> convertFunc)
|
||||
/// <summary>
|
||||
/// Converts array with a custom converter function for each element.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSrc">Input data type.</typeparam>
|
||||
/// <typeparam name="TDst">Output data type.</typeparam>
|
||||
/// <param name="src">The input array.</param>
|
||||
/// <param name="convertFunc">Converter callback.</param>
|
||||
/// <returns>The output array.</returns>
|
||||
public static TDst[] ConvertArray<TSrc, TDst>(Span<TSrc> src, Func<TSrc, TDst> convertFunc)
|
||||
{
|
||||
TDst[] dst = new TDst[src.Length];
|
||||
for (int i = 0; i < src.Length; i++)
|
||||
@@ -184,7 +223,15 @@ namespace FlaxEngine.Interop
|
||||
return dst;
|
||||
}
|
||||
|
||||
internal static TDst[] ConvertArray<TSrc, TDst>(TSrc[] src, Func<TSrc, TDst> convertFunc)
|
||||
/// <summary>
|
||||
/// Converts array with a custom converter function for each element.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSrc">Input data type.</typeparam>
|
||||
/// <typeparam name="TDst">Output data type.</typeparam>
|
||||
/// <param name="src">The input array.</param>
|
||||
/// <param name="convertFunc">Converter callback.</param>
|
||||
/// <returns>The output array.</returns>
|
||||
public static TDst[] ConvertArray<TSrc, TDst>(TSrc[] src, Func<TSrc, TDst> convertFunc)
|
||||
{
|
||||
TDst[] dst = new TDst[src.Length];
|
||||
for (int i = 0; i < src.Length; i++)
|
||||
@@ -1024,11 +1071,12 @@ namespace FlaxEngine.Interop
|
||||
private static uint pinnedBoxedValuesPointer = 0;
|
||||
private static (IntPtr ptr, int size)[] pinnedAllocations = new (IntPtr ptr, int size)[256];
|
||||
private static uint pinnedAllocationsPointer = 0;
|
||||
|
||||
|
||||
private delegate TInternal ToNativeDelegate<T, TInternal>(T value);
|
||||
|
||||
private delegate IntPtr UnboxerDelegate(object value, object converter);
|
||||
|
||||
private static ConcurrentDictionary<Type, (UnboxerDelegate deleg, object toNativeDeleg)> unboxers = new (1, 3);
|
||||
private static ConcurrentDictionary<Type, (UnboxerDelegate deleg, object toNativeDeleg)> unboxers = new(1, 3);
|
||||
private static MethodInfo unboxerMethod = typeof(ValueTypeUnboxer).GetMethod(nameof(ValueTypeUnboxer.UnboxPointer), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
private static MethodInfo unboxerToNativeMethod = typeof(ValueTypeUnboxer).GetMethod(nameof(ValueTypeUnboxer.UnboxPointerWithConverter), BindingFlags.Static | BindingFlags.NonPublic);
|
||||
|
||||
@@ -1089,7 +1137,8 @@ namespace FlaxEngine.Interop
|
||||
return new IntPtr(Unsafe.AsPointer(ref Unsafe.Unbox<T>(value)));
|
||||
}
|
||||
|
||||
private static IntPtr UnboxPointerWithConverter<T, TInternal>(object value, object converter) where T : struct where TInternal : struct
|
||||
private static IntPtr UnboxPointerWithConverter<T, TInternal>(object value, object converter) where T : struct
|
||||
where TInternal : struct
|
||||
{
|
||||
ToNativeDelegate<T, TInternal> toNative = Unsafe.As<ToNativeDelegate<T, TInternal>>(converter);
|
||||
return PinValue<TInternal>(toNative(Unsafe.Unbox<T>(value)));
|
||||
@@ -1099,12 +1148,12 @@ namespace FlaxEngine.Interop
|
||||
private delegate IntPtr InvokeThunkDelegate(ManagedHandle instanceHandle, IntPtr param1, IntPtr param2, IntPtr param3, IntPtr param4, IntPtr param5, IntPtr param6, IntPtr param7);
|
||||
|
||||
/// <summary>
|
||||
/// Returns all types that that owned by this assembly.
|
||||
/// Returns all types owned by this assembly.
|
||||
/// </summary>
|
||||
private static Type[] GetAssemblyTypes(Assembly assembly)
|
||||
{
|
||||
var referencedAssemblies = assembly.GetReferencedAssemblies();
|
||||
var allAssemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
var allAssemblies = Utils.GetAssemblies();
|
||||
var referencedTypes = new List<string>();
|
||||
foreach (var assemblyName in referencedAssemblies)
|
||||
{
|
||||
|
||||
@@ -76,11 +76,11 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
// Set reflection probe data
|
||||
EnvironmentProbe* probe = nullptr;
|
||||
// TODO: optimize env probe searching for a transparent material - use spatial cache for renderer to find it
|
||||
const Vector3 drawCallOrigin = drawCall.ObjectPosition + view.Origin;
|
||||
const BoundingSphere objectBoundsWorld(drawCall.ObjectPosition + view.Origin, drawCall.ObjectRadius);
|
||||
for (int32 i = 0; i < cache->EnvironmentProbes.Count(); i++)
|
||||
{
|
||||
const auto p = cache->EnvironmentProbes[i];
|
||||
if (p->GetSphere().Contains(drawCallOrigin) != ContainmentType::Disjoint)
|
||||
if (CollisionsHelper::SphereIntersectsSphere(objectBoundsWorld, p->GetSphere()))
|
||||
{
|
||||
probe = p;
|
||||
break;
|
||||
@@ -99,10 +99,12 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
|
||||
// Set local lights
|
||||
data.LocalLightsCount = 0;
|
||||
const BoundingSphere objectBounds(drawCall.ObjectPosition, drawCall.ObjectRadius);
|
||||
// TODO: optimize lights searching for a transparent material - use spatial cache for renderer to find it
|
||||
for (int32 i = 0; i < cache->PointLights.Count() && data.LocalLightsCount < MaxLocalLights; i++)
|
||||
{
|
||||
const auto& light = cache->PointLights[i];
|
||||
if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.ObjectPosition) != ContainmentType::Disjoint)
|
||||
if (CollisionsHelper::SphereIntersectsSphere(objectBounds, BoundingSphere(light.Position, light.Radius)))
|
||||
{
|
||||
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], false);
|
||||
data.LocalLightsCount++;
|
||||
@@ -111,7 +113,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span<by
|
||||
for (int32 i = 0; i < cache->SpotLights.Count() && data.LocalLightsCount < MaxLocalLights; i++)
|
||||
{
|
||||
const auto& light = cache->SpotLights[i];
|
||||
if (BoundingSphere(light.Position, light.Radius).Contains(drawCall.ObjectPosition) != ContainmentType::Disjoint)
|
||||
if (CollisionsHelper::SphereIntersectsSphere(objectBounds, BoundingSphere(light.Position, light.Radius)))
|
||||
{
|
||||
light.SetupLightData(&data.LocalLights[data.LocalLightsCount], false);
|
||||
data.LocalLightsCount++;
|
||||
|
||||
@@ -429,6 +429,7 @@ void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, cons
|
||||
drawCall.Material = material;
|
||||
drawCall.World = world;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius * drawCall.World.GetScaleVector().GetAbsolute().MaxValue();
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = world;
|
||||
drawCall.Surface.Lightmap = nullptr;
|
||||
@@ -495,6 +496,7 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
|
||||
drawCall.Material = material;
|
||||
drawCall.World = *info.World;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
|
||||
@@ -555,6 +557,7 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in
|
||||
drawCall.Material = material;
|
||||
drawCall.World = *info.World;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.Lightmap = (info.Flags & StaticFlags::Lightmap) != StaticFlags::None ? info.Lightmap : nullptr;
|
||||
|
||||
@@ -198,6 +198,7 @@ void SkinnedMesh::Draw(const RenderContext& renderContext, const DrawInfo& info,
|
||||
drawCall.Material = material;
|
||||
drawCall.World = *info.World;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.Lightmap = nullptr;
|
||||
@@ -258,6 +259,7 @@ void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawI
|
||||
drawCall.Material = material;
|
||||
drawCall.World = *info.World;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = info.Bounds.Radius; // TODO: should it be kept in sync with ObjectPosition?
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.Surface.PrevWorld = info.DrawState->PrevWorld;
|
||||
drawCall.Surface.Lightmap = nullptr;
|
||||
|
||||
@@ -122,7 +122,7 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const
|
||||
{
|
||||
// Create shader
|
||||
ID3D11DomainShader* buffer = nullptr;
|
||||
VALIDATE_DIRECTX_CALL(_device->GetDevice()->CreateDomainShader(cacheBytes, cacheSize, nullptr, &buffer));
|
||||
result = _device->GetDevice()->CreateDomainShader(cacheBytes, cacheSize, nullptr, &buffer);
|
||||
LOG_DIRECTX_RESULT_WITH_RETURN(result, nullptr);
|
||||
|
||||
// Create object
|
||||
|
||||
@@ -100,6 +100,7 @@ void Skybox::ApplySky(GPUContext* context, RenderContext& renderContext, const M
|
||||
Platform::MemoryClear(&drawCall, sizeof(DrawCall));
|
||||
drawCall.World = world;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius;
|
||||
drawCall.Surface.GeometrySize = _box.GetSize();
|
||||
drawCall.WorldDeterminantSign = Math::FloatSelect(world.RotDeterminant(), 1, -1);
|
||||
drawCall.PerInstanceRandom = GetPerInstanceRandom();
|
||||
|
||||
@@ -405,6 +405,7 @@ void SplineModel::Draw(RenderContext& renderContext)
|
||||
const Transform splineTransform = GetTransform();
|
||||
renderContext.View.GetWorldMatrix(splineTransform, drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation() + drawCall.Deformable.LocalMatrix.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius; // TODO: use radius for the spline chunk rather than whole spline
|
||||
const float worldDeterminantSign = drawCall.World.RotDeterminant() * drawCall.Deformable.LocalMatrix.RotDeterminant();
|
||||
for (int32 segment = 0; segment < _instances.Count(); segment++)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ void SceneTicking::TickData::RemoveTick(void* callee)
|
||||
{
|
||||
for (int32 i = 0; i < Ticks.Count(); i++)
|
||||
{
|
||||
if (Ticks[i].Callee == callee)
|
||||
if (Ticks.Get()[i].Callee == callee)
|
||||
{
|
||||
Ticks.RemoveAt(i);
|
||||
break;
|
||||
@@ -45,7 +45,7 @@ void SceneTicking::TickData::Tick()
|
||||
TickScripts(Scripts);
|
||||
|
||||
for (int32 i = 0; i < Ticks.Count(); i++)
|
||||
Ticks[i].Call();
|
||||
Ticks.Get()[i].Call();
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
@@ -54,7 +54,7 @@ void SceneTicking::TickData::RemoveTickExecuteInEditor(void* callee)
|
||||
{
|
||||
for (int32 i = 0; i < TicksExecuteInEditor.Count(); i++)
|
||||
{
|
||||
if (TicksExecuteInEditor[i].Callee == callee)
|
||||
if (TicksExecuteInEditor.Get()[i].Callee == callee)
|
||||
{
|
||||
TicksExecuteInEditor.RemoveAt(i);
|
||||
break;
|
||||
@@ -67,7 +67,7 @@ void SceneTicking::TickData::TickExecuteInEditor()
|
||||
TickScripts(ScriptsExecuteInEditor);
|
||||
|
||||
for (int32 i = 0; i < TicksExecuteInEditor.Count(); i++)
|
||||
TicksExecuteInEditor[i].Call();
|
||||
TicksExecuteInEditor.Get()[i].Call();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -938,7 +938,8 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
|
||||
// Setup a draw call common data
|
||||
DrawCall drawCall;
|
||||
drawCall.PerInstanceRandom = effect->GetPerInstanceRandom();
|
||||
drawCall.ObjectPosition = effect->GetPosition();
|
||||
drawCall.ObjectPosition = effect->GetSphere().Center - view.Origin;
|
||||
drawCall.ObjectRadius = effect->GetSphere().Radius;
|
||||
|
||||
// Draw all emitters
|
||||
for (int32 emitterIndex = 0; emitterIndex < effect->Instance.Emitters.Count(); emitterIndex++)
|
||||
|
||||
@@ -85,27 +85,34 @@ NSString* AppleUtils::ToNSString(const char* string)
|
||||
|
||||
NSArray* AppleUtils::ParseArguments(NSString* argsString) {
|
||||
NSMutableArray *argsArray = [NSMutableArray array];
|
||||
NSScanner *scanner = [NSScanner scannerWithString:argsString];
|
||||
NSString *currentArg = nil;
|
||||
NSMutableString *currentArg = [NSMutableString string];
|
||||
BOOL insideQuotes = NO;
|
||||
|
||||
while (![scanner isAtEnd]) {
|
||||
if (insideQuotes) {
|
||||
[scanner scanUpToString:@"\"" intoString:¤tArg];
|
||||
[scanner scanString:@"\"" intoString:NULL];
|
||||
insideQuotes = NO;
|
||||
} else {
|
||||
[scanner scanUpToString:@" " intoString:¤tArg];
|
||||
[scanner scanString:@" " intoString:NULL];
|
||||
}
|
||||
for (NSInteger i = 0; i < argsString.length; ++i) {
|
||||
unichar c = [argsString characterAtIndex:i];
|
||||
|
||||
if ([currentArg isEqualToString:@"\""]) {
|
||||
insideQuotes = YES;
|
||||
} else if (currentArg) {
|
||||
[argsArray addObject:currentArg];
|
||||
if (c == '\"') {
|
||||
if (insideQuotes) {
|
||||
[argsArray addObject:[currentArg copy]];
|
||||
[currentArg setString:@""];
|
||||
insideQuotes = NO;
|
||||
} else {
|
||||
insideQuotes = YES;
|
||||
}
|
||||
} else if (c == ' ' && !insideQuotes) {
|
||||
if (currentArg.length > 0) {
|
||||
[argsArray addObject:[currentArg copy]];
|
||||
[currentArg setString:@""];
|
||||
}
|
||||
} else {
|
||||
[currentArg appendFormat:@"%C", c];
|
||||
}
|
||||
}
|
||||
|
||||
if (currentArg.length > 0) {
|
||||
[argsArray addObject:[currentArg copy]];
|
||||
}
|
||||
|
||||
return [argsArray copy];
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace FlaxEngine
|
||||
AllowDragAndDrop = true,
|
||||
IsRegularWindow = true,
|
||||
HasSizingFrame = true,
|
||||
ShowAfterFirstPaint = true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(CreateWindowSettings);
|
||||
/// <summary>
|
||||
/// Enable/disable window auto-show after the first paint.
|
||||
/// </summary>
|
||||
API_FIELD() bool ShowAfterFirstPaint = false;
|
||||
API_FIELD() bool ShowAfterFirstPaint = true;
|
||||
|
||||
/// <summary>
|
||||
/// The custom data (platform dependant).
|
||||
|
||||
@@ -258,6 +258,11 @@ struct DrawCall
|
||||
/// </summary>
|
||||
Float3 ObjectPosition;
|
||||
|
||||
/// <summary>
|
||||
/// Object bounding sphere radius that contains it whole (sphere at ObjectPosition).
|
||||
/// </summary>
|
||||
float ObjectRadius;
|
||||
|
||||
/// <summary>
|
||||
/// The world matrix determinant sign (used for geometry that is two sided or has inverse scale - needs to flip normal vectors and change triangles culling).
|
||||
/// </summary>
|
||||
|
||||
@@ -464,6 +464,7 @@ void GBufferPass::DrawDecals(RenderContext& renderContext, GPUTextureView* light
|
||||
transform.Scale *= decal->GetSize();
|
||||
renderContext.View.GetWorldMatrix(transform, drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = decal->GetSphere().Radius;
|
||||
|
||||
context->ResetRenderTarget();
|
||||
|
||||
|
||||
@@ -855,6 +855,7 @@ DRAW:
|
||||
{
|
||||
auto& batch = BatchedDrawCalls.Get()[list.PreBatchedDrawCalls.Get()[i]];
|
||||
auto drawCall = batch.DrawCall;
|
||||
drawCall.ObjectRadius = 0.0f;
|
||||
bindParams.FirstDrawCall = &drawCall;
|
||||
const auto* instancesData = batch.Instances.Get();
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ public:
|
||||
static MClass* GetClass(MClass* elementKlass);
|
||||
static int32 GetLength(const MArray* obj);
|
||||
static void* GetAddress(const MArray* obj);
|
||||
static MArray* Unbox(MObject* obj);
|
||||
|
||||
template<typename T>
|
||||
FORCE_INLINE static T* GetAddress(const MArray* obj)
|
||||
|
||||
@@ -363,11 +363,12 @@ struct MConverter<Array<T>>
|
||||
|
||||
void Unbox(Array<T>& result, MObject* data)
|
||||
{
|
||||
const int32 length = data ? MCore::Array::GetLength((MArray*)data) : 0;
|
||||
MArray* array = MCore::Array::Unbox(data);
|
||||
const int32 length = array ? MCore::Array::GetLength(array) : 0;
|
||||
result.Resize(length);
|
||||
MConverter<T> converter;
|
||||
Span<T> resultSpan(result.Get(), length);
|
||||
converter.ToNativeArray(resultSpan, (MArray*)data);
|
||||
converter.ToNativeArray(resultSpan, array);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -408,6 +408,12 @@ void* MCore::Array::GetAddress(const MArray* obj)
|
||||
return CallStaticMethod<void*, void*>(GetArrayPointerPtr, (void*)obj);
|
||||
}
|
||||
|
||||
MArray* MCore::Array::Unbox(MObject* obj)
|
||||
{
|
||||
static void* GetArrayPtr = GetStaticMethodPointer(TEXT("GetArray"));
|
||||
return (MArray*)CallStaticMethod<void*, void*>(GetArrayPtr, (void*)obj);
|
||||
}
|
||||
|
||||
MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned)
|
||||
{
|
||||
ASSERT(obj);
|
||||
|
||||
@@ -804,6 +804,11 @@ void* MCore::Array::GetAddress(const MArray* obj)
|
||||
return mono_array_addr_with_size((MonoArray*)obj, 0, 0);
|
||||
}
|
||||
|
||||
MArray* MCore::Array::Unbox(MObject* obj)
|
||||
{
|
||||
return (MArray*)obj;
|
||||
}
|
||||
|
||||
MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned)
|
||||
{
|
||||
return mono_gchandle_new(obj, pinned);
|
||||
|
||||
@@ -141,6 +141,11 @@ void* MCore::Array::GetAddress(const MArray* obj)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MArray* MCore::Array::Unbox(MObject* obj)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MGCHandle MCore::GCHandle::New(MObject* obj, bool pinned)
|
||||
{
|
||||
return (MGCHandle)(uintptr)obj;
|
||||
|
||||
@@ -45,7 +45,7 @@ bool TerrainChunk::PrepareDraw(const RenderContext& renderContext)
|
||||
|
||||
// Calculate chunk distance to view
|
||||
const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View);
|
||||
const float distance = Float3::Distance(_boundsCenter - lodView->Origin, lodView->Position);
|
||||
const float distance = Float3::Distance(_sphere.Center - lodView->Origin, lodView->Position);
|
||||
lod = (int32)Math::Pow(distance / chunkEdgeSize, lodDistribution);
|
||||
lod += lodBias;
|
||||
|
||||
@@ -88,6 +88,7 @@ void TerrainChunk::Draw(const RenderContext& renderContext) const
|
||||
drawCall.Material = _cachedDrawMaterial;
|
||||
renderContext.View.GetWorldMatrix(_transform, drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius;
|
||||
drawCall.Terrain.Patch = _patch;
|
||||
drawCall.Terrain.HeightmapUVScaleBias = _heightmapUVScaleBias;
|
||||
drawCall.Terrain.OffsetUV = Vector2((float)(_patch->_x * TerrainPatch::CHUNKS_COUNT_EDGE + _x), (float)(_patch->_z * TerrainPatch::CHUNKS_COUNT_EDGE + _z));
|
||||
@@ -145,6 +146,7 @@ void TerrainChunk::Draw(const RenderContext& renderContext, MaterialBase* materi
|
||||
drawCall.Material = material;
|
||||
renderContext.View.GetWorldMatrix(_transform, drawCall.World);
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius;
|
||||
drawCall.Terrain.Patch = _patch;
|
||||
drawCall.Terrain.HeightmapUVScaleBias = _heightmapUVScaleBias;
|
||||
drawCall.Terrain.OffsetUV = Vector2((float)(_patch->_x * TerrainPatch::CHUNKS_COUNT_EDGE + _x), (float)(_patch->_z * TerrainPatch::CHUNKS_COUNT_EDGE + _z));
|
||||
@@ -202,7 +204,7 @@ void TerrainChunk::UpdateBounds()
|
||||
OrientedBoundingBox obb(Vector3::Zero, Vector3::One);
|
||||
obb.Transform(localTransform);
|
||||
obb.GetBoundingBox(_bounds);
|
||||
_boundsCenter = _bounds.GetCenter();
|
||||
BoundingSphere::FromBox(_bounds, _sphere);
|
||||
|
||||
_bounds.Minimum -= boundsExtent;
|
||||
_bounds.Maximum += boundsExtent;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Core/Math/BoundingBox.h"
|
||||
#include "Engine/Core/Math/BoundingSphere.h"
|
||||
#include "Engine/Core/Math/Matrix.h"
|
||||
#include "Engine/Core/Math/Transform.h"
|
||||
#include "Engine/Core/ISerializable.h"
|
||||
@@ -29,7 +30,7 @@ private:
|
||||
Float4 _heightmapUVScaleBias;
|
||||
Transform _transform;
|
||||
BoundingBox _bounds;
|
||||
Vector3 _boundsCenter;
|
||||
BoundingSphere _sphere;
|
||||
float _perInstanceRandom;
|
||||
float _yOffset, _yHeight;
|
||||
|
||||
|
||||
@@ -366,6 +366,7 @@ void TextRender::Draw(RenderContext& renderContext)
|
||||
DrawCall drawCall;
|
||||
drawCall.World = world;
|
||||
drawCall.ObjectPosition = drawCall.World.GetTranslation();
|
||||
drawCall.ObjectRadius = _sphere.Radius;
|
||||
drawCall.Surface.GeometrySize = _localBox.GetSize();
|
||||
drawCall.Surface.PrevWorld = _drawState.PrevWorld;
|
||||
drawCall.Surface.Lightmap = nullptr;
|
||||
|
||||
@@ -40,11 +40,11 @@ ShaderGraphValue::ShaderGraphValue(const Variant& v)
|
||||
break;
|
||||
case VariantType::Float:
|
||||
Type = VariantType::Types::Float;
|
||||
Value = String::Format(TEXT("{}"), v.AsFloat);
|
||||
Value = String::Format(TEXT("{:.8f}"), v.AsFloat);
|
||||
break;
|
||||
case VariantType::Double:
|
||||
Type = VariantType::Types::Float;
|
||||
Value = String::Format(TEXT("{}"), (float)v.AsDouble);
|
||||
Value = String::Format(TEXT("{:.8f}"), (float)v.AsDouble);
|
||||
break;
|
||||
case VariantType::Float2:
|
||||
{
|
||||
|
||||
@@ -464,7 +464,7 @@ namespace Flax.Build.Bindings
|
||||
return "FlaxEngine.Object.GetUnmanagedPtr({0})";
|
||||
case "Function":
|
||||
// delegate
|
||||
return "Marshal.GetFunctionPointerForDelegate({0})";
|
||||
return "NativeInterop.GetFunctionPointerForDelegate({0})";
|
||||
default:
|
||||
var apiType = FindApiTypeInfo(buildData, typeInfo, caller);
|
||||
if (apiType != null)
|
||||
|
||||
@@ -1452,7 +1452,8 @@ namespace Flax.Build.Bindings
|
||||
var useThunk = buildData.Platform.HasDynamicCodeExecutionSupport && Configuration.AOTMode == DotNetAOTModes.None;
|
||||
if (useThunk)
|
||||
{
|
||||
contents.AppendLine($" PROFILE_CPU_NAMED(\"{classInfo.FullNameManaged}::{functionInfo.Name}\");");
|
||||
//contents.AppendLine($" PROFILE_CPU_NAMED(\"{classInfo.FullNameManaged}::{functionInfo.Name}\");");
|
||||
contents.AppendLine(" PROFILE_CPU_SRC_LOC(method->ProfilerData);");
|
||||
|
||||
// Convert parameters into managed format as boxed values
|
||||
var thunkParams = string.Empty;
|
||||
|
||||
@@ -126,6 +126,10 @@ namespace Flax.Build
|
||||
if (!platform.HasRequiredSDKsInstalled && (!projectInfo.IsCSharpOnlyProject || platform != Platform.BuildPlatform))
|
||||
continue;
|
||||
|
||||
// Prevent generating configuration data for Windows x86
|
||||
if (architecture == TargetArchitecture.x86 && targetPlatform == TargetPlatform.Windows)
|
||||
continue;
|
||||
|
||||
string configurationText = targetName + '.' + platformName + '.' + configurationName;
|
||||
string architectureName = architecture.ToString();
|
||||
if (platform is IProjectCustomizer customizer)
|
||||
@@ -493,7 +497,7 @@ namespace Flax.Build
|
||||
else if (dependencyModule.BinaryModuleName == "FlaxEngine")
|
||||
{
|
||||
// TODO: instead of this hack find a way to reference the prebuilt target bindings binary (example: game C# project references FlaxEngine C# prebuilt dll)
|
||||
project.CSharp.FileReferences.Add(Path.Combine(Globals.EngineRoot, "Binaries/Editor/Win64/Development/FlaxEngine.CSharp.dll"));
|
||||
project.CSharp.FileReferences.Add(Path.Combine(Globals.EngineRoot, Platform.GetEditorBinaryDirectory(), "Development/FlaxEngine.CSharp.dll"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -501,6 +505,35 @@ namespace Flax.Build
|
||||
}
|
||||
}
|
||||
|
||||
// When generating C#-only projects for Game that uses source-engine distribution replace dependencies on FlaxEngine with fixed dll file refs to fix Intellisense issues
|
||||
if (rootProject.IsCSharpOnlyProject)
|
||||
{
|
||||
Project flaxDependencyToRemove = null;
|
||||
foreach (var project in projects)
|
||||
{
|
||||
if (project.BaseName != "FlaxEngine")
|
||||
{
|
||||
var flaxDependency = project.Dependencies.FirstOrDefault(x => x.BaseName == "FlaxEngine");
|
||||
if (flaxDependency != null)
|
||||
{
|
||||
project.Dependencies.Remove(flaxDependency);
|
||||
|
||||
// TODO: instead of this hack find a way to reference the prebuilt target bindings binary (example: game C# project references FlaxEngine C# prebuilt dll)
|
||||
project.CSharp.FileReferences.Add(Path.Combine(Globals.EngineRoot, Platform.GetEditorBinaryDirectory(), "Development/FlaxEngine.CSharp.dll"));
|
||||
|
||||
// Remove FlaxEngine from projects to prevent duplicated types errors in Intellisense (eg. Actor type defined in both FlaxEngine.CSharp.dll and FlaxEngine.csproj)
|
||||
flaxDependencyToRemove = flaxDependency;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flaxDependencyToRemove != null)
|
||||
{
|
||||
projects.Remove(flaxDependencyToRemove);
|
||||
foreach (var project in projects)
|
||||
project.Dependencies.Remove(flaxDependencyToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup custom projects
|
||||
GenerateCustomProjects?.Invoke(projects);
|
||||
nativeProjectGenerator.GenerateCustomProjects(projects);
|
||||
|
||||
@@ -215,8 +215,12 @@ namespace Flax.Build
|
||||
}
|
||||
}
|
||||
|
||||
// Use x64 when cross-compiling from ARM64
|
||||
if (architecture == TargetArchitecture.ARM64 && (Configuration.BuildArchitectures != null && Configuration.BuildArchitectures[0] == TargetArchitecture.x64))
|
||||
bool isRunningOnArm64Targetx64 = architecture == TargetArchitecture.ARM64 && (Configuration.BuildArchitectures != null && Configuration.BuildArchitectures[0] == TargetArchitecture.x64);
|
||||
|
||||
// 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)
|
||||
{
|
||||
rid = "osx-x64";
|
||||
dotnetPath = Path.Combine(dotnetPath, "x64");
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Flax.Build.Platforms
|
||||
{
|
||||
/// <summary>
|
||||
@@ -41,5 +43,20 @@ namespace Flax.Build.Platforms
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if running an x64 binary an arm64 host machine.
|
||||
/// </summary>
|
||||
public unsafe static bool GetProcessIsTranslated()
|
||||
{
|
||||
int ret = 0;
|
||||
ulong size = sizeof(int);
|
||||
if (sysctlbyname("sysctl.proc_translated", &ret, &size, null, 0) == -1)
|
||||
return false;
|
||||
return ret != 0;
|
||||
}
|
||||
|
||||
[DllImport("c")]
|
||||
private static unsafe extern int sysctlbyname(string name, void* oldp, ulong* oldlenp, void* newp, ulong newlen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,8 +174,35 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
else
|
||||
fileType = "None";
|
||||
|
||||
var projectPath = Utilities.MakePathRelativeTo(file, projectDirectory);
|
||||
csProjectFileContent.AppendLine(string.Format(" <{0} Include=\"{1}\" />", fileType, projectPath));
|
||||
var filePath = file.Replace('/', '\\'); // Normalize path
|
||||
var projectPath = Utilities.MakePathRelativeTo(filePath, projectDirectory);
|
||||
string linkPath = null;
|
||||
if (projectPath.StartsWith(@"..\..\..\"))
|
||||
{
|
||||
// Create folder structure for project external files
|
||||
var sourceIndex = filePath.LastIndexOf(@"\Source\");
|
||||
if (sourceIndex != -1)
|
||||
{
|
||||
projectPath = filePath;
|
||||
string fileProjectRoot = filePath.Substring(0, sourceIndex);
|
||||
string fileProjectName = Path.GetFileName(fileProjectRoot);
|
||||
string fileProjectRelativePath = filePath.Substring(sourceIndex + 1);
|
||||
|
||||
// Remove Source-directory from path
|
||||
if (fileProjectRelativePath.IndexOf('\\') != -1)
|
||||
fileProjectRelativePath = fileProjectRelativePath.Substring(fileProjectRelativePath.IndexOf('\\') + 1);
|
||||
|
||||
if (fileProjectRoot == project.SourceFolderPath)
|
||||
linkPath = fileProjectRelativePath;
|
||||
else // BuildScripts project
|
||||
linkPath = Path.Combine(fileProjectName, fileProjectRelativePath);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(linkPath))
|
||||
csProjectFileContent.AppendLine(string.Format(" <{0} Include=\"{1}\" Link=\"{2}\" />", fileType, projectPath, linkPath));
|
||||
else
|
||||
csProjectFileContent.AppendLine(string.Format(" <{0} Include=\"{1}\" />", fileType, projectPath));
|
||||
}
|
||||
|
||||
if (project.GeneratedSourceFiles != null)
|
||||
@@ -188,7 +215,8 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
else
|
||||
fileType = "None";
|
||||
|
||||
csProjectFileContent.AppendLine(string.Format(" <{0} Visible=\"false\" Include=\"{1}\" />", fileType, file));
|
||||
var filePath = file.Replace('/', '\\');
|
||||
csProjectFileContent.AppendLine(string.Format(" <{0} Visible=\"false\" Include=\"{1}\" />", fileType, filePath));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -236,6 +236,20 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
/// <inheritdoc />
|
||||
public override void GenerateSolution(Solution solution)
|
||||
{
|
||||
// Ensure that the main project is the first one (initially selected by Visual Studio)
|
||||
if (solution.MainProject != null && solution.Projects.Length != 0 && solution.Projects[0] != solution.MainProject)
|
||||
{
|
||||
for (int i = 1; i < solution.Projects.Length; i++)
|
||||
{
|
||||
if (solution.Projects[i] == solution.MainProject)
|
||||
{
|
||||
solution.Projects[i] = solution.Projects[0];
|
||||
solution.Projects[0] = solution.MainProject;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to extract info from the existing solution file to make random IDs stable
|
||||
var solutionId = Guid.NewGuid();
|
||||
var folderIds = new Dictionary<string, Guid>();
|
||||
@@ -402,6 +416,10 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
if (project.Configurations == null || project.Configurations.Count == 0)
|
||||
throw new Exception("Missing configurations for project " + project.Name);
|
||||
|
||||
// Prevent generating default Debug|AnyCPU and Release|AnyCPU configurations from Flax projects
|
||||
if (project.Name == "BuildScripts" || project.Name == "Flax.Build" || project.Name == "Flax.Build.Tests")
|
||||
continue;
|
||||
|
||||
foreach (var configuration in project.Configurations)
|
||||
{
|
||||
configurations.Add(new SolutionConfiguration(configuration));
|
||||
@@ -540,8 +558,8 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
{
|
||||
var profiles = new Dictionary<string, string>();
|
||||
var profile = new StringBuilder();
|
||||
var editorPath = Path.Combine(Globals.EngineRoot, "Binaries/Editor/Win64/Development/FlaxEditor.exe").Replace('/', '\\').Replace("\\", "\\\\");
|
||||
var workspacePath = solutionDirectory.Replace('/', '\\').Replace("\\", "\\\\");
|
||||
var editorPath = Utilities.NormalizePath(Path.Combine(Globals.EngineRoot, Platform.GetEditorBinaryDirectory(), $"Development/FlaxEditor{Utilities.GetPlatformExecutableExt()}"));
|
||||
var workspacePath = Utilities.NormalizePath(solutionDirectory);
|
||||
foreach (var project in projects)
|
||||
{
|
||||
if (project.Type == TargetType.DotNetCore)
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Flax.Build
|
||||
@@ -746,5 +747,19 @@ namespace Flax.Build
|
||||
text = text.Replace(findWhat, replaceWith);
|
||||
File.WriteAllText(file, text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns back the exe ext for the current platform
|
||||
/// </summary>
|
||||
public static string GetPlatformExecutableExt()
|
||||
{
|
||||
var extEnding = ".exe";
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
extEnding = "";
|
||||
}
|
||||
|
||||
return extEnding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user