C#: Re-write Array, Dictionary, NodePath, String icalls as P/Invoke

This commit is contained in:
Ignacio Roldán Etcheverry 2021-09-12 19:49:39 +02:00
parent 66a89c7925
commit bbde1b1f09
13 changed files with 839 additions and 828 deletions

View file

@ -106,7 +106,7 @@ Error CSharpLanguage::execute_file(const String &p_path) {
return OK;
}
extern void *godotsharp_pinvoke_funcs[95];
extern void *godotsharp_pinvoke_funcs[130];
[[maybe_unused]] volatile void **do_not_strip_godotsharp_pinvoke_funcs;
void CSharpLanguage::init() {

View file

@ -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 index.
/// </summary>
/// <value>The object at the given 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 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);
/// <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 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);
[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
@ -449,11 +465,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;
@ -544,12 +559,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++)
{
@ -566,7 +583,14 @@ namespace Godot.Collections
/// <returns>A 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>

View file

@ -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,15 +274,23 @@ namespace Godot.Collections
{
UpdateEntry();
}
return entry;
}
}
private void UpdateEntry()
private unsafe void UpdateEntry()
{
dirty = false;
godot_icall_Dictionary_KeyValuePairAt(ref dictionary.NativeValue, index, out object key, out object value);
entry = new DictionaryEntry(key, value);
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref dictionary.NativeValue, index,
out godot_variant key,
out godot_variant value);
using (key)
using (value)
{
entry = new DictionaryEntry(Marshaling.variant_to_mono_object(&key),
Marshaling.variant_to_mono_object(&value));
}
}
public object Key => Entry.Key;
@ -274,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 object key, out object 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
@ -401,7 +393,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>
@ -433,11 +426,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;
@ -451,7 +452,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);
}
}
@ -464,15 +465,22 @@ 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 object key, out object value);
return new KeyValuePair<TKey, TValue>((TKey)key, (TValue)value);
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref _underlyingDict.NativeValue, index,
out godot_variant key,
out godot_variant value);
using (key)
using (value)
{
return new KeyValuePair<TKey, TValue>((TKey)Marshaling.variant_to_mono_object(&key),
(TValue)Marshaling.variant_to_mono_object(&value));
}
}
/// <summary>
@ -500,9 +508,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>
@ -511,18 +520,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;
@ -552,9 +560,19 @@ 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;
return NativeFuncs.godotsharp_variant_equals(&variantKey, &retValue);
}
}
/// <summary>
@ -569,12 +587,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++)
{
@ -583,9 +603,22 @@ 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;
if (NativeFuncs.godotsharp_variant_equals(&variantKey, &retValue))
return NativeFuncs.godotsharp_dictionary_remove_key(ref _underlyingDict.NativeValue, &variantKey);
return false;
}
}
// IEnumerable<KeyValuePair<TKey, TValue>>

View file

@ -161,6 +161,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)]
@ -252,14 +255,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;
}
}
@ -287,15 +310,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)]
@ -303,15 +328,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)]
@ -319,15 +346,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)]
@ -335,15 +364,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)]
@ -351,15 +382,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)]
@ -367,15 +400,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)]
@ -383,15 +418,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)]
@ -399,15 +436,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)]
@ -415,14 +454,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;
}
}

View file

@ -152,7 +152,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))
@ -415,7 +416,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();
@ -426,7 +428,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;
@ -439,7 +441,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.
@ -599,8 +602,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;
}
}
@ -753,7 +757,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)
@ -762,7 +766,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();
@ -980,7 +984,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
@ -1118,11 +1122,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);
@ -1141,8 +1141,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);
@ -1161,8 +1161,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)
@ -1182,8 +1182,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)
@ -1203,8 +1203,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)
@ -1224,8 +1224,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)
@ -1245,10 +1245,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]);
@ -1278,8 +1278,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)
@ -1299,8 +1299,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)
@ -1320,8 +1320,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)

View file

@ -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
@ -122,34 +136,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);
@ -230,23 +253,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)]
@ -264,11 +294,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);
@ -324,5 +363,127 @@ 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);
// 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_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);
}
}

View file

@ -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;

View file

@ -63,61 +63,46 @@ 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);
}
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);
}
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);
}
public int GetNameCount()
{
return godot_icall_NodePath_get_name_count(ref NativeValue);
return NativeFuncs.godotsharp_node_path_get_name_count(ref NativeValue);
}
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);
}
public int GetSubNameCount()
{
return godot_icall_NodePath_get_subname_count(ref NativeValue);
return NativeFuncs.godotsharp_node_path_get_subname_count(ref NativeValue);
}
public bool IsAbsolute()
{
return godot_icall_NodePath_is_absolute(ref NativeValue);
return NativeFuncs.godotsharp_node_path_is_absolute(ref NativeValue);
}
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_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);
}
}

View file

@ -5,6 +5,7 @@ using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using Godot.NativeInterop;
namespace Godot
{
@ -157,6 +158,7 @@ namespace Godot
{
return 0;
}
if (from == 0 && to == len)
{
str = instance;
@ -355,7 +357,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>
@ -366,7 +369,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>
@ -380,7 +384,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>
@ -623,6 +628,7 @@ namespace Godot
{
match = instance[source] == text[target];
}
if (match)
{
source++;
@ -682,9 +688,9 @@ namespace Godot
}
bool validChar = instance[i] >= '0' &&
instance[i] <= '9' || instance[i] >= 'a' &&
instance[i] <= 'z' || instance[i] >= 'A' &&
instance[i] <= 'Z' || instance[i] == '_';
instance[i] <= '9' || instance[i] >= 'a' &&
instance[i] <= 'z' || instance[i] >= 'A' &&
instance[i] <= 'Z' || instance[i] == '_';
if (!validChar)
return false;
@ -808,15 +814,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);
}
}
@ -847,25 +856,25 @@ namespace Godot
/// <summary>
/// Return the MD5 hash of the string as an array of bytes.
/// </summary>
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 extern static byte[] godot_icall_String_md5_buffer(string str);
/// <summary>
/// Return the MD5 hash of the string as a string.
/// </summary>
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 extern static 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>
@ -981,26 +990,24 @@ namespace Godot
/// <summary>
/// Perform a search for a substring, but start from the end of the string instead of the beginning.
/// </summary>
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 extern static 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.
/// </summary>
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 extern static int godot_icall_String_rfindn(string str, string what, int from);
/// <summary>
/// Return the right side of the string from a given position.
/// </summary>
@ -1042,25 +1049,25 @@ namespace Godot
return instance.Substr(0, end + 1);
}
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 extern static byte[] godot_icall_String_sha256_buffer(string str);
/// <summary>
/// Return the SHA-256 hash of the string as a string.
/// </summary>
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 extern static string godot_icall_String_sha256_text(string str);
/// <summary>
/// Return the similarity index of the text compared to this string.
/// 1 means totally similar and 0 means totally dissimilar.
@ -1072,6 +1079,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
@ -1108,7 +1116,8 @@ namespace Godot
/// </summary>
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>
@ -1137,7 +1146,8 @@ namespace Godot
return ret.ToArray();
}
private static readonly char[] _nonPrintable = {
private static readonly char[] _nonPrintable =
{
(char)00, (char)01, (char)02, (char)03, (char)04, (char)05,
(char)06, (char)07, (char)08, (char)09, (char)10, (char)11,
(char)12, (char)13, (char)14, (char)15, (char)16, (char)17,

View file

@ -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(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(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, MonoObject **key, MonoObject **value) {
*key = GDMonoMarshal::variant_to_mono_object(ptr->get_key_at_index(index));
*value = GDMonoMarshal::variant_to_mono_object(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);
}

View file

@ -1,72 +0,0 @@
/*************************************************************************/
/* node_path_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 "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_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_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);
}

View file

@ -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(godot_method_bind *p_metho
godot_method_bind_ptrcall(p_method_bind, p_instance, p_args, p_ret);
}
GD_PINVOKE_EXPORT godot_variant godotsharp_method_bind_call(godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int p_arg_count, godot_variant_call_error *p_call_error) {
GD_PINVOKE_EXPORT godot_variant godotsharp_method_bind_call(godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int32_t p_arg_count, godot_variant_call_error *p_call_error) {
return godot_method_bind_call(p_method_bind, p_instance, p_args, p_arg_count, p_call_error);
}
@ -445,6 +448,10 @@ GD_PINVOKE_EXPORT godot_packed_color_array godotsharp_variant_as_packed_color_ar
return godot_variant_as_packed_color_array(p_self);
}
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(godot_string *r_dest, const char16_t *p_contents) {
@ -465,12 +472,24 @@ GD_PINVOKE_EXPORT void godotsharp_node_path_new_copy(godot_node_path *r_dest, co
// array.h
GD_PINVOKE_EXPORT void godotsharp_array_new(godot_array *r_dest) {
godot_array_new(r_dest);
}
GD_PINVOKE_EXPORT void godotsharp_array_new_copy(godot_array *r_dest, const godot_array *p_src) {
godot_array_new_copy(r_dest, 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(godot_dictionary *r_dest) {
godot_dictionary_new(r_dest);
}
GD_PINVOKE_EXPORT void godotsharp_dictionary_new_copy(godot_dictionary *r_dest, const godot_dictionary *p_src) {
godot_dictionary_new_copy(r_dest, p_src);
}
@ -545,12 +564,148 @@ GD_PINVOKE_EXPORT void godotsharp_dictionary_destroy(godot_dictionary *p_self) {
godot_dictionary_destroy(p_self);
}
// Array
int32_t godotsharp_array_add(Array *p_self, const Variant *p_item) {
p_self->append(*p_item);
return p_self->size();
}
void godotsharp_array_duplicate(const Array *p_self, bool p_deep, Array *r_dest) {
memnew_placement(r_dest, Array(p_self->duplicate(p_deep)));
}
int32_t godotsharp_array_index_of(const Array *p_self, const Variant *p_item) {
return p_self->find(*p_item);
}
void godotsharp_array_insert(Array *p_self, int32_t p_index, const Variant *p_item) {
p_self->insert(p_index, *p_item);
}
void godotsharp_array_remove_at(Array *p_self, int32_t p_index) {
p_self->remove(p_index);
}
int32_t godotsharp_array_resize(Array *p_self, int32_t p_new_size) {
return (int32_t)p_self->resize(p_new_size);
}
void godotsharp_array_shuffle(Array *p_self) {
p_self->shuffle();
}
// Dictionary
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;
}
void godotsharp_dictionary_set_value(Dictionary *p_self, const Variant *p_key, const Variant *p_value) {
p_self->operator[](*p_key) = *p_value;
}
void godotsharp_dictionary_keys(const Dictionary *p_self, Array *r_dest) {
memnew_placement(r_dest, Array(p_self->keys()));
}
void godotsharp_dictionary_values(const Dictionary *p_self, Array *r_dest) {
memnew_placement(r_dest, Array(p_self->values()));
}
int32_t godotsharp_dictionary_count(const Dictionary *p_self) {
return p_self->size();
}
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)));
}
void godotsharp_dictionary_add(Dictionary *p_self, const Variant *p_key, const Variant *p_value) {
p_self->operator[](*p_key) = *p_value;
}
void godotsharp_dictionary_clear(Dictionary *p_self) {
p_self->clear();
}
bool godotsharp_dictionary_contains_key(const Dictionary *p_self, const Variant *p_key) {
return p_self->has(*p_key);
}
void godotsharp_dictionary_duplicate(const Dictionary *p_self, bool p_deep, Dictionary *r_dest) {
memnew_placement(r_dest, Dictionary(p_self->duplicate(p_deep)));
}
bool godotsharp_dictionary_remove_key(Dictionary *p_self, const Variant *p_key) {
return p_self->erase(*p_key);
}
void godotsharp_string_md5_buffer(const String *p_self, PackedByteArray *r_md5_buffer) {
memnew_placement(r_md5_buffer, PackedByteArray(p_self->md5_buffer()));
}
void godotsharp_string_md5_text(const String *p_self, String *r_md5_text) {
memnew_placement(r_md5_text, String(p_self->md5_text()));
}
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);
}
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);
}
void godotsharp_string_sha256_buffer(const String *p_self, PackedByteArray *r_sha256_buffer) {
memnew_placement(r_sha256_buffer, PackedByteArray(p_self->sha256_buffer()));
}
void godotsharp_string_sha256_text(const String *p_self, String *r_sha256_text) {
memnew_placement(r_sha256_text, String(p_self->sha256_text()));
}
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()));
}
void godotsharp_node_path_get_concatenated_subnames(const NodePath *p_self, String *r_subnames) {
memnew_placement(r_subnames, String(p_self->get_concatenated_subnames()));
}
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)));
}
int32_t godotsharp_node_path_get_name_count(const NodePath *p_self) {
return p_self->get_name_count();
}
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)));
}
int32_t godotsharp_node_path_get_subname_count(const NodePath *p_self) {
return p_self->get_subname_count();
}
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[95] = {
void *godotsharp_pinvoke_funcs[130] = {
(void *)godotsharp_method_bind_get_method,
(void *)godotsharp_get_class_constructor,
(void *)godotsharp_invoke_class_constructor,
@ -624,10 +779,14 @@ void *godotsharp_pinvoke_funcs[95] = {
(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,
@ -645,5 +804,36 @@ void *godotsharp_pinvoke_funcs[95] = {
(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_node_path_get_as_property_path,
(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
};

View file

@ -1,75 +0,0 @@
/*************************************************************************/
/* string_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 "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);
}
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);
}