Merge remote-tracking branch 'upstream/master' into ContentContextCondition

This commit is contained in:
davevanegdom
2023-09-19 01:10:51 +02:00
16 changed files with 190 additions and 54 deletions

View File

@@ -90,6 +90,12 @@ namespace FlaxEditor.Modules
hint = "Too long name."; hint = "Too long name.";
return false; return false;
} }
if (item.IsFolder && shortName.EndsWith("."))
{
hint = "Name cannot end with '.'";
return false;
}
// Find invalid characters // Find invalid characters
if (Utilities.Utils.HasInvalidPathChar(shortName)) if (Utilities.Utils.HasInvalidPathChar(shortName))
@@ -120,7 +126,7 @@ namespace FlaxEditor.Modules
// Cache data // Cache data
string sourcePath = item.Path; string sourcePath = item.Path;
string sourceFolder = System.IO.Path.GetDirectoryName(sourcePath); string sourceFolder = System.IO.Path.GetDirectoryName(sourcePath);
string extension = System.IO.Path.GetExtension(sourcePath); string extension = item.IsFolder ? "" : System.IO.Path.GetExtension(sourcePath);
string destinationPath = StringUtils.CombinePaths(sourceFolder, shortName + extension); string destinationPath = StringUtils.CombinePaths(sourceFolder, shortName + extension);
if (item.IsFolder) if (item.IsFolder)

View File

@@ -24,7 +24,8 @@ namespace
String version; String version;
RiderInstallation(const String& path_, const String& version_) RiderInstallation(const String& path_, const String& version_)
: path(path_), version(version_) : path(path_)
, version(version_)
{ {
} }
}; };
@@ -44,6 +45,10 @@ namespace
if (document.HasParseError()) if (document.HasParseError())
return; return;
// Check if this is actually rider and not another jetbrains product
if (document.FindMember("name")->value != "JetBrains Rider")
return;
// Find version // Find version
auto versionMember = document.FindMember("version"); auto versionMember = document.FindMember("version");
if (versionMember == document.MemberEnd()) if (versionMember == document.MemberEnd())
@@ -141,14 +146,14 @@ bool sortInstallations(RiderInstallation* const& i1, RiderInstallation* const& i
int32 version2[3] = { 0 }; int32 version2[3] = { 0 };
StringUtils::Parse(values1[0].Get(), &version1[0]); StringUtils::Parse(values1[0].Get(), &version1[0]);
StringUtils::Parse(values1[1].Get(), &version1[1]); StringUtils::Parse(values1[1].Get(), &version1[1]);
if(values1.Count() > 2) if (values1.Count() > 2)
StringUtils::Parse(values1[2].Get(), &version1[2]); StringUtils::Parse(values1[2].Get(), &version1[2]);
StringUtils::Parse(values2[0].Get(), &version2[0]); StringUtils::Parse(values2[0].Get(), &version2[0]);
StringUtils::Parse(values2[1].Get(), &version2[1]); StringUtils::Parse(values2[1].Get(), &version2[1]);
if(values2.Count() > 2) if (values2.Count() > 2)
StringUtils::Parse(values2[2].Get(), &version2[2]); StringUtils::Parse(values2[2].Get(), &version2[2]);
// Compare by MAJOR.MINOR.BUILD // Compare by MAJOR.MINOR.BUILD
@@ -174,7 +179,7 @@ void RiderCodeEditor::FindEditors(Array<CodeEditor*>* output)
String localAppDataPath; String localAppDataPath;
FileSystem::GetSpecialFolderPath(SpecialFolder::LocalAppData, localAppDataPath); FileSystem::GetSpecialFolderPath(SpecialFolder::LocalAppData, localAppDataPath);
#if PLATFORM_WINDOWS #if PLATFORM_WINDOWS
// Lookup from all known registry locations // Lookup from all known registry locations
SearchRegistry(&installations, HKEY_CURRENT_USER, TEXT("SOFTWARE\\WOW6432Node\\JetBrains\\Rider for Unreal Engine")); SearchRegistry(&installations, HKEY_CURRENT_USER, TEXT("SOFTWARE\\WOW6432Node\\JetBrains\\Rider for Unreal Engine"));
@@ -187,6 +192,7 @@ void RiderCodeEditor::FindEditors(Array<CodeEditor*>* output)
SearchRegistry(&installations, HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\WOW6432Node\\JetBrains\\JetBrains Rider")); SearchRegistry(&installations, HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\WOW6432Node\\JetBrains\\JetBrains Rider"));
// Versions installed via JetBrains Toolbox // Versions installed via JetBrains Toolbox
FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT("Programs"));
FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT("JetBrains\\Toolbox\\apps\\Rider\\ch-0\\")); FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT("JetBrains\\Toolbox\\apps\\Rider\\ch-0\\"));
FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT("JetBrains\\Toolbox\\apps\\Rider\\ch-1\\")); // Beta versions FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT("JetBrains\\Toolbox\\apps\\Rider\\ch-1\\")); // Beta versions
#endif #endif
@@ -201,6 +207,7 @@ void RiderCodeEditor::FindEditors(Array<CodeEditor*>* output)
FileSystem::GetChildDirectories(subDirectories, TEXT("/opt/")); FileSystem::GetChildDirectories(subDirectories, TEXT("/opt/"));
// Versions installed via JetBrains Toolbox // Versions installed via JetBrains Toolbox
SearchDirectory(&installations, localAppDataPath / TEXT(".local/share/JetBrains/Toolbox/apps/rider/"));
FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT(".local/share/JetBrains/Toolbox/apps/Rider/ch-0")); FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT(".local/share/JetBrains/Toolbox/apps/Rider/ch-0"));
FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT(".local/share/JetBrains/Toolbox/apps/Rider/ch-1")); // Beta versions FileSystem::GetChildDirectories(subDirectories, localAppDataPath / TEXT(".local/share/JetBrains/Toolbox/apps/Rider/ch-1")); // Beta versions
@@ -210,7 +217,24 @@ void RiderCodeEditor::FindEditors(Array<CodeEditor*>* output)
TEXT("flatpak run com.jetbrains.Rider")); TEXT("flatpak run com.jetbrains.Rider"));
#endif #endif
for (auto directory : subDirectories) #if PLATFORM_MAC
String applicationSupportFolder;
FileSystem::GetSpecialFolderPath(SpecialFolder::ProgramData, applicationSupportFolder);
Array<String> subMacDirectories;
FileSystem::GetChildDirectories(subMacDirectories, applicationSupportFolder / TEXT("JetBrains/Toolbox/apps/Rider/ch-0/"));
FileSystem::GetChildDirectories(subMacDirectories, applicationSupportFolder / TEXT("JetBrains/Toolbox/apps/Rider/ch-1/"));
for (const String& directory : subMacDirectories)
{
String riderAppDirectory = directory / TEXT("Rider.app/Contents/Resources");
SearchDirectory(&installations, riderAppDirectory);
}
// Check the local installer version
SearchDirectory(&installations, TEXT("/Applications/Rider.app/Contents/Resources"));
#endif
for (const String& directory : subDirectories)
SearchDirectory(&installations, directory); SearchDirectory(&installations, directory);
// Sort found installations by version number // Sort found installations by version number

View File

@@ -126,7 +126,7 @@ namespace FlaxEditor.Surface.Archetypes
Title = "Clamp", Title = "Clamp",
Description = "Clamps value to the specified range", Description = "Clamps value to the specified range",
Flags = NodeFlags.AllGraphs, Flags = NodeFlags.AllGraphs,
Size = new Float2(110, 60), Size = new Float2(140, 60),
ConnectionsHints = ConnectionsHint.Numeric, ConnectionsHints = ConnectionsHint.Numeric,
IndependentBoxes = new[] { 0 }, IndependentBoxes = new[] { 0 },
DependentBoxes = new[] { 1, 2, 3 }, DependentBoxes = new[] { 1, 2, 3 },

View File

@@ -520,7 +520,7 @@ namespace FlaxEditor.Windows
} }
// Cache data // Cache data
string extension = Path.GetExtension(item.Path); string extension = item.IsFolder ? "" : Path.GetExtension(item.Path);
var newPath = StringUtils.CombinePaths(item.ParentFolder.Path, newShortName + extension); var newPath = StringUtils.CombinePaths(item.ParentFolder.Path, newShortName + extension);
// Check if was renaming mock element // Check if was renaming mock element

View File

@@ -32,6 +32,7 @@ namespace FlaxEngine.Interop
public static class NativeToManaged public static class NativeToManaged
{ {
public static object ConvertToManaged(IntPtr unmanaged) => unmanaged == IntPtr.Zero ? null : ManagedHandle.FromIntPtr(unmanaged).Target; public static object ConvertToManaged(IntPtr unmanaged) => unmanaged == IntPtr.Zero ? null : ManagedHandle.FromIntPtr(unmanaged).Target;
public static IntPtr ConvertToUnmanaged(object managed) => managed != null ? ManagedHandle.ToIntPtr(managed, GCHandleType.Weak) : IntPtr.Zero;
public static void Free(IntPtr unmanaged) public static void Free(IntPtr unmanaged)
{ {
@@ -44,6 +45,7 @@ namespace FlaxEngine.Interop
#endif #endif
public static class ManagedToNative public static class ManagedToNative
{ {
public static object ConvertToManaged(IntPtr unmanaged) => unmanaged == IntPtr.Zero ? null : ManagedHandle.FromIntPtr(unmanaged).Target;
public static IntPtr ConvertToUnmanaged(object managed) => managed != null ? ManagedHandle.ToIntPtr(managed, GCHandleType.Weak) : IntPtr.Zero; public static IntPtr ConvertToUnmanaged(object managed) => managed != null ? ManagedHandle.ToIntPtr(managed, GCHandleType.Weak) : IntPtr.Zero;
public static void Free(IntPtr unmanaged) public static void Free(IntPtr unmanaged)
@@ -147,29 +149,16 @@ namespace FlaxEngine.Interop
#if FLAX_EDITOR #if FLAX_EDITOR
[HideInEditor] [HideInEditor]
#endif #endif
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ManagedToUnmanagedIn, typeof(ObjectMarshaller.ManagedToNative))] [CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ManagedToUnmanagedIn, typeof(ObjectMarshaller))]
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.UnmanagedToManagedOut, typeof(ObjectMarshaller.ManagedToNative))] [CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.UnmanagedToManagedOut, typeof(ObjectMarshaller))]
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ElementIn, typeof(ObjectMarshaller.ManagedToNative))] [CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ElementIn, typeof(ObjectMarshaller))]
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ManagedToUnmanagedOut, typeof(ObjectMarshaller.NativeToManaged))] [CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ManagedToUnmanagedOut, typeof(ObjectMarshaller))]
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.UnmanagedToManagedIn, typeof(ObjectMarshaller.NativeToManaged))] [CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.UnmanagedToManagedIn, typeof(ObjectMarshaller))]
[CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ElementOut, typeof(ObjectMarshaller.NativeToManaged))] [CustomMarshaller(typeof(FlaxEngine.Object), MarshalMode.ElementOut, typeof(ObjectMarshaller))]
public static class ObjectMarshaller public static class ObjectMarshaller
{ {
#if FLAX_EDITOR public static FlaxEngine.Object ConvertToManaged(IntPtr unmanaged) => unmanaged != IntPtr.Zero ? Unsafe.As<FlaxEngine.Object>(ManagedHandle.FromIntPtr(unmanaged).Target) : null;
[HideInEditor] public static IntPtr ConvertToUnmanaged(FlaxEngine.Object managed) => Unsafe.As<object>(managed) != null ? ManagedHandle.ToIntPtr(managed) : IntPtr.Zero;
#endif
public static class NativeToManaged
{
public static FlaxEngine.Object ConvertToManaged(IntPtr unmanaged) => unmanaged != IntPtr.Zero ? Unsafe.As<FlaxEngine.Object>(ManagedHandle.FromIntPtr(unmanaged).Target) : null;
}
#if FLAX_EDITOR
[HideInEditor]
#endif
public static class ManagedToNative
{
public static IntPtr ConvertToUnmanaged(FlaxEngine.Object managed) => Unsafe.As<object>(managed) != null ? ManagedHandle.ToIntPtr(managed) : IntPtr.Zero;
}
} }
#if FLAX_EDITOR #if FLAX_EDITOR
@@ -342,6 +331,7 @@ namespace FlaxEngine.Interop
public static class NativeToManaged public static class NativeToManaged
{ {
public static Dictionary<T, U> ConvertToManaged(IntPtr unmanaged) => DictionaryMarshaller<T, U>.ToManaged(unmanaged); public static Dictionary<T, U> ConvertToManaged(IntPtr unmanaged) => DictionaryMarshaller<T, U>.ToManaged(unmanaged);
public static IntPtr ConvertToUnmanaged(Dictionary<T, U> managed) => DictionaryMarshaller<T, U>.ToNative(managed, GCHandleType.Weak);
public static void Free(IntPtr unmanaged) => DictionaryMarshaller<T, U>.Free(unmanaged); public static void Free(IntPtr unmanaged) => DictionaryMarshaller<T, U>.Free(unmanaged);
} }
@@ -350,8 +340,8 @@ namespace FlaxEngine.Interop
#endif #endif
public static class ManagedToNative public static class ManagedToNative
{ {
public static Dictionary<T, U> ConvertToManaged(IntPtr unmanaged) => DictionaryMarshaller<T, U>.ToManaged(unmanaged);
public static IntPtr ConvertToUnmanaged(Dictionary<T, U> managed) => DictionaryMarshaller<T, U>.ToNative(managed, GCHandleType.Weak); public static IntPtr ConvertToUnmanaged(Dictionary<T, U> managed) => DictionaryMarshaller<T, U>.ToNative(managed, GCHandleType.Weak);
public static void Free(IntPtr unmanaged) public static void Free(IntPtr unmanaged)
{ {
//DictionaryMarshaller<T, U>.Free(unmanaged); // No need to free weak handles //DictionaryMarshaller<T, U>.Free(unmanaged); // No need to free weak handles
@@ -425,6 +415,28 @@ namespace FlaxEngine.Interop
return new T[numElements]; return new T[numElements];
} }
public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T[] managed, out int numElements)
{
if (managed is null)
{
numElements = 0;
return null;
}
numElements = managed.Length;
(ManagedHandle managedArrayHandle, _) = ManagedArray.AllocatePooledArray<TUnmanagedElement>(managed.Length);
return (TUnmanagedElement*)ManagedHandle.ToIntPtr(managedArrayHandle);
}
public static ReadOnlySpan<T> GetManagedValuesSource(T[] managed) => managed;
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged)
{
if (unmanaged == null)
return Span<TUnmanagedElement>.Empty;
ManagedArray managedArray = Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(new IntPtr(unmanaged)).Target);
return managedArray.ToSpan<TUnmanagedElement>();
}
public static Span<T> GetManagedValuesDestination(T[] managed) => managed; public static Span<T> GetManagedValuesDestination(T[] managed) => managed;
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TUnmanagedElement* unmanaged, int numElements) public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(TUnmanagedElement* unmanaged, int numElements)
@@ -591,6 +603,7 @@ namespace FlaxEngine.Interop
public static class NativeToManaged public static class NativeToManaged
{ {
public static string ConvertToManaged(IntPtr unmanaged) => ManagedString.ToManaged(unmanaged); public static string ConvertToManaged(IntPtr unmanaged) => ManagedString.ToManaged(unmanaged);
public static unsafe IntPtr ConvertToUnmanaged(string managed) => managed == null ? IntPtr.Zero : ManagedHandle.ToIntPtr(managed, GCHandleType.Weak);
public static void Free(IntPtr unmanaged) => ManagedString.Free(unmanaged); public static void Free(IntPtr unmanaged) => ManagedString.Free(unmanaged);
} }
@@ -599,11 +612,8 @@ namespace FlaxEngine.Interop
#endif #endif
public static class ManagedToNative public static class ManagedToNative
{ {
public static unsafe IntPtr ConvertToUnmanaged(string managed) public static string ConvertToManaged(IntPtr unmanaged) => ManagedString.ToManaged(unmanaged);
{ public static unsafe IntPtr ConvertToUnmanaged(string managed) => managed == null ? IntPtr.Zero : ManagedHandle.ToIntPtr(managed, GCHandleType.Weak);
return managed == null ? IntPtr.Zero : ManagedHandle.ToIntPtr(managed, GCHandleType.Weak);
}
public static void Free(IntPtr unmanaged) public static void Free(IntPtr unmanaged)
{ {
//ManagedString.Free(unmanaged); // No need to free weak handles //ManagedString.Free(unmanaged); // No need to free weak handles

View File

@@ -184,7 +184,7 @@ namespace FlaxEngine.Interop
{ {
string moduleName = Marshal.PtrToStringAnsi(moduleNamePtr); string moduleName = Marshal.PtrToStringAnsi(moduleNamePtr);
string modulePath = Marshal.PtrToStringAnsi(modulePathPtr); string modulePath = Marshal.PtrToStringAnsi(modulePathPtr);
nativeLibraryPaths[moduleName] = modulePath; libraryPaths[moduleName] = modulePath;
} }
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
@@ -909,7 +909,7 @@ namespace FlaxEngine.Interop
loadedNativeLibraries.Remove(nativeLibraryName); loadedNativeLibraries.Remove(nativeLibraryName);
} }
if (nativeLibraryName != null) if (nativeLibraryName != null)
nativeLibraryPaths.Remove(nativeLibraryName); libraryPaths.Remove(nativeLibraryName);
} }
[UnmanagedCallersOnly] [UnmanagedCallersOnly]

View File

@@ -50,7 +50,7 @@ namespace FlaxEngine.Interop
private static Dictionary<Type, int> _typeSizeCache = new(); private static Dictionary<Type, int> _typeSizeCache = new();
private static Dictionary<string, IntPtr> loadedNativeLibraries = new(); private static Dictionary<string, IntPtr> loadedNativeLibraries = new();
internal static Dictionary<string, string> nativeLibraryPaths = new(); internal static Dictionary<string, string> libraryPaths = new();
private static Dictionary<Assembly, string> assemblyOwnedNativeLibraries = new(); private static Dictionary<Assembly, string> assemblyOwnedNativeLibraries = new();
internal static AssemblyLoadContext scriptingAssemblyLoadContext; internal static AssemblyLoadContext scriptingAssemblyLoadContext;
@@ -59,7 +59,7 @@ namespace FlaxEngine.Interop
{ {
if (!loadedNativeLibraries.TryGetValue(libraryName, out IntPtr nativeLibrary)) if (!loadedNativeLibraries.TryGetValue(libraryName, out IntPtr nativeLibrary))
{ {
if (!nativeLibraryPaths.TryGetValue(libraryName, out var nativeLibraryPath)) if (!libraryPaths.TryGetValue(libraryName, out var nativeLibraryPath))
nativeLibraryPath = libraryName; nativeLibraryPath = libraryName;
nativeLibrary = NativeLibrary.Load(nativeLibraryPath, assembly, dllImportSearchPath); nativeLibrary = NativeLibrary.Load(nativeLibraryPath, assembly, dllImportSearchPath);
@@ -101,9 +101,9 @@ namespace FlaxEngine.Interop
private static Assembly OnScriptingAssemblyLoadContextResolving(AssemblyLoadContext assemblyLoadContext, AssemblyName assemblyName) private static Assembly OnScriptingAssemblyLoadContextResolving(AssemblyLoadContext assemblyLoadContext, AssemblyName assemblyName)
{ {
// FIXME: There should be a better way to resolve the path to EditorTargetPath where the dependencies are stored // FIXME: There should be a better way to resolve the path to EditorTargetPath where the dependencies are stored
foreach (string nativeLibraryPath in nativeLibraryPaths.Values) foreach (string libraryPath in libraryPaths.Values)
{ {
string editorTargetPath = Path.GetDirectoryName(nativeLibraryPath); string editorTargetPath = Path.GetDirectoryName(libraryPath);
var assemblyPath = Path.Combine(editorTargetPath, assemblyName.Name + ".dll"); var assemblyPath = Path.Combine(editorTargetPath, assemblyName.Name + ".dll");
if (File.Exists(assemblyPath)) if (File.Exists(assemblyPath))

View File

@@ -462,6 +462,9 @@ int32 MacPlatform::CreateProcess(CreateProcessSettings& settings)
} }
} }
// Sanatize the string if the exePath has spaces with properly espcaped spaces for popen
exePath.Replace(TEXT(" "), TEXT("\\ "));
const String cmdLine = exePath + TEXT(" ") + settings.Arguments; const String cmdLine = exePath + TEXT(" ") + settings.Arguments;
const StringAsANSI<> cmdLineAnsi(*cmdLine, cmdLine.Length()); const StringAsANSI<> cmdLineAnsi(*cmdLine, cmdLine.Length());
FILE* pipe = popen(cmdLineAnsi.Get(), "r"); FILE* pipe = popen(cmdLineAnsi.Get(), "r");

View File

@@ -1009,12 +1009,36 @@ void ManagedBinaryModule::InitType(MClass* mclass)
} }
if (baseType.Module == this) if (baseType.Module == this)
InitType(baseClass); // Ensure base is initialized before InitType(baseClass); // Ensure base is initialized before
baseType.Module->TypeNameToTypeIndex.TryGet(baseClass->GetFullName(), *(int32*)&baseType.TypeIndex); baseType.Module->TypeNameToTypeIndex.TryGet(baseClass->GetFullName(), *(int32*)&baseType.TypeIndex);
// So we must special case this flow of a generic class of which its possible the generic base class is not in the same module
if (baseType.TypeIndex == -1 && baseClass->IsGeneric())
{
auto genericNameIndex = baseClass->GetFullName().FindLast('`');
// we add 2 because of the way generic names work its `N
auto genericClassName = baseClass->GetFullName().Substring(0, genericNameIndex + 2);
// We check for the generic class name instead of the baseclass fullname
baseType.Module->TypeNameToTypeIndex.TryGet(genericClassName, *(int32*)&baseType.TypeIndex);
}
if (!baseType) if (!baseType)
{ {
LOG(Error, "Missing base class for managed class {0} from assembly {1}.", String(typeName), Assembly->ToString()); LOG(Error, "Missing base class for managed class {0} from assembly {1}.", String(typeName), Assembly->ToString());
return; return;
} }
if (baseType.TypeIndex == -1)
{
if (baseType.Module)
LOG(Error, "Missing base class for managed class {0} from assembly {1}.", String(baseClass->GetFullName()), baseType.Module->GetName().ToString());
else
// Not sure this can happen but never hurts to account for it
LOG(Error, "Missing base class for managed class {0} from unknown assembly.", String(baseClass->GetFullName()));
return;
}
ScriptingTypeHandle nativeType = baseType; ScriptingTypeHandle nativeType = baseType;
while (true) while (true)
{ {

View File

@@ -719,6 +719,13 @@ bool MAssembly::LoadImage(const String& assemblyPath, const StringView& nativePa
StringAnsi nativeName = _name.EndsWith(".CSharp") ? StringAnsi(_name.Get(), _name.Length() - 7) : StringAnsi(_name); StringAnsi nativeName = _name.EndsWith(".CSharp") ? StringAnsi(_name.Get(), _name.Length() - 7) : StringAnsi(_name);
RegisterNativeLibrary(nativeName.Get(), StringAnsi(nativePath).Get()); RegisterNativeLibrary(nativeName.Get(), StringAnsi(nativePath).Get());
} }
#if USE_EDITOR
// Register the editor module location for Assembly resolver
else
{
RegisterNativeLibrary(_name.Get(), StringAnsi(assemblyPath).Get());
}
#endif
_hasCachedClasses = false; _hasCachedClasses = false;
_assemblyPath = assemblyPath; _assemblyPath = assemblyPath;
@@ -1597,7 +1604,10 @@ bool InitHostfxr()
void* hostfxr = Platform::LoadLibrary(path.Get()); void* hostfxr = Platform::LoadLibrary(path.Get());
if (hostfxr == nullptr) if (hostfxr == nullptr)
{ {
LOG(Fatal, "Failed to load hostfxr library ({0})", path); if (FileSystem::FileExists(path))
LOG(Fatal, "Failed to load hostfxr library, possible platform/architecture mismatch with the library. See log for more information. ({0})", path);
else
LOG(Fatal, "Failed to load hostfxr library ({0})", path);
return true; return true;
} }
hostfxr_initialize_for_runtime_config = (hostfxr_initialize_for_runtime_config_fn)Platform::GetProcAddress(hostfxr, "hostfxr_initialize_for_runtime_config"); hostfxr_initialize_for_runtime_config = (hostfxr_initialize_for_runtime_config_fn)Platform::GetProcAddress(hostfxr, "hostfxr_initialize_for_runtime_config");
@@ -1636,7 +1646,28 @@ bool InitHostfxr()
if (rc != 0 || handle == nullptr) if (rc != 0 || handle == nullptr)
{ {
hostfxr_close(handle); hostfxr_close(handle);
LOG(Fatal, "Failed to initialize hostfxr: {0:x} ({1})", (unsigned int)rc, String(init_params.dotnet_root)); if (rc == 0x80008096) // FrameworkMissingFailure
{
String platformStr;
switch (PLATFORM_TYPE)
{
case PlatformType::Windows:
case PlatformType::UWP:
platformStr = PLATFORM_64BITS ? "Windows x64" : "Windows x86";
break;
case PlatformType::Linux:
platformStr = PLATFORM_ARCH_ARM64 ? "Linux Arm64" : PLATFORM_ARCH_ARM ? "Linux Arm32" : PLATFORM_64BITS ? "Linux x64" : "Linux x86";
break;
case PlatformType::Mac:
platformStr = PLATFORM_ARCH_ARM || PLATFORM_ARCH_ARM64 ? "macOS Arm64" : PLATFORM_64BITS ? "macOS x64" : "macOS x86";
break;
default:;
platformStr = "";
}
LOG(Fatal, "Failed to resolve compatible .NET runtime version in '{0}'. Make sure the correct platform version for runtime is installed ({1})", platformStr, String(init_params.dotnet_root));
}
else
LOG(Fatal, "Failed to initialize hostfxr: {0:x} ({1})", (unsigned int)rc, String(init_params.dotnet_root));
return true; return true;
} }

View File

@@ -19,7 +19,7 @@ namespace FlaxEngine.Tests
{ {
var result = 0; var result = 0;
var libraryName = "FlaxEngine"; var libraryName = "FlaxEngine";
var library = NativeLibrary.Load(Interop.NativeInterop.nativeLibraryPaths[libraryName]); var library = NativeLibrary.Load(Interop.NativeInterop.libraryPaths[libraryName]);
if (library == IntPtr.Zero) if (library == IntPtr.Zero)
return -1; return -1;
var types = typeof(FlaxEngine.Object).Assembly.GetTypes(); var types = typeof(FlaxEngine.Object).Assembly.GetTypes();

View File

@@ -60,6 +60,7 @@ public class Slider : ContainerControl
private float _thumbCenter; private float _thumbCenter;
private Float2 _thumbSize = new Float2(16, 16); private Float2 _thumbSize = new Float2(16, 16);
private bool _isSliding; private bool _isSliding;
private bool _mouseOverThumb;
/// <summary> /// <summary>
/// Gets or sets the value (normalized to range 0-100). /// Gets or sets the value (normalized to range 0-100).
@@ -163,21 +164,27 @@ public class Slider : ContainerControl
public IBrush FillTrackBrush { get; set; } public IBrush FillTrackBrush { get; set; }
/// <summary> /// <summary>
/// The color of the slider thumb when it's not selected /// The color of the slider thumb when it's not selected.
/// </summary> /// </summary>
[EditorDisplay("Thumb Style"), EditorOrder(2030), Tooltip("The color of the slider thumb when it's not selected."), ExpandGroups] [EditorDisplay("Thumb Style"), EditorOrder(2030), Tooltip("The color of the slider thumb when it's not selected."), ExpandGroups]
public Color ThumbColor { get; set; } public Color ThumbColor { get; set; }
/// <summary>
/// The color of the slider thumb when it's highlighted.
/// </summary>
[EditorDisplay("Thumb Style"), EditorOrder(2031), Tooltip("The color of the slider thumb when it's highlighted.")]
public Color ThumbColorHighlighted { get; set; }
/// <summary> /// <summary>
/// The color of the slider thumb when it's selected /// The color of the slider thumb when it's selected.
/// </summary> /// </summary>
[EditorDisplay("Thumb Style"), EditorOrder(2031), Tooltip("The color of the slider thumb when it's selected.")] [EditorDisplay("Thumb Style"), EditorOrder(2032), Tooltip("The color of the slider thumb when it's selected.")]
public Color ThumbColorSelected { get; set; } public Color ThumbColorSelected { get; set; }
/// <summary> /// <summary>
/// Gets or sets the brush used for slider thumb drawing. /// Gets or sets the brush used for slider thumb drawing.
/// </summary> /// </summary>
[EditorDisplay("Thumb Style"), EditorOrder(2032), Tooltip("The brush of the slider thumb.")] [EditorDisplay("Thumb Style"), EditorOrder(2033), Tooltip("The brush of the slider thumb.")]
public IBrush ThumbBrush { get; set; } public IBrush ThumbBrush { get; set; }
/// <summary> /// <summary>
@@ -222,6 +229,7 @@ public class Slider : ContainerControl
TrackFillLineColor = style.LightBackground; TrackFillLineColor = style.LightBackground;
ThumbColor = style.BackgroundNormal; ThumbColor = style.BackgroundNormal;
ThumbColorSelected = style.BackgroundSelected; ThumbColorSelected = style.BackgroundSelected;
ThumbColorHighlighted = style.BackgroundHighlighted;
UpdateThumb(); UpdateThumb();
} }
@@ -270,7 +278,7 @@ public class Slider : ContainerControl
} }
// Draw thumb // Draw thumb
var thumbColor = _isSliding ? ThumbColorSelected : ThumbColor; var thumbColor = _isSliding ? ThumbColorSelected : (_mouseOverThumb ? ThumbColorHighlighted : ThumbColor);
if (ThumbBrush != null) if (ThumbBrush != null)
ThumbBrush.Draw(_thumbRect, thumbColor); ThumbBrush.Draw(_thumbRect, thumbColor);
else else
@@ -317,6 +325,7 @@ public class Slider : ContainerControl
/// <inheritdoc /> /// <inheritdoc />
public override void OnMouseMove(Float2 location) public override void OnMouseMove(Float2 location)
{ {
_mouseOverThumb = _thumbRect.Contains(location);
if (_isSliding) if (_isSliding)
{ {
// Update sliding // Update sliding

View File

@@ -1340,6 +1340,7 @@ namespace Flax.Build.Bindings
public static class NativeToManaged public static class NativeToManaged
{ {
public static {{classInfo.Name}} ConvertToManaged(IntPtr unmanaged) => Unsafe.As<{{classInfo.Name}}>(ManagedHandleMarshaller.NativeToManaged.ConvertToManaged(unmanaged)); public static {{classInfo.Name}} ConvertToManaged(IntPtr unmanaged) => Unsafe.As<{{classInfo.Name}}>(ManagedHandleMarshaller.NativeToManaged.ConvertToManaged(unmanaged));
public static IntPtr ConvertToUnmanaged({{classInfo.Name}} managed) => ManagedHandleMarshaller.ManagedToNative.ConvertToUnmanaged(managed);
public static void Free(IntPtr unmanaged) => ManagedHandleMarshaller.NativeToManaged.Free(unmanaged); public static void Free(IntPtr unmanaged) => ManagedHandleMarshaller.NativeToManaged.Free(unmanaged);
} }
#if FLAX_EDITOR #if FLAX_EDITOR
@@ -1347,6 +1348,7 @@ namespace Flax.Build.Bindings
#endif #endif
public static class ManagedToNative public static class ManagedToNative
{ {
public static {{classInfo.Name}} ConvertToManaged(IntPtr unmanaged) => Unsafe.As<{{classInfo.Name}}>(ManagedHandleMarshaller.NativeToManaged.ConvertToManaged(unmanaged));
public static IntPtr ConvertToUnmanaged({{classInfo.Name}} managed) => ManagedHandleMarshaller.ManagedToNative.ConvertToUnmanaged(managed); public static IntPtr ConvertToUnmanaged({{classInfo.Name}} managed) => ManagedHandleMarshaller.ManagedToNative.ConvertToUnmanaged(managed);
public static void Free(IntPtr unmanaged) => ManagedHandleMarshaller.ManagedToNative.Free(unmanaged); public static void Free(IntPtr unmanaged) => ManagedHandleMarshaller.ManagedToNative.Free(unmanaged);
} }
@@ -1668,6 +1670,7 @@ namespace Flax.Build.Bindings
contents.Append(indent).AppendLine("[HideInEditor]"); contents.Append(indent).AppendLine("[HideInEditor]");
contents.Append(indent).AppendLine("public static class NativeToManaged").Append(indent).AppendLine("{"); contents.Append(indent).AppendLine("public static class NativeToManaged").Append(indent).AppendLine("{");
contents.Append(indent2).AppendLine($"public static {structureInfo.Name} ConvertToManaged({structureInfo.Name}Internal unmanaged) => {marshallerName}.ToManaged(unmanaged);"); contents.Append(indent2).AppendLine($"public static {structureInfo.Name} ConvertToManaged({structureInfo.Name}Internal unmanaged) => {marshallerName}.ToManaged(unmanaged);");
contents.Append(indent2).AppendLine($"public static {structureInfo.Name}Internal ConvertToUnmanaged({structureInfo.Name} managed) => {marshallerName}.ToNative(managed);");
contents.Append(indent2).AppendLine($"public static void Free({structureInfo.Name}Internal unmanaged)"); contents.Append(indent2).AppendLine($"public static void Free({structureInfo.Name}Internal unmanaged)");
contents.Append(indent2).AppendLine("{").Append(indent3).AppendLine(freeContents2.Replace("\n", "\n" + indent3).ToString().TrimEnd()).Append(indent2).AppendLine("}"); contents.Append(indent2).AppendLine("{").Append(indent3).AppendLine(freeContents2.Replace("\n", "\n" + indent3).ToString().TrimEnd()).Append(indent2).AppendLine("}");
contents.Append(indent).AppendLine("}"); contents.Append(indent).AppendLine("}");
@@ -1676,6 +1679,7 @@ namespace Flax.Build.Bindings
if (buildData.Target != null && buildData.Target.IsEditor) if (buildData.Target != null && buildData.Target.IsEditor)
contents.Append(indent).AppendLine("[HideInEditor]"); contents.Append(indent).AppendLine("[HideInEditor]");
contents.Append(indent).AppendLine($"public static class ManagedToNative").Append(indent).AppendLine("{"); contents.Append(indent).AppendLine($"public static class ManagedToNative").Append(indent).AppendLine("{");
contents.Append(indent2).AppendLine($"public static {structureInfo.Name} ConvertToManaged({structureInfo.Name}Internal unmanaged) => {marshallerName}.ToManaged(unmanaged);");
contents.Append(indent2).AppendLine($"public static {structureInfo.Name}Internal ConvertToUnmanaged({structureInfo.Name} managed) => {marshallerName}.ToNative(managed);"); contents.Append(indent2).AppendLine($"public static {structureInfo.Name}Internal ConvertToUnmanaged({structureInfo.Name} managed) => {marshallerName}.ToNative(managed);");
contents.Append(indent2).AppendLine($"public static void Free({structureInfo.Name}Internal unmanaged) => {marshallerName}.Free(unmanaged);"); contents.Append(indent2).AppendLine($"public static void Free({structureInfo.Name}Internal unmanaged) => {marshallerName}.Free(unmanaged);");
contents.Append(indent).AppendLine("}"); contents.Append(indent).AppendLine("}");

View File

@@ -207,6 +207,7 @@ namespace Flax.Build
case TargetPlatform.Mac: case TargetPlatform.Mac:
{ {
#if USE_NETCORE #if USE_NETCORE
dotnetPath = Path.Combine(dotnetSdk.RootPath, "dotnet");
cscPath = Path.Combine(dotnetSdk.RootPath, $"sdk/{dotnetSdk.VersionName}/Roslyn/bincore/csc.dll"); cscPath = Path.Combine(dotnetSdk.RootPath, $"sdk/{dotnetSdk.VersionName}/Roslyn/bincore/csc.dll");
referenceAssemblies = Path.Combine(dotnetSdk.RootPath, $"packs/Microsoft.NETCore.App.Ref/{dotnetSdk.RuntimeVersionName}/ref/net{runtimeVersionShort}/"); referenceAssemblies = Path.Combine(dotnetSdk.RootPath, $"packs/Microsoft.NETCore.App.Ref/{dotnetSdk.RuntimeVersionName}/ref/net{runtimeVersionShort}/");
referenceAnalyzers = Path.Combine(dotnetSdk.RootPath, $"packs/Microsoft.NETCore.App.Ref/{dotnetSdk.RuntimeVersionName}/analyzers/dotnet/cs/"); referenceAnalyzers = Path.Combine(dotnetSdk.RootPath, $"packs/Microsoft.NETCore.App.Ref/{dotnetSdk.RuntimeVersionName}/analyzers/dotnet/cs/");

View File

@@ -212,6 +212,15 @@ namespace Flax.Build
ridFallback = ""; ridFallback = "";
if (string.IsNullOrEmpty(dotnetPath)) if (string.IsNullOrEmpty(dotnetPath))
dotnetPath = "/usr/local/share/dotnet/"; dotnetPath = "/usr/local/share/dotnet/";
// Use x64 when cross-compiling from ARM64
if (architecture == TargetArchitecture.ARM64 && (Configuration.BuildArchitectures != null && Configuration.BuildArchitectures[0] == TargetArchitecture.x64))
{
rid = "osx-x64";
dotnetPath = Path.Combine(dotnetPath, "x64");
architecture = TargetArchitecture.x64;
}
break; break;
} }
default: throw new InvalidPlatformException(platform); default: throw new InvalidPlatformException(platform);
@@ -271,7 +280,7 @@ namespace Flax.Build
// Found // Found
IsValid = true; IsValid = true;
Log.Verbose($"Found .NET SDK {VersionName} (runtime {RuntimeVersionName}) at {RootPath}"); Log.Info($"Using .NET SDK {VersionName}, runtime {RuntimeVersionName} ({RootPath})");
foreach (var e in _hostRuntimes) foreach (var e in _hostRuntimes)
Log.Verbose($" - Host Runtime for {e.Key.Key} {e.Key.Value}"); Log.Verbose($" - Host Runtime for {e.Key.Key} {e.Key.Value}");
} }

View File

@@ -1,5 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System.IO;
namespace Flax.Build.Platforms namespace Flax.Build.Platforms
{ {
/// <summary> /// <summary>
@@ -11,6 +13,9 @@ namespace Flax.Build.Platforms
/// <inheritdoc /> /// <inheritdoc />
public override TargetPlatform Target => TargetPlatform.iOS; public override TargetPlatform Target => TargetPlatform.iOS;
/// <inheritdoc />
public override bool HasRequiredSDKsInstalled { get; }
/// <inheritdoc /> /// <inheritdoc />
public override bool HasDynamicCodeExecutionSupport => false; public override bool HasDynamicCodeExecutionSupport => false;
@@ -21,11 +26,21 @@ namespace Flax.Build.Platforms
{ {
if (Platform.BuildTargetPlatform != TargetPlatform.Mac) if (Platform.BuildTargetPlatform != TargetPlatform.Mac)
return; return;
if (!HasRequiredSDKsInstalled) if (!XCode.Instance.IsValid)
{ {
Log.Warning("Missing XCode. Cannot build for iOS platform."); Log.Warning("Missing XCode. Cannot build for iOS platform.");
return; return;
} }
// We should check and see if the actual iphoneSDK is installed
string iphoneSDKPath = Utilities.ReadProcessOutput("/usr/bin/xcrun", "--sdk iphoneos --show-sdk-path");
if (string.IsNullOrEmpty(iphoneSDKPath) || !Directory.Exists(iphoneSDKPath))
{
Log.Warning("Missing iPhoneSDK. Cannot build for iOS platform.");
HasRequiredSDKsInstalled = false;
}
else
HasRequiredSDKsInstalled = true;
} }
/// <inheritdoc /> /// <inheritdoc />