using System;
using System.Runtime.CompilerServices;
namespace Godot
{
public partial class Object : IDisposable
{
private bool _disposed = false;
internal IntPtr NativePtr;
internal bool MemoryOwn;
public Object() : this(false)
{
if (NativePtr == IntPtr.Zero)
{
#if NET
unsafe
{
ptr = NativeCtor();
}
#else
NativePtr = _gd__invoke_class_constructor(NativeCtor);
#endif
NativeInterop.InteropUtils.TieManagedToUnmanaged(this, NativePtr);
}
_InitializeGodotScriptInstanceInternals();
}
internal void _InitializeGodotScriptInstanceInternals()
{
godot_icall_Object_ConnectEventSignals(NativePtr);
}
internal Object(bool memoryOwn)
{
this.MemoryOwn = memoryOwn;
}
public IntPtr NativeInstance => NativePtr;
internal static IntPtr GetPtr(Object instance)
{
if (instance == null)
return IntPtr.Zero;
if (instance._disposed)
throw new ObjectDisposedException(instance.GetType().FullName);
return instance.NativePtr;
}
~Object()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (NativePtr != IntPtr.Zero)
{
if (MemoryOwn)
{
MemoryOwn = false;
godot_icall_RefCounted_Disposed(this, NativePtr, !disposing);
}
else
{
godot_icall_Object_Disposed(this, NativePtr);
}
this.NativePtr = IntPtr.Zero;
}
_disposed = true;
}
public override string ToString()
{
return godot_icall_Object_ToString(GetPtr(this));
}
///
/// Returns a new awaiter configured to complete when the instance
/// emits the signal specified by the parameter.
///
///
/// The instance the awaiter will be listening to.
///
///
/// The signal the awaiter will be waiting for.
///
///
/// This sample prints a message once every frame up to 100 times.
///
/// public override void _Ready()
/// {
/// for (int i = 0; i < 100; i++)
/// {
/// await ToSignal(GetTree(), "idle_frame");
/// GD.Print($"Frame {i}");
/// }
/// }
///
///
public SignalAwaiter ToSignal(Object source, StringName signal)
{
return new SignalAwaiter(source, signal, this);
}
///
/// Gets a new associated with this instance.
///
public dynamic DynamicObject => new DynamicGodotObject(this);
internal static unsafe IntPtr ClassDB_get_method(StringName type, string method)
{
IntPtr methodBind;
fixed (char* methodChars = method)
{
methodBind = NativeInterop.NativeFuncs
.godotsharp_method_bind_get_method(ref type.NativeValue, methodChars);
}
if (methodBind == IntPtr.Zero)
throw new NativeMethodBindNotFoundException(type + "." + method);
return methodBind;
}
#if NET
internal static unsafe delegate* unmanaged _gd__ClassDB_get_constructor(StringName type)
{
// for some reason the '??' operator doesn't support 'delegate*'
var nativeConstructor = NativeInterop.NativeFuncs
.godotsharp_get_class_constructor(ref type.NativeValue);
if (nativeConstructor == null)
throw new NativeConstructorNotFoundException(type);
return nativeConstructor;
}
#else
internal static IntPtr ClassDB_get_constructor(StringName type)
{
// for some reason the '??' operator doesn't support 'delegate*'
var nativeConstructor = NativeInterop.NativeFuncs
.godotsharp_get_class_constructor(ref type.NativeValue);
if (nativeConstructor == IntPtr.Zero)
throw new NativeConstructorNotFoundException(type);
return nativeConstructor;
}
internal static IntPtr _gd__invoke_class_constructor(IntPtr ctorFuncPtr)
=> NativeInterop.NativeFuncs.godotsharp_invoke_class_constructor(ctorFuncPtr);
#endif
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void godot_icall_Object_Disposed(Object obj, IntPtr ptr);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void godot_icall_RefCounted_Disposed(Object obj, IntPtr ptr, bool isFinalizer);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void godot_icall_Object_ConnectEventSignals(IntPtr obj);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern string godot_icall_Object_ToString(IntPtr ptr);
}
}