Upd: Array & Dictionary support for the ObjectInterfaceReferences

This commit is contained in:
Andrei Gagua
2026-05-24 13:27:46 +03:00
parent f8d436ca75
commit 54a103d840
7 changed files with 272 additions and 168 deletions
@@ -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);
}
@@ -14,6 +14,8 @@ namespace FlaxEditor.CustomEditors
[HideInEditor]
public class DictionaryValueContainer : ValueContainer
{
private readonly object[] _attributes;
/// <summary>
/// The key in the collection.
/// </summary>
@@ -36,9 +38,12 @@ namespace FlaxEditor.CustomEditors
/// <param name="elementType">Type of the collection elements.</param>
/// <param name="key">The key.</param>
/// <param name="values">The collection values.</param>
public DictionaryValueContainer(ScriptType elementType, object key, ValueContainer values)
/// <param name="attributes">The dictionary property attributes to inherit.</param>
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;
}
}
/// <inheritdoc />
public override object[] GetAttributes()
{
return _attributes ?? base.GetAttributes();
}
}
}
@@ -14,6 +14,9 @@
#if PLATFORM_WINDOWS
#include "Engine/Platform/Win32/IncludeWindowsHeaders.h"
#elif PLATFORM_MAC
#include "Engine/Platform/Apple/AppleUtils.h"
#include <AppKit/AppKit.h>
#endif
namespace
@@ -68,10 +71,14 @@ namespace
if (!launcherPath.HasChars() || !FileSystem::FileExists(exePath))
return;
if (launchOverridePath != String::Empty)
installations->Add(New<RiderInstallation>(launchOverridePath, versionMember->value.GetText()));
else
installations->Add(New<RiderInstallation>(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<RiderInstallation>(installPath, versionMember->value.GetText()));
}
#if PLATFORM_WINDOWS
@@ -221,17 +228,29 @@ void RiderCodeEditor::FindEditors(Array<CodeEditor*>* 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<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);
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)
@@ -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<MTypeObject*>(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
@@ -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<typename KeyType, typename ValueType>
static MObject* ToManaged(const Dictionary<KeyType, ValueType>& 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<MTypeObject*>(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)
@@ -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("]");
}
}
@@ -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})";
}