diff --git a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs
index 1fe849f09..7dfce6055 100644
--- a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs
@@ -260,7 +260,7 @@ namespace FlaxEditor.CustomEditors.Editors
var overrideEditor = overrideEditorType != null ? (CustomEditor)Activator.CreateInstance(overrideEditorType) : null;
var property = panel.AddPropertyItem(new DictionaryItemLabel(this, key));
var itemLayout = useSharedLayout ? (LayoutElementsContainer)property : property.VerticalPanel();
- itemLayout.Object(new DictionaryValueContainer(valuesType, key, Values), overrideEditor);
+ itemLayout.Object(new DictionaryValueContainer(valuesType, key, Values, attributes), overrideEditor);
if (_readOnly && itemLayout.Children.Count > 0)
GenericEditor.OnReadOnlyProperty(itemLayout);
}
diff --git a/Source/Editor/CustomEditors/Values/DictionaryValueContainer.cs b/Source/Editor/CustomEditors/Values/DictionaryValueContainer.cs
index b143b44b1..435e5a515 100644
--- a/Source/Editor/CustomEditors/Values/DictionaryValueContainer.cs
+++ b/Source/Editor/CustomEditors/Values/DictionaryValueContainer.cs
@@ -14,6 +14,8 @@ namespace FlaxEditor.CustomEditors
[HideInEditor]
public class DictionaryValueContainer : ValueContainer
{
+ private readonly object[] _attributes;
+
///
/// The key in the collection.
///
@@ -36,9 +38,12 @@ namespace FlaxEditor.CustomEditors
/// Type of the collection elements.
/// The key.
/// The collection values.
- public DictionaryValueContainer(ScriptType elementType, object key, ValueContainer values)
+ /// The dictionary property attributes to inherit.
+ public DictionaryValueContainer(ScriptType elementType, object key, ValueContainer values, object[] attributes = null)
: this(elementType, key)
{
+ _attributes = attributes;
+
Capacity = values.Count;
for (int i = 0; i < values.Count; i++)
{
@@ -123,5 +128,11 @@ namespace FlaxEditor.CustomEditors
_hasReferenceValue = true;
}
}
+
+ ///
+ public override object[] GetAttributes()
+ {
+ return _attributes ?? base.GetAttributes();
+ }
}
}
diff --git a/Source/Editor/Scripting/CodeEditors/RiderCodeEditor.cpp b/Source/Editor/Scripting/CodeEditors/RiderCodeEditor.cpp
index b63815dce..de6001efd 100644
--- a/Source/Editor/Scripting/CodeEditors/RiderCodeEditor.cpp
+++ b/Source/Editor/Scripting/CodeEditors/RiderCodeEditor.cpp
@@ -14,6 +14,9 @@
#if PLATFORM_WINDOWS
#include "Engine/Platform/Win32/IncludeWindowsHeaders.h"
+#elif PLATFORM_MAC
+#include "Engine/Platform/Apple/AppleUtils.h"
+#include
#endif
namespace
@@ -68,10 +71,14 @@ namespace
if (!launcherPath.HasChars() || !FileSystem::FileExists(exePath))
return;
- if (launchOverridePath != String::Empty)
- installations->Add(New(launchOverridePath, versionMember->value.GetText()));
- else
- installations->Add(New(exePath, versionMember->value.GetText()));
+ String installPath = launchOverridePath != String::Empty ? launchOverridePath : exePath;
+ StringUtils::PathRemoveRelativeParts(installPath);
+ for (RiderInstallation* installation : *installations)
+ {
+ if (installation->path == installPath)
+ return;
+ }
+ installations->Add(New(installPath, versionMember->value.GetText()));
}
#if PLATFORM_WINDOWS
@@ -221,17 +228,29 @@ void RiderCodeEditor::FindEditors(Array* output)
String applicationSupportFolder;
FileSystem::GetSpecialFolderPath(SpecialFolder::ProgramData, applicationSupportFolder);
+ NSURL* appURL = [[NSWorkspace sharedWorkspace] URLForApplicationWithBundleIdentifier:@"com.jetbrains.rider"];
+ if (appURL != nullptr)
+ {
+ const String appPath = AppleUtils::ToString((CFStringRef)[appURL path]);
+ SearchDirectory(&installations, appPath / TEXT("Contents/Resources"), appPath);
+ }
+
Array 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);
+ String riderAppPath = directory / TEXT("Rider.app");
+ SearchDirectory(&installations, riderAppPath / TEXT("Contents/Resources"), riderAppPath);
}
// Check the local installer version
- SearchDirectory(&installations, TEXT("/Applications/Rider.app/Contents/Resources"));
+ SearchDirectory(&installations, TEXT("/Applications/Rider.app/Contents/Resources"), TEXT("/Applications/Rider.app"));
+
+ String userFolder;
+ FileSystem::GetSpecialFolderPath(SpecialFolder::Documents, userFolder);
+ String riderAppPath = userFolder / TEXT("../Applications/Rider.app");
+ SearchDirectory(&installations, riderAppPath / TEXT("Contents/Resources"), riderAppPath);
#endif
for (const String& directory : subDirectories)
diff --git a/Source/Engine/Scripting/Internal/ManagedDictionary.cpp b/Source/Engine/Scripting/Internal/ManagedDictionary.cpp
index d2f74e054..3cd4bfd8b 100644
--- a/Source/Engine/Scripting/Internal/ManagedDictionary.cpp
+++ b/Source/Engine/Scripting/Internal/ManagedDictionary.cpp
@@ -15,4 +15,160 @@ MMethod* ManagedDictionary::CreateInstance;
MMethod* ManagedDictionary::AddDictionaryItem;
MMethod* ManagedDictionary::GetDictionaryKeys;
#endif
+
+ManagedDictionary::ManagedDictionary(MObject* instance)
+{
+ Instance = instance;
+
+#if !USE_MONO_AOT
+ // Cache the thunks of the dictionary helper methods
+ if (MakeGenericType == nullptr)
+ {
+ MClass* scriptingClass = Scripting::GetStaticClass();
+ CHECK(scriptingClass);
+
+ MMethod* makeGenericTypeMethod = scriptingClass->GetMethod("MakeGenericType", 2);
+ CHECK(makeGenericTypeMethod);
+ MakeGenericType = (MakeGenericTypeThunk)makeGenericTypeMethod->GetThunk();
+
+ MMethod* createInstanceMethod = StdTypesContainer::Instance()->ActivatorClass->GetMethod("CreateInstance", 2);
+ CHECK(createInstanceMethod);
+ CreateInstance = (CreateInstanceThunk)createInstanceMethod->GetThunk();
+
+ MMethod* addDictionaryItemMethod = scriptingClass->GetMethod("AddDictionaryItem", 3);
+ CHECK(addDictionaryItemMethod);
+ AddDictionaryItem = (AddDictionaryItemThunk)addDictionaryItemMethod->GetThunk();
+
+ MMethod* getDictionaryKeysItemMethod = scriptingClass->GetMethod("GetDictionaryKeys", 1);
+ CHECK(getDictionaryKeysItemMethod);
+ GetDictionaryKeys = (GetDictionaryKeysThunk)getDictionaryKeysItemMethod->GetThunk();
+ }
+#else
+ if (MakeGenericType == nullptr)
+ {
+ MClass* scriptingClass = Scripting::GetStaticClass();
+ CHECK(scriptingClass);
+
+ MakeGenericType = scriptingClass->GetMethod("MakeGenericType", 2);
+ CHECK(MakeGenericType);
+
+ CreateInstance = StdTypesContainer::Instance()->ActivatorClass->GetMethod("CreateInstance", 2);
+ CHECK(CreateInstance);
+
+ AddDictionaryItem = scriptingClass->GetMethod("AddDictionaryItem", 3);
+ CHECK(AddDictionaryItem);
+
+ GetDictionaryKeys = scriptingClass->GetMethod("GetDictionaryKeys", 1);
+ CHECK(GetDictionaryKeys);
+ }
+#endif
+}
+
+MTypeObject* ManagedDictionary::GetClass(MType* keyType, MType* valueType)
+{
+ // Check if the generic type was generated earlier
+ KeyValueType cacheKey = { keyType, valueType };
+ MTypeObject* dictionaryType;
+ if (CachedTypes.TryGet(cacheKey, dictionaryType))
+ return dictionaryType;
+
+ MTypeObject* genericType = MUtils::GetType(StdTypesContainer::Instance()->DictionaryClass);
+#if USE_NETCORE
+ MArray* genericArgs = MCore::Array::New(MCore::TypeCache::IntPtr, 2);
+#else
+ MArray* genericArgs = MCore::Array::New(MCore::TypeCache::Object, 2);
+#endif
+ MTypeObject** genericArgsPtr = MCore::Array::GetAddress(genericArgs);
+ genericArgsPtr[0] = INTERNAL_TYPE_GET_OBJECT(keyType);
+ genericArgsPtr[1] = INTERNAL_TYPE_GET_OBJECT(valueType);
+
+ MObject* exception = nullptr;
+#if !USE_MONO_AOT
+ dictionaryType = MakeGenericType(nullptr, genericType, genericArgs, &exception);
+#else
+ void* params[2];
+ params[0] = genericType;
+ params[1] = genericArgs;
+ dictionaryType = (MTypeObject*)MakeGenericType->Invoke(nullptr, params, &exception);
+#endif
+ if (exception)
+ {
+ MException ex(exception);
+ ex.Log(LogType::Error, TEXT(""));
+ return nullptr;
+ }
+ CachedTypes.Add(cacheKey, dictionaryType);
+ return dictionaryType;
+}
+
+ManagedDictionary ManagedDictionary::New(MType* keyType, MType* valueType)
+{
+ ManagedDictionary result;
+ MTypeObject* dictionaryType = GetClass(keyType, valueType);
+ if (!dictionaryType)
+ return result;
+
+ MObject* exception = nullptr;
+#if !USE_MONO_AOT
+ MObject* instance = CreateInstance(nullptr, dictionaryType, nullptr, &exception);
+#else
+ void* params[2];
+ params[0] = dictionaryType;
+ params[1] = nullptr;
+ MObject* instance = CreateInstance->Invoke(nullptr, params, &exception);
+#endif
+ if (exception)
+ {
+ MException ex(exception);
+ ex.Log(LogType::Error, TEXT(""));
+ return result;
+ }
+
+ result.Instance = instance;
+ return result;
+}
+
+void ManagedDictionary::Add(MObject* key, MObject* value)
+{
+ CHECK(Instance);
+
+ MObject* exception = nullptr;
+#if !USE_MONO_AOT
+ AddDictionaryItem(nullptr, Instance, key, value, &exception);
+#else
+ void* params[3];
+ params[0] = Instance;
+ params[1] = key;
+ params[2] = value;
+ AddDictionaryItem->Invoke(Instance, params, &exception);
+#endif
+ if (exception)
+ {
+ MException ex(exception);
+ ex.Log(LogType::Error, TEXT(""));
+ }
+}
+
+MArray* ManagedDictionary::GetKeys() const
+{
+ CHECK_RETURN(Instance, nullptr);
+#if !USE_MONO_AOT
+ return GetDictionaryKeys(nullptr, Instance, nullptr);
+#else
+ void* params[1];
+ params[0] = Instance;
+ return (MArray*)GetDictionaryKeys->Invoke(nullptr, params, nullptr);
+#endif
+}
+
+MObject* ManagedDictionary::GetValue(MObject* key) const
+{
+ CHECK_RETURN(Instance, nullptr);
+ MClass* klass = MCore::Object::GetClass(Instance);
+ MMethod* getItemMethod = klass->GetMethod("System.Collections.IDictionary.get_Item", 1);
+ CHECK_RETURN(getItemMethod, nullptr);
+ void* params[1];
+ params[0] = key;
+ return getItemMethod->Invoke(Instance, params, nullptr);
+}
#endif
diff --git a/Source/Engine/Scripting/Internal/ManagedDictionary.h b/Source/Engine/Scripting/Internal/ManagedDictionary.h
index 5e2638af7..f4663ac58 100644
--- a/Source/Engine/Scripting/Internal/ManagedDictionary.h
+++ b/Source/Engine/Scripting/Internal/ManagedDictionary.h
@@ -57,53 +57,7 @@ private:
public:
MObject* Instance;
- ManagedDictionary(MObject* instance = nullptr)
- {
- Instance = instance;
-
-#if !USE_MONO_AOT
- // Cache the thunks of the dictionary helper methods
- if (MakeGenericType == nullptr)
- {
- MClass* scriptingClass = Scripting::GetStaticClass();
- CHECK(scriptingClass);
-
- MMethod* makeGenericTypeMethod = scriptingClass->GetMethod("MakeGenericType", 2);
- CHECK(makeGenericTypeMethod);
- MakeGenericType = (MakeGenericTypeThunk)makeGenericTypeMethod->GetThunk();
-
- MMethod* createInstanceMethod = StdTypesContainer::Instance()->ActivatorClass->GetMethod("CreateInstance", 2);
- CHECK(createInstanceMethod);
- CreateInstance = (CreateInstanceThunk)createInstanceMethod->GetThunk();
-
- MMethod* addDictionaryItemMethod = scriptingClass->GetMethod("AddDictionaryItem", 3);
- CHECK(addDictionaryItemMethod);
- AddDictionaryItem = (AddDictionaryItemThunk)addDictionaryItemMethod->GetThunk();
-
- MMethod* getDictionaryKeysItemMethod = scriptingClass->GetMethod("GetDictionaryKeys", 1);
- CHECK(getDictionaryKeysItemMethod);
- GetDictionaryKeys = (GetDictionaryKeysThunk)getDictionaryKeysItemMethod->GetThunk();
- }
-#else
- if (MakeGenericType == nullptr)
- {
- MClass* scriptingClass = Scripting::GetStaticClass();
- CHECK(scriptingClass);
-
- MakeGenericType = scriptingClass->GetMethod("MakeGenericType", 2);
- CHECK(MakeGenericType);
-
- CreateInstance = StdTypesContainer::Instance()->ActivatorClass->GetMethod("CreateInstance", 2);
- CHECK(CreateInstance);
-
- AddDictionaryItem = scriptingClass->GetMethod("AddDictionaryItem", 3);
- CHECK(AddDictionaryItem);
-
- GetDictionaryKeys = scriptingClass->GetMethod("GetDictionaryKeys", 1);
- CHECK(GetDictionaryKeys);
- }
-#endif
- }
+ ManagedDictionary(MObject* instance = nullptr);
template
static MObject* ToManaged(const Dictionary& data, MType* keyType, MType* valueType)
@@ -154,113 +108,15 @@ public:
return result;
}
- static MTypeObject* GetClass(MType* keyType, MType* valueType)
- {
- // Check if the generic type was generated earlier
- KeyValueType cacheKey = { keyType, valueType };
- MTypeObject* dictionaryType;
- if (CachedTypes.TryGet(cacheKey, dictionaryType))
- return dictionaryType;
+ static MTypeObject* GetClass(MType* keyType, MType* valueType);
- MTypeObject* genericType = MUtils::GetType(StdTypesContainer::Instance()->DictionaryClass);
-#if USE_NETCORE
- MArray* genericArgs = MCore::Array::New(MCore::TypeCache::IntPtr, 2);
-#else
- MArray* genericArgs = MCore::Array::New(MCore::TypeCache::Object, 2);
-#endif
- MTypeObject** genericArgsPtr = MCore::Array::GetAddress(genericArgs);
- genericArgsPtr[0] = INTERNAL_TYPE_GET_OBJECT(keyType);
- genericArgsPtr[1] = INTERNAL_TYPE_GET_OBJECT(valueType);
+ static ManagedDictionary New(MType* keyType, MType* valueType);
- MObject* exception = nullptr;
-#if !USE_MONO_AOT
- dictionaryType = MakeGenericType(nullptr, genericType, genericArgs, &exception);
-#else
- void* params[2];
- params[0] = genericType;
- params[1] = genericArgs;
- dictionaryType = (MTypeObject*)MakeGenericType->Invoke(nullptr, params, &exception);
-#endif
- if (exception)
- {
- MException ex(exception);
- ex.Log(LogType::Error, TEXT(""));
- return nullptr;
- }
- CachedTypes.Add(cacheKey, dictionaryType);
- return dictionaryType;
- }
+ void Add(MObject* key, MObject* value);
- static ManagedDictionary New(MType* keyType, MType* valueType)
- {
- ManagedDictionary result;
- MTypeObject* dictionaryType = GetClass(keyType, valueType);
- if (!dictionaryType)
- return result;
+ MArray* GetKeys() const;
- MObject* exception = nullptr;
-#if !USE_MONO_AOT
- MObject* instance = CreateInstance(nullptr, dictionaryType, nullptr, &exception);
-#else
- void* params[2];
- params[0] = dictionaryType;
- params[1] = nullptr;
- MObject* instance = CreateInstance->Invoke(nullptr, params, &exception);
-#endif
- if (exception)
- {
- MException ex(exception);
- ex.Log(LogType::Error, TEXT(""));
- return result;
- }
-
- result.Instance = instance;
- return result;
- }
-
- void Add(MObject* key, MObject* value)
- {
- CHECK(Instance);
-
- MObject* exception = nullptr;
-#if !USE_MONO_AOT
- AddDictionaryItem(nullptr, Instance, key, value, &exception);
-#else
- void* params[3];
- params[0] = Instance;
- params[1] = key;
- params[2] = value;
- AddDictionaryItem->Invoke(Instance, params, &exception);
-#endif
- if (exception)
- {
- MException ex(exception);
- ex.Log(LogType::Error, TEXT(""));
- }
- }
-
- MArray* GetKeys() const
- {
- CHECK_RETURN(Instance, nullptr);
-#if !USE_MONO_AOT
- return GetDictionaryKeys(nullptr, Instance, nullptr);
-#else
- void* params[1];
- params[0] = Instance;
- return (MArray*)GetDictionaryKeys->Invoke(nullptr, params, nullptr);
-#endif
- }
-
- MObject* GetValue(MObject* key) const
- {
- CHECK_RETURN(Instance, nullptr);
- MClass* klass = MCore::Object::GetClass(Instance);
- MMethod* getItemMethod = klass->GetMethod("System.Collections.IDictionary.get_Item", 1);
- CHECK_RETURN(getItemMethod, nullptr);
- void* params[1];
- params[0] = key;
- return getItemMethod->Invoke(Instance, params, nullptr);
- }
+ MObject* GetValue(MObject* key) const;
};
inline uint32 GetHash(const ManagedDictionary::KeyValueType& other)
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
index 433dbdda6..604d501ab 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs
@@ -375,12 +375,16 @@ namespace Flax.Build.Bindings
if (arrayApiType != null && arrayApiType.MarshalAs != null)
arrayTypeInfo = arrayApiType.MarshalAs;
}
- return GenerateCSharpNativeToManaged(buildData, arrayTypeInfo, caller) + "[]";
+ return GenerateCSharpNativeToManaged(buildData, arrayTypeInfo, caller, marshalling) + "[]";
}
// Dictionary
if (typeInfo.Type == "Dictionary" && typeInfo.GenericArgs != null)
- return string.Format("System.Collections.Generic.Dictionary<{0}, {1}>", GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller, marshalling), GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[1], caller, marshalling));
+ {
+ var keyType = marshalling && typeInfo.GenericArgs[0].IsInterfaceRef ? "object" : GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[0], caller, marshalling);
+ var valueType = marshalling && typeInfo.GenericArgs[1].IsInterfaceRef ? "object" : GenerateCSharpNativeToManaged(buildData, typeInfo.GenericArgs[1], caller, marshalling);
+ return string.Format("System.Collections.Generic.Dictionary<{0}, {1}>", keyType, valueType);
+ }
// HashSet
if (typeInfo.Type == "HashSet" && typeInfo.GenericArgs != null)
@@ -554,11 +558,21 @@ namespace Flax.Build.Bindings
{
// Convert array that uses different type for marshalling
var arrayTypeInfo = typeInfo.GenericArgs[0];
+ if (arrayTypeInfo.IsInterfaceRef)
+ return "{0} != null ? FlaxEngine.Interop.NativeInterop.ManagedArrayToGCHandleArray({0}) : null";
var arrayApiType = FindApiTypeInfo(buildData, arrayTypeInfo, caller);
if (arrayApiType != null && arrayApiType.MarshalAs != null)
return $"{{0}}.ConvertArray(x => ({GenerateCSharpNativeToManaged(buildData, arrayApiType.MarshalAs, caller)})x)";
}
return string.Empty;
+ case "Dictionary":
+ if (typeInfo.GenericArgs != null && typeInfo.GenericArgs.Count == 2 && (typeInfo.GenericArgs[0].IsInterfaceRef || typeInfo.GenericArgs[1].IsInterfaceRef))
+ {
+ var keyConverter = typeInfo.GenericArgs[0].IsInterfaceRef ? "(object)x.Key" : "x.Key";
+ var valueConverter = typeInfo.GenericArgs[1].IsInterfaceRef ? "(object)x.Value" : "x.Value";
+ return $"{{0}} != null ? System.Linq.Enumerable.ToDictionary({{0}}, x => {keyConverter}, x => {valueConverter}) : null";
+ }
+ return string.Empty;
default:
// Interface reference property
if (typeInfo.IsInterfaceRef)
@@ -787,8 +801,20 @@ namespace Flax.Build.Bindings
}
#endif
const string interfaceResultName = "__interfaceResult";
+ const string interfaceArrayResultName = "__interfaceArrayResult";
+ const string interfaceDictionaryResultName = "__interfaceDictionaryResult";
var returnInterfaceRef = !functionInfo.Glue.UseReferenceForResult && functionInfo.ReturnType.IsInterfaceRef;
+ var returnInterfaceRefArray = !functionInfo.Glue.UseReferenceForResult &&
+ (functionInfo.ReturnType.Type == "Array" || functionInfo.ReturnType.Type == "Span" || functionInfo.ReturnType.Type == "DataContainer") &&
+ functionInfo.ReturnType.GenericArgs != null &&
+ functionInfo.ReturnType.GenericArgs.Count != 0 &&
+ functionInfo.ReturnType.GenericArgs[0].IsInterfaceRef;
+ var returnInterfaceRefDictionary = !functionInfo.Glue.UseReferenceForResult &&
+ functionInfo.ReturnType.Type == "Dictionary" &&
+ functionInfo.ReturnType.GenericArgs != null &&
+ functionInfo.ReturnType.GenericArgs.Count == 2 &&
+ (functionInfo.ReturnType.GenericArgs[0].IsInterfaceRef || functionInfo.ReturnType.GenericArgs[1].IsInterfaceRef);
if (functionInfo.Glue.UseReferenceForResult)
{
@@ -797,6 +823,14 @@ namespace Flax.Build.Bindings
{
contents.Append("var ").Append(interfaceResultName).Append(" = ");
}
+ else if (returnInterfaceRefArray)
+ {
+ contents.Append("var ").Append(interfaceArrayResultName).Append(" = ");
+ }
+ else if (returnInterfaceRefDictionary)
+ {
+ contents.Append("var ").Append(interfaceDictionaryResultName).Append(" = ");
+ }
else if (!functionInfo.ReturnType.IsVoid)
{
contents.Append("return ");
@@ -872,7 +906,20 @@ namespace Flax.Build.Bindings
var managedType = GenerateCSharpNativeToManaged(buildData, functionInfo.ReturnType.GenericArgs[0], caller);
contents.Append("; return ").Append(interfaceResultName).Append(" != IntPtr.Zero ? Unsafe.As<").Append(managedType).Append(">(ManagedHandle.FromIntPtr(").Append(interfaceResultName).Append(").Target) : null");
}
- if ((functionInfo.ReturnType.Type == "Array" || functionInfo.ReturnType.Type == "Span" || functionInfo.ReturnType.Type == "DataContainer") && functionInfo.ReturnType.GenericArgs != null)
+ else if (returnInterfaceRefArray)
+ {
+ var managedType = GenerateCSharpNativeToManaged(buildData, functionInfo.ReturnType.GenericArgs[0].GenericArgs[0], caller);
+ contents.Append("; return ").Append(interfaceArrayResultName).Append("?.ConvertArray(x => x != IntPtr.Zero ? Unsafe.As<").Append(managedType).Append(">(ManagedHandle.FromIntPtr(x).Target) : null)");
+ }
+ else if (returnInterfaceRefDictionary)
+ {
+ var keyTypeInfo = functionInfo.ReturnType.GenericArgs[0];
+ var valueTypeInfo = functionInfo.ReturnType.GenericArgs[1];
+ var keyConverter = keyTypeInfo.IsInterfaceRef ? $"x.Key != null ? Unsafe.As<{GenerateCSharpNativeToManaged(buildData, keyTypeInfo.GenericArgs[0], caller)}>(x.Key) : null" : "x.Key";
+ var valueConverter = valueTypeInfo.IsInterfaceRef ? $"x.Value != null ? Unsafe.As<{GenerateCSharpNativeToManaged(buildData, valueTypeInfo.GenericArgs[0], caller)}>(x.Value) : null" : "x.Value";
+ contents.Append("; return ").Append(interfaceDictionaryResultName).Append(" != null ? System.Linq.Enumerable.ToDictionary(").Append(interfaceDictionaryResultName).Append(", x => ").Append(keyConverter).Append(", x => ").Append(valueConverter).Append(") : null");
+ }
+ else if ((functionInfo.ReturnType.Type == "Array" || functionInfo.ReturnType.Type == "Span" || functionInfo.ReturnType.Type == "DataContainer") && functionInfo.ReturnType.GenericArgs != null)
{
// Convert array that uses different type for marshalling
var arrayTypeInfo = functionInfo.ReturnType.GenericArgs[0];
@@ -1009,9 +1056,24 @@ namespace Flax.Build.Bindings
{
GenerateCSharpAttributes(buildData, contents, indent, apiTypeInfo, memberInfo.Attributes, memberInfo.Comment, true, useUnmanaged, defaultValue, memberInfo.DeprecatedMessage, defaultValueType);
var memberType = (memberInfo as FieldInfo)?.Type ?? (memberInfo as PropertyInfo)?.Type;
- if (memberType != null && memberType.IsInterfaceRef)
+ var interfaceRefType = memberType;
+ if ((memberType?.Type == "Array" || memberType?.Type == "Span" || memberType?.Type == "DataContainer") &&
+ memberType.GenericArgs != null &&
+ memberType.GenericArgs.Count != 0 &&
+ memberType.GenericArgs[0].IsInterfaceRef)
{
- var attribute = memberType.Type == "SoftObjectInterfaceReference" ? "SoftObjectInterfaceReference" : "ScriptingObjectInterfaceReference";
+ interfaceRefType = memberType.GenericArgs[0];
+ }
+ else if (memberType?.Type == "Dictionary" &&
+ memberType.GenericArgs != null &&
+ memberType.GenericArgs.Count == 2 &&
+ (memberType.GenericArgs[0].IsInterfaceRef || memberType.GenericArgs[1].IsInterfaceRef))
+ {
+ interfaceRefType = memberType.GenericArgs[1].IsInterfaceRef ? memberType.GenericArgs[1] : memberType.GenericArgs[0];
+ }
+ if (interfaceRefType != null && interfaceRefType.IsInterfaceRef)
+ {
+ var attribute = interfaceRefType.Type == "SoftObjectInterfaceReference" ? "SoftObjectInterfaceReference" : "ScriptingObjectInterfaceReference";
contents.Append(indent).Append("[FlaxEngine.").Append(attribute).AppendLine("]");
}
}
diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
index e67bde3af..da53fa78b 100644
--- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
+++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cpp.cs
@@ -656,8 +656,8 @@ namespace Flax.Build.Bindings
{
CppIncludeFiles.Add("Engine/Scripting/Internal/ManagedDictionary.h");
type = "MObject*";
- var keyClass = GenerateCppGetNativeType(buildData, typeInfo.GenericArgs[0], caller, functionInfo);
- var valueClass = GenerateCppGetNativeType(buildData, typeInfo.GenericArgs[1], caller, functionInfo);
+ var keyClass = typeInfo.GenericArgs[0].IsInterfaceRef ? "MCore::TypeCache::Object->GetType()" : GenerateCppGetNativeType(buildData, typeInfo.GenericArgs[0], caller, functionInfo);
+ var valueClass = typeInfo.GenericArgs[1].IsInterfaceRef ? "MCore::TypeCache::Object->GetType()" : GenerateCppGetNativeType(buildData, typeInfo.GenericArgs[1], caller, functionInfo);
return "ManagedDictionary::ToManaged({0}, " + keyClass + ", " + valueClass + ")";
}
@@ -1023,8 +1023,8 @@ namespace Flax.Build.Bindings
if (typeInfo.Type == "Dictionary" && typeInfo.GenericArgs != null)
{
CppIncludeFiles.Add("Engine/Scripting/Internal/ManagedDictionary.h");
- var keyClass = GenerateCppGetNativeType(buildData, typeInfo.GenericArgs[0], caller);
- var valueClass = GenerateCppGetNativeType(buildData, typeInfo.GenericArgs[1], caller);
+ var keyClass = typeInfo.GenericArgs[0].IsInterfaceRef ? "MCore::TypeCache::Object->GetType()" : GenerateCppGetNativeType(buildData, typeInfo.GenericArgs[0], caller);
+ var valueClass = typeInfo.GenericArgs[1].IsInterfaceRef ? "MCore::TypeCache::Object->GetType()" : GenerateCppGetNativeType(buildData, typeInfo.GenericArgs[1], caller);
return $"ManagedDictionary::ToManaged({value}, {keyClass}, {valueClass})";
}