diff --git a/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs b/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs index e89c80372..cfba940c2 100644 --- a/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs +++ b/Source/Editor/CustomEditors/Editors/AssetRefEditor.cs @@ -80,6 +80,8 @@ namespace FlaxEditor.CustomEditors.Editors assetType = customType; 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)); + else + assetType = ScriptType.Void; } } diff --git a/Source/Editor/GUI/AssetPicker.cs b/Source/Editor/GUI/AssetPicker.cs index bfded5380..3e5d22eb0 100644 --- a/Source/Editor/GUI/AssetPicker.cs +++ b/Source/Editor/GUI/AssetPicker.cs @@ -475,22 +475,31 @@ namespace FlaxEditor.GUI if (_type != ScriptType.Null) { // Show asset picker popup - AssetSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item => + var popup = AssetSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item => { SelectedItem = item; RootWindow.Focus(); Focus(); }); + if (_selected != null) + { + var selectedAssetName = Path.GetFileNameWithoutExtension(_selected.Path); + popup.ScrollToAndHighlightItemByName(selectedAssetName); + } } else { // Show content item picker popup - ContentSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item => + var popup = ContentSearchPopup.Show(this, Button1Rect.BottomLeft, IsValid, item => { SelectedItem = item; RootWindow.Focus(); Focus(); }); + if (_selectedItem != null) + { + popup.ScrollToAndHighlightItemByName(_selectedItem.ShortName); + } } } else if (_selected != null || _selectedItem != null) diff --git a/Source/Editor/GUI/ItemsListContextMenu.cs b/Source/Editor/GUI/ItemsListContextMenu.cs index ae470235d..42d236991 100644 --- a/Source/Editor/GUI/ItemsListContextMenu.cs +++ b/Source/Editor/GUI/ItemsListContextMenu.cs @@ -265,6 +265,35 @@ namespace FlaxEditor.GUI _searchBox.Focus(); } + /// + /// Scrolls the scroll panel to a specific Item + /// + /// The item to scroll to. + public void ScrollViewTo(Item item) + { + _scrollPanel.ScrollViewTo(item, true); + } + + /// + /// Scrolls to the item and focuses it by name. + /// + /// The item name. + 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; + } + } + } + /// /// Sorts the items list (by item name by default). /// diff --git a/Source/Engine/Animations/AnimationGraph.cs b/Source/Engine/Animations/AnimationGraph.cs index 46b3acfc1..2e26b8370 100644 --- a/Source/Engine/Animations/AnimationGraph.cs +++ b/Source/Engine/Animations/AnimationGraph.cs @@ -1,7 +1,6 @@ // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using System; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; @@ -94,9 +93,11 @@ namespace FlaxEngine public AnimatedModel Instance; } + [HideInEditor] [CustomMarshaller(typeof(Context), MarshalMode.Default, typeof(ContextMarshaller))] internal static class ContextMarshaller { + [HideInEditor] [StructLayout(LayoutKind.Sequential)] public struct ContextNative { @@ -116,7 +117,7 @@ namespace FlaxEngine internal static Context ToManaged(ContextNative managed) { - return new Context() + return new Context { Graph = managed.Graph, GraphExecutor = managed.GraphExecutor, @@ -129,9 +130,10 @@ namespace FlaxEngine Instance = AnimatedModelMarshaller.ConvertToManaged(managed.Instance), }; } + internal static ContextNative ToNative(Context managed) { - return new ContextNative() + return new ContextNative { Graph = managed.Graph, GraphExecutor = managed.GraphExecutor, @@ -144,6 +146,7 @@ namespace FlaxEngine Instance = AnimatedModelMarshaller.ConvertToUnmanaged(managed.Instance), }; } + internal static void Free(ContextNative unmanaged) { } @@ -243,6 +246,12 @@ namespace FlaxEngine throw new ArgumentNullException(nameof(source)); if (destination == null) 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->Unused = source->Unused; Utils.MemoryCopy(new IntPtr(destination->Nodes), new IntPtr(source->Nodes), (ulong)(source->NodesCount * sizeof(Transform))); diff --git a/Source/Engine/Animations/Graph/AnimGraph.Custom.cpp b/Source/Engine/Animations/Graph/AnimGraph.Custom.cpp index d74c523f1..cdd5b03eb 100644 --- a/Source/Engine/Animations/Graph/AnimGraph.Custom.cpp +++ b/Source/Engine/Animations/Graph/AnimGraph.Custom.cpp @@ -5,7 +5,6 @@ #include "Engine/Scripting/Scripting.h" #include "Engine/Scripting/BinaryModule.h" #include "Engine/Scripting/ManagedCLR/MCore.h" -#include "Engine/Scripting/ManagedCLR/MDomain.h" #include "Engine/Scripting/ManagedCLR/MMethod.h" #include "Engine/Scripting/ManagedCLR/MClass.h" #include "Engine/Scripting/ManagedCLR/MUtils.h" @@ -189,12 +188,8 @@ bool AnimGraph::InitCustomNode(Node* node) return false; } - // Create node values managed array + // Initialization can happen on Content Thread so ensure to have runtime attached MCore::Thread::Attach(); - MArray* values = MCore::Array::New( MCore::TypeCache::Object, node->Values.Count()); - MObject** valuesPtr = MCore::Array::GetAddress(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) MObject* obj = type->CreateInstance(); @@ -202,7 +197,7 @@ bool AnimGraph::InitCustomNode(Node* node) // Initialize node InternalInitData initData; - initData.Values = values; + initData.Values = MUtils::ToArray(node->Values, MCore::TypeCache::Object); initData.BaseModel = BaseModel.GetManagedInstance(); void* params[1]; params[0] = &initData; @@ -211,7 +206,6 @@ bool AnimGraph::InitCustomNode(Node* node) if (exception) { MCore::GCHandle::Free(handleGC); - MException ex(exception); ex.Log(LogType::Warning, TEXT("AnimGraph")); return false; diff --git a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp index 31b97fb52..82842376e 100644 --- a/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp +++ b/Source/Engine/Animations/Graph/AnimGroup.Animation.cpp @@ -235,8 +235,9 @@ void AnimGraphExecutor::ProcessAnimation(AnimGraphImpulse* nodes, AnimGraphNode* const float nestedAnimLength = nestedAnim.Anim->GetLength(); const float nestedAnimDuration = nestedAnim.Anim->GetDuration(); const float nestedAnimSpeed = nestedAnim.Speed * speed; - nestedAnimPos = nestedAnimPos / nestedAnimDuration * nestedAnimSpeed; - nestedAnimPrevPos = nestedAnimPrevPos / nestedAnimDuration * nestedAnimSpeed; + const float frameRateMatchScale = (float)nestedAnim.Anim->Data.FramesPerSecond / (float)anim->Data.FramesPerSecond; + nestedAnimPos = nestedAnimPos / nestedAnimDuration * nestedAnimSpeed * frameRateMatchScale; + nestedAnimPrevPos = nestedAnimPrevPos / nestedAnimDuration * nestedAnimSpeed * frameRateMatchScale; GetAnimSamplePos(nestedAnim.Loop, nestedAnimLength, nestedAnim.StartTime, nestedAnimPrevPos, nestedAnimPos, nestedAnimPos, nestedAnimPrevPos); ProcessAnimation(nodes, node, true, nestedAnimLength, nestedAnimPos, nestedAnimPrevPos, nestedAnim.Anim, 1.0f, weight, mode); diff --git a/Source/Engine/Content/Storage/FlaxStorage.cpp b/Source/Engine/Content/Storage/FlaxStorage.cpp index 52d7c34b5..d530e5456 100644 --- a/Source/Engine/Content/Storage/FlaxStorage.cpp +++ b/Source/Engine/Content/Storage/FlaxStorage.cpp @@ -205,9 +205,6 @@ FlaxStorage::~FlaxStorage() { // Validate if has been disposed ASSERT(IsDisposed()); - - // Validate other fields - // Note: disposed storage has no open files CHECK(_chunksLock == 0); CHECK(_refCount == 0); 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 _file.DeleteAll(); #endif - } FlaxStorage::LockData FlaxStorage::LockSafe() @@ -550,11 +546,9 @@ bool FlaxStorage::Load() } break; default: - { LOG(Warning, "Unsupported storage format version: {1}. {0}", ToString(), _version); return true; } - } // Mark as loaded (version number describes 'isLoaded' state) _version = version; @@ -573,7 +567,7 @@ bool FlaxStorage::Reload() // Perform clean reloading Dispose(); - bool failed = Load(); + const bool failed = Load(); OnReloaded(this, failed); @@ -1434,10 +1428,8 @@ void FlaxFile::GetEntries(Array& output) const void FlaxFile::Dispose() { - // Base FlaxStorage::Dispose(); - // Clean _asset.ID = Guid::Empty; } @@ -1482,7 +1474,7 @@ bool FlaxPackage::HasAsset(const Guid& id) const bool FlaxPackage::HasAsset(const AssetInfo& info) const { ASSERT(_path == info.Path); - Entry* e = _entries.TryGet(info.ID); + const Entry* e = _entries.TryGet(info.ID); return e && e->TypeName == info.TypeName; } @@ -1511,10 +1503,8 @@ void FlaxPackage::GetEntries(Array& output) const void FlaxPackage::Dispose() { - // Base FlaxStorage::Dispose(); - // Clean _entries.Clear(); } diff --git a/Source/Engine/Core/Types/Version.h b/Source/Engine/Core/Types/Version.h index 57c6e10fe..1dc36ea38 100644 --- a/Source/Engine/Core/Types/Version.h +++ b/Source/Engine/Core/Types/Version.h @@ -72,15 +72,6 @@ public: return _major; } - /// - /// Gets the high 16 bits of the revision number. - /// - /// A 16-bit signed integer. - FORCE_INLINE int16 MajorRevision() const - { - return static_cast(_revision >> 16); - } - /// /// Gets the value of the minor component of the version number for the current Version object. /// @@ -90,15 +81,6 @@ public: return _minor; } - /// - /// Gets the low 16 bits of the revision number. - /// - /// A 16-bit signed integer. - FORCE_INLINE int16 MinorRevision() const - { - return static_cast(_revision & 65535); - } - /// /// Gets the value of the revision component of the version number for the current Version object. /// @@ -126,61 +108,26 @@ public: return _major == obj._major && _minor == obj._minor && _build == obj._build && _revision == obj._revision; } - /// - /// Determines whether two specified Version objects are equal. - /// - /// The other Version object. - /// True if equals ; otherwise, false. FORCE_INLINE bool operator==(const Version& other) const { return Equals(other); } - - /// - /// Determines whether the first specified Version object is greater than the second specified Version object. - /// - /// The first Version object. - /// True if is greater than ; otherwise, false. - FORCE_INLINE bool operator >(const Version& other) const + FORCE_INLINE bool operator>(const Version& other) const { return other < *this; } - - /// - /// Determines whether the first specified Version object is greater than or equal to the second specified Version object. - /// /summary> - /// The other Version object. - /// True if is greater than or equal to ; otherwise, false. - FORCE_INLINE bool operator >=(const Version& other) const + FORCE_INLINE bool operator>=(const Version& other) const { return other <= *this; } - - /// - /// Determines whether two specified Version objects are not equal. - /// - /// The other Version object. - /// True if does not equal ; otherwise, false. FORCE_INLINE bool operator!=(const Version& other) const { return !(*this == other); } - - /// - /// Determines whether the first specified Version object is less than the second specified Version object. - /// - /// The first other object. - /// True if is less than ; otherwise, false. FORCE_INLINE bool operator<(const Version& other) const { return CompareTo(other) < 0; } - - /// - /// Determines whether the first specified Version object is less than or equal to the second Version object. - /// - /// The other Version object. - /// True if is less than or equal to ; otherwise, false. FORCE_INLINE bool operator<=(const Version& other) const { return CompareTo(other) <= 0; diff --git a/Source/Engine/Engine/NativeInterop.Managed.cs b/Source/Engine/Engine/NativeInterop.Managed.cs index 797b02d5b..95146a95c 100644 --- a/Source/Engine/Engine/NativeInterop.Managed.cs +++ b/Source/Engine/Engine/NativeInterop.Managed.cs @@ -274,12 +274,12 @@ namespace FlaxEngine.Interop #if FLAX_EDITOR [HideInEditor] #endif - internal static class ManagedString + public static class ManagedString { internal static ManagedHandle EmptyStringHandle = ManagedHandle.Alloc(string.Empty); [System.Diagnostics.DebuggerStepThrough] - internal static unsafe IntPtr ToNative(string str) + public static unsafe IntPtr ToNative(string str) { if (str == null) return IntPtr.Zero; @@ -290,7 +290,7 @@ namespace FlaxEngine.Interop } [System.Diagnostics.DebuggerStepThrough] - internal static unsafe IntPtr ToNativeWeak(string str) + public static unsafe IntPtr ToNativeWeak(string str) { if (str == null) return IntPtr.Zero; @@ -301,7 +301,7 @@ namespace FlaxEngine.Interop } [System.Diagnostics.DebuggerStepThrough] - internal static string ToManaged(IntPtr ptr) + public static string ToManaged(IntPtr ptr) { if (ptr == IntPtr.Zero) return null; @@ -309,7 +309,7 @@ namespace FlaxEngine.Interop } [System.Diagnostics.DebuggerStepThrough] - internal static void Free(IntPtr ptr) + public static void Free(IntPtr ptr) { if (ptr == IntPtr.Zero) return; diff --git a/Source/Engine/Engine/NativeInterop.cs b/Source/Engine/Engine/NativeInterop.cs index acfd7181b..da372ac90 100644 --- a/Source/Engine/Engine/NativeInterop.cs +++ b/Source/Engine/Engine/NativeInterop.cs @@ -444,7 +444,7 @@ namespace FlaxEngine.Interop } else { - toManagedFieldMethod = typeof(MarshalHelper<>.ReferenceTypeField<>).MakeGenericType(type, fieldType).GetMethod(nameof(MarshalHelper.ReferenceTypeField.ToManagedField), bindingFlags); + toManagedFieldMethod = typeof(MarshalHelper<>.ReferenceTypeField<>).MakeGenericType(type, arrayElementType).GetMethod(nameof(MarshalHelper.ReferenceTypeField.ToManagedFieldArray), bindingFlags); toNativeFieldMethod = typeof(MarshalHelper<>.ReferenceTypeField<>).MakeGenericType(type, fieldType).GetMethod(nameof(MarshalHelper.ReferenceTypeField.ToNativeField), bindingFlags); } } @@ -663,6 +663,17 @@ namespace FlaxEngine.Interop MarshalHelperReferenceType.ToManaged(ref fieldValueRef, Unsafe.Read(fieldPtr.ToPointer()), false); } + internal static void ToManagedFieldArray(FieldInfo field, ref T fieldOwner, IntPtr fieldPtr, out int fieldOffset) + { + fieldOffset = Unsafe.SizeOf(); + IntPtr fieldStartPtr = fieldPtr; + fieldPtr = EnsureAlignment(fieldPtr, IntPtr.Size); + fieldOffset += (fieldPtr - fieldStartPtr).ToInt32(); + + ref TField[] fieldValueRef = ref GetFieldReference(field, ref fieldOwner); + MarshalHelperReferenceType.ToManagedArray(ref fieldValueRef, Unsafe.Read(fieldPtr.ToPointer()), false); + } + internal static void ToNativeField(FieldInfo field, ref T fieldOwner, IntPtr fieldPtr, out int fieldOffset) { fieldOffset = Unsafe.SizeOf(); @@ -691,14 +702,15 @@ namespace FlaxEngine.Interop internal static void ToManaged(ref T managedValue, IntPtr nativePtr, bool byRef) { Type type = typeof(T); - if (type.IsByRef || byRef) + byRef |= type.IsByRef; + if (byRef) { if (type.IsByRef) type = type.GetElementType(); Assert.IsTrue(type.IsValueType); } - if (type == typeof(IntPtr)) + if (type == typeof(IntPtr) && byRef) managedValue = (T)(object)nativePtr; else if (type == typeof(ManagedHandle)) managedValue = (T)(object)ManagedHandle.FromIntPtr(nativePtr); @@ -778,10 +790,12 @@ namespace FlaxEngine.Interop if (type == typeof(string)) managedValue = Unsafe.As(ManagedString.ToManaged(nativePtr)); + else if (nativePtr == IntPtr.Zero) + managedValue = null; else if (type.IsClass) - managedValue = nativePtr != IntPtr.Zero ? Unsafe.As(ManagedHandle.FromIntPtr(nativePtr).Target) : null; + managedValue = Unsafe.As(ManagedHandle.FromIntPtr(nativePtr).Target); else if (type.IsInterface) // Dictionary - managedValue = nativePtr != IntPtr.Zero ? Unsafe.As(ManagedHandle.FromIntPtr(nativePtr).Target) : null; + managedValue = Unsafe.As(ManagedHandle.FromIntPtr(nativePtr).Target); else throw new NotImplementedException(); } diff --git a/Source/Engine/Scripting/Internal/ManagedSerialization.cpp b/Source/Engine/Scripting/Internal/ManagedSerialization.cpp index f1543a326..f5ea46b5e 100644 --- a/Source/Engine/Scripting/Internal/ManagedSerialization.cpp +++ b/Source/Engine/Scripting/Internal/ManagedSerialization.cpp @@ -108,7 +108,7 @@ void ManagedSerialization::Deserialize(const StringAnsiView& data, MObject* obje // Prepare arguments void* args[3]; args[0] = object; - args[1] = (void*)str; + args[1] = (void*)&str; args[2] = (void*)&len; // Call serialization tool diff --git a/Source/Engine/Scripting/ManagedCLR/MUtils.cpp b/Source/Engine/Scripting/ManagedCLR/MUtils.cpp index d97ff92cd..be8e10fab 100644 --- a/Source/Engine/Scripting/ManagedCLR/MUtils.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MUtils.cpp @@ -3,7 +3,6 @@ #include "MUtils.h" #include "MClass.h" #include "MCore.h" -#include "MDomain.h" #include "Engine/Core/Log.h" #include "Engine/Core/Types/DataContainer.h" #include "Engine/Core/Types/Version.h" @@ -449,7 +448,7 @@ Variant MUtils::UnboxVariant(MObject* value) { auto& a = array[i]; a.SetType(elementType); - Platform::MemoryCopy(&a.AsData,(byte*)ptr + elementSize * i, elementSize); + Platform::MemoryCopy(&a.AsData, (byte*)ptr + elementSize * i, elementSize); } break; case VariantType::Transform: @@ -1004,11 +1003,11 @@ MClass* MUtils::GetClass(const Variant& value) case VariantType::Enum: return Scripting::FindClass(StringAnsiView(value.Type.TypeName)); case VariantType::ManagedObject: - { - MObject* obj = (MObject*)value; - if (obj) - return MCore::Object::GetClass(obj); - } + { + MObject* obj = (MObject*)value; + if (obj) + return MCore::Object::GetClass(obj); + } default: ; } return GetClass(value.Type); @@ -1224,10 +1223,10 @@ MObject* MUtils::ToManaged(const Version& value) auto versionToManaged = scriptingClass->GetMethod("VersionToManaged", 4); CHECK_RETURN(versionToManaged, nullptr); - int major = value.Major(); - int minor = value.Minor(); - int build = value.Build(); - int revision = value.Revision(); + int32 major = value.Major(); + int32 minor = value.Minor(); + int32 build = value.Build(); + int32 revision = value.Revision(); void* params[4]; params[0] = &major; @@ -1244,26 +1243,29 @@ MObject* MUtils::ToManaged(const Version& value) Version MUtils::ToNative(MObject* value) { + Version result; if (value) #if USE_NETCORE { - auto ver = Version(); - auto scriptingClass = Scripting::GetStaticClass(); - CHECK_RETURN(scriptingClass, ver); - auto versionToNative = scriptingClass->GetMethod("VersionToNative", 2); - CHECK_RETURN(versionToNative, ver); + CHECK_RETURN(scriptingClass, result); + auto versionToNative = scriptingClass->GetMethod("VersionToNative", 5); + CHECK_RETURN(versionToNative, result); - void* params[2]; + void* params[5]; 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); - return ver; + + return result; } #else return *(Version*)MCore::Object::Unbox(value); #endif - return Version(); + return result; } #endif diff --git a/Source/Engine/Scripting/Scripting.cs b/Source/Engine/Scripting/Scripting.cs index 7a91b2d96..2b49d97d4 100644 --- a/Source/Engine/Scripting/Scripting.cs +++ b/Source/Engine/Scripting/Scripting.cs @@ -229,22 +229,24 @@ namespace FlaxEngine 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(versionHandle.Target); if (version != null) { - Marshal.WriteInt32(nativePtr, 0, version.Major); - Marshal.WriteInt32(nativePtr, 4, version.Minor); - Marshal.WriteInt32(nativePtr, 8, version.Build); - Marshal.WriteInt32(nativePtr, 12, version.Revision); - } - else - { - Marshal.WriteInt32(nativePtr, 0, 0); - Marshal.WriteInt32(nativePtr, 4, 0); - Marshal.WriteInt32(nativePtr, 8, -1); - Marshal.WriteInt32(nativePtr, 12, -1); + major = version.Major; + minor = version.Minor; + build = version.Build; + revision = version.Revision; } } diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs index 920e74f67..087dc898f 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.CSharp.cs @@ -1203,6 +1203,8 @@ namespace Flax.Build.Bindings contents.Append("ref "); else if (parameterInfo.IsThis) contents.Append("this "); + else if (parameterInfo.IsParams) + contents.Append("params "); contents.Append(managedType); contents.Append(' '); contents.Append(parameterInfo.Name); @@ -1263,6 +1265,8 @@ namespace Flax.Build.Bindings contents.Append("ref "); else if (parameterInfo.IsThis) contents.Append("this "); + else if (parameterInfo.IsParams) + contents.Append("params "); contents.Append(managedType); contents.Append(' '); contents.Append(parameterInfo.Name); @@ -1988,6 +1992,8 @@ namespace Flax.Build.Bindings contents.Append("ref "); else if (parameterInfo.IsThis) contents.Append("this "); + else if (parameterInfo.IsParams) + contents.Append("params "); contents.Append(managedType); contents.Append(' '); contents.Append(parameterInfo.Name); diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs index 72896f186..c2a785c9c 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Cache.cs @@ -19,7 +19,7 @@ namespace Flax.Build.Bindings partial class BindingsGenerator { private static readonly Dictionary TypeCache = new Dictionary(); - private const int CacheVersion = 18; + private const int CacheVersion = 19; internal static void Write(BinaryWriter writer, string e) { diff --git a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs index 1eeefaf27..d4fcd9629 100644 --- a/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs +++ b/Source/Tools/Flax.Build/Bindings/BindingsGenerator.Parsing.cs @@ -337,6 +337,9 @@ namespace Flax.Build.Bindings case "this": currentParam.IsThis = true; break; + case "params": + currentParam.IsParams = true; + break; case "attributes": currentParam.Attributes = tag.Value; break; diff --git a/Source/Tools/Flax.Build/Bindings/FunctionInfo.cs b/Source/Tools/Flax.Build/Bindings/FunctionInfo.cs index 3676e8e76..bae49e98e 100644 --- a/Source/Tools/Flax.Build/Bindings/FunctionInfo.cs +++ b/Source/Tools/Flax.Build/Bindings/FunctionInfo.cs @@ -19,6 +19,7 @@ namespace Flax.Build.Bindings public bool IsRef; public bool IsOut; public bool IsThis; + public bool IsParams; public bool HasDefaultValue => !string.IsNullOrEmpty(DefaultValue); @@ -37,6 +38,7 @@ namespace Flax.Build.Bindings writer.Write(IsRef); writer.Write(IsOut); writer.Write(IsThis); + writer.Write(IsParams); } public void Read(BinaryReader reader) @@ -49,6 +51,7 @@ namespace Flax.Build.Bindings IsRef = reader.ReadBoolean(); IsOut = reader.ReadBoolean(); IsThis = reader.ReadBoolean(); + IsParams = reader.ReadBoolean(); } public override string ToString()