diff options
author | Ignacio Roldán Etcheverry <ignalfonsore@gmail.com> | 2021-09-12 19:49:39 +0200 |
---|---|---|
committer | Ignacio Roldán Etcheverry <ignalfonsore@gmail.com> | 2022-08-22 03:35:59 +0200 |
commit | 9a51430441eecafbd07a7b9eb46967e2c3dd8b5d (patch) | |
tree | bf95b0249e028588a23e029216a22663ec9243a7 /modules/mono/glue | |
parent | c4ccabd3fb81702820ff0943532c3d8a1f1d1c9d (diff) |
C#: Re-write Array, Dictionary, NodePath, String icalls as P/Invoke
Diffstat (limited to 'modules/mono/glue')
12 files changed, 857 insertions, 858 deletions
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs index c32895baab..893ab81e5d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Array.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Collections; using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; using Godot.NativeInterop; namespace Godot.Collections @@ -22,7 +21,7 @@ namespace Godot.Collections /// </summary> public Array() { - godot_icall_Array_Ctor(out NativeValue); + NativeValue = NativeFuncs.godotsharp_array_new(); } /// <summary> @@ -48,11 +47,15 @@ namespace Godot.Collections public Array(params object[] array) : this() { if (array == null) - { throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'"); - } - godot_icall_Array_Ctor_MonoArray(array, out NativeValue); + NativeValue = NativeFuncs.godotsharp_array_new(); + int length = array.Length; + + Resize(length); + + for (int i = 0; i < length; i++) + this[i] = array[i]; } private Array(godot_array nativeValueToOwn) @@ -92,7 +95,7 @@ namespace Godot.Collections public Array Duplicate(bool deep = false) { godot_array newArray; - godot_icall_Array_Duplicate(ref NativeValue, deep, out newArray); + NativeFuncs.godotsharp_array_duplicate(ref NativeValue, deep, out newArray); return CreateTakingOwnershipOfDisposableValue(newArray); } @@ -101,18 +104,12 @@ namespace Godot.Collections /// </summary> /// <param name="newSize">The new size of the array.</param> /// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns> - public Error Resize(int newSize) - { - return godot_icall_Array_Resize(ref NativeValue, newSize); - } + public Error Resize(int newSize) => NativeFuncs.godotsharp_array_resize(ref NativeValue, newSize); /// <summary> /// Shuffles the contents of this <see cref="Array"/> into a random order. /// </summary> - public void Shuffle() - { - godot_icall_Array_Shuffle(ref NativeValue); - } + public void Shuffle() => NativeFuncs.godotsharp_array_shuffle(ref NativeValue); /// <summary> /// Concatenates these two <see cref="Array"/>s. @@ -122,9 +119,16 @@ namespace Godot.Collections /// <returns>A new Godot Array with the contents of both arrays.</returns> public static Array operator +(Array left, Array right) { - godot_array newArray; - godot_icall_Array_Concatenate(ref left.NativeValue, ref right.NativeValue, out newArray); - return CreateTakingOwnershipOfDisposableValue(newArray); + int leftCount = left.Count; + int rightCount = right.Count; + + Array newArray = left.Duplicate(deep: false); + newArray.Resize(leftCount + rightCount); + + for (int i = 0; i < rightCount; i++) + newArray[i + leftCount] = right[i]; + + return newArray; } // IList @@ -137,18 +141,20 @@ namespace Godot.Collections /// Returns the object at the given <paramref name="index"/>. /// </summary> /// <value>The object at the given <paramref name="index"/>.</value> - public object this[int index] + public unsafe object this[int index] { get { - godot_icall_Array_At(ref NativeValue, index, out godot_variant elem); - unsafe - { - using (elem) - return Marshaling.variant_to_mono_object(&elem); - } + GetVariantBorrowElementAt(index, out godot_variant borrowElem); + return Marshaling.variant_to_mono_object(&borrowElem); + } + set + { + if (index < 0 || index >= Count) + throw new IndexOutOfRangeException(); + godot_variant* ptrw = NativeFuncs.godotsharp_array_ptrw(ref NativeValue); + ptrw[index] = Marshaling.mono_object_to_variant(value); } - set => godot_icall_Array_SetAt(ref NativeValue, index, value); } /// <summary> @@ -157,19 +163,23 @@ namespace Godot.Collections /// </summary> /// <param name="value">The object to add.</param> /// <returns>The new size after adding the object.</returns> - public int Add(object value) => godot_icall_Array_Add(ref NativeValue, value); + public unsafe int Add(object value) + { + using godot_variant variantValue = Marshaling.mono_object_to_variant(value); + return NativeFuncs.godotsharp_array_add(ref NativeValue, &variantValue); + } /// <summary> /// Checks if this <see cref="Array"/> contains the given object. /// </summary> /// <param name="value">The item to look for.</param> /// <returns>Whether or not this array contains the given object.</returns> - public bool Contains(object value) => godot_icall_Array_Contains(ref NativeValue, value); + public bool Contains(object value) => IndexOf(value) != -1; /// <summary> /// Erases all items from this <see cref="Array"/>. /// </summary> - public void Clear() => godot_icall_Array_Clear(ref NativeValue); + public void Clear() => Resize(0); /// <summary> /// Searches this <see cref="Array"/> for an object @@ -177,7 +187,11 @@ namespace Godot.Collections /// </summary> /// <param name="value">The object to search for.</param> /// <returns>The index of the object, or -1 if not found.</returns> - public int IndexOf(object value) => godot_icall_Array_IndexOf(ref NativeValue, value); + public unsafe int IndexOf(object value) + { + using godot_variant variantValue = Marshaling.mono_object_to_variant(value); + return NativeFuncs.godotsharp_array_index_of(ref NativeValue, &variantValue); + } /// <summary> /// Inserts a new object at a given position in the array. @@ -187,20 +201,38 @@ namespace Godot.Collections /// </summary> /// <param name="index">The index to insert at.</param> /// <param name="value">The object to insert.</param> - public void Insert(int index, object value) => godot_icall_Array_Insert(ref NativeValue, index, value); + public unsafe void Insert(int index, object value) + { + if (index < 0 || index > Count) + throw new IndexOutOfRangeException(); + + using godot_variant variantValue = Marshaling.mono_object_to_variant(value); + NativeFuncs.godotsharp_array_insert(ref NativeValue, index, &variantValue); + } /// <summary> /// Removes the first occurrence of the specified <paramref name="value"/> /// from this <see cref="Array"/>. /// </summary> /// <param name="value">The value to remove.</param> - public void Remove(object value) => godot_icall_Array_Remove(ref NativeValue, value); + public void Remove(object value) + { + int index = IndexOf(value); + if (index >= 0) + RemoveAt(index); + } /// <summary> /// Removes an element from this <see cref="Array"/> by index. /// </summary> /// <param name="index">The index of the element to remove.</param> - public void RemoveAt(int index) => godot_icall_Array_RemoveAt(ref NativeValue, index); + public void RemoveAt(int index) + { + if (index < 0 || index > Count) + throw new IndexOutOfRangeException(); + + NativeFuncs.godotsharp_array_remove_at(ref NativeValue, index); + } // ICollection @@ -209,7 +241,7 @@ namespace Godot.Collections /// This is also known as the size or length of the array. /// </summary> /// <returns>The number of elements.</returns> - public int Count => godot_icall_Array_Count(ref NativeValue); + public int Count => NativeValue.Size; object ICollection.SyncRoot => this; @@ -220,17 +252,35 @@ namespace Godot.Collections /// untyped C# array, starting at the given index. /// </summary> /// <param name="array">The array to copy to.</param> - /// <param name="index">The index to start at.</param> - public void CopyTo(System.Array array, int index) + /// <param name="destIndex">The index to start at.</param> + public void CopyTo(System.Array array, int destIndex) { if (array == null) throw new ArgumentNullException(nameof(array), "Value cannot be null."); - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension."); + if (destIndex < 0) + { + throw new ArgumentOutOfRangeException(nameof(destIndex), + "Number was less than the array's lower bound in the first dimension."); + } - // Internal call may throw ArgumentException - godot_icall_Array_CopyTo(ref NativeValue, array, index); + int count = Count; + + if (array.Length < (destIndex + count)) + { + throw new ArgumentException( + "Destination array was not long enough. Check destIndex and length, and the array's lower bounds."); + } + + unsafe + { + for (int i = 0; i < count; i++) + { + object obj = Marshaling.variant_to_mono_object(&(*NativeValue._p)._arrayVector._ptr[i]); + array.SetValue(obj, destIndex); + destIndex++; + } + } } // IEnumerable @@ -253,64 +303,30 @@ namespace Godot.Collections /// Converts this <see cref="Array"/> to a string. /// </summary> /// <returns>A string representation of this array.</returns> - public override string ToString() + public override unsafe string ToString() { - return godot_icall_Array_ToString(ref NativeValue); + using godot_string str = default; + NativeFuncs.godotsharp_array_to_string(ref NativeValue, &str); + return Marshaling.mono_string_from_godot(&str); } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Array_Ctor(out godot_array dest); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Array_Ctor_MonoArray(System.Array array, out godot_array dest); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Array_At(ref godot_array ptr, int index, out godot_variant elem); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Array_SetAt(ref godot_array ptr, int index, object value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern int godot_icall_Array_Count(ref godot_array ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern int godot_icall_Array_Add(ref godot_array ptr, object item); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Array_Clear(ref godot_array ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Array_Concatenate(ref godot_array left, ref godot_array right, out godot_array dest); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool godot_icall_Array_Contains(ref godot_array ptr, object item); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Array_CopyTo(ref godot_array ptr, System.Array array, int arrayIndex); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Array_Duplicate(ref godot_array ptr, bool deep, out godot_array dest); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern int godot_icall_Array_IndexOf(ref godot_array ptr, object item); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Array_Insert(ref godot_array ptr, int index, object item); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool godot_icall_Array_Remove(ref godot_array ptr, object item); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Array_RemoveAt(ref godot_array ptr, int index); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern Error godot_icall_Array_Resize(ref godot_array ptr, int newSize); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern Error godot_icall_Array_Shuffle(ref godot_array ptr); + /// <summary> + /// The variant returned via the <paramref name="elem"/> parameter is owned by the Array and must not be disposed. + /// </summary> + internal void GetVariantBorrowElementAt(int index, out godot_variant elem) + { + if (index < 0 || index >= Count) + throw new IndexOutOfRangeException(); + GetVariantBorrowElementAtUnchecked(index, out elem); + } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern string godot_icall_Array_ToString(ref godot_array ptr); + /// <summary> + /// The variant returned via the <paramref name="elem"/> parameter is owned by the Array and must not be disposed. + /// </summary> + internal unsafe void GetVariantBorrowElementAtUnchecked(int index, out godot_variant elem) + { + elem = (*NativeValue._p)._arrayVector._ptr[index]; + } } internal interface IGenericGodotArray @@ -451,11 +467,10 @@ namespace Godot.Collections { get { - Array.godot_icall_Array_At(ref _underlyingArray.NativeValue, index, out godot_variant elem); + _underlyingArray.GetVariantBorrowElementAt(index, out godot_variant borrowElem); unsafe { - using (elem) - return (T)Marshaling.variant_to_mono_object_of_type(&elem, TypeOfElements); + return (T)Marshaling.variant_to_mono_object_of_type(&borrowElem, TypeOfElements); } } set => _underlyingArray[index] = value; @@ -546,12 +561,14 @@ namespace Godot.Collections throw new ArgumentNullException(nameof(array), "Value cannot be null."); if (arrayIndex < 0) - throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension."); + throw new ArgumentOutOfRangeException(nameof(arrayIndex), + "Number was less than the array's lower bound in the first dimension."); int count = _underlyingArray.Count; if (array.Length < (arrayIndex + count)) - throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds."); + throw new ArgumentException( + "Destination array was not long enough. Check destIndex and length, and the array's lower bounds."); for (int i = 0; i < count; i++) { @@ -568,7 +585,14 @@ namespace Godot.Collections /// <returns>A <see langword="bool"/> indicating success or failure.</returns> public bool Remove(T item) { - return Array.godot_icall_Array_Remove(ref _underlyingArray.NativeValue, item); + int index = IndexOf(item); + if (index >= 0) + { + RemoveAt(index); + return true; + } + + return false; } // IEnumerable<T> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs index d0c7e4523b..932ee33fe3 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Dictionary.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Collections; -using System.Runtime.CompilerServices; using Godot.NativeInterop; using System.Diagnostics.CodeAnalysis; @@ -23,7 +22,7 @@ namespace Godot.Collections /// </summary> public Dictionary() { - godot_icall_Dictionary_Ctor(out NativeValue); + NativeValue = NativeFuncs.godotsharp_dictionary_new(); } /// <summary> @@ -77,7 +76,7 @@ namespace Godot.Collections public Dictionary Duplicate(bool deep = false) { godot_dictionary newDictionary; - godot_icall_Dictionary_Duplicate(ref NativeValue, deep, out newDictionary); + NativeFuncs.godotsharp_dictionary_duplicate(ref NativeValue, deep, out newDictionary); return CreateTakingOwnershipOfDisposableValue(newDictionary); } @@ -91,7 +90,7 @@ namespace Godot.Collections get { godot_array keysArray; - godot_icall_Dictionary_Keys(ref NativeValue, out keysArray); + NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out keysArray); return Array.CreateTakingOwnershipOfDisposableValue(keysArray); } } @@ -104,7 +103,7 @@ namespace Godot.Collections get { godot_array valuesArray; - godot_icall_Dictionary_Values(ref NativeValue, out valuesArray); + NativeFuncs.godotsharp_dictionary_values(ref NativeValue, out valuesArray); return Array.CreateTakingOwnershipOfDisposableValue(valuesArray); } } @@ -112,10 +111,15 @@ namespace Godot.Collections private (Array keys, Array values, int count) GetKeyValuePairs() { godot_array keysArray; - godot_array valuesArray; - int count = godot_icall_Dictionary_KeyValuePairs(ref NativeValue, out keysArray, out valuesArray); + NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out keysArray); var keys = Array.CreateTakingOwnershipOfDisposableValue(keysArray); + + godot_array valuesArray; + NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out valuesArray); var values = Array.CreateTakingOwnershipOfDisposableValue(valuesArray); + + int count = NativeFuncs.godotsharp_dictionary_count(ref NativeValue); + return (keys, values, count); } @@ -127,18 +131,28 @@ namespace Godot.Collections /// Returns the object at the given <paramref name="key"/>. /// </summary> /// <value>The object at the given <paramref name="key"/>.</value> - public object this[object key] + public unsafe object this[object key] { get { - godot_icall_Dictionary_GetValue(ref NativeValue, key, out godot_variant value); - unsafe + using godot_variant variantKey = Marshaling.mono_object_to_variant(key); + if (NativeFuncs.godotsharp_dictionary_try_get_value(ref NativeValue, &variantKey, + out godot_variant value)) { using (value) return Marshaling.variant_to_mono_object(&value); } + else + { + throw new KeyNotFoundException(); + } + } + set + { + using godot_variant variantKey = Marshaling.mono_object_to_variant(key); + using godot_variant variantValue = Marshaling.mono_object_to_variant(value); + NativeFuncs.godotsharp_dictionary_set_value(ref NativeValue, &variantKey, &variantValue); } - set => godot_icall_Dictionary_SetValue(ref NativeValue, key, value); } /// <summary> @@ -147,19 +161,32 @@ namespace Godot.Collections /// </summary> /// <param name="key">The key at which to add the object.</param> /// <param name="value">The object to add.</param> - public void Add(object key, object value) => godot_icall_Dictionary_Add(ref NativeValue, key, value); + public unsafe void Add(object key, object value) + { + using godot_variant variantKey = Marshaling.mono_object_to_variant(key); + + if (NativeFuncs.godotsharp_dictionary_contains_key(ref NativeValue, &variantKey)) + throw new ArgumentException("An element with the same key already exists", nameof(key)); + + using godot_variant variantValue = Marshaling.mono_object_to_variant(value); + NativeFuncs.godotsharp_dictionary_add(ref NativeValue, &variantKey, &variantValue); + } /// <summary> /// Erases all items from this <see cref="Dictionary"/>. /// </summary> - public void Clear() => godot_icall_Dictionary_Clear(ref NativeValue); + public void Clear() => NativeFuncs.godotsharp_dictionary_clear(ref NativeValue); /// <summary> /// Checks if this <see cref="Dictionary"/> contains the given key. /// </summary> /// <param name="key">The key to look for.</param> /// <returns>Whether or not this dictionary contains the given key.</returns> - public bool Contains(object key) => godot_icall_Dictionary_ContainsKey(ref NativeValue, key); + public unsafe bool Contains(object key) + { + using godot_variant variantKey = Marshaling.mono_object_to_variant(key); + return NativeFuncs.godotsharp_dictionary_contains_key(ref NativeValue, &variantKey); + } /// <summary> /// Gets an enumerator for this <see cref="Dictionary"/>. @@ -171,7 +198,11 @@ namespace Godot.Collections /// Removes an element from this <see cref="Dictionary"/> by key. /// </summary> /// <param name="key">The key of the element to remove.</param> - public void Remove(object key) => godot_icall_Dictionary_RemoveKey(ref NativeValue, key); + public unsafe void Remove(object key) + { + using godot_variant variantKey = Marshaling.mono_object_to_variant(key); + NativeFuncs.godotsharp_dictionary_remove_key(ref NativeValue, &variantKey); + } // ICollection @@ -184,7 +215,7 @@ namespace Godot.Collections /// This is also known as the size or length of the dictionary. /// </summary> /// <returns>The number of elements.</returns> - public int Count => godot_icall_Dictionary_Count(ref NativeValue); + public int Count => NativeFuncs.godotsharp_dictionary_count(ref NativeValue); /// <summary> /// Copies the elements of this <see cref="Dictionary"/> to the given @@ -198,12 +229,14 @@ namespace Godot.Collections throw new ArgumentNullException(nameof(array), "Value cannot be null."); if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension."); + throw new ArgumentOutOfRangeException(nameof(index), + "Number was less than the array's lower bound in the first dimension."); var (keys, values, count) = GetKeyValuePairs(); if (array.Length < (index + count)) - throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds."); + throw new ArgumentException( + "Destination array was not long enough. Check destIndex and length, and the array's lower bounds."); for (int i = 0; i < count; i++) { @@ -241,23 +274,22 @@ namespace Godot.Collections { UpdateEntry(); } + return _entry; } } - private void UpdateEntry() + private unsafe void UpdateEntry() { _dirty = false; - godot_icall_Dictionary_KeyValuePairAt(ref _dictionary.NativeValue, _index, out var vKey, out var vValue); - unsafe + NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref _dictionary.NativeValue, _index, + out godot_variant key, + out godot_variant value); + using (key) + using (value) { - using (vKey) - using (vValue) - { - var key = Marshaling.variant_to_mono_object(&vKey); - var value = Marshaling.variant_to_mono_object(&vValue); - _entry = new DictionaryEntry(key, value); - } + _entry = new DictionaryEntry(Marshaling.variant_to_mono_object(&key), + Marshaling.variant_to_mono_object(&value)); } } @@ -283,61 +315,12 @@ namespace Godot.Collections /// Converts this <see cref="Dictionary"/> to a string. /// </summary> /// <returns>A string representation of this dictionary.</returns> - public override string ToString() + public override unsafe string ToString() { - return godot_icall_Dictionary_ToString(ref NativeValue); + using godot_string str = default; + NativeFuncs.godotsharp_dictionary_to_string(ref NativeValue, &str); + return Marshaling.mono_string_from_godot(&str); } - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Dictionary_Ctor(out godot_dictionary dest); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Dictionary_GetValue(ref godot_dictionary ptr, object key, out godot_variant value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Dictionary_SetValue(ref godot_dictionary ptr, object key, object value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Dictionary_Keys(ref godot_dictionary ptr, out godot_array dest); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Dictionary_Values(ref godot_dictionary ptr, out godot_array dest); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern int godot_icall_Dictionary_KeyValuePairs(ref godot_dictionary ptr, out godot_array keys, out godot_array values); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Dictionary_KeyValuePairAt(ref godot_dictionary ptr, int index, out godot_variant key, out godot_variant value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Dictionary_Add(ref godot_dictionary ptr, object key, object value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern int godot_icall_Dictionary_Count(ref godot_dictionary ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Dictionary_Clear(ref godot_dictionary ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool godot_icall_Dictionary_Contains(ref godot_dictionary ptr, object key, object value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool godot_icall_Dictionary_ContainsKey(ref godot_dictionary ptr, object key); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void godot_icall_Dictionary_Duplicate(ref godot_dictionary ptr, bool deep, out godot_dictionary dest); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool godot_icall_Dictionary_RemoveKey(ref godot_dictionary ptr, object key); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool godot_icall_Dictionary_Remove(ref godot_dictionary ptr, object key, object value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern bool godot_icall_Dictionary_TryGetValue(ref godot_dictionary ptr, object key, out godot_variant value); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern string godot_icall_Dictionary_ToString(ref godot_dictionary ptr); } internal interface IGenericGodotDictionary @@ -412,7 +395,8 @@ namespace Godot.Collections } // Explicit name to make it very clear - internal static Dictionary<TKey, TValue> CreateTakingOwnershipOfDisposableValue(godot_dictionary nativeValueToOwn) + internal static Dictionary<TKey, TValue> CreateTakingOwnershipOfDisposableValue( + godot_dictionary nativeValueToOwn) => new Dictionary<TKey, TValue>(Dictionary.CreateTakingOwnershipOfDisposableValue(nativeValueToOwn)); /// <summary> @@ -444,11 +428,19 @@ namespace Godot.Collections { get { - Dictionary.godot_icall_Dictionary_GetValue(ref _underlyingDict.NativeValue, key, out godot_variant value); unsafe { - using (value) - return (TValue)Marshaling.variant_to_mono_object_of_type(&value, TypeOfValues); + using godot_variant variantKey = Marshaling.mono_object_to_variant(key); + if (NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue, + &variantKey, out godot_variant value)) + { + using (value) + return (TValue)Marshaling.variant_to_mono_object_of_type(&value, TypeOfValues); + } + else + { + throw new KeyNotFoundException(); + } } } set => _underlyingDict[key] = value; @@ -462,7 +454,7 @@ namespace Godot.Collections get { godot_array keyArray; - Dictionary.godot_icall_Dictionary_Keys(ref _underlyingDict.NativeValue, out keyArray); + NativeFuncs.godotsharp_dictionary_keys(ref _underlyingDict.NativeValue, out keyArray); return Array<TKey>.CreateTakingOwnershipOfDisposableValue(keyArray); } } @@ -475,23 +467,21 @@ namespace Godot.Collections get { godot_array valuesArray; - Dictionary.godot_icall_Dictionary_Values(ref _underlyingDict.NativeValue, out valuesArray); + NativeFuncs.godotsharp_dictionary_values(ref _underlyingDict.NativeValue, out valuesArray); return Array<TValue>.CreateTakingOwnershipOfDisposableValue(valuesArray); } } - private KeyValuePair<TKey, TValue> GetKeyValuePair(int index) + private unsafe KeyValuePair<TKey, TValue> GetKeyValuePair(int index) { - Dictionary.godot_icall_Dictionary_KeyValuePairAt(ref _underlyingDict.NativeValue, index, out var vKey, out var vValue); - unsafe + NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref _underlyingDict.NativeValue, index, + out godot_variant key, + out godot_variant value); + using (key) + using (value) { - using (vKey) - using (vValue) - { - var key = Marshaling.variant_to_mono_object_of_type(&vKey, TypeOfKeys); - var value = Marshaling.variant_to_mono_object_of_type(&vValue, TypeOfValues); - return new KeyValuePair<TKey, TValue>((TKey)key, (TValue)value); - } + return new KeyValuePair<TKey, TValue>((TKey)Marshaling.variant_to_mono_object(&key), + (TValue)Marshaling.variant_to_mono_object(&value)); } } @@ -520,9 +510,10 @@ namespace Godot.Collections /// Removes an element from this <see cref="Dictionary{TKey, TValue}"/> by key. /// </summary> /// <param name="key">The key of the element to remove.</param> - public bool Remove(TKey key) + public unsafe bool Remove(TKey key) { - return Dictionary.godot_icall_Dictionary_RemoveKey(ref _underlyingDict.NativeValue, key); + using godot_variant variantKey = Marshaling.mono_object_to_variant(key); + return NativeFuncs.godotsharp_dictionary_remove_key(ref _underlyingDict.NativeValue, &variantKey); } /// <summary> @@ -531,18 +522,17 @@ namespace Godot.Collections /// <param name="key">The key of the element to get.</param> /// <param name="value">The value at the given <paramref name="key"/>.</param> /// <returns>If an object was found for the given <paramref name="key"/>.</returns> - public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) + public unsafe bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) { - bool found = Dictionary.godot_icall_Dictionary_TryGetValue(ref _underlyingDict.NativeValue, key, out godot_variant retValue); + using godot_variant variantKey = Marshaling.mono_object_to_variant(key); + bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue, + &variantKey, out godot_variant retValue); - unsafe + using (retValue) { - using (retValue) - { - value = found ? - (TValue)Marshaling.variant_to_mono_object_of_type(&retValue, TypeOfValues) : - default; - } + value = found ? + (TValue)Marshaling.variant_to_mono_object_of_type(&retValue, TypeOfValues) : + default; } return found; @@ -572,9 +562,20 @@ namespace Godot.Collections _underlyingDict.Clear(); } - bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) + unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) { - return _underlyingDict.Contains(new KeyValuePair<object, object>(item.Key, item.Value)); + using godot_variant variantKey = Marshaling.mono_object_to_variant(item.Key); + bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue, + &variantKey, out godot_variant retValue); + + using (retValue) + { + if (!found) + return false; + + using godot_variant variantValue = Marshaling.mono_object_to_variant(item.Value); + return NativeFuncs.godotsharp_variant_equals(&variantValue, &retValue); + } } /// <summary> @@ -589,12 +590,14 @@ namespace Godot.Collections throw new ArgumentNullException(nameof(array), "Value cannot be null."); if (arrayIndex < 0) - throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension."); + throw new ArgumentOutOfRangeException(nameof(arrayIndex), + "Number was less than the array's lower bound in the first dimension."); int count = Count; if (array.Length < (arrayIndex + count)) - throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds."); + throw new ArgumentException( + "Destination array was not long enough. Check destIndex and length, and the array's lower bounds."); for (int i = 0; i < count; i++) { @@ -603,9 +606,23 @@ namespace Godot.Collections } } - bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) + unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) { - return Dictionary.godot_icall_Dictionary_Remove(ref _underlyingDict.NativeValue, item.Key, item.Value); + using godot_variant variantKey = Marshaling.mono_object_to_variant(item.Key); + bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue, + &variantKey, out godot_variant retValue); + + using (retValue) + { + if (!found) + return false; + + using godot_variant variantValue = Marshaling.mono_object_to_variant(item.Value); + if (NativeFuncs.godotsharp_variant_equals(&variantValue, &retValue)) + return NativeFuncs.godotsharp_dictionary_remove_key(ref _underlyingDict.NativeValue, &variantKey); + + return false; + } } // IEnumerable<KeyValuePair<TKey, TValue>> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs index 6ee8cbc0bc..ddcb6b9091 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs @@ -171,6 +171,9 @@ namespace Godot.NativeInterop NativeFuncs.godotsharp_string_destroy(ref this); _ptr = IntPtr.Zero; } + + // Size including the null termination character + public unsafe int Size => _ptr != IntPtr.Zero ? *((int*)_ptr - 1) : 0; } [StructLayout(LayoutKind.Sequential)] @@ -262,14 +265,34 @@ namespace Godot.NativeInterop // ReSharper disable once InconsistentNaming internal struct godot_array : IDisposable { - internal IntPtr _p; + internal unsafe ArrayPrivate* _p; - public void Dispose() + [StructLayout(LayoutKind.Sequential)] + internal struct ArrayPrivate { - if (_p == IntPtr.Zero) + private uint _safeRefCount; + + internal VariantVector _arrayVector; + // There's more here, but we don't care as we never store this in C# + } + + [StructLayout(LayoutKind.Sequential)] + internal struct VariantVector + { + internal IntPtr _writeProxy; + internal unsafe godot_variant* _ptr; + + public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0; + } + + public unsafe int Size => _p != null ? _p->_arrayVector.Size : 0; + + public unsafe void Dispose() + { + if (_p == null) return; NativeFuncs.godotsharp_array_destroy(ref this); - _p = IntPtr.Zero; + _p = null; } } @@ -297,15 +320,17 @@ namespace Godot.NativeInterop internal struct godot_packed_byte_array : IDisposable { internal IntPtr _writeProxy; - internal IntPtr _ptr; + internal unsafe byte* _ptr; - public void Dispose() + public unsafe void Dispose() { - if (_ptr == IntPtr.Zero) + if (_ptr == null) return; NativeFuncs.godotsharp_packed_byte_array_destroy(ref this); - _ptr = IntPtr.Zero; + _ptr = null; } + + public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0; } [StructLayout(LayoutKind.Sequential)] @@ -313,15 +338,17 @@ namespace Godot.NativeInterop internal struct godot_packed_int32_array : IDisposable { internal IntPtr _writeProxy; - internal IntPtr _ptr; + internal unsafe int* _ptr; - public void Dispose() + public unsafe void Dispose() { - if (_ptr == IntPtr.Zero) + if (_ptr == null) return; NativeFuncs.godotsharp_packed_int32_array_destroy(ref this); - _ptr = IntPtr.Zero; + _ptr = null; } + + public unsafe int Size => _ptr != null ? *(_ptr - 1) : 0; } [StructLayout(LayoutKind.Sequential)] @@ -329,15 +356,17 @@ namespace Godot.NativeInterop internal struct godot_packed_int64_array : IDisposable { internal IntPtr _writeProxy; - internal IntPtr _ptr; + internal unsafe long* _ptr; - public void Dispose() + public unsafe void Dispose() { - if (_ptr == IntPtr.Zero) + if (_ptr == null) return; NativeFuncs.godotsharp_packed_int64_array_destroy(ref this); - _ptr = IntPtr.Zero; + _ptr = null; } + + public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0; } [StructLayout(LayoutKind.Sequential)] @@ -345,15 +374,17 @@ namespace Godot.NativeInterop internal struct godot_packed_float32_array : IDisposable { internal IntPtr _writeProxy; - internal IntPtr _ptr; + internal unsafe float* _ptr; - public void Dispose() + public unsafe void Dispose() { - if (_ptr == IntPtr.Zero) + if (_ptr == null) return; NativeFuncs.godotsharp_packed_float32_array_destroy(ref this); - _ptr = IntPtr.Zero; + _ptr = null; } + + public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0; } [StructLayout(LayoutKind.Sequential)] @@ -361,15 +392,17 @@ namespace Godot.NativeInterop internal struct godot_packed_float64_array : IDisposable { internal IntPtr _writeProxy; - internal IntPtr _ptr; + internal unsafe double* _ptr; - public void Dispose() + public unsafe void Dispose() { - if (_ptr == IntPtr.Zero) + if (_ptr == null) return; NativeFuncs.godotsharp_packed_float64_array_destroy(ref this); - _ptr = IntPtr.Zero; + _ptr = null; } + + public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0; } [StructLayout(LayoutKind.Sequential)] @@ -377,15 +410,17 @@ namespace Godot.NativeInterop internal struct godot_packed_string_array : IDisposable { internal IntPtr _writeProxy; - internal IntPtr _ptr; + internal unsafe godot_string* _ptr; - public void Dispose() + public unsafe void Dispose() { - if (_ptr == IntPtr.Zero) + if (_ptr == null) return; NativeFuncs.godotsharp_packed_string_array_destroy(ref this); - _ptr = IntPtr.Zero; + _ptr = null; } + + public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0; } [StructLayout(LayoutKind.Sequential)] @@ -393,15 +428,17 @@ namespace Godot.NativeInterop internal struct godot_packed_vector2_array : IDisposable { internal IntPtr _writeProxy; - internal IntPtr _ptr; + internal unsafe Vector2* _ptr; - public void Dispose() + public unsafe void Dispose() { - if (_ptr == IntPtr.Zero) + if (_ptr == null) return; NativeFuncs.godotsharp_packed_vector2_array_destroy(ref this); - _ptr = IntPtr.Zero; + _ptr = null; } + + public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0; } [StructLayout(LayoutKind.Sequential)] @@ -409,15 +446,17 @@ namespace Godot.NativeInterop internal struct godot_packed_vector3_array : IDisposable { internal IntPtr _writeProxy; - internal IntPtr _ptr; + internal unsafe Vector3* _ptr; - public void Dispose() + public unsafe void Dispose() { - if (_ptr == IntPtr.Zero) + if (_ptr == null) return; NativeFuncs.godotsharp_packed_vector3_array_destroy(ref this); - _ptr = IntPtr.Zero; + _ptr = null; } + + public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0; } [StructLayout(LayoutKind.Sequential)] @@ -425,14 +464,16 @@ namespace Godot.NativeInterop internal struct godot_packed_color_array : IDisposable { internal IntPtr _writeProxy; - internal IntPtr _ptr; + internal unsafe Color* _ptr; - public void Dispose() + public unsafe void Dispose() { - if (_ptr == IntPtr.Zero) + if (_ptr == null) return; NativeFuncs.godotsharp_packed_color_array_destroy(ref this); - _ptr = IntPtr.Zero; + _ptr = null; } + + public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0; } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs index 9b6f9633d1..590fb082e8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs @@ -161,7 +161,8 @@ namespace Godot.NativeInterop if (genericTypeDefinition == typeof(IDictionary<,>)) return Variant.Type.Dictionary; - if (genericTypeDefinition == typeof(ICollection<>) || genericTypeDefinition == typeof(IEnumerable<>)) + if (genericTypeDefinition == typeof(ICollection<>) || + genericTypeDefinition == typeof(IEnumerable<>)) return Variant.Type.Array; } else if (type == typeof(object)) @@ -430,7 +431,8 @@ namespace Godot.NativeInterop { // TODO: Validate key and value types are compatible with Variant #if NET - Collections.IGenericGodotDictionary genericGodotDictionary = IDictionaryToGenericGodotDictionary((dynamic)p_obj); + Collections.IGenericGodotDictionary genericGodotDictionary = + IDictionaryToGenericGodotDictionary((dynamic)p_obj); #else var genericArguments = type.GetGenericArguments(); @@ -441,7 +443,7 @@ namespace Godot.NativeInterop .MakeGenericMethod(genericArguments[0], genericArguments[1]); var genericGodotDictionary = (Collections.IGenericGodotDictionary)method - .Invoke(null, new[] {p_obj}); + .Invoke(null, new[] { p_obj }); #endif var godotDict = genericGodotDictionary.UnderlyingDictionary; @@ -454,7 +456,8 @@ namespace Godot.NativeInterop { // TODO: Validate element type is compatible with Variant #if NET - var nativeGodotArray = mono_array_to_Array(System.Runtime.InteropServices.CollectionsMarshal.AsSpan((dynamic)p_obj)); + var nativeGodotArray = + mono_array_to_Array(System.Runtime.InteropServices.CollectionsMarshal.AsSpan((dynamic)p_obj)); #else // With .NET Standard we need a package reference for Microsoft.CSharp in order to // use dynamic, so we have this workaround for now until we switch to .NET 5/6. @@ -623,8 +626,9 @@ namespace Godot.NativeInterop return VariantUtils.ConvertToUInt64(p_var); default: { - GD.PushError("Attempted to convert Variant to enum value of unsupported underlying type. Name: " + - type.FullName + " : " + enumUnderlyingType.FullName + "."); + GD.PushError( + "Attempted to convert Variant to enum value of unsupported underlying type. Name: " + + type.FullName + " : " + enumUnderlyingType.FullName + "."); return null; } } @@ -777,7 +781,7 @@ namespace Godot.NativeInterop VariantUtils.ConvertToDictionary(p_var)); return Activator.CreateInstance(fullType, BindingFlags.Public | BindingFlags.Instance, null, - args: new object[] {underlyingDict}, null); + args: new object[] { underlyingDict }, null); } static object variant_to_generic_godot_collections_array(godot_variant* p_var, Type fullType) @@ -786,7 +790,7 @@ namespace Godot.NativeInterop VariantUtils.ConvertToArray(p_var)); return Activator.CreateInstance(fullType, BindingFlags.Public | BindingFlags.Instance, null, - args: new object[] {underlyingArray}, null); + args: new object[] { underlyingArray }, null); } var genericTypeDefinition = type.GetGenericTypeDefinition(); @@ -1010,7 +1014,7 @@ namespace Godot.NativeInterop const int sizeOfChar32 = 4; byte* bytes = (byte*)(*p_string)._ptr; - int size = *((int*)(*p_string)._ptr - 1); + int size = (*p_string).Size; if (size == 0) return string.Empty; size -= 1; // zero at the end @@ -1148,11 +1152,7 @@ namespace Godot.NativeInterop public static godot_array mono_array_to_Array(Span<object> p_array) { if (p_array.IsEmpty) - { - godot_array ret; - Collections.Array.godot_icall_Array_Ctor(out ret); - return ret; - } + return NativeFuncs.godotsharp_array_new(); using var array = new Collections.Array(); array.Resize(p_array.Length); @@ -1171,8 +1171,8 @@ namespace Godot.NativeInterop public static unsafe byte[] PackedByteArray_to_mono_array(godot_packed_byte_array* p_array) { - byte* buffer = (byte*)(*p_array)._ptr; - int size = *((int*)(*p_array)._ptr - 1); + byte* buffer = (*p_array)._ptr; + int size = (*p_array).Size; var array = new byte[size]; fixed (byte* dest = array) Buffer.MemoryCopy(buffer, dest, size, size); @@ -1191,8 +1191,8 @@ namespace Godot.NativeInterop public static unsafe int[] PackedInt32Array_to_mono_array(godot_packed_int32_array* p_array) { - int* buffer = (int*)(*p_array)._ptr; - int size = *((int*)(*p_array)._ptr - 1); + int* buffer = (*p_array)._ptr; + int size = (*p_array).Size; int sizeInBytes = size * sizeof(int); var array = new int[size]; fixed (int* dest = array) @@ -1212,8 +1212,8 @@ namespace Godot.NativeInterop public static unsafe long[] PackedInt64Array_to_mono_array(godot_packed_int64_array* p_array) { - long* buffer = (long*)(*p_array)._ptr; - int size = *((int*)(*p_array)._ptr - 1); + long* buffer = (*p_array)._ptr; + int size = (*p_array).Size; int sizeInBytes = size * sizeof(long); var array = new long[size]; fixed (long* dest = array) @@ -1233,8 +1233,8 @@ namespace Godot.NativeInterop public static unsafe float[] PackedFloat32Array_to_mono_array(godot_packed_float32_array* p_array) { - float* buffer = (float*)(*p_array)._ptr; - int size = *((int*)(*p_array)._ptr - 1); + float* buffer = (*p_array)._ptr; + int size = (*p_array).Size; int sizeInBytes = size * sizeof(float); var array = new float[size]; fixed (float* dest = array) @@ -1254,8 +1254,8 @@ namespace Godot.NativeInterop public static unsafe double[] PackedFloat64Array_to_mono_array(godot_packed_float64_array* p_array) { - double* buffer = (double*)(*p_array)._ptr; - int size = *((int*)(*p_array)._ptr - 1); + double* buffer = (*p_array)._ptr; + int size = (*p_array).Size; int sizeInBytes = size * sizeof(double); var array = new double[size]; fixed (double* dest = array) @@ -1275,10 +1275,10 @@ namespace Godot.NativeInterop public static unsafe string[] PackedStringArray_to_mono_array(godot_packed_string_array* p_array) { - godot_string* buffer = (godot_string*)(*p_array)._ptr; + godot_string* buffer = (*p_array)._ptr; if (buffer == null) return new string[] { }; - int size = *((int*)(*p_array)._ptr - 1); + int size = (*p_array).Size; var array = new string[size]; for (int i = 0; i < size; i++) array[i] = mono_string_from_godot(&buffer[i]); @@ -1308,8 +1308,8 @@ namespace Godot.NativeInterop public static unsafe Vector2[] PackedVector2Array_to_mono_array(godot_packed_vector2_array* p_array) { - Vector2* buffer = (Vector2*)(*p_array)._ptr; - int size = *((int*)(*p_array)._ptr - 1); + Vector2* buffer = (*p_array)._ptr; + int size = (*p_array).Size; int sizeInBytes = size * sizeof(Vector2); var array = new Vector2[size]; fixed (Vector2* dest = array) @@ -1329,8 +1329,8 @@ namespace Godot.NativeInterop public static unsafe Vector3[] PackedVector3Array_to_mono_array(godot_packed_vector3_array* p_array) { - Vector3* buffer = (Vector3*)(*p_array)._ptr; - int size = *((int*)(*p_array)._ptr - 1); + Vector3* buffer = (*p_array)._ptr; + int size = (*p_array).Size; int sizeInBytes = size * sizeof(Vector3); var array = new Vector3[size]; fixed (Vector3* dest = array) @@ -1350,8 +1350,8 @@ namespace Godot.NativeInterop public static unsafe Color[] PackedColorArray_to_mono_array(godot_packed_color_array* p_array) { - Color* buffer = (Color*)(*p_array)._ptr; - int size = *((int*)(*p_array)._ptr - 1); + Color* buffer = (*p_array)._ptr; + int size = (*p_array).Size; int sizeInBytes = size * sizeof(Color); var array = new Color[size]; fixed (Color* dest = array) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs index 2f1056219d..0680ec7be5 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs @@ -17,7 +17,8 @@ namespace Godot.NativeInterop // Custom functions [DllImport(GodotDllName)] - public static extern IntPtr godotsharp_method_bind_get_method(ref godot_string_name p_classname, char* p_methodname); + public static extern IntPtr godotsharp_method_bind_get_method(ref godot_string_name p_classname, + char* p_methodname); #if NET [DllImport(GodotDllName)] @@ -50,47 +51,60 @@ namespace Godot.NativeInterop public static extern void godotsharp_node_path_as_string(godot_string* r_dest, godot_node_path* p_np); [DllImport(GodotDllName)] - public static extern godot_packed_byte_array godotsharp_packed_byte_array_new_mem_copy(byte* p_src, int p_length); + public static extern godot_packed_byte_array godotsharp_packed_byte_array_new_mem_copy(byte* p_src, + int p_length); [DllImport(GodotDllName)] - public static extern godot_packed_int32_array godotsharp_packed_int32_array_new_mem_copy(int* p_src, int p_length); + public static extern godot_packed_int32_array godotsharp_packed_int32_array_new_mem_copy(int* p_src, + int p_length); [DllImport(GodotDllName)] - public static extern godot_packed_int64_array godotsharp_packed_int64_array_new_mem_copy(long* p_src, int p_length); + public static extern godot_packed_int64_array godotsharp_packed_int64_array_new_mem_copy(long* p_src, + int p_length); [DllImport(GodotDllName)] - public static extern godot_packed_float32_array godotsharp_packed_float32_array_new_mem_copy(float* p_src, int p_length); + public static extern godot_packed_float32_array godotsharp_packed_float32_array_new_mem_copy(float* p_src, + int p_length); [DllImport(GodotDllName)] - public static extern godot_packed_float64_array godotsharp_packed_float64_array_new_mem_copy(double* p_src, int p_length); + public static extern godot_packed_float64_array godotsharp_packed_float64_array_new_mem_copy(double* p_src, + int p_length); [DllImport(GodotDllName)] - public static extern godot_packed_vector2_array godotsharp_packed_vector2_array_new_mem_copy(Vector2* p_src, int p_length); + public static extern godot_packed_vector2_array godotsharp_packed_vector2_array_new_mem_copy(Vector2* p_src, + int p_length); [DllImport(GodotDllName)] - public static extern godot_packed_vector3_array godotsharp_packed_vector3_array_new_mem_copy(Vector3* p_src, int p_length); + public static extern godot_packed_vector3_array godotsharp_packed_vector3_array_new_mem_copy(Vector3* p_src, + int p_length); [DllImport(GodotDllName)] - public static extern godot_packed_color_array godotsharp_packed_color_array_new_mem_copy(Color* p_src, int p_length); + public static extern godot_packed_color_array godotsharp_packed_color_array_new_mem_copy(Color* p_src, + int p_length); [DllImport(GodotDllName)] - public static extern void godotsharp_packed_string_array_add(godot_packed_string_array* r_dest, godot_string* p_element); + public static extern void godotsharp_packed_string_array_add(godot_packed_string_array* r_dest, + godot_string* p_element); [DllImport(GodotDllName)] - public static extern void godotsharp_callable_new_with_delegate(IntPtr p_delegate_handle, godot_callable* r_callable); + public static extern void godotsharp_callable_new_with_delegate(IntPtr p_delegate_handle, + godot_callable* r_callable); [DllImport(GodotDllName)] - public static extern bool godotsharp_callable_get_data_for_marshalling(godot_callable* p_callable, IntPtr* r_delegate_handle, IntPtr* r_object, godot_string_name* r_name); + public static extern godot_bool godotsharp_callable_get_data_for_marshalling(godot_callable* p_callable, + IntPtr* r_delegate_handle, IntPtr* r_object, godot_string_name* r_name); // GDNative functions // gdnative.h [DllImport(GodotDllName)] - public static extern void godotsharp_method_bind_ptrcall(IntPtr p_method_bind, IntPtr p_instance, void** p_args, void* p_ret); + public static extern void godotsharp_method_bind_ptrcall(IntPtr p_method_bind, IntPtr p_instance, void** p_args, + void* p_ret); [DllImport(GodotDllName)] - public static extern godot_variant godotsharp_method_bind_call(IntPtr p_method_bind, IntPtr p_instance, godot_variant** p_args, int p_arg_count, godot_variant_call_error* p_call_error); + public static extern godot_variant godotsharp_method_bind_call(IntPtr p_method_bind, IntPtr p_instance, + godot_variant** p_args, int p_arg_count, godot_variant_call_error* p_call_error); // variant.h @@ -131,34 +145,43 @@ namespace Godot.NativeInterop public static extern void godotsharp_variant_new_array(godot_variant* r_dest, godot_array* p_arr); [DllImport(GodotDllName)] - public static extern void godotsharp_variant_new_packed_byte_array(godot_variant* r_dest, godot_packed_byte_array* p_pba); + public static extern void godotsharp_variant_new_packed_byte_array(godot_variant* r_dest, + godot_packed_byte_array* p_pba); [DllImport(GodotDllName)] - public static extern void godotsharp_variant_new_packed_int32_array(godot_variant* r_dest, godot_packed_int32_array* p_pia); + public static extern void godotsharp_variant_new_packed_int32_array(godot_variant* r_dest, + godot_packed_int32_array* p_pia); [DllImport(GodotDllName)] - public static extern void godotsharp_variant_new_packed_int64_array(godot_variant* r_dest, godot_packed_int64_array* p_pia); + public static extern void godotsharp_variant_new_packed_int64_array(godot_variant* r_dest, + godot_packed_int64_array* p_pia); [DllImport(GodotDllName)] - public static extern void godotsharp_variant_new_packed_float32_array(godot_variant* r_dest, godot_packed_float32_array* p_pra); + public static extern void godotsharp_variant_new_packed_float32_array(godot_variant* r_dest, + godot_packed_float32_array* p_pra); [DllImport(GodotDllName)] - public static extern void godotsharp_variant_new_packed_float64_array(godot_variant* r_dest, godot_packed_float64_array* p_pra); + public static extern void godotsharp_variant_new_packed_float64_array(godot_variant* r_dest, + godot_packed_float64_array* p_pra); [DllImport(GodotDllName)] - public static extern void godotsharp_variant_new_packed_string_array(godot_variant* r_dest, godot_packed_string_array* p_psa); + public static extern void godotsharp_variant_new_packed_string_array(godot_variant* r_dest, + godot_packed_string_array* p_psa); [DllImport(GodotDllName)] - public static extern void godotsharp_variant_new_packed_vector2_array(godot_variant* r_dest, godot_packed_vector2_array* p_pv2a); + public static extern void godotsharp_variant_new_packed_vector2_array(godot_variant* r_dest, + godot_packed_vector2_array* p_pv2a); [DllImport(GodotDllName)] - public static extern void godotsharp_variant_new_packed_vector3_array(godot_variant* r_dest, godot_packed_vector3_array* p_pv3a); + public static extern void godotsharp_variant_new_packed_vector3_array(godot_variant* r_dest, + godot_packed_vector3_array* p_pv3a); [DllImport(GodotDllName)] - public static extern void godotsharp_variant_new_packed_color_array(godot_variant* r_dest, godot_packed_color_array* p_pca); + public static extern void godotsharp_variant_new_packed_color_array(godot_variant* r_dest, + godot_packed_color_array* p_pca); [DllImport(GodotDllName)] - public static extern bool godotsharp_variant_as_bool(godot_variant* p_self); + public static extern godot_bool godotsharp_variant_as_bool(godot_variant* p_self); [DllImport(GodotDllName)] public static extern Int64 godotsharp_variant_as_int(godot_variant* p_self); @@ -248,23 +271,30 @@ namespace Godot.NativeInterop public static extern godot_packed_int64_array godotsharp_variant_as_packed_int64_array(godot_variant* p_self); [DllImport(GodotDllName)] - public static extern godot_packed_float32_array godotsharp_variant_as_packed_float32_array(godot_variant* p_self); + public static extern godot_packed_float32_array godotsharp_variant_as_packed_float32_array( + godot_variant* p_self); [DllImport(GodotDllName)] - public static extern godot_packed_float64_array godotsharp_variant_as_packed_float64_array(godot_variant* p_self); + public static extern godot_packed_float64_array godotsharp_variant_as_packed_float64_array( + godot_variant* p_self); [DllImport(GodotDllName)] public static extern godot_packed_string_array godotsharp_variant_as_packed_string_array(godot_variant* p_self); [DllImport(GodotDllName)] - public static extern godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array(godot_variant* p_self); + public static extern godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array( + godot_variant* p_self); [DllImport(GodotDllName)] - public static extern godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array(godot_variant* p_self); + public static extern godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array( + godot_variant* p_self); [DllImport(GodotDllName)] public static extern godot_packed_color_array godotsharp_variant_as_packed_color_array(godot_variant* p_self); + [DllImport(GodotDllName)] + public static extern godot_bool godotsharp_variant_equals(godot_variant* p_a, godot_variant* p_b); + // string.h [DllImport(GodotDllName)] @@ -283,11 +313,20 @@ namespace Godot.NativeInterop // array.h [DllImport(GodotDllName)] + public static extern void godotsharp_array_new(godot_array* p_self); + + [DllImport(GodotDllName)] public static extern void godotsharp_array_new_copy(godot_array* r_dest, godot_array* p_src); + [DllImport(GodotDllName)] + public static extern godot_variant* godotsharp_array_ptrw(ref godot_array p_self); + // dictionary.h [DllImport(GodotDllName)] + public static extern void godotsharp_dictionary_new(godot_dictionary* p_self); + + [DllImport(GodotDllName)] public static extern void godotsharp_dictionary_new_copy(godot_dictionary* r_dest, godot_dictionary* p_src); // destroy functions @@ -342,5 +381,134 @@ namespace Godot.NativeInterop [DllImport(GodotDllName)] public static extern void godotsharp_dictionary_destroy(ref godot_dictionary p_self); + + // Array + + [DllImport(GodotDllName)] + public static extern int godotsharp_array_add(ref godot_array p_self, godot_variant* p_item); + + [DllImport(GodotDllName)] + public static extern void + godotsharp_array_duplicate(ref godot_array p_self, godot_bool p_deep, out godot_array r_dest); + + [DllImport(GodotDllName)] + public static extern int godotsharp_array_index_of(ref godot_array p_self, godot_variant* p_item); + + [DllImport(GodotDllName)] + public static extern void godotsharp_array_insert(ref godot_array p_self, int p_index, godot_variant* p_item); + + [DllImport(GodotDllName)] + public static extern void godotsharp_array_remove_at(ref godot_array p_self, int p_index); + + [DllImport(GodotDllName)] + public static extern Error godotsharp_array_resize(ref godot_array p_self, int p_new_size); + + [DllImport(GodotDllName)] + public static extern Error godotsharp_array_shuffle(ref godot_array p_self); + + [DllImport(GodotDllName)] + public static extern void godotsharp_array_to_string(ref godot_array p_self, godot_string* r_str); + + // Dictionary + + [DllImport(GodotDllName)] + public static extern godot_bool godotsharp_dictionary_try_get_value(ref godot_dictionary p_self, + godot_variant* p_key, + out godot_variant r_value); + + [DllImport(GodotDllName)] + public static extern void godotsharp_dictionary_set_value(ref godot_dictionary p_self, godot_variant* p_key, + godot_variant* p_value); + + [DllImport(GodotDllName)] + public static extern void godotsharp_dictionary_keys(ref godot_dictionary p_self, out godot_array r_dest); + + [DllImport(GodotDllName)] + public static extern void godotsharp_dictionary_values(ref godot_dictionary p_self, out godot_array r_dest); + + [DllImport(GodotDllName)] + public static extern int godotsharp_dictionary_count(ref godot_dictionary p_self); + + [DllImport(GodotDllName)] + public static extern void godotsharp_dictionary_key_value_pair_at(ref godot_dictionary p_self, int p_index, + out godot_variant r_key, out godot_variant r_value); + + [DllImport(GodotDllName)] + public static extern void godotsharp_dictionary_add(ref godot_dictionary p_self, godot_variant* p_key, + godot_variant* p_value); + + [DllImport(GodotDllName)] + public static extern void godotsharp_dictionary_clear(ref godot_dictionary p_self); + + [DllImport(GodotDllName)] + public static extern godot_bool godotsharp_dictionary_contains_key(ref godot_dictionary p_self, + godot_variant* p_key); + + [DllImport(GodotDllName)] + public static extern void godotsharp_dictionary_duplicate(ref godot_dictionary p_self, godot_bool p_deep, + out godot_dictionary r_dest); + + [DllImport(GodotDllName)] + public static extern godot_bool godotsharp_dictionary_remove_key(ref godot_dictionary p_self, + godot_variant* p_key); + + [DllImport(GodotDllName)] + public static extern void godotsharp_dictionary_to_string(ref godot_dictionary p_self, godot_string* r_str); + + // StringExtensions + + [DllImport(GodotDllName)] + public static extern void godotsharp_string_md5_buffer(godot_string* p_self, + godot_packed_byte_array* r_md5_buffer); + + [DllImport(GodotDllName)] + public static extern void godotsharp_string_md5_text(godot_string* p_self, godot_string* r_md5_text); + + [DllImport(GodotDllName)] + public static extern int godotsharp_string_rfind(godot_string* p_self, godot_string* p_what, int p_from); + + [DllImport(GodotDllName)] + public static extern int godotsharp_string_rfindn(godot_string* p_self, godot_string* p_what, int p_from); + + [DllImport(GodotDllName)] + public static extern void godotsharp_string_sha256_buffer(godot_string* p_self, + godot_packed_byte_array* r_sha256_buffer); + + [DllImport(GodotDllName)] + public static extern void godotsharp_string_sha256_text(godot_string* p_self, godot_string* r_sha256_text); + + [DllImport(GodotDllName)] + public static extern void godotsharp_string_simplify_path(godot_string* p_self, godot_string* r_simplified_path); + + // NodePath + + [DllImport(GodotDllName)] + public static extern void godotsharp_node_path_get_as_property_path(ref godot_node_path p_self, + ref godot_node_path r_dest); + + [DllImport(GodotDllName)] + public static extern void godotsharp_node_path_get_concatenated_names(ref godot_node_path p_self, + godot_string* r_names); + + [DllImport(GodotDllName)] + public static extern void godotsharp_node_path_get_concatenated_subnames(ref godot_node_path p_self, + godot_string* r_subnames); + + [DllImport(GodotDllName)] + public static extern void godotsharp_node_path_get_name(ref godot_node_path p_self, int p_idx, + godot_string* r_name); + + [DllImport(GodotDllName)] + public static extern int godotsharp_node_path_get_name_count(ref godot_node_path p_self); + + [DllImport(GodotDllName)] + public static extern void godotsharp_node_path_get_subname(ref godot_node_path p_self, int p_idx, + godot_string* r_subname); + + [DllImport(GodotDllName)] + public static extern int godotsharp_node_path_get_subname_count(ref godot_node_path p_self); + + [DllImport(GodotDllName)] + public static extern bool godotsharp_node_path_is_absolute(ref godot_node_path p_self); } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs index 70df79c1de..6001b3a0de 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.extended.cs @@ -29,6 +29,13 @@ namespace Godot.NativeInterop public static godot_node_path godotsharp_node_path_new_copy(godot_node_path src) => godotsharp_node_path_new_copy(&src); + public static godot_array godotsharp_array_new() + { + godot_array ret; + godotsharp_array_new(&ret); + return ret; + } + public static godot_array godotsharp_array_new_copy(godot_array* src) { godot_array ret; @@ -40,6 +47,13 @@ namespace Godot.NativeInterop public static godot_array godotsharp_array_new_copy(godot_array src) => godotsharp_array_new_copy(&src); + public static godot_dictionary godotsharp_dictionary_new() + { + godot_dictionary ret; + godotsharp_dictionary_new(&ret); + return ret; + } + public static godot_dictionary godotsharp_dictionary_new_copy(godot_dictionary* src) { godot_dictionary ret; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs index 90e51e8a1a..541364b281 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs @@ -161,7 +161,7 @@ namespace Godot public NodePath GetAsPropertyPath() { godot_node_path propertyPath = default; - godot_icall_NodePath_get_as_property_path(ref NativeValue, ref propertyPath); + NativeFuncs.godotsharp_node_path_get_as_property_path(ref NativeValue, ref propertyPath); return CreateTakingOwnershipOfDisposableValue(propertyPath); } @@ -175,9 +175,11 @@ namespace Godot /// </code> /// </example> /// <returns>The names concatenated with <c>/</c>.</returns> - public string GetConcatenatedNames() + public unsafe string GetConcatenatedNames() { - return godot_icall_NodePath_get_concatenated_names(ref NativeValue); + using godot_string names = default; + NativeFuncs.godotsharp_node_path_get_concatenated_names(ref NativeValue, &names); + return Marshaling.mono_string_from_godot(&names); } /// <summary> @@ -191,9 +193,11 @@ namespace Godot /// </code> /// </example> /// <returns>The subnames concatenated with <c>:</c>.</returns> - public string GetConcatenatedSubNames() + public unsafe string GetConcatenatedSubNames() { - return godot_icall_NodePath_get_concatenated_subnames(ref NativeValue); + using godot_string subNames = default; + NativeFuncs.godotsharp_node_path_get_concatenated_subnames(ref NativeValue, &subNames); + return Marshaling.mono_string_from_godot(&subNames); } /// <summary> @@ -209,9 +213,11 @@ namespace Godot /// </example> /// <param name="idx">The name index.</param> /// <returns>The name at the given index <paramref name="idx"/>.</returns> - public string GetName(int idx) + public unsafe string GetName(int idx) { - return godot_icall_NodePath_get_name(ref NativeValue, idx); + using godot_string name = default; + NativeFuncs.godotsharp_node_path_get_name(ref NativeValue, idx, &name); + return Marshaling.mono_string_from_godot(&name); } /// <summary> @@ -222,7 +228,7 @@ namespace Godot /// <returns>The number of node names which make up the path.</returns> public int GetNameCount() { - return godot_icall_NodePath_get_name_count(ref NativeValue); + return NativeFuncs.godotsharp_node_path_get_name_count(ref NativeValue); } /// <summary> @@ -230,9 +236,11 @@ namespace Godot /// </summary> /// <param name="idx">The subname index.</param> /// <returns>The subname at the given index <paramref name="idx"/>.</returns> - public string GetSubName(int idx) + public unsafe string GetSubName(int idx) { - return godot_icall_NodePath_get_subname(ref NativeValue, idx); + using godot_string subName = default; + NativeFuncs.godotsharp_node_path_get_subname(ref NativeValue, idx, &subName); + return Marshaling.mono_string_from_godot(&subName); } /// <summary> @@ -243,7 +251,7 @@ namespace Godot /// <returns>The number of subnames in the path.</returns> public int GetSubNameCount() { - return godot_icall_NodePath_get_subname_count(ref NativeValue); + return NativeFuncs.godotsharp_node_path_get_subname_count(ref NativeValue); } /// <summary> @@ -255,7 +263,7 @@ namespace Godot /// <returns>If the <see cref="NodePath"/> is an absolute path.</returns> public bool IsAbsolute() { - return godot_icall_NodePath_is_absolute(ref NativeValue); + return NativeFuncs.godotsharp_node_path_is_absolute(ref NativeValue); } /// <summary> @@ -263,29 +271,5 @@ namespace Godot /// </summary> /// <returns>If the <see cref="NodePath"/> is empty.</returns> public bool IsEmpty => godot_node_path.IsEmpty(in NativeValue); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void godot_icall_NodePath_get_as_property_path(ref godot_node_path ptr, ref godot_node_path dest); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern string godot_icall_NodePath_get_concatenated_names(ref godot_node_path ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern string godot_icall_NodePath_get_concatenated_subnames(ref godot_node_path ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern string godot_icall_NodePath_get_name(ref godot_node_path ptr, int arg1); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern int godot_icall_NodePath_get_name_count(ref godot_node_path ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern string godot_icall_NodePath_get_subname(ref godot_node_path ptr, int arg1); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern int godot_icall_NodePath_get_subname_count(ref godot_node_path ptr); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool godot_icall_NodePath_is_absolute(ref godot_node_path ptr); } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs index 058c5447e2..6c3d673fdc 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using System.Security; using System.Text; using System.Text.RegularExpressions; +using Godot.NativeInterop; namespace Godot { @@ -177,6 +178,7 @@ namespace Godot { return 0; } + if (from == 0 && to == len) { str = instance; @@ -471,7 +473,8 @@ namespace Godot /// <returns>The starting position of the substring, or -1 if not found.</returns> public static int Find(this string instance, string what, int from = 0, bool caseSensitive = true) { - return instance.IndexOf(what, from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase); + return instance.IndexOf(what, from, + caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase); } /// <summary> @@ -490,7 +493,8 @@ namespace Godot { // TODO: Could be more efficient if we get a char version of `IndexOf`. // See https://github.com/dotnet/runtime/issues/44116 - return instance.IndexOf(what.ToString(), from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase); + return instance.IndexOf(what.ToString(), from, + caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase); } /// <summary>Find the last occurrence of a substring.</summary> @@ -519,7 +523,8 @@ namespace Godot /// <returns>The starting position of the substring, or -1 if not found.</returns> public static int FindLast(this string instance, string what, int from, bool caseSensitive = true) { - return instance.LastIndexOf(what, from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase); + return instance.LastIndexOf(what, from, + caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase); } /// <summary> @@ -804,6 +809,7 @@ namespace Godot { match = instance[source] == text[target]; } + if (match) { source++; @@ -1015,15 +1021,18 @@ namespace Godot switch (expr[0]) { case '*': - return ExprMatch(instance, expr.Substring(1), caseSensitive) || (instance.Length > 0 && ExprMatch(instance.Substring(1), expr, caseSensitive)); + return ExprMatch(instance, expr.Substring(1), caseSensitive) || (instance.Length > 0 && + ExprMatch(instance.Substring(1), expr, caseSensitive)); case '?': - return instance.Length > 0 && instance[0] != '.' && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive); + return instance.Length > 0 && instance[0] != '.' && + ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive); default: if (instance.Length == 0) return false; if (caseSensitive) return instance[0] == expr[0]; - return (char.ToUpper(instance[0]) == char.ToUpper(expr[0])) && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive); + return (char.ToUpper(instance[0]) == char.ToUpper(expr[0])) && + ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive); } } @@ -1068,28 +1077,28 @@ namespace Godot /// <seealso cref="MD5Text(string)"/> /// <param name="instance">The string to hash.</param> /// <returns>The MD5 hash of the string.</returns> - public static byte[] MD5Buffer(this string instance) + public static unsafe byte[] MD5Buffer(this string instance) { - return godot_icall_String_md5_buffer(instance); + using godot_string instanceStr = Marshaling.mono_string_to_godot(instance); + using godot_packed_byte_array md5Buffer = default; + NativeFuncs.godotsharp_string_md5_buffer(&instanceStr, &md5Buffer); + return Marshaling.PackedByteArray_to_mono_array(&md5Buffer); } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern byte[] godot_icall_String_md5_buffer(string str); - /// <summary> /// Returns the MD5 hash of the string as a string. /// </summary> /// <seealso cref="MD5Buffer(string)"/> /// <param name="instance">The string to hash.</param> /// <returns>The MD5 hash of the string.</returns> - public static string MD5Text(this string instance) + public static unsafe string MD5Text(this string instance) { - return godot_icall_String_md5_text(instance); + using godot_string instanceStr = Marshaling.mono_string_to_godot(instance); + using godot_string md5Text = default; + NativeFuncs.godotsharp_string_md5_text(&instanceStr, &md5Text); + return Marshaling.mono_string_from_godot(&md5Text); } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern string godot_icall_String_md5_text(string str); - /// <summary> /// Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater. /// </summary> @@ -1242,14 +1251,13 @@ namespace Godot /// <param name="what">The substring to search in the string.</param> /// <param name="from">The position at which to start searching.</param> /// <returns>The position at which the substring was found, or -1 if not found.</returns> - public static int RFind(this string instance, string what, int from = -1) + public static unsafe int RFind(this string instance, string what, int from = -1) { - return godot_icall_String_rfind(instance, what, from); + using godot_string instanceStr = Marshaling.mono_string_to_godot(instance); + using godot_string whatStr = Marshaling.mono_string_to_godot(instance); + return NativeFuncs.godotsharp_string_rfind(&instanceStr, &whatStr, from); } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern int godot_icall_String_rfind(string str, string what, int from); - /// <summary> /// Perform a search for a substring, but start from the end of the string instead of the beginning. /// Also search case-insensitive. @@ -1259,14 +1267,13 @@ namespace Godot /// <param name="what">The substring to search in the string.</param> /// <param name="from">The position at which to start searching.</param> /// <returns>The position at which the substring was found, or -1 if not found.</returns> - public static int RFindN(this string instance, string what, int from = -1) + public static unsafe int RFindN(this string instance, string what, int from = -1) { - return godot_icall_String_rfindn(instance, what, from); + using godot_string instanceStr = Marshaling.mono_string_to_godot(instance); + using godot_string whatStr = Marshaling.mono_string_to_godot(instance); + return NativeFuncs.godotsharp_string_rfindn(&instanceStr, &whatStr, from); } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern int godot_icall_String_rfindn(string str, string what, int from); - /// <summary> /// Returns the right side of the string from a given position. /// </summary> @@ -1319,28 +1326,28 @@ namespace Godot /// <seealso cref="SHA256Text(string)"/> /// <param name="instance">The string to hash.</param> /// <returns>The SHA-256 hash of the string.</returns> - public static byte[] SHA256Buffer(this string instance) + public static unsafe byte[] SHA256Buffer(this string instance) { - return godot_icall_String_sha256_buffer(instance); + using godot_string instanceStr = Marshaling.mono_string_to_godot(instance); + using godot_packed_byte_array sha256Buffer = default; + NativeFuncs.godotsharp_string_sha256_buffer(&instanceStr, &sha256Buffer); + return Marshaling.PackedByteArray_to_mono_array(&sha256Buffer); } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern byte[] godot_icall_String_sha256_buffer(string str); - /// <summary> /// Returns the SHA-256 hash of the string as a string. /// </summary> /// <seealso cref="SHA256Buffer(string)"/> /// <param name="instance">The string to hash.</param> /// <returns>The SHA-256 hash of the string.</returns> - public static string SHA256Text(this string instance) + public static unsafe string SHA256Text(this string instance) { - return godot_icall_String_sha256_text(instance); + using godot_string instanceStr = Marshaling.mono_string_to_godot(instance); + using godot_string sha256Text = default; + NativeFuncs.godotsharp_string_sha256_text(&instanceStr, &sha256Text); + return Marshaling.mono_string_from_godot(&sha256Text); } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern string godot_icall_String_sha256_text(string str); - /// <summary> /// Returns the similarity index of the text compared to this string. /// 1 means totally similar and 0 means totally dissimilar. @@ -1355,6 +1362,7 @@ namespace Godot // Equal strings are totally similar return 1.0f; } + if (instance.Length < 2 || text.Length < 2) { // No way to calculate similarity without a single bigram @@ -1388,14 +1396,14 @@ namespace Godot /// <summary> /// Returns a simplified canonical path. /// </summary> - public static string SimplifyPath(this string instance) + public static unsafe string SimplifyPath(this string instance) { - return godot_icall_String_simplify_path(instance); + using godot_string instanceStr = Marshaling.mono_string_to_godot(instance); + using godot_string simplifiedPath = default; + NativeFuncs.godotsharp_string_simplify_path(&instanceStr, &simplifiedPath); + return Marshaling.mono_string_from_godot(&simplifiedPath); } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern string godot_icall_String_simplify_path(string str); - /// <summary> /// Split the string by a divisor string, return an array of the substrings. /// Example "One,Two,Three" will return ["One","Two","Three"] if split by ",". @@ -1409,7 +1417,8 @@ namespace Godot /// <returns>The array of strings split from the string.</returns> public static string[] Split(this string instance, string divisor, bool allowEmpty = true) { - return instance.Split(new[] { divisor }, allowEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries); + return instance.Split(new[] { divisor }, + allowEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries); } /// <summary> diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp deleted file mode 100644 index 30adea60cc..0000000000 --- a/modules/mono/glue/collections_glue.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/*************************************************************************/ -/* collections_glue.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include <mono/metadata/exception.h> - -#include "core/variant/array.h" - -#include "../mono_gd/gd_mono_cache.h" -#include "../mono_gd/gd_mono_class.h" -#include "../mono_gd/gd_mono_marshal.h" -#include "../mono_gd/gd_mono_utils.h" - -void godot_icall_Array_Ctor(Array *r_dest) { - memnew_placement(r_dest, Array); -} - -void godot_icall_Array_At(Array *ptr, int32_t index, Variant *r_elem) { - if (index < 0 || index >= ptr->size()) { - GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range()); - *r_elem = Variant(); - return; - } - *r_elem = ptr->operator[](index); -} - -void godot_icall_Array_SetAt(Array *ptr, int32_t index, MonoObject *value) { - if (index < 0 || index >= ptr->size()) { - GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range()); - return; - } - ptr->operator[](index) = GDMonoMarshal::mono_object_to_variant(value); -} - -int32_t godot_icall_Array_Count(Array *ptr) { - return ptr->size(); -} - -int32_t godot_icall_Array_Add(Array *ptr, MonoObject *item) { - ptr->append(GDMonoMarshal::mono_object_to_variant(item)); - return ptr->size(); -} - -void godot_icall_Array_Clear(Array *ptr) { - ptr->clear(); -} - -MonoBoolean godot_icall_Array_Contains(Array *ptr, MonoObject *item) { - return ptr->find(GDMonoMarshal::mono_object_to_variant(item)) != -1; -} - -void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int32_t array_index) { - unsigned int count = ptr->size(); - - if (mono_array_length(array) < (array_index + count)) { - MonoException *exc = mono_get_exception_argument("", "Destination array was not long enough. Check destIndex and length, and the array's lower bounds."); - GDMonoUtils::set_pending_exception(exc); - return; - } - - for (unsigned int i = 0; i < count; i++) { - MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(ptr->operator[](i)); - mono_array_setref(array, array_index, boxed); - array_index++; - } -} - -void godot_icall_Array_Ctor_MonoArray(MonoArray *mono_array, Array *r_dest) { - memnew_placement(r_dest, Array); - unsigned int count = mono_array_length(mono_array); - r_dest->resize(count); - for (unsigned int i = 0; i < count; i++) { - MonoObject *item = mono_array_get(mono_array, MonoObject *, i); - godot_icall_Array_SetAt(r_dest, i, item); - } -} - -void godot_icall_Array_Duplicate(Array *ptr, MonoBoolean deep, Array *r_dest) { - memnew_placement(r_dest, Array(ptr->duplicate(deep))); -} - -void godot_icall_Array_Concatenate(Array *left, Array *right, Array *r_dest) { - int count = left->size() + right->size(); - memnew_placement(r_dest, Array(left->duplicate(false))); - r_dest->resize(count); - for (unsigned int i = 0; i < (unsigned int)right->size(); i++) { - r_dest->operator[](i + left->size()) = right->operator[](i); - } -} - -int32_t godot_icall_Array_IndexOf(Array *ptr, MonoObject *item) { - return ptr->find(GDMonoMarshal::mono_object_to_variant(item)); -} - -void godot_icall_Array_Insert(Array *ptr, int32_t index, MonoObject *item) { - if (index < 0 || index > ptr->size()) { - GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range()); - return; - } - ptr->insert(index, GDMonoMarshal::mono_object_to_variant(item)); -} - -MonoBoolean godot_icall_Array_Remove(Array *ptr, MonoObject *item) { - int idx = ptr->find(GDMonoMarshal::mono_object_to_variant(item)); - if (idx >= 0) { - ptr->remove_at(idx); - return true; - } - return false; -} - -void godot_icall_Array_RemoveAt(Array *ptr, int32_t index) { - if (index < 0 || index >= ptr->size()) { - GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range()); - return; - } - ptr->remove_at(index); -} - -int32_t godot_icall_Array_Resize(Array *ptr, int32_t new_size) { - return (int32_t)ptr->resize(new_size); -} - -void godot_icall_Array_Shuffle(Array *ptr) { - ptr->shuffle(); -} - -MonoString *godot_icall_Array_ToString(Array *ptr) { - return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String()); -} - -void godot_icall_Dictionary_Ctor(Dictionary *r_dest) { - memnew_placement(r_dest, Dictionary); -} - -void godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key, Variant *r_value) { - Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key)); - if (ret == nullptr) { - MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr()); -#ifdef DEBUG_ENABLED - CRASH_COND(!exc); -#endif - GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException)); - GDMonoUtils::set_pending_exception((MonoException *)exc); - *r_value = Variant(); - return; - } - *r_value = *ret; -} - -void godot_icall_Dictionary_SetValue(Dictionary *ptr, MonoObject *key, MonoObject *value) { - ptr->operator[](GDMonoMarshal::mono_object_to_variant(key)) = GDMonoMarshal::mono_object_to_variant(value); -} - -void godot_icall_Dictionary_Keys(Dictionary *ptr, Array *r_dest) { - memnew_placement(r_dest, Array(ptr->keys())); -} - -void godot_icall_Dictionary_Values(Dictionary *ptr, Array *r_dest) { - memnew_placement(r_dest, Array(ptr->values())); -} - -int32_t godot_icall_Dictionary_Count(Dictionary *ptr) { - return ptr->size(); -} - -int32_t godot_icall_Dictionary_KeyValuePairs(Dictionary *ptr, Array *keys, Array *values) { - memnew_placement(keys, Array(ptr->keys())); - memnew_placement(values, Array(ptr->values())); - return ptr->size(); -} - -void godot_icall_Dictionary_KeyValuePairAt(Dictionary *ptr, int index, Variant *r_key, Variant *r_value) { - memnew_placement(r_key, Variant(ptr->get_key_at_index(index))); - memnew_placement(r_value, Variant(ptr->get_value_at_index(index))); -} - -void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value) { - Variant varKey = GDMonoMarshal::mono_object_to_variant(key); - Variant *ret = ptr->getptr(varKey); - if (ret != nullptr) { - GDMonoUtils::set_pending_exception(mono_get_exception_argument("key", "An element with the same key already exists")); - return; - } - ptr->operator[](varKey) = GDMonoMarshal::mono_object_to_variant(value); -} - -void godot_icall_Dictionary_Clear(Dictionary *ptr) { - ptr->clear(); -} - -MonoBoolean godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value) { - // no dupes - Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key)); - return ret != nullptr && *ret == GDMonoMarshal::mono_object_to_variant(value); -} - -MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key) { - return ptr->has(GDMonoMarshal::mono_object_to_variant(key)); -} - -void godot_icall_Dictionary_Duplicate(Dictionary *ptr, MonoBoolean deep, Dictionary *r_dest) { - memnew_placement(r_dest, Dictionary(ptr->duplicate(deep))); -} - -MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) { - return ptr->erase(GDMonoMarshal::mono_object_to_variant(key)); -} - -MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value) { - Variant varKey = GDMonoMarshal::mono_object_to_variant(key); - - // no dupes - Variant *ret = ptr->getptr(varKey); - if (ret != nullptr && *ret == GDMonoMarshal::mono_object_to_variant(value)) { - ptr->erase(varKey); - return true; - } - - return false; -} - -MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, Variant *value) { - Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key)); - if (ret == nullptr) { - *value = Variant(); - return false; - } - *value = *ret; - return true; -} - -MonoString *godot_icall_Dictionary_ToString(Dictionary *ptr) { - return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String()); -} - -void godot_register_collections_icalls() { - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor", godot_icall_Array_Ctor); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor_MonoArray", godot_icall_Array_Ctor_MonoArray); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_At", godot_icall_Array_At); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_SetAt", godot_icall_Array_SetAt); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Count", godot_icall_Array_Count); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Add", godot_icall_Array_Add); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Clear", godot_icall_Array_Clear); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Concatenate", godot_icall_Array_Concatenate); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Contains", godot_icall_Array_Contains); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_CopyTo", godot_icall_Array_CopyTo); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Duplicate", godot_icall_Array_Duplicate); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_IndexOf", godot_icall_Array_IndexOf); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Insert", godot_icall_Array_Insert); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Remove", godot_icall_Array_Remove); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_RemoveAt", godot_icall_Array_RemoveAt); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Resize", godot_icall_Array_Resize); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Shuffle", godot_icall_Array_Shuffle); - GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_ToString", godot_icall_Array_ToString); - - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Ctor", godot_icall_Dictionary_Ctor); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue", godot_icall_Dictionary_GetValue); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_SetValue", godot_icall_Dictionary_SetValue); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Keys", godot_icall_Dictionary_Keys); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Values", godot_icall_Dictionary_Values); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Count", godot_icall_Dictionary_Count); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairs", godot_icall_Dictionary_KeyValuePairs); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairAt", godot_icall_Dictionary_KeyValuePairAt); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Add", godot_icall_Dictionary_Add); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Clear", godot_icall_Dictionary_Clear); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Contains", godot_icall_Dictionary_Contains); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ContainsKey", godot_icall_Dictionary_ContainsKey); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Duplicate", godot_icall_Dictionary_Duplicate); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_RemoveKey", godot_icall_Dictionary_RemoveKey); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Remove", godot_icall_Dictionary_Remove); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue", godot_icall_Dictionary_TryGetValue); - GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ToString", godot_icall_Dictionary_ToString); -} diff --git a/modules/mono/glue/node_path_glue.cpp b/modules/mono/glue/node_path_glue.cpp deleted file mode 100644 index 770ed31260..0000000000 --- a/modules/mono/glue/node_path_glue.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/*************************************************************************/ -/* node_path_glue.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "core/string/node_path.h" -#include "core/string/ustring.h" - -#include "../mono_gd/gd_mono_marshal.h" - -MonoBoolean godot_icall_NodePath_is_absolute(NodePath *p_ptr) { - return (MonoBoolean)p_ptr->is_absolute(); -} - -int32_t godot_icall_NodePath_get_name_count(NodePath *p_ptr) { - return p_ptr->get_name_count(); -} - -MonoString *godot_icall_NodePath_get_name(NodePath *p_ptr, uint32_t p_idx) { - return GDMonoMarshal::mono_string_from_godot(p_ptr->get_name(p_idx)); -} - -int32_t godot_icall_NodePath_get_subname_count(NodePath *p_ptr) { - return p_ptr->get_subname_count(); -} - -MonoString *godot_icall_NodePath_get_subname(NodePath *p_ptr, uint32_t p_idx) { - return GDMonoMarshal::mono_string_from_godot(p_ptr->get_subname(p_idx)); -} - -MonoString *godot_icall_NodePath_get_concatenated_names(NodePath *p_ptr) { - return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_names()); -} - -MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr) { - return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_subnames()); -} - -void godot_icall_NodePath_get_as_property_path(NodePath *p_ptr, NodePath *r_dest) { - *r_dest = p_ptr->get_as_property_path(); -} - -void godot_register_node_path_icalls() { - GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_as_property_path", godot_icall_NodePath_get_as_property_path); - GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_names", godot_icall_NodePath_get_concatenated_names); - GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_subnames", godot_icall_NodePath_get_concatenated_subnames); - GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name", godot_icall_NodePath_get_name); - GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name_count", godot_icall_NodePath_get_name_count); - GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_subname", godot_icall_NodePath_get_subname); - GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_subname_count", godot_icall_NodePath_get_subname_count); - GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_is_absolute", godot_icall_NodePath_is_absolute); -} diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp index a9c47f8880..f5a04bf05c 100644 --- a/modules/mono/glue/runtime_interop.cpp +++ b/modules/mono/glue/runtime_interop.cpp @@ -56,6 +56,9 @@ extern "C" { #define GD_PINVOKE_EXPORT MAYBE_UNUSED #endif +// For ArrayPrivate and DictionaryPrivate +static_assert(sizeof(SafeRefCount) == sizeof(uint32_t)); + typedef Object *(*godotsharp_class_creation_func)(); GD_PINVOKE_EXPORT MethodBind *godotsharp_method_bind_get_method(const StringName *p_classname, const char16_t *p_methodname) { @@ -185,7 +188,7 @@ GD_PINVOKE_EXPORT void godotsharp_packed_string_array_add(PackedStringArray *r_d GD_PINVOKE_EXPORT void godotsharp_callable_new_with_delegate(void *p_delegate_handle, Callable *r_callable) { // TODO: Use pooling for ManagedCallable instances. CallableCustom *managed_callable = memnew(ManagedCallable(p_delegate_handle)); - *r_callable = Callable(managed_callable); + memnew_placement(r_callable, Callable(managed_callable)); } GD_PINVOKE_EXPORT bool godotsharp_callable_get_data_for_marshalling(const Callable *p_callable, @@ -198,31 +201,31 @@ GD_PINVOKE_EXPORT bool godotsharp_callable_get_data_for_marshalling(const Callab ManagedCallable *managed_callable = static_cast<ManagedCallable *>(custom); *r_delegate_handle = managed_callable->get_delegate(); *r_object = nullptr; - *r_name = StringName(); + memnew_placement(r_name, StringName()); return true; } else if (compare_equal_func == SignalAwaiterCallable::compare_equal_func_ptr) { SignalAwaiterCallable *signal_awaiter_callable = static_cast<SignalAwaiterCallable *>(custom); *r_delegate_handle = nullptr; *r_object = ObjectDB::get_instance(signal_awaiter_callable->get_object()); - *r_name = signal_awaiter_callable->get_signal(); + memnew_placement(r_name, StringName(signal_awaiter_callable->get_signal())); return true; } else if (compare_equal_func == EventSignalCallable::compare_equal_func_ptr) { EventSignalCallable *event_signal_callable = static_cast<EventSignalCallable *>(custom); *r_delegate_handle = nullptr; *r_object = ObjectDB::get_instance(event_signal_callable->get_object()); - *r_name = event_signal_callable->get_signal(); + memnew_placement(r_name, StringName(event_signal_callable->get_signal())); return true; } // Some other CallableCustom. We only support ManagedCallable. *r_delegate_handle = nullptr; *r_object = nullptr; - *r_name = StringName(); + memnew_placement(r_name, StringName()); return false; } else { *r_delegate_handle = nullptr; *r_object = ObjectDB::get_instance(p_callable->get_object_id()); - *r_name = p_callable->get_method(); + memnew_placement(r_name, StringName(p_callable->get_method())); return true; } } @@ -235,7 +238,7 @@ GD_PINVOKE_EXPORT void godotsharp_method_bind_ptrcall(MethodBind *p_method_bind, p_method_bind->ptrcall(p_instance, p_args, p_ret); } -GD_PINVOKE_EXPORT godot_variant godotsharp_method_bind_call(MethodBind *p_method_bind, Object *p_instance, const godot_variant **p_args, const int p_arg_count, Callable::CallError *p_call_error) { +GD_PINVOKE_EXPORT godot_variant godotsharp_method_bind_call(MethodBind *p_method_bind, Object *p_instance, const godot_variant **p_args, const int32_t p_arg_count, Callable::CallError *p_call_error) { godot_variant ret; memnew_placement(&ret, Variant()); @@ -575,6 +578,10 @@ GD_PINVOKE_EXPORT godot_packed_array godotsharp_variant_as_packed_color_array(co return raw_dest; } +GD_PINVOKE_EXPORT bool godotsharp_variant_equals(const godot_variant *p_a, const godot_variant *p_b) { + return *reinterpret_cast<const Variant *>(p_a) == *reinterpret_cast<const Variant *>(p_b); +} + // string.h GD_PINVOKE_EXPORT void godotsharp_string_new_with_utf16_chars(String *r_dest, const char16_t *p_contents) { @@ -596,12 +603,24 @@ GD_PINVOKE_EXPORT void godotsharp_node_path_new_copy(NodePath *r_dest, const Nod // array.h +GD_PINVOKE_EXPORT void godotsharp_array_new(Array *r_dest) { + memnew_placement(r_dest, Array); +} + GD_PINVOKE_EXPORT void godotsharp_array_new_copy(Array *r_dest, const Array *p_src) { memnew_placement(r_dest, Array(*p_src)); } +GD_PINVOKE_EXPORT godot_variant *godotsharp_array_ptrw(godot_array *p_self) { + return reinterpret_cast<godot_variant *>(&reinterpret_cast<Array *>(p_self)->operator[](0)); +} + // dictionary.h +GD_PINVOKE_EXPORT void godotsharp_dictionary_new(Dictionary *r_dest) { + memnew_placement(r_dest, Dictionary); +} + GD_PINVOKE_EXPORT void godotsharp_dictionary_new_copy(Dictionary *r_dest, const Dictionary *p_src) { memnew_placement(r_dest, Dictionary(*p_src)); } @@ -676,12 +695,156 @@ GD_PINVOKE_EXPORT void godotsharp_dictionary_destroy(Dictionary *p_self) { p_self->~Dictionary(); } +// Array + +GD_PINVOKE_EXPORT int32_t godotsharp_array_add(Array *p_self, const Variant *p_item) { + p_self->append(*p_item); + return p_self->size(); +} + +GD_PINVOKE_EXPORT void godotsharp_array_duplicate(const Array *p_self, bool p_deep, Array *r_dest) { + memnew_placement(r_dest, Array(p_self->duplicate(p_deep))); +} + +GD_PINVOKE_EXPORT int32_t godotsharp_array_index_of(const Array *p_self, const Variant *p_item) { + return p_self->find(*p_item); +} + +GD_PINVOKE_EXPORT void godotsharp_array_insert(Array *p_self, int32_t p_index, const Variant *p_item) { + p_self->insert(p_index, *p_item); +} + +GD_PINVOKE_EXPORT void godotsharp_array_remove_at(Array *p_self, int32_t p_index) { + p_self->remove_at(p_index); +} + +GD_PINVOKE_EXPORT int32_t godotsharp_array_resize(Array *p_self, int32_t p_new_size) { + return (int32_t)p_self->resize(p_new_size); +} + +GD_PINVOKE_EXPORT void godotsharp_array_shuffle(Array *p_self) { + p_self->shuffle(); +} + +// Dictionary + +GD_PINVOKE_EXPORT bool godotsharp_dictionary_try_get_value(const Dictionary *p_self, const Variant *p_key, Variant *r_value) { + const Variant *ret = p_self->getptr(*p_key); + if (ret == nullptr) { + memnew_placement(r_value, Variant()); + return false; + } + memnew_placement(r_value, Variant(*ret)); + return true; +} + +GD_PINVOKE_EXPORT void godotsharp_dictionary_set_value(Dictionary *p_self, const Variant *p_key, const Variant *p_value) { + p_self->operator[](*p_key) = *p_value; +} + +GD_PINVOKE_EXPORT void godotsharp_dictionary_keys(const Dictionary *p_self, Array *r_dest) { + memnew_placement(r_dest, Array(p_self->keys())); +} + +GD_PINVOKE_EXPORT void godotsharp_dictionary_values(const Dictionary *p_self, Array *r_dest) { + memnew_placement(r_dest, Array(p_self->values())); +} + +GD_PINVOKE_EXPORT int32_t godotsharp_dictionary_count(const Dictionary *p_self) { + return p_self->size(); +} + +GD_PINVOKE_EXPORT void godotsharp_dictionary_key_value_pair_at(const Dictionary *p_self, int32_t p_index, Variant *r_key, Variant *r_value) { + memnew_placement(r_key, Variant(p_self->get_key_at_index(p_index))); + memnew_placement(r_value, Variant(p_self->get_value_at_index(p_index))); +} + +GD_PINVOKE_EXPORT void godotsharp_dictionary_add(Dictionary *p_self, const Variant *p_key, const Variant *p_value) { + p_self->operator[](*p_key) = *p_value; +} + +GD_PINVOKE_EXPORT void godotsharp_dictionary_clear(Dictionary *p_self) { + p_self->clear(); +} + +GD_PINVOKE_EXPORT bool godotsharp_dictionary_contains_key(const Dictionary *p_self, const Variant *p_key) { + return p_self->has(*p_key); +} + +GD_PINVOKE_EXPORT void godotsharp_dictionary_duplicate(const Dictionary *p_self, bool p_deep, Dictionary *r_dest) { + memnew_placement(r_dest, Dictionary(p_self->duplicate(p_deep))); +} + +GD_PINVOKE_EXPORT bool godotsharp_dictionary_remove_key(Dictionary *p_self, const Variant *p_key) { + return p_self->erase(*p_key); +} + +GD_PINVOKE_EXPORT void godotsharp_string_md5_buffer(const String *p_self, PackedByteArray *r_md5_buffer) { + memnew_placement(r_md5_buffer, PackedByteArray(p_self->md5_buffer())); +} + +GD_PINVOKE_EXPORT void godotsharp_string_md5_text(const String *p_self, String *r_md5_text) { + memnew_placement(r_md5_text, String(p_self->md5_text())); +} + +GD_PINVOKE_EXPORT int32_t godotsharp_string_rfind(const String *p_self, const String *p_what, int32_t p_from) { + return p_self->rfind(*p_what, p_from); +} + +GD_PINVOKE_EXPORT int32_t godotsharp_string_rfindn(const String *p_self, const String *p_what, int32_t p_from) { + return p_self->rfindn(*p_what, p_from); +} + +GD_PINVOKE_EXPORT void godotsharp_string_sha256_buffer(const String *p_self, PackedByteArray *r_sha256_buffer) { + memnew_placement(r_sha256_buffer, PackedByteArray(p_self->sha256_buffer())); +} + +GD_PINVOKE_EXPORT void godotsharp_string_sha256_text(const String *p_self, String *r_sha256_text) { + memnew_placement(r_sha256_text, String(p_self->sha256_text())); +} + +GD_PINVOKE_EXPORT void godotsharp_string_simplify_path(const String *p_self, String *r_simplified_path) { + memnew_placement(r_simplified_path, String(p_self->simplify_path())); +} + +GD_PINVOKE_EXPORT void godotsharp_node_path_get_as_property_path(const NodePath *p_ptr, NodePath *r_dest) { + memnew_placement(r_dest, NodePath(p_ptr->get_as_property_path())); +} + +GD_PINVOKE_EXPORT void godotsharp_node_path_get_concatenated_names(const NodePath *p_self, String *r_subnames) { + memnew_placement(r_subnames, String(p_self->get_concatenated_names())); +} + +GD_PINVOKE_EXPORT void godotsharp_node_path_get_concatenated_subnames(const NodePath *p_self, String *r_subnames) { + memnew_placement(r_subnames, String(p_self->get_concatenated_subnames())); +} + +GD_PINVOKE_EXPORT void godotsharp_node_path_get_name(const NodePath *p_self, uint32_t p_idx, String *r_name) { + memnew_placement(r_name, String(p_self->get_name(p_idx))); +} + +GD_PINVOKE_EXPORT int32_t godotsharp_node_path_get_name_count(const NodePath *p_self) { + return p_self->get_name_count(); +} + +GD_PINVOKE_EXPORT void godotsharp_node_path_get_subname(const NodePath *p_self, uint32_t p_idx, String *r_subname) { + memnew_placement(r_subname, String(p_self->get_subname(p_idx))); +} + +GD_PINVOKE_EXPORT int32_t godotsharp_node_path_get_subname_count(const NodePath *p_self) { + return p_self->get_subname_count(); +} + +GD_PINVOKE_EXPORT bool godotsharp_node_path_is_absolute(const NodePath *p_self) { + return p_self->is_absolute(); +} + #ifdef __cplusplus } #endif // We need this to prevent the functions from being stripped. -void *godotsharp_pinvoke_funcs[101] = { +void *godotsharp_pinvoke_funcs[138] = { (void *)godotsharp_method_bind_get_method, (void *)godotsharp_get_class_constructor, (void *)godotsharp_invoke_class_constructor, @@ -761,10 +924,14 @@ void *godotsharp_pinvoke_funcs[101] = { (void *)godotsharp_variant_as_packed_vector2_array, (void *)godotsharp_variant_as_packed_vector3_array, (void *)godotsharp_variant_as_packed_color_array, + (void *)godotsharp_variant_equals, (void *)godotsharp_string_new_with_utf16_chars, (void *)godotsharp_string_name_new_copy, (void *)godotsharp_node_path_new_copy, + (void *)godotsharp_array_new, (void *)godotsharp_array_new_copy, + (void *)godotsharp_array_ptrw, + (void *)godotsharp_dictionary_new, (void *)godotsharp_dictionary_new_copy, (void *)godotsharp_packed_byte_array_destroy, (void *)godotsharp_packed_int32_array_destroy, @@ -782,5 +949,38 @@ void *godotsharp_pinvoke_funcs[101] = { (void *)godotsharp_signal_destroy, (void *)godotsharp_callable_destroy, (void *)godotsharp_array_destroy, - (void *)godotsharp_dictionary_destroy + (void *)godotsharp_dictionary_destroy, + (void *)godotsharp_array_add, + (void *)godotsharp_array_duplicate, + (void *)godotsharp_array_index_of, + (void *)godotsharp_array_insert, + (void *)godotsharp_array_remove_at, + (void *)godotsharp_array_resize, + (void *)godotsharp_array_shuffle, + (void *)godotsharp_dictionary_try_get_value, + (void *)godotsharp_dictionary_set_value, + (void *)godotsharp_dictionary_keys, + (void *)godotsharp_dictionary_values, + (void *)godotsharp_dictionary_count, + (void *)godotsharp_dictionary_key_value_pair_at, + (void *)godotsharp_dictionary_add, + (void *)godotsharp_dictionary_clear, + (void *)godotsharp_dictionary_contains_key, + (void *)godotsharp_dictionary_duplicate, + (void *)godotsharp_dictionary_remove_key, + (void *)godotsharp_string_md5_buffer, + (void *)godotsharp_string_md5_text, + (void *)godotsharp_string_rfind, + (void *)godotsharp_string_rfindn, + (void *)godotsharp_string_sha256_buffer, + (void *)godotsharp_string_sha256_text, + (void *)godotsharp_string_simplify_path, + (void *)godotsharp_node_path_get_as_property_path, + (void *)godotsharp_node_path_get_concatenated_names, + (void *)godotsharp_node_path_get_concatenated_subnames, + (void *)godotsharp_node_path_get_name, + (void *)godotsharp_node_path_get_name_count, + (void *)godotsharp_node_path_get_subname, + (void *)godotsharp_node_path_get_subname_count, + (void *)godotsharp_node_path_is_absolute }; diff --git a/modules/mono/glue/string_glue.cpp b/modules/mono/glue/string_glue.cpp deleted file mode 100644 index fe1c0b5f8c..0000000000 --- a/modules/mono/glue/string_glue.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/*************************************************************************/ -/* string_glue.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "core/string/ustring.h" -#include "core/templates/vector.h" -#include "core/variant/variant.h" - -#include "../mono_gd/gd_mono_marshal.h" - -MonoArray *godot_icall_String_md5_buffer(MonoString *p_str) { - Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_buffer(); - // TODO Check possible Array/Vector<uint8_t> problem? - return GDMonoMarshal::Array_to_mono_array(Variant(ret)); -} - -MonoString *godot_icall_String_md5_text(MonoString *p_str) { - String ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_text(); - return GDMonoMarshal::mono_string_from_godot(ret); -} - -int godot_icall_String_rfind(MonoString *p_str, MonoString *p_what, int p_from) { - String what = GDMonoMarshal::mono_string_to_godot(p_what); - return GDMonoMarshal::mono_string_to_godot(p_str).rfind(what, p_from); -} - -int godot_icall_String_rfindn(MonoString *p_str, MonoString *p_what, int p_from) { - String what = GDMonoMarshal::mono_string_to_godot(p_what); - return GDMonoMarshal::mono_string_to_godot(p_str).rfindn(what, p_from); -} - -MonoArray *godot_icall_String_sha256_buffer(MonoString *p_str) { - Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).sha256_buffer(); - return GDMonoMarshal::Array_to_mono_array(Variant(ret)); -} - -MonoString *godot_icall_String_sha256_text(MonoString *p_str) { - String ret = GDMonoMarshal::mono_string_to_godot(p_str).sha256_text(); - return GDMonoMarshal::mono_string_from_godot(ret); -} - -MonoString *godot_icall_String_simplify_path(MonoString *p_str) { - String ret = GDMonoMarshal::mono_string_to_godot(p_str).simplify_path(); - return GDMonoMarshal::mono_string_from_godot(ret); -} - -void godot_register_string_icalls() { - GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_md5_buffer", godot_icall_String_md5_buffer); - GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_md5_text", godot_icall_String_md5_text); - GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_rfind", godot_icall_String_rfind); - GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_rfindn", godot_icall_String_rfindn); - GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_sha256_buffer", godot_icall_String_sha256_buffer); - GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_sha256_text", godot_icall_String_sha256_text); - GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_simplify_path", godot_icall_String_simplify_path); -} |