Upd: Array & Dictionary support for the ObjectInterfaceReferences
This commit is contained in:
@@ -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})";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user