Merge remote-tracking branch 'origin/master' into 1.7

This commit is contained in:
Wojtek Figat
2023-07-24 23:21:03 +02:00
17 changed files with 137 additions and 126 deletions

View File

@@ -80,6 +80,8 @@ namespace FlaxEditor.CustomEditors.Editors
assetType = customType; assetType = customType;
else if (!Content.Settings.GameSettings.OptionalPlatformSettings.Contains(assetReference.TypeName)) else if (!Content.Settings.GameSettings.OptionalPlatformSettings.Contains(assetReference.TypeName))
Debug.LogWarning(string.Format("Unknown asset type '{0}' to use for asset picker filter.", assetReference.TypeName)); Debug.LogWarning(string.Format("Unknown asset type '{0}' to use for asset picker filter.", assetReference.TypeName));
else
assetType = ScriptType.Void;
} }
} }

View File

@@ -475,22 +475,31 @@ namespace FlaxEditor.GUI
if (_type != ScriptType.Null) if (_type != ScriptType.Null)
{ {
// Show asset picker popup // Show asset picker popup
AssetSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item => var popup = AssetSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item =>
{ {
SelectedItem = item; SelectedItem = item;
RootWindow.Focus(); RootWindow.Focus();
Focus(); Focus();
}); });
if (_selected != null)
{
var selectedAssetName = Path.GetFileNameWithoutExtension(_selected.Path);
popup.ScrollToAndHighlightItemByName(selectedAssetName);
}
} }
else else
{ {
// Show content item picker popup // Show content item picker popup
ContentSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item => var popup = ContentSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item =>
{ {
SelectedItem = item; SelectedItem = item;
RootWindow.Focus(); RootWindow.Focus();
Focus(); Focus();
}); });
if (_selectedItem != null)
{
popup.ScrollToAndHighlightItemByName(_selectedItem.ShortName);
}
} }
} }
else if (_selected != null || _selectedItem != null) else if (_selected != null || _selectedItem != null)

View File

@@ -265,6 +265,35 @@ namespace FlaxEditor.GUI
_searchBox.Focus(); _searchBox.Focus();
} }
/// <summary>
/// Scrolls the scroll panel to a specific Item
/// </summary>
/// <param name="item">The item to scroll to.</param>
public void ScrollViewTo(Item item)
{
_scrollPanel.ScrollViewTo(item, true);
}
/// <summary>
/// Scrolls to the item and focuses it by name.
/// </summary>
/// <param name="itemName">The item name.</param>
public void ScrollToAndHighlightItemByName(string itemName)
{
foreach (var child in ItemsPanel.Children)
{
if (child is not ItemsListContextMenu.Item item)
continue;
if (string.Equals(item.Name, itemName, StringComparison.Ordinal))
{
// Highlight and scroll to item
item.Focus();
ScrollViewTo(item);
break;
}
}
}
/// <summary> /// <summary>
/// Sorts the items list (by item name by default). /// Sorts the items list (by item name by default).
/// </summary> /// </summary>

View File

@@ -1,7 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System; using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling; using System.Runtime.InteropServices.Marshalling;
@@ -94,9 +93,11 @@ namespace FlaxEngine
public AnimatedModel Instance; public AnimatedModel Instance;
} }
[HideInEditor]
[CustomMarshaller(typeof(Context), MarshalMode.Default, typeof(ContextMarshaller))] [CustomMarshaller(typeof(Context), MarshalMode.Default, typeof(ContextMarshaller))]
internal static class ContextMarshaller internal static class ContextMarshaller
{ {
[HideInEditor]
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct ContextNative public struct ContextNative
{ {
@@ -116,7 +117,7 @@ namespace FlaxEngine
internal static Context ToManaged(ContextNative managed) internal static Context ToManaged(ContextNative managed)
{ {
return new Context() return new Context
{ {
Graph = managed.Graph, Graph = managed.Graph,
GraphExecutor = managed.GraphExecutor, GraphExecutor = managed.GraphExecutor,
@@ -129,9 +130,10 @@ namespace FlaxEngine
Instance = AnimatedModelMarshaller.ConvertToManaged(managed.Instance), Instance = AnimatedModelMarshaller.ConvertToManaged(managed.Instance),
}; };
} }
internal static ContextNative ToNative(Context managed) internal static ContextNative ToNative(Context managed)
{ {
return new ContextNative() return new ContextNative
{ {
Graph = managed.Graph, Graph = managed.Graph,
GraphExecutor = managed.GraphExecutor, GraphExecutor = managed.GraphExecutor,
@@ -144,6 +146,7 @@ namespace FlaxEngine
Instance = AnimatedModelMarshaller.ConvertToUnmanaged(managed.Instance), Instance = AnimatedModelMarshaller.ConvertToUnmanaged(managed.Instance),
}; };
} }
internal static void Free(ContextNative unmanaged) internal static void Free(ContextNative unmanaged)
{ {
} }
@@ -243,6 +246,12 @@ namespace FlaxEngine
throw new ArgumentNullException(nameof(source)); throw new ArgumentNullException(nameof(source));
if (destination == null) if (destination == null)
throw new ArgumentNullException(nameof(destination)); throw new ArgumentNullException(nameof(destination));
if (source->NodesCount <= 0 || source->NodesCount > 4096)
throw new ArgumentOutOfRangeException(nameof(source));
if (destination->NodesCount <= 0 || destination->NodesCount > 4096)
throw new ArgumentOutOfRangeException(nameof(destination));
if (source->NodesCount != destination->NodesCount)
throw new ArgumentOutOfRangeException();
destination->NodesCount = source->NodesCount; destination->NodesCount = source->NodesCount;
destination->Unused = source->Unused; destination->Unused = source->Unused;
Utils.MemoryCopy(new IntPtr(destination->Nodes), new IntPtr(source->Nodes), (ulong)(source->NodesCount * sizeof(Transform))); Utils.MemoryCopy(new IntPtr(destination->Nodes), new IntPtr(source->Nodes), (ulong)(source->NodesCount * sizeof(Transform)));

View File

@@ -5,7 +5,6 @@
#include "Engine/Scripting/Scripting.h" #include "Engine/Scripting/Scripting.h"
#include "Engine/Scripting/BinaryModule.h" #include "Engine/Scripting/BinaryModule.h"
#include "Engine/Scripting/ManagedCLR/MCore.h" #include "Engine/Scripting/ManagedCLR/MCore.h"
#include "Engine/Scripting/ManagedCLR/MDomain.h"
#include "Engine/Scripting/ManagedCLR/MMethod.h" #include "Engine/Scripting/ManagedCLR/MMethod.h"
#include "Engine/Scripting/ManagedCLR/MClass.h" #include "Engine/Scripting/ManagedCLR/MClass.h"
#include "Engine/Scripting/ManagedCLR/MUtils.h" #include "Engine/Scripting/ManagedCLR/MUtils.h"
@@ -189,12 +188,8 @@ bool AnimGraph::InitCustomNode(Node* node)
return false; return false;
} }
// Create node values managed array // Initialization can happen on Content Thread so ensure to have runtime attached
MCore::Thread::Attach(); MCore::Thread::Attach();
MArray* values = MCore::Array::New( MCore::TypeCache::Object, node->Values.Count());
MObject** valuesPtr = MCore::Array::GetAddress<MObject*>(values);
for (int32 i = 0; i < node->Values.Count(); i++)
valuesPtr[i] = MUtils::BoxVariant(node->Values[i]);
// Allocate managed node object (create GC handle to prevent destruction) // Allocate managed node object (create GC handle to prevent destruction)
MObject* obj = type->CreateInstance(); MObject* obj = type->CreateInstance();
@@ -202,7 +197,7 @@ bool AnimGraph::InitCustomNode(Node* node)
// Initialize node // Initialize node
InternalInitData initData; InternalInitData initData;
initData.Values = values; initData.Values = MUtils::ToArray(node->Values, MCore::TypeCache::Object);
initData.BaseModel = BaseModel.GetManagedInstance(); initData.BaseModel = BaseModel.GetManagedInstance();
void* params[1]; void* params[1];
params[0] = &initData; params[0] = &initData;
@@ -211,7 +206,6 @@ bool AnimGraph::InitCustomNode(Node* node)
if (exception) if (exception)
{ {
MCore::GCHandle::Free(handleGC); MCore::GCHandle::Free(handleGC);
MException ex(exception); MException ex(exception);
ex.Log(LogType::Warning, TEXT("AnimGraph")); ex.Log(LogType::Warning, TEXT("AnimGraph"));
return false; return false;

View File

@@ -235,8 +235,9 @@ void AnimGraphExecutor::ProcessAnimation(AnimGraphImpulse* nodes, AnimGraphNode*
const float nestedAnimLength = nestedAnim.Anim->GetLength(); const float nestedAnimLength = nestedAnim.Anim->GetLength();
const float nestedAnimDuration = nestedAnim.Anim->GetDuration(); const float nestedAnimDuration = nestedAnim.Anim->GetDuration();
const float nestedAnimSpeed = nestedAnim.Speed * speed; const float nestedAnimSpeed = nestedAnim.Speed * speed;
nestedAnimPos = nestedAnimPos / nestedAnimDuration * nestedAnimSpeed; const float frameRateMatchScale = (float)nestedAnim.Anim->Data.FramesPerSecond / (float)anim->Data.FramesPerSecond;
nestedAnimPrevPos = nestedAnimPrevPos / nestedAnimDuration * nestedAnimSpeed; nestedAnimPos = nestedAnimPos / nestedAnimDuration * nestedAnimSpeed * frameRateMatchScale;
nestedAnimPrevPos = nestedAnimPrevPos / nestedAnimDuration * nestedAnimSpeed * frameRateMatchScale;
GetAnimSamplePos(nestedAnim.Loop, nestedAnimLength, nestedAnim.StartTime, nestedAnimPrevPos, nestedAnimPos, nestedAnimPos, nestedAnimPrevPos); GetAnimSamplePos(nestedAnim.Loop, nestedAnimLength, nestedAnim.StartTime, nestedAnimPrevPos, nestedAnimPos, nestedAnimPos, nestedAnimPrevPos);
ProcessAnimation(nodes, node, true, nestedAnimLength, nestedAnimPos, nestedAnimPrevPos, nestedAnim.Anim, 1.0f, weight, mode); ProcessAnimation(nodes, node, true, nestedAnimLength, nestedAnimPos, nestedAnimPrevPos, nestedAnim.Anim, 1.0f, weight, mode);

View File

@@ -205,9 +205,6 @@ FlaxStorage::~FlaxStorage()
{ {
// Validate if has been disposed // Validate if has been disposed
ASSERT(IsDisposed()); ASSERT(IsDisposed());
// Validate other fields
// Note: disposed storage has no open files
CHECK(_chunksLock == 0); CHECK(_chunksLock == 0);
CHECK(_refCount == 0); CHECK(_refCount == 0);
ASSERT(_chunks.IsEmpty()); ASSERT(_chunks.IsEmpty());
@@ -216,7 +213,6 @@ FlaxStorage::~FlaxStorage()
// Ensure to close any outstanding file handles to prevent file locking in case it failed to load // Ensure to close any outstanding file handles to prevent file locking in case it failed to load
_file.DeleteAll(); _file.DeleteAll();
#endif #endif
} }
FlaxStorage::LockData FlaxStorage::LockSafe() FlaxStorage::LockData FlaxStorage::LockSafe()
@@ -550,11 +546,9 @@ bool FlaxStorage::Load()
} }
break; break;
default: default:
{
LOG(Warning, "Unsupported storage format version: {1}. {0}", ToString(), _version); LOG(Warning, "Unsupported storage format version: {1}. {0}", ToString(), _version);
return true; return true;
} }
}
// Mark as loaded (version number describes 'isLoaded' state) // Mark as loaded (version number describes 'isLoaded' state)
_version = version; _version = version;
@@ -573,7 +567,7 @@ bool FlaxStorage::Reload()
// Perform clean reloading // Perform clean reloading
Dispose(); Dispose();
bool failed = Load(); const bool failed = Load();
OnReloaded(this, failed); OnReloaded(this, failed);
@@ -1434,10 +1428,8 @@ void FlaxFile::GetEntries(Array<Entry>& output) const
void FlaxFile::Dispose() void FlaxFile::Dispose()
{ {
// Base
FlaxStorage::Dispose(); FlaxStorage::Dispose();
// Clean
_asset.ID = Guid::Empty; _asset.ID = Guid::Empty;
} }
@@ -1482,7 +1474,7 @@ bool FlaxPackage::HasAsset(const Guid& id) const
bool FlaxPackage::HasAsset(const AssetInfo& info) const bool FlaxPackage::HasAsset(const AssetInfo& info) const
{ {
ASSERT(_path == info.Path); ASSERT(_path == info.Path);
Entry* e = _entries.TryGet(info.ID); const Entry* e = _entries.TryGet(info.ID);
return e && e->TypeName == info.TypeName; return e && e->TypeName == info.TypeName;
} }
@@ -1511,10 +1503,8 @@ void FlaxPackage::GetEntries(Array<Entry>& output) const
void FlaxPackage::Dispose() void FlaxPackage::Dispose()
{ {
// Base
FlaxStorage::Dispose(); FlaxStorage::Dispose();
// Clean
_entries.Clear(); _entries.Clear();
} }

View File

@@ -72,15 +72,6 @@ public:
return _major; return _major;
} }
/// <summary>
/// Gets the high 16 bits of the revision number.
/// </summary>
/// <returns>A 16-bit signed integer.</returns>
FORCE_INLINE int16 MajorRevision() const
{
return static_cast<int16>(_revision >> 16);
}
/// <summary> /// <summary>
/// Gets the value of the minor component of the version number for the current Version object. /// Gets the value of the minor component of the version number for the current Version object.
/// </summary> /// </summary>
@@ -90,15 +81,6 @@ public:
return _minor; return _minor;
} }
/// <summary>
/// Gets the low 16 bits of the revision number.
/// </summary>
/// <returns>A 16-bit signed integer.</returns>
FORCE_INLINE int16 MinorRevision() const
{
return static_cast<int16>(_revision & 65535);
}
/// <summary> /// <summary>
/// Gets the value of the revision component of the version number for the current Version object. /// Gets the value of the revision component of the version number for the current Version object.
/// </summary> /// </summary>
@@ -126,61 +108,26 @@ public:
return _major == obj._major && _minor == obj._minor && _build == obj._build && _revision == obj._revision; return _major == obj._major && _minor == obj._minor && _build == obj._build && _revision == obj._revision;
} }
/// <summary>
/// Determines whether two specified Version objects are equal.
/// </summary>
/// <param name="other">The other Version object.</param>
/// <returns>True if <paramref name="v1" /> equals <paramref name="v2" />; otherwise, false.</returns>
FORCE_INLINE bool operator==(const Version& other) const FORCE_INLINE bool operator==(const Version& other) const
{ {
return Equals(other); return Equals(other);
} }
FORCE_INLINE bool operator>(const Version& other) const
/// <summary>
/// Determines whether the first specified Version object is greater than the second specified Version object.
/// </summary>
/// <param name="other">The first Version object.</param>
/// <returns>True if <paramref name="v1" /> is greater than <paramref name="v2" />; otherwise, false.</returns>
FORCE_INLINE bool operator >(const Version& other) const
{ {
return other < *this; return other < *this;
} }
FORCE_INLINE bool operator>=(const Version& other) const
/// <summary>
/// Determines whether the first specified Version object is greater than or equal to the second specified Version object.
/// /summary>
/// <param name="other">The other Version object.</param>
/// <returns>True if <paramref name="v1" /> is greater than or equal to <paramref name="v2" />; otherwise, false.</returns>
FORCE_INLINE bool operator >=(const Version& other) const
{ {
return other <= *this; return other <= *this;
} }
/// <summary>
/// Determines whether two specified Version objects are not equal.
/// </summary>
/// <param name="other">The other Version object.</param>
/// <returns>True if <paramref name="v1" /> does not equal <paramref name="v2" />; otherwise, false.</returns>
FORCE_INLINE bool operator!=(const Version& other) const FORCE_INLINE bool operator!=(const Version& other) const
{ {
return !(*this == other); return !(*this == other);
} }
/// <summary>
/// Determines whether the first specified Version object is less than the second specified Version object.
/// </summary>
/// <param name="other">The first other object.</param>
/// <returns>True if <paramref name="v1" /> is less than <paramref name="v2" />; otherwise, false.</returns>
FORCE_INLINE bool operator<(const Version& other) const FORCE_INLINE bool operator<(const Version& other) const
{ {
return CompareTo(other) < 0; return CompareTo(other) < 0;
} }
/// <summary>
/// Determines whether the first specified Version object is less than or equal to the second Version object.
/// </summary>
/// <param name="other">The other Version object.</param>
/// <returns>True if <paramref name="v1" /> is less than or equal to <paramref name="v2" />; otherwise, false.</returns>
FORCE_INLINE bool operator<=(const Version& other) const FORCE_INLINE bool operator<=(const Version& other) const
{ {
return CompareTo(other) <= 0; return CompareTo(other) <= 0;

View File

@@ -274,12 +274,12 @@ namespace FlaxEngine.Interop
#if FLAX_EDITOR #if FLAX_EDITOR
[HideInEditor] [HideInEditor]
#endif #endif
internal static class ManagedString public static class ManagedString
{ {
internal static ManagedHandle EmptyStringHandle = ManagedHandle.Alloc(string.Empty); internal static ManagedHandle EmptyStringHandle = ManagedHandle.Alloc(string.Empty);
[System.Diagnostics.DebuggerStepThrough] [System.Diagnostics.DebuggerStepThrough]
internal static unsafe IntPtr ToNative(string str) public static unsafe IntPtr ToNative(string str)
{ {
if (str == null) if (str == null)
return IntPtr.Zero; return IntPtr.Zero;
@@ -290,7 +290,7 @@ namespace FlaxEngine.Interop
} }
[System.Diagnostics.DebuggerStepThrough] [System.Diagnostics.DebuggerStepThrough]
internal static unsafe IntPtr ToNativeWeak(string str) public static unsafe IntPtr ToNativeWeak(string str)
{ {
if (str == null) if (str == null)
return IntPtr.Zero; return IntPtr.Zero;
@@ -301,7 +301,7 @@ namespace FlaxEngine.Interop
} }
[System.Diagnostics.DebuggerStepThrough] [System.Diagnostics.DebuggerStepThrough]
internal static string ToManaged(IntPtr ptr) public static string ToManaged(IntPtr ptr)
{ {
if (ptr == IntPtr.Zero) if (ptr == IntPtr.Zero)
return null; return null;
@@ -309,7 +309,7 @@ namespace FlaxEngine.Interop
} }
[System.Diagnostics.DebuggerStepThrough] [System.Diagnostics.DebuggerStepThrough]
internal static void Free(IntPtr ptr) public static void Free(IntPtr ptr)
{ {
if (ptr == IntPtr.Zero) if (ptr == IntPtr.Zero)
return; return;

View File

@@ -444,7 +444,7 @@ namespace FlaxEngine.Interop
} }
else else
{ {
toManagedFieldMethod = typeof(MarshalHelper<>.ReferenceTypeField<>).MakeGenericType(type, fieldType).GetMethod(nameof(MarshalHelper<T>.ReferenceTypeField<ReferenceTypePlaceholder>.ToManagedField), bindingFlags); toManagedFieldMethod = typeof(MarshalHelper<>.ReferenceTypeField<>).MakeGenericType(type, arrayElementType).GetMethod(nameof(MarshalHelper<T>.ReferenceTypeField<ReferenceTypePlaceholder>.ToManagedFieldArray), bindingFlags);
toNativeFieldMethod = typeof(MarshalHelper<>.ReferenceTypeField<>).MakeGenericType(type, fieldType).GetMethod(nameof(MarshalHelper<T>.ReferenceTypeField<ReferenceTypePlaceholder>.ToNativeField), bindingFlags); toNativeFieldMethod = typeof(MarshalHelper<>.ReferenceTypeField<>).MakeGenericType(type, fieldType).GetMethod(nameof(MarshalHelper<T>.ReferenceTypeField<ReferenceTypePlaceholder>.ToNativeField), bindingFlags);
} }
} }
@@ -663,6 +663,17 @@ namespace FlaxEngine.Interop
MarshalHelperReferenceType<TField>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(fieldPtr.ToPointer()), false); MarshalHelperReferenceType<TField>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(fieldPtr.ToPointer()), false);
} }
internal static void ToManagedFieldArray(FieldInfo field, ref T fieldOwner, IntPtr fieldPtr, out int fieldOffset)
{
fieldOffset = Unsafe.SizeOf<IntPtr>();
IntPtr fieldStartPtr = fieldPtr;
fieldPtr = EnsureAlignment(fieldPtr, IntPtr.Size);
fieldOffset += (fieldPtr - fieldStartPtr).ToInt32();
ref TField[] fieldValueRef = ref GetFieldReference<TField[]>(field, ref fieldOwner);
MarshalHelperReferenceType<TField>.ToManagedArray(ref fieldValueRef, Unsafe.Read<IntPtr>(fieldPtr.ToPointer()), false);
}
internal static void ToNativeField(FieldInfo field, ref T fieldOwner, IntPtr fieldPtr, out int fieldOffset) internal static void ToNativeField(FieldInfo field, ref T fieldOwner, IntPtr fieldPtr, out int fieldOffset)
{ {
fieldOffset = Unsafe.SizeOf<IntPtr>(); fieldOffset = Unsafe.SizeOf<IntPtr>();
@@ -691,14 +702,15 @@ namespace FlaxEngine.Interop
internal static void ToManaged(ref T managedValue, IntPtr nativePtr, bool byRef) internal static void ToManaged(ref T managedValue, IntPtr nativePtr, bool byRef)
{ {
Type type = typeof(T); Type type = typeof(T);
if (type.IsByRef || byRef) byRef |= type.IsByRef;
if (byRef)
{ {
if (type.IsByRef) if (type.IsByRef)
type = type.GetElementType(); type = type.GetElementType();
Assert.IsTrue(type.IsValueType); Assert.IsTrue(type.IsValueType);
} }
if (type == typeof(IntPtr)) if (type == typeof(IntPtr) && byRef)
managedValue = (T)(object)nativePtr; managedValue = (T)(object)nativePtr;
else if (type == typeof(ManagedHandle)) else if (type == typeof(ManagedHandle))
managedValue = (T)(object)ManagedHandle.FromIntPtr(nativePtr); managedValue = (T)(object)ManagedHandle.FromIntPtr(nativePtr);
@@ -778,10 +790,12 @@ namespace FlaxEngine.Interop
if (type == typeof(string)) if (type == typeof(string))
managedValue = Unsafe.As<T>(ManagedString.ToManaged(nativePtr)); managedValue = Unsafe.As<T>(ManagedString.ToManaged(nativePtr));
else if (nativePtr == IntPtr.Zero)
managedValue = null;
else if (type.IsClass) else if (type.IsClass)
managedValue = nativePtr != IntPtr.Zero ? Unsafe.As<T>(ManagedHandle.FromIntPtr(nativePtr).Target) : null; managedValue = Unsafe.As<T>(ManagedHandle.FromIntPtr(nativePtr).Target);
else if (type.IsInterface) // Dictionary else if (type.IsInterface) // Dictionary
managedValue = nativePtr != IntPtr.Zero ? Unsafe.As<T>(ManagedHandle.FromIntPtr(nativePtr).Target) : null; managedValue = Unsafe.As<T>(ManagedHandle.FromIntPtr(nativePtr).Target);
else else
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@@ -108,7 +108,7 @@ void ManagedSerialization::Deserialize(const StringAnsiView& data, MObject* obje
// Prepare arguments // Prepare arguments
void* args[3]; void* args[3];
args[0] = object; args[0] = object;
args[1] = (void*)str; args[1] = (void*)&str;
args[2] = (void*)&len; args[2] = (void*)&len;
// Call serialization tool // Call serialization tool

View File

@@ -3,7 +3,6 @@
#include "MUtils.h" #include "MUtils.h"
#include "MClass.h" #include "MClass.h"
#include "MCore.h" #include "MCore.h"
#include "MDomain.h"
#include "Engine/Core/Log.h" #include "Engine/Core/Log.h"
#include "Engine/Core/Types/DataContainer.h" #include "Engine/Core/Types/DataContainer.h"
#include "Engine/Core/Types/Version.h" #include "Engine/Core/Types/Version.h"
@@ -449,7 +448,7 @@ Variant MUtils::UnboxVariant(MObject* value)
{ {
auto& a = array[i]; auto& a = array[i];
a.SetType(elementType); a.SetType(elementType);
Platform::MemoryCopy(&a.AsData,(byte*)ptr + elementSize * i, elementSize); Platform::MemoryCopy(&a.AsData, (byte*)ptr + elementSize * i, elementSize);
} }
break; break;
case VariantType::Transform: case VariantType::Transform:
@@ -1004,11 +1003,11 @@ MClass* MUtils::GetClass(const Variant& value)
case VariantType::Enum: case VariantType::Enum:
return Scripting::FindClass(StringAnsiView(value.Type.TypeName)); return Scripting::FindClass(StringAnsiView(value.Type.TypeName));
case VariantType::ManagedObject: case VariantType::ManagedObject:
{ {
MObject* obj = (MObject*)value; MObject* obj = (MObject*)value;
if (obj) if (obj)
return MCore::Object::GetClass(obj); return MCore::Object::GetClass(obj);
} }
default: ; default: ;
} }
return GetClass(value.Type); return GetClass(value.Type);
@@ -1224,10 +1223,10 @@ MObject* MUtils::ToManaged(const Version& value)
auto versionToManaged = scriptingClass->GetMethod("VersionToManaged", 4); auto versionToManaged = scriptingClass->GetMethod("VersionToManaged", 4);
CHECK_RETURN(versionToManaged, nullptr); CHECK_RETURN(versionToManaged, nullptr);
int major = value.Major(); int32 major = value.Major();
int minor = value.Minor(); int32 minor = value.Minor();
int build = value.Build(); int32 build = value.Build();
int revision = value.Revision(); int32 revision = value.Revision();
void* params[4]; void* params[4];
params[0] = &major; params[0] = &major;
@@ -1244,26 +1243,29 @@ MObject* MUtils::ToManaged(const Version& value)
Version MUtils::ToNative(MObject* value) Version MUtils::ToNative(MObject* value)
{ {
Version result;
if (value) if (value)
#if USE_NETCORE #if USE_NETCORE
{ {
auto ver = Version();
auto scriptingClass = Scripting::GetStaticClass(); auto scriptingClass = Scripting::GetStaticClass();
CHECK_RETURN(scriptingClass, ver); CHECK_RETURN(scriptingClass, result);
auto versionToNative = scriptingClass->GetMethod("VersionToNative", 2); auto versionToNative = scriptingClass->GetMethod("VersionToNative", 5);
CHECK_RETURN(versionToNative, ver); CHECK_RETURN(versionToNative, result);
void* params[2]; void* params[5];
params[0] = value; params[0] = value;
params[1] = &ver; params[1] = (byte*)&result;
params[2] = (byte*)&result + sizeof(int32);
params[3] = (byte*)&result + sizeof(int32) * 2;
params[4] = (byte*)&result + sizeof(int32) * 3;
versionToNative->Invoke(nullptr, params, nullptr); versionToNative->Invoke(nullptr, params, nullptr);
return ver;
return result;
} }
#else #else
return *(Version*)MCore::Object::Unbox(value); return *(Version*)MCore::Object::Unbox(value);
#endif #endif
return Version(); return result;
} }
#endif #endif

View File

@@ -229,22 +229,24 @@ namespace FlaxEngine
return ManagedHandle.Alloc(new CultureInfo(lcid)); return ManagedHandle.Alloc(new CultureInfo(lcid));
} }
internal static void VersionToNative(ManagedHandle versionHandle, IntPtr nativePtr) [StructLayout(LayoutKind.Sequential)]
internal struct VersionNative
{
public int Major;
public int Minor;
public int Build;
public int Revision;
}
internal static void VersionToNative(ManagedHandle versionHandle, ref int major, ref int minor, ref int build, ref int revision)
{ {
Version version = Unsafe.As<Version>(versionHandle.Target); Version version = Unsafe.As<Version>(versionHandle.Target);
if (version != null) if (version != null)
{ {
Marshal.WriteInt32(nativePtr, 0, version.Major); major = version.Major;
Marshal.WriteInt32(nativePtr, 4, version.Minor); minor = version.Minor;
Marshal.WriteInt32(nativePtr, 8, version.Build); build = version.Build;
Marshal.WriteInt32(nativePtr, 12, version.Revision); revision = version.Revision;
}
else
{
Marshal.WriteInt32(nativePtr, 0, 0);
Marshal.WriteInt32(nativePtr, 4, 0);
Marshal.WriteInt32(nativePtr, 8, -1);
Marshal.WriteInt32(nativePtr, 12, -1);
} }
} }

View File

@@ -1203,6 +1203,8 @@ namespace Flax.Build.Bindings
contents.Append("ref "); contents.Append("ref ");
else if (parameterInfo.IsThis) else if (parameterInfo.IsThis)
contents.Append("this "); contents.Append("this ");
else if (parameterInfo.IsParams)
contents.Append("params ");
contents.Append(managedType); contents.Append(managedType);
contents.Append(' '); contents.Append(' ');
contents.Append(parameterInfo.Name); contents.Append(parameterInfo.Name);
@@ -1263,6 +1265,8 @@ namespace Flax.Build.Bindings
contents.Append("ref "); contents.Append("ref ");
else if (parameterInfo.IsThis) else if (parameterInfo.IsThis)
contents.Append("this "); contents.Append("this ");
else if (parameterInfo.IsParams)
contents.Append("params ");
contents.Append(managedType); contents.Append(managedType);
contents.Append(' '); contents.Append(' ');
contents.Append(parameterInfo.Name); contents.Append(parameterInfo.Name);
@@ -1988,6 +1992,8 @@ namespace Flax.Build.Bindings
contents.Append("ref "); contents.Append("ref ");
else if (parameterInfo.IsThis) else if (parameterInfo.IsThis)
contents.Append("this "); contents.Append("this ");
else if (parameterInfo.IsParams)
contents.Append("params ");
contents.Append(managedType); contents.Append(managedType);
contents.Append(' '); contents.Append(' ');
contents.Append(parameterInfo.Name); contents.Append(parameterInfo.Name);

View File

@@ -19,7 +19,7 @@ namespace Flax.Build.Bindings
partial class BindingsGenerator partial class BindingsGenerator
{ {
private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>(); private static readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
private const int CacheVersion = 18; private const int CacheVersion = 19;
internal static void Write(BinaryWriter writer, string e) internal static void Write(BinaryWriter writer, string e)
{ {

View File

@@ -337,6 +337,9 @@ namespace Flax.Build.Bindings
case "this": case "this":
currentParam.IsThis = true; currentParam.IsThis = true;
break; break;
case "params":
currentParam.IsParams = true;
break;
case "attributes": case "attributes":
currentParam.Attributes = tag.Value; currentParam.Attributes = tag.Value;
break; break;

View File

@@ -19,6 +19,7 @@ namespace Flax.Build.Bindings
public bool IsRef; public bool IsRef;
public bool IsOut; public bool IsOut;
public bool IsThis; public bool IsThis;
public bool IsParams;
public bool HasDefaultValue => !string.IsNullOrEmpty(DefaultValue); public bool HasDefaultValue => !string.IsNullOrEmpty(DefaultValue);
@@ -37,6 +38,7 @@ namespace Flax.Build.Bindings
writer.Write(IsRef); writer.Write(IsRef);
writer.Write(IsOut); writer.Write(IsOut);
writer.Write(IsThis); writer.Write(IsThis);
writer.Write(IsParams);
} }
public void Read(BinaryReader reader) public void Read(BinaryReader reader)
@@ -49,6 +51,7 @@ namespace Flax.Build.Bindings
IsRef = reader.ReadBoolean(); IsRef = reader.ReadBoolean();
IsOut = reader.ReadBoolean(); IsOut = reader.ReadBoolean();
IsThis = reader.ReadBoolean(); IsThis = reader.ReadBoolean();
IsParams = reader.ReadBoolean();
} }
public override string ToString() public override string ToString()