C#: Remove IL post-processor build dependency
We were using it to workaround a limitation of `Unsafe.AsPointer` and `ref struct`s. However, we can get the same result with some tricks, since we have control over the declaration of these structs.
This commit is contained in:
parent
1bf4397e5b
commit
186d7f6239
|
@ -1,5 +1,2 @@
|
||||||
# Do not ignore solution files inside the mono module. Overrides Godot's global gitignore.
|
# Do not ignore solution files inside the mono module. Overrides Godot's global gitignore.
|
||||||
!*.sln
|
!*.sln
|
||||||
|
|
||||||
# Fody
|
|
||||||
FodyWeavers.xsd
|
|
||||||
|
|
|
@ -0,0 +1,313 @@
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Godot.NativeInterop;
|
||||||
|
|
||||||
|
// Ref structs are not allowed as generic type parameters, so we can't use Unsafe.AsPointer<T>/AsRef<T>.
|
||||||
|
// As a workaround we create our own overloads for our structs with some tricks under the hood.
|
||||||
|
|
||||||
|
public static class CustomUnsafe
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_ref* AsPointer(ref godot_ref value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_ref* ReadOnlyRefAsPointer(in godot_ref value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_ref AsRef(godot_ref* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_ref AsRef(in godot_ref source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_variant_call_error* AsPointer(ref godot_variant_call_error value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_variant_call_error* ReadOnlyRefAsPointer(in godot_variant_call_error value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_variant_call_error AsRef(godot_variant_call_error* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_variant_call_error AsRef(in godot_variant_call_error source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_variant* AsPointer(ref godot_variant value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_variant* ReadOnlyRefAsPointer(in godot_variant value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_variant AsRef(godot_variant* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_variant AsRef(in godot_variant source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_string* AsPointer(ref godot_string value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_string* ReadOnlyRefAsPointer(in godot_string value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_string AsRef(godot_string* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_string AsRef(in godot_string source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_string_name* AsPointer(ref godot_string_name value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_string_name* ReadOnlyRefAsPointer(in godot_string_name value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_string_name AsRef(godot_string_name* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_string_name AsRef(in godot_string_name source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_node_path* AsPointer(ref godot_node_path value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_node_path* ReadOnlyRefAsPointer(in godot_node_path value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_node_path AsRef(godot_node_path* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_node_path AsRef(in godot_node_path source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_signal* AsPointer(ref godot_signal value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_signal* ReadOnlyRefAsPointer(in godot_signal value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_signal AsRef(godot_signal* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_signal AsRef(in godot_signal source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_callable* AsPointer(ref godot_callable value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_callable* ReadOnlyRefAsPointer(in godot_callable value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_callable AsRef(godot_callable* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_callable AsRef(in godot_callable source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_array* AsPointer(ref godot_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_array* ReadOnlyRefAsPointer(in godot_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_array AsRef(godot_array* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_array AsRef(in godot_array source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_dictionary* AsPointer(ref godot_dictionary value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_dictionary* ReadOnlyRefAsPointer(in godot_dictionary value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_dictionary AsRef(godot_dictionary* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_dictionary AsRef(in godot_dictionary source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_byte_array* AsPointer(ref godot_packed_byte_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_byte_array* ReadOnlyRefAsPointer(in godot_packed_byte_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_byte_array AsRef(godot_packed_byte_array* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_byte_array AsRef(in godot_packed_byte_array source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_int32_array* AsPointer(ref godot_packed_int32_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_int32_array* ReadOnlyRefAsPointer(in godot_packed_int32_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_int32_array AsRef(godot_packed_int32_array* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_int32_array AsRef(in godot_packed_int32_array source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_int64_array* AsPointer(ref godot_packed_int64_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_int64_array* ReadOnlyRefAsPointer(in godot_packed_int64_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_int64_array AsRef(godot_packed_int64_array* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_int64_array AsRef(in godot_packed_int64_array source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_float32_array* AsPointer(ref godot_packed_float32_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_float32_array* ReadOnlyRefAsPointer(in godot_packed_float32_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_float32_array AsRef(godot_packed_float32_array* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_float32_array AsRef(in godot_packed_float32_array source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_float64_array* AsPointer(ref godot_packed_float64_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_float64_array* ReadOnlyRefAsPointer(in godot_packed_float64_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_float64_array AsRef(godot_packed_float64_array* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_float64_array AsRef(in godot_packed_float64_array source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_string_array* AsPointer(ref godot_packed_string_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_string_array* ReadOnlyRefAsPointer(in godot_packed_string_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_string_array AsRef(godot_packed_string_array* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_string_array AsRef(in godot_packed_string_array source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_vector2_array* AsPointer(ref godot_packed_vector2_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_vector2_array* ReadOnlyRefAsPointer(in godot_packed_vector2_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_vector2_array AsRef(godot_packed_vector2_array* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_vector2_array AsRef(in godot_packed_vector2_array source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_vector3_array* AsPointer(ref godot_packed_vector3_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_vector3_array* ReadOnlyRefAsPointer(in godot_packed_vector3_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_vector3_array AsRef(godot_packed_vector3_array* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_vector3_array AsRef(in godot_packed_vector3_array source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_color_array* AsPointer(ref godot_packed_color_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe godot_packed_color_array* ReadOnlyRefAsPointer(in godot_packed_color_array value)
|
||||||
|
=> value.GetUnsafeAddress();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_color_array AsRef(godot_packed_color_array* source)
|
||||||
|
=> ref *source;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static unsafe ref godot_packed_color_array AsRef(in godot_packed_color_array source)
|
||||||
|
=> ref *ReadOnlyRefAsPointer(in source);
|
||||||
|
}
|
|
@ -35,6 +35,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_ref
|
public ref struct godot_ref
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_ref* GetUnsafeAddress()
|
||||||
|
=> (godot_ref*)Unsafe.AsPointer(ref Unsafe.AsRef(in _reference));
|
||||||
|
|
||||||
private IntPtr _reference;
|
private IntPtr _reference;
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -73,6 +77,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_variant_call_error
|
public ref struct godot_variant_call_error
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_variant_call_error* GetUnsafeAddress()
|
||||||
|
=> (godot_variant_call_error*)Unsafe.AsPointer(ref Unsafe.AsRef(in error));
|
||||||
|
|
||||||
private godot_variant_call_error_error error;
|
private godot_variant_call_error_error error;
|
||||||
private int argument;
|
private int argument;
|
||||||
private int expected;
|
private int expected;
|
||||||
|
@ -100,6 +108,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_variant
|
public ref struct godot_variant
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_variant* GetUnsafeAddress()
|
||||||
|
=> (godot_variant*)Unsafe.AsPointer(ref Unsafe.AsRef(in _typeField));
|
||||||
|
|
||||||
// Variant.Type is generated as an enum of type long, so we can't use for the field as it must only take 32-bits.
|
// Variant.Type is generated as an enum of type long, so we can't use for the field as it must only take 32-bits.
|
||||||
[FieldOffset(0)] private int _typeField;
|
[FieldOffset(0)] private int _typeField;
|
||||||
|
|
||||||
|
@ -147,7 +159,7 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public struct godot_variant_obj_data
|
public struct godot_variant_obj_data
|
||||||
{
|
{
|
||||||
public UInt64 id;
|
public ulong id;
|
||||||
public IntPtr obj;
|
public IntPtr obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,6 +443,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_string
|
public ref struct godot_string
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_string* GetUnsafeAddress()
|
||||||
|
=> (godot_string*)Unsafe.AsPointer(ref Unsafe.AsRef(in _ptr));
|
||||||
|
|
||||||
private IntPtr _ptr;
|
private IntPtr _ptr;
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -459,6 +475,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_string_name
|
public ref struct godot_string_name
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_string_name* GetUnsafeAddress()
|
||||||
|
=> (godot_string_name*)Unsafe.AsPointer(ref Unsafe.AsRef(in _data));
|
||||||
|
|
||||||
private IntPtr _data;
|
private IntPtr _data;
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -528,6 +548,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_node_path
|
public ref struct godot_node_path
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_node_path* GetUnsafeAddress()
|
||||||
|
=> (godot_node_path*)Unsafe.AsPointer(ref Unsafe.AsRef(in _data));
|
||||||
|
|
||||||
private IntPtr _data;
|
private IntPtr _data;
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -572,13 +596,19 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_signal
|
public ref struct godot_signal
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_signal* GetUnsafeAddress()
|
||||||
|
=> (godot_signal*)Unsafe.AsPointer(ref Unsafe.AsRef(in _getUnsafeAddressHelper));
|
||||||
|
|
||||||
|
[FieldOffset(0)] private byte _getUnsafeAddressHelper;
|
||||||
|
|
||||||
[FieldOffset(0)] private godot_string_name _name;
|
[FieldOffset(0)] private godot_string_name _name;
|
||||||
|
|
||||||
// There's padding here on 32-bit
|
// There's padding here on 32-bit
|
||||||
|
|
||||||
[FieldOffset(8)] private UInt64 _objectId;
|
[FieldOffset(8)] private ulong _objectId;
|
||||||
|
|
||||||
public godot_signal(godot_string_name name, ulong objectId)
|
public godot_signal(godot_string_name name, ulong objectId) : this()
|
||||||
{
|
{
|
||||||
_name = name;
|
_name = name;
|
||||||
_objectId = objectId;
|
_objectId = objectId;
|
||||||
|
@ -590,7 +620,7 @@ namespace Godot.NativeInterop
|
||||||
get => _name;
|
get => _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UInt64 ObjectId
|
public ulong ObjectId
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get => _objectId;
|
get => _objectId;
|
||||||
|
@ -609,12 +639,18 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_callable
|
public ref struct godot_callable
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_callable* GetUnsafeAddress()
|
||||||
|
=> (godot_callable*)Unsafe.AsPointer(ref Unsafe.AsRef(in _getUnsafeAddressHelper));
|
||||||
|
|
||||||
|
[FieldOffset(0)] private byte _getUnsafeAddressHelper;
|
||||||
|
|
||||||
[FieldOffset(0)] private godot_string_name _method;
|
[FieldOffset(0)] private godot_string_name _method;
|
||||||
|
|
||||||
// There's padding here on 32-bit
|
// There's padding here on 32-bit
|
||||||
|
|
||||||
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
|
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
|
||||||
[FieldOffset(8)] private UInt64 _objectId;
|
[FieldOffset(8)] private ulong _objectId;
|
||||||
[FieldOffset(8)] private IntPtr _custom;
|
[FieldOffset(8)] private IntPtr _custom;
|
||||||
|
|
||||||
public godot_callable(godot_string_name method, ulong objectId) : this()
|
public godot_callable(godot_string_name method, ulong objectId) : this()
|
||||||
|
@ -637,11 +673,17 @@ namespace Godot.NativeInterop
|
||||||
// A correctly constructed value needs to call the native default constructor to allocate `_p`.
|
// A correctly constructed value needs to call the native default constructor to allocate `_p`.
|
||||||
// Don't pass a C# default constructed `godot_array` to native code, unless it's going to
|
// Don't pass a C# default constructed `godot_array` to native code, unless it's going to
|
||||||
// be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
|
// be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_array
|
public ref struct godot_array
|
||||||
{
|
{
|
||||||
private unsafe ArrayPrivate* _p;
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_array* GetUnsafeAddress()
|
||||||
|
=> (godot_array*)Unsafe.AsPointer(ref Unsafe.AsRef(in _getUnsafeAddressHelper));
|
||||||
|
|
||||||
|
[FieldOffset(0)] private byte _getUnsafeAddressHelper;
|
||||||
|
|
||||||
|
[FieldOffset(0)] private unsafe ArrayPrivate* _p;
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
private struct ArrayPrivate
|
private struct ArrayPrivate
|
||||||
|
@ -722,6 +764,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_dictionary
|
public ref struct godot_dictionary
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_dictionary* GetUnsafeAddress()
|
||||||
|
=> (godot_dictionary*)Unsafe.AsPointer(ref Unsafe.AsRef(in _p));
|
||||||
|
|
||||||
private IntPtr _p;
|
private IntPtr _p;
|
||||||
|
|
||||||
public readonly bool IsAllocated
|
public readonly bool IsAllocated
|
||||||
|
@ -759,6 +805,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_packed_byte_array
|
public ref struct godot_packed_byte_array
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_packed_byte_array* GetUnsafeAddress()
|
||||||
|
=> (godot_packed_byte_array*)Unsafe.AsPointer(ref Unsafe.AsRef(in _writeProxy));
|
||||||
|
|
||||||
private IntPtr _writeProxy;
|
private IntPtr _writeProxy;
|
||||||
private unsafe byte* _ptr;
|
private unsafe byte* _ptr;
|
||||||
|
|
||||||
|
@ -787,6 +837,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_packed_int32_array
|
public ref struct godot_packed_int32_array
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_packed_int32_array* GetUnsafeAddress()
|
||||||
|
=> (godot_packed_int32_array*)Unsafe.AsPointer(ref Unsafe.AsRef(in _writeProxy));
|
||||||
|
|
||||||
private IntPtr _writeProxy;
|
private IntPtr _writeProxy;
|
||||||
private unsafe int* _ptr;
|
private unsafe int* _ptr;
|
||||||
|
|
||||||
|
@ -815,6 +869,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_packed_int64_array
|
public ref struct godot_packed_int64_array
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_packed_int64_array* GetUnsafeAddress()
|
||||||
|
=> (godot_packed_int64_array*)Unsafe.AsPointer(ref Unsafe.AsRef(in _writeProxy));
|
||||||
|
|
||||||
private IntPtr _writeProxy;
|
private IntPtr _writeProxy;
|
||||||
private unsafe long* _ptr;
|
private unsafe long* _ptr;
|
||||||
|
|
||||||
|
@ -843,6 +901,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_packed_float32_array
|
public ref struct godot_packed_float32_array
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_packed_float32_array* GetUnsafeAddress()
|
||||||
|
=> (godot_packed_float32_array*)Unsafe.AsPointer(ref Unsafe.AsRef(in _writeProxy));
|
||||||
|
|
||||||
private IntPtr _writeProxy;
|
private IntPtr _writeProxy;
|
||||||
private unsafe float* _ptr;
|
private unsafe float* _ptr;
|
||||||
|
|
||||||
|
@ -871,6 +933,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_packed_float64_array
|
public ref struct godot_packed_float64_array
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_packed_float64_array* GetUnsafeAddress()
|
||||||
|
=> (godot_packed_float64_array*)Unsafe.AsPointer(ref Unsafe.AsRef(in _writeProxy));
|
||||||
|
|
||||||
private IntPtr _writeProxy;
|
private IntPtr _writeProxy;
|
||||||
private unsafe double* _ptr;
|
private unsafe double* _ptr;
|
||||||
|
|
||||||
|
@ -899,6 +965,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_packed_string_array
|
public ref struct godot_packed_string_array
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_packed_string_array* GetUnsafeAddress()
|
||||||
|
=> (godot_packed_string_array*)Unsafe.AsPointer(ref Unsafe.AsRef(in _writeProxy));
|
||||||
|
|
||||||
private IntPtr _writeProxy;
|
private IntPtr _writeProxy;
|
||||||
private unsafe godot_string* _ptr;
|
private unsafe godot_string* _ptr;
|
||||||
|
|
||||||
|
@ -927,6 +997,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_packed_vector2_array
|
public ref struct godot_packed_vector2_array
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_packed_vector2_array* GetUnsafeAddress()
|
||||||
|
=> (godot_packed_vector2_array*)Unsafe.AsPointer(ref Unsafe.AsRef(in _writeProxy));
|
||||||
|
|
||||||
private IntPtr _writeProxy;
|
private IntPtr _writeProxy;
|
||||||
private unsafe Vector2* _ptr;
|
private unsafe Vector2* _ptr;
|
||||||
|
|
||||||
|
@ -955,6 +1029,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_packed_vector3_array
|
public ref struct godot_packed_vector3_array
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_packed_vector3_array* GetUnsafeAddress()
|
||||||
|
=> (godot_packed_vector3_array*)Unsafe.AsPointer(ref Unsafe.AsRef(in _writeProxy));
|
||||||
|
|
||||||
private IntPtr _writeProxy;
|
private IntPtr _writeProxy;
|
||||||
private unsafe Vector3* _ptr;
|
private unsafe Vector3* _ptr;
|
||||||
|
|
||||||
|
@ -983,6 +1061,10 @@ namespace Godot.NativeInterop
|
||||||
// ReSharper disable once InconsistentNaming
|
// ReSharper disable once InconsistentNaming
|
||||||
public ref struct godot_packed_color_array
|
public ref struct godot_packed_color_array
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal readonly unsafe godot_packed_color_array* GetUnsafeAddress()
|
||||||
|
=> (godot_packed_color_array*)Unsafe.AsPointer(ref Unsafe.AsRef(in _writeProxy));
|
||||||
|
|
||||||
private IntPtr _writeProxy;
|
private IntPtr _writeProxy;
|
||||||
private unsafe Color* _ptr;
|
private unsafe Color* _ptr;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
|
||||||
<InlineIL />
|
|
||||||
</Weavers>
|
|
|
@ -1,93 +0,0 @@
|
||||||
<Project>
|
|
||||||
<!-- Generate Godot.NativeInterop.CustomUnsafe C# class-->
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Ref structs are not allowed as generic type parameters, so we can't use Unsafe.AsPointer<T>/AsRef<T>.
|
|
||||||
As a workaround we generate overloads of those methods for our structs using Fody with inline IL.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Fody" Version="6.6.0" PrivateAssets="all" />
|
|
||||||
<PackageReference Include="InlineIL.Fody" Version="1.7.1" PrivateAssets="all" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<GodotInteropStructs Include="godot_ref" />
|
|
||||||
<GodotInteropStructs Include="godot_variant_call_error" />
|
|
||||||
<GodotInteropStructs Include="godot_variant" />
|
|
||||||
<GodotInteropStructs Include="godot_string" />
|
|
||||||
<GodotInteropStructs Include="godot_string_name" />
|
|
||||||
<GodotInteropStructs Include="godot_node_path" />
|
|
||||||
<GodotInteropStructs Include="godot_signal" />
|
|
||||||
<GodotInteropStructs Include="godot_callable" />
|
|
||||||
<GodotInteropStructs Include="godot_array" />
|
|
||||||
<GodotInteropStructs Include="godot_dictionary" />
|
|
||||||
<GodotInteropStructs Include="godot_packed_byte_array" />
|
|
||||||
<GodotInteropStructs Include="godot_packed_int32_array" />
|
|
||||||
<GodotInteropStructs Include="godot_packed_int64_array" />
|
|
||||||
<GodotInteropStructs Include="godot_packed_float32_array" />
|
|
||||||
<GodotInteropStructs Include="godot_packed_float64_array" />
|
|
||||||
<GodotInteropStructs Include="godot_packed_string_array" />
|
|
||||||
<GodotInteropStructs Include="godot_packed_vector2_array" />
|
|
||||||
<GodotInteropStructs Include="godot_packed_vector3_array" />
|
|
||||||
<GodotInteropStructs Include="godot_packed_color_array" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="GenerateGodotCustomUnsafe"
|
|
||||||
DependsOnTargets="_GenerateGodotCustomUnsafe"
|
|
||||||
BeforeTargets="PrepareForBuild;CompileDesignTime;BeforeCompile;CoreCompile">
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="$(IntermediateOutputPath)CustomUnsafe.%(GodotInteropStructs.Identity).g.cs" />
|
|
||||||
<FileWrites Include="$(IntermediateOutputPath)CustomUnsafe.%(GodotInteropStructs.Identity).g.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Target>
|
|
||||||
<Target Name="_GenerateGodotCustomUnsafe"
|
|
||||||
Inputs="$(MSBuildProjectFile);$(MSBuildThisFileDirectory);@(GodotInteropStructs)"
|
|
||||||
Outputs="$(IntermediateOutputPath)CustomUnsafe.%(GodotInteropStructs.Identity).g.cs">
|
|
||||||
<PropertyGroup>
|
|
||||||
<GodotInteropStruct>%(GodotInteropStructs.Identity)</GodotInteropStruct>
|
|
||||||
<GenerateGodotCustomUnsafeCode><![CDATA[
|
|
||||||
using System.Runtime.CompilerServices%3b
|
|
||||||
using InlineIL%3b
|
|
||||||
using static InlineIL.IL.Emit%3b
|
|
||||||
|
|
||||||
namespace Godot.NativeInterop
|
|
||||||
{
|
|
||||||
public static partial class CustomUnsafe
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static unsafe $(GodotInteropStruct)* AsPointer(ref $(GodotInteropStruct) value)
|
|
||||||
{
|
|
||||||
Ldarg(nameof(value))%3b
|
|
||||||
Conv_U()%3b
|
|
||||||
return ($(GodotInteropStruct)*)IL.ReturnPointer()%3b
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static unsafe $(GodotInteropStruct)* ReadOnlyRefAsPointer(in $(GodotInteropStruct) value)
|
|
||||||
{
|
|
||||||
Ldarg(nameof(value))%3b
|
|
||||||
Conv_U()%3b
|
|
||||||
return ($(GodotInteropStruct)*)IL.ReturnPointer()%3b
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static unsafe ref $(GodotInteropStruct) AsRef($(GodotInteropStruct)* source)
|
|
||||||
{
|
|
||||||
return ref *source%3b
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static unsafe ref $(GodotInteropStruct) AsRef(in $(GodotInteropStruct) source)
|
|
||||||
{
|
|
||||||
return ref *ReadOnlyRefAsPointer(in source)%3b
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]></GenerateGodotCustomUnsafeCode>
|
|
||||||
</PropertyGroup>
|
|
||||||
<WriteLinesToFile Lines="$(GenerateGodotCustomUnsafeCode)"
|
|
||||||
File="$(IntermediateOutputPath)CustomUnsafe.%(GodotInteropStructs.Identity).g.cs"
|
|
||||||
Overwrite="True" WriteOnlyWhenDifferent="True" />
|
|
||||||
</Target>
|
|
||||||
</Project>
|
|
|
@ -41,11 +41,6 @@
|
||||||
<PackageReference Include="ReflectionAnalyzers" Version="0.1.22-dev" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" />
|
<PackageReference Include="ReflectionAnalyzers" Version="0.1.22-dev" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" />
|
||||||
<!--PackageReference Include="IDisposableAnalyzers" Version="3.4.13" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" /-->
|
<!--PackageReference Include="IDisposableAnalyzers" Version="3.4.13" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" /-->
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Targets for generating Godot.NativeInterop.CustomUnsafe -->
|
|
||||||
<Import Project="GenerateGodotCustomUnsafe.targets" />
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="GenerateGodotCustomUnsafe.targets" />
|
|
||||||
</ItemGroup>
|
|
||||||
<!-- Sources -->
|
<!-- Sources -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Core\AABB.cs" />
|
<Compile Include="Core\AABB.cs" />
|
||||||
|
@ -89,6 +84,7 @@
|
||||||
<Compile Include="Core\Interfaces\ISerializationListener.cs" />
|
<Compile Include="Core\Interfaces\ISerializationListener.cs" />
|
||||||
<Compile Include="Core\Mathf.cs" />
|
<Compile Include="Core\Mathf.cs" />
|
||||||
<Compile Include="Core\MathfEx.cs" />
|
<Compile Include="Core\MathfEx.cs" />
|
||||||
|
<Compile Include="Core\NativeInterop\CustomUnsafe.cs" />
|
||||||
<Compile Include="Core\NativeInterop\ExceptionUtils.cs" />
|
<Compile Include="Core\NativeInterop\ExceptionUtils.cs" />
|
||||||
<Compile Include="Core\NativeInterop\GodotDllImportResolver.cs" />
|
<Compile Include="Core\NativeInterop\GodotDllImportResolver.cs" />
|
||||||
<Compile Include="Core\NativeInterop\InteropUtils.cs" />
|
<Compile Include="Core\NativeInterop\InteropUtils.cs" />
|
||||||
|
|
Loading…
Reference in New Issue