Refactor manually written managed bindings to use C-style exported P/Invoke
This commit is contained in:
@@ -29,12 +29,20 @@ struct FLAXENGINE_API VTableFunctionInjector
|
||||
*VTableAddr = OriginalValue;
|
||||
}
|
||||
};
|
||||
#elif defined(_MSC_VER)
|
||||
#define MSVC_FUNC_EXPORT(name) __pragma(comment(linker, "/EXPORT:" #name "=" __FUNCDNAME__))
|
||||
#endif
|
||||
|
||||
#if USE_MONO
|
||||
|
||||
#if USE_NETCORE
|
||||
#define ADD_INTERNAL_CALL(fullName, method)
|
||||
#define DEFINE_INTERNAL_CALL(returnType) extern "C" DLLEXPORT returnType
|
||||
#else
|
||||
extern "C" FLAXENGINE_API void mono_add_internal_call(const char* name, const void* method);
|
||||
#define ADD_INTERNAL_CALL(fullName, method) mono_add_internal_call(fullName, (const void*)method)
|
||||
#define DEFINE_INTERNAL_CALL(returnType) static returnType
|
||||
#endif
|
||||
|
||||
#if BUILD_RELEASE && 0
|
||||
|
||||
@@ -76,9 +84,7 @@ extern "C" FLAXENGINE_API void mono_add_internal_call(const char* name, const vo
|
||||
|
||||
#else
|
||||
|
||||
extern void DotNetAddInternalCall(const wchar_t* fullName, void* function);
|
||||
|
||||
#define ADD_INTERNAL_CALL(fullName, method) DotNetAddInternalCall(TEXT(fullName), (void*)(method))
|
||||
#define ADD_INTERNAL_CALL(fullName, method)
|
||||
#define INTERNAL_CALL_CHECK(obj)
|
||||
#define INTERNAL_CALL_CHECK_EXP(expression)
|
||||
#define INTERNAL_CALL_CHECK_RETURN(obj, defaultValue)
|
||||
|
||||
@@ -240,7 +240,7 @@ namespace FlaxEngine
|
||||
/// </summary>
|
||||
/// <param name="ptr">The pointer to the unmanaged (native) object.</param>
|
||||
/// <returns>The object.</returns>
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Object::FromUnmanagedPtr", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_FromUnmanagedPtr", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
public static partial Object FromUnmanagedPtr(IntPtr ptr);
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -251,34 +251,34 @@ namespace FlaxEngine
|
||||
|
||||
#region Internal Calls
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Object::Internal_Create1", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_Create1", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
internal static partial Object Internal_Create1([MarshalUsing(typeof(SystemTypeMarshaller))] Type type);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Object::Internal_Create2", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_Create2", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
internal static partial Object Internal_Create2(string typeName);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Object::Internal_ManagedInstanceCreated", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_ManagedInstanceCreated", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
internal static partial void Internal_ManagedInstanceCreated(Object managedInstance);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Object::Internal_ManagedInstanceDeleted", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_ManagedInstanceDeleted", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
internal static partial void Internal_ManagedInstanceDeleted(IntPtr nativeInstance);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Object::Internal_Destroy", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_Destroy", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
internal static partial void Internal_Destroy(IntPtr obj, float timeLeft);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Object::Internal_GetTypeName", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_GetTypeName", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
internal static partial string Internal_GetTypeName(IntPtr obj);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Object::Internal_FindObject", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_FindObject", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
internal static partial Object Internal_FindObject(ref Guid id, [MarshalUsing(typeof(SystemTypeMarshaller))] Type type);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Object::Internal_TryFindObject", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_TryFindObject", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
internal static partial Object Internal_TryFindObject(ref Guid id, [MarshalUsing(typeof(SystemTypeMarshaller))] Type type);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Object::Internal_ChangeID", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_ChangeID", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
internal static partial void Internal_ChangeID(IntPtr obj, ref Guid id);
|
||||
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Object::Internal_GetUnmanagedInterface", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_GetUnmanagedInterface", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
internal static partial IntPtr Internal_GetUnmanagedInterface(IntPtr obj, [MarshalUsing(typeof(SystemTypeMarshaller))] Type type);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#if USE_MONO
|
||||
|
||||
namespace ProfilerInternal
|
||||
namespace
|
||||
{
|
||||
#if COMPILE_WITH_PROFILER
|
||||
Array<int32, InlinedAllocation<32>> ManagedEventsGPU;
|
||||
@@ -37,74 +37,86 @@ namespace ProfilerInternal
|
||||
ChunkedArray<Location, 256> ManagedSourceLocations;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void BeginEvent(MonoString* nameObj)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Profiler::BeginEvent")
|
||||
DEFINE_INTERNAL_CALL(void) ProfilerInternal_BeginEvent(MonoString* nameObj)
|
||||
{
|
||||
#if COMPILE_WITH_PROFILER
|
||||
const StringView name((const Char*)mono_string_chars(nameObj), mono_string_length(nameObj));
|
||||
ProfilerCPU::BeginEvent(*name);
|
||||
const StringView name((const Char*)mono_string_chars(nameObj), mono_string_length(nameObj));
|
||||
ProfilerCPU::BeginEvent(*name);
|
||||
#if TRACY_ENABLE
|
||||
#if PROFILE_CPU_USE_TRANSIENT_DATA
|
||||
tracy::ScopedZone::Begin(__LINE__, __FILE__, strlen( __FILE__ ), __FUNCTION__, strlen( __FUNCTION__ ), name.Get(), name.Length() );
|
||||
tracy::ScopedZone::Begin(__LINE__, __FILE__, strlen( __FILE__ ), __FUNCTION__, strlen( __FUNCTION__ ), name.Get(), name.Length() );
|
||||
#else
|
||||
ScopeLock lock(ManagedSourceLocationsLocker);
|
||||
tracy::SourceLocationData* srcLoc = nullptr;
|
||||
for (auto e = ManagedSourceLocations.Begin(); e.IsNotEnd(); ++e)
|
||||
{
|
||||
if (name == e->Name)
|
||||
{
|
||||
srcLoc = &e->SrcLocation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!srcLoc)
|
||||
{
|
||||
auto& e = ManagedSourceLocations.AddOne();
|
||||
e.Name = name;
|
||||
e.NameAnsi = name.Get();
|
||||
srcLoc = &e.SrcLocation;
|
||||
srcLoc->name = e.NameAnsi.Get();
|
||||
srcLoc->function = nullptr;
|
||||
srcLoc->file = nullptr;
|
||||
srcLoc->line = 0;
|
||||
srcLoc->color = 0;
|
||||
}
|
||||
//static constexpr tracy::SourceLocationData tracySrcLoc{ nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 };
|
||||
tracy::ScopedZone::Begin(srcLoc);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void EndEvent()
|
||||
ScopeLock lock(ManagedSourceLocationsLocker);
|
||||
tracy::SourceLocationData* srcLoc = nullptr;
|
||||
for (auto e = ManagedSourceLocations.Begin(); e.IsNotEnd(); ++e)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Profiler::EndEvent")
|
||||
if (name == e->Name)
|
||||
{
|
||||
srcLoc = &e->SrcLocation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!srcLoc)
|
||||
{
|
||||
auto& e = ManagedSourceLocations.AddOne();
|
||||
e.Name = name;
|
||||
e.NameAnsi = name.Get();
|
||||
srcLoc = &e.SrcLocation;
|
||||
srcLoc->name = e.NameAnsi.Get();
|
||||
srcLoc->function = nullptr;
|
||||
srcLoc->file = nullptr;
|
||||
srcLoc->line = 0;
|
||||
srcLoc->color = 0;
|
||||
}
|
||||
//static constexpr tracy::SourceLocationData tracySrcLoc{ nullptr, __FUNCTION__, __FILE__, (uint32_t)__LINE__, 0 };
|
||||
tracy::ScopedZone::Begin(srcLoc);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) ProfilerInternal_EndEvent()
|
||||
{
|
||||
#if COMPILE_WITH_PROFILER
|
||||
#if TRACY_ENABLE
|
||||
tracy::ScopedZone::End();
|
||||
tracy::ScopedZone::End();
|
||||
#endif
|
||||
ProfilerCPU::EndEvent();
|
||||
ProfilerCPU::EndEvent();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void BeginEventGPU(MonoString* nameObj)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Profiler::BeginEventGPU")
|
||||
DEFINE_INTERNAL_CALL(void) ProfilerInternal_BeginEventGPU(MonoString* nameObj)
|
||||
{
|
||||
#if COMPILE_WITH_PROFILER
|
||||
const auto index = ProfilerGPU::BeginEvent((const Char*)mono_string_chars(nameObj));
|
||||
ManagedEventsGPU.Push(index);
|
||||
const auto index = ProfilerGPU::BeginEvent((const Char*)mono_string_chars(nameObj));
|
||||
ManagedEventsGPU.Push(index);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void EndEventGPU()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Profiler::EndEventGPU")
|
||||
DEFINE_INTERNAL_CALL(void) ProfilerInternal_EndEventGPU()
|
||||
{
|
||||
#if COMPILE_WITH_PROFILER
|
||||
const auto index = ManagedEventsGPU.Pop();
|
||||
ProfilerGPU::EndEvent(index);
|
||||
const auto index = ManagedEventsGPU.Pop();
|
||||
ProfilerGPU::EndEvent(index);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(bool) ScriptingInternal_HasGameModulesLoaded()
|
||||
{
|
||||
return Scripting::HasGameModulesLoaded();
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(bool) ScriptingInternal_IsTypeFromGameScripts(MonoReflectionType* type)
|
||||
{
|
||||
return Scripting::IsTypeFromGameScripts(Scripting::FindClass(MUtils::GetClass(type)));
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) ScriptingInternal_FlushRemovedObjects()
|
||||
{
|
||||
ASSERT(IsInMainThread());
|
||||
ObjectsRemovalService::Flush();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -112,41 +124,18 @@ namespace ProfilerInternal
|
||||
class ScriptingInternal
|
||||
{
|
||||
public:
|
||||
#if USE_MONO
|
||||
static bool HasGameModulesLoaded()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Scripting::HasGameModulesLoaded")
|
||||
return Scripting::HasGameModulesLoaded();
|
||||
}
|
||||
|
||||
static bool IsTypeFromGameScripts(MonoReflectionType* type)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Scripting::IsTypeFromGameScripts")
|
||||
return Scripting::IsTypeFromGameScripts(Scripting::FindClass(MUtils::GetClass(type)));
|
||||
}
|
||||
|
||||
static void FlushRemovedObjects()
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Scripting::FlushRemovedObjects")
|
||||
ASSERT(IsInMainThread());
|
||||
ObjectsRemovalService::Flush();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void InitRuntime()
|
||||
{
|
||||
#if USE_MONO
|
||||
// Scripting API
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Scripting::HasGameModulesLoaded", &HasGameModulesLoaded);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Scripting::IsTypeFromGameScripts", &IsTypeFromGameScripts);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Scripting::FlushRemovedObjects", &FlushRemovedObjects);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Scripting::HasGameModulesLoaded", &ScriptingInternal_HasGameModulesLoaded);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Scripting::IsTypeFromGameScripts", &ScriptingInternal_IsTypeFromGameScripts);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Scripting::FlushRemovedObjects", &ScriptingInternal_FlushRemovedObjects);
|
||||
|
||||
// Profiler API
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Profiler::BeginEvent", &ProfilerInternal::BeginEvent);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Profiler::EndEvent", &ProfilerInternal::EndEvent);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Profiler::BeginEventGPU", &ProfilerInternal::BeginEventGPU);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Profiler::EndEventGPU", &ProfilerInternal::EndEventGPU);
|
||||
#endif
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Profiler::BeginEvent", &ProfilerInternal_BeginEvent);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Profiler::EndEvent", &ProfilerInternal_EndEvent);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Profiler::BeginEventGPU", &ProfilerInternal_BeginEventGPU);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Profiler::EndEventGPU", &ProfilerInternal_EndEventGPU);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -201,35 +201,30 @@ bool ScriptingService::Init()
|
||||
void ScriptingService::Update()
|
||||
{
|
||||
PROFILE_CPU_NAMED("Scripting::Update");
|
||||
|
||||
INVOKE_EVENT(Update);
|
||||
}
|
||||
|
||||
void ScriptingService::LateUpdate()
|
||||
{
|
||||
PROFILE_CPU_NAMED("Scripting::LateUpdate");
|
||||
|
||||
INVOKE_EVENT(LateUpdate);
|
||||
}
|
||||
|
||||
void ScriptingService::FixedUpdate()
|
||||
{
|
||||
PROFILE_CPU_NAMED("Scripting::FixedUpdate");
|
||||
|
||||
INVOKE_EVENT(FixedUpdate);
|
||||
}
|
||||
|
||||
void ScriptingService::Draw()
|
||||
{
|
||||
PROFILE_CPU_NAMED("Scripting::Draw");
|
||||
|
||||
INVOKE_EVENT(Draw);
|
||||
}
|
||||
|
||||
void ScriptingService::BeforeExit()
|
||||
{
|
||||
PROFILE_CPU_NAMED("Scripting::BeforeExit");
|
||||
|
||||
INVOKE_EVENT(Exit);
|
||||
}
|
||||
|
||||
@@ -927,7 +922,6 @@ ScriptingObject* Scripting::FindObject(const MObject* managedInstance)
|
||||
|
||||
void Scripting::OnManagedInstanceDeleted(ScriptingObject* obj)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Object::Internal_ManagedInstanceDeleted")
|
||||
PROFILE_CPU();
|
||||
ASSERT(obj);
|
||||
|
||||
|
||||
@@ -310,7 +310,7 @@ namespace FlaxEngine
|
||||
/// Returns true if game scripts assembly has been loaded.
|
||||
/// </summary>
|
||||
/// <returns>True if game scripts assembly is loaded, otherwise false.</returns>
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Scripting::HasGameModulesLoaded", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ScriptingInternal_HasGameModulesLoaded", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
public static partial bool HasGameModulesLoaded();
|
||||
|
||||
@@ -318,14 +318,14 @@ namespace FlaxEngine
|
||||
/// Returns true if given type is from one of the game scripts assemblies.
|
||||
/// </summary>
|
||||
/// <returns>True if the type is from game assembly, otherwise false.</returns>
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Scripting::IsTypeFromGameScripts", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ScriptingInternal_IsTypeFromGameScripts", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[return: MarshalAs(UnmanagedType.U1)]
|
||||
public static partial bool IsTypeFromGameScripts([MarshalUsing(typeof(SystemTypeMarshaller))] Type type);
|
||||
|
||||
/// <summary>
|
||||
/// Flushes the removed objects (disposed objects using Object.Destroy).
|
||||
/// </summary>
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Scripting::FlushRemovedObjects", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ScriptingInternal_FlushRemovedObjects", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
public static partial void FlushRemovedObjects();
|
||||
}
|
||||
|
||||
@@ -341,26 +341,26 @@ namespace FlaxEngine
|
||||
/// Begins profiling a piece of code with a custom label.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the event.</param>
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Profiler::BeginEvent", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ProfilerInternal_BeginEvent", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
public static partial void BeginEvent(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Ends profiling an event.
|
||||
/// </summary>
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Profiler::EndEvent", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ProfilerInternal_EndEvent", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
public static partial void EndEvent();
|
||||
|
||||
/// <summary>
|
||||
/// Begins GPU profiling a piece of code with a custom label.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the event.</param>
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Profiler::BeginEventGPU", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ProfilerInternal_BeginEventGPU", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
public static partial void BeginEventGPU(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Ends GPU profiling an event.
|
||||
/// </summary>
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.Profiler::EndEventGPU", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
[LibraryImport("FlaxEngine", EntryPoint = "ProfilerInternal_EndEventGPU", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(FlaxEngine.StringMarshaller))]
|
||||
public static partial void EndEventGPU();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +221,16 @@ void ScriptingObject::ChangeID(const Guid& newId)
|
||||
_type.GetType().Module->OnObjectIdChanged(this, prevId);
|
||||
}
|
||||
|
||||
void ScriptingObject::SetManagedInstance(MonoObject* instance)
|
||||
{
|
||||
ASSERT(_gcHandle == 0);
|
||||
#if USE_NETCORE
|
||||
_gcHandle = (MGCHandle)instance;
|
||||
#else
|
||||
_gcHandle = MUtils::NewGCHandle(instance, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScriptingObject::OnManagedInstanceDeleted()
|
||||
{
|
||||
// Release the handle
|
||||
@@ -444,6 +454,16 @@ ManagedScriptingObject::ManagedScriptingObject(const SpawnParams& params)
|
||||
{
|
||||
}
|
||||
|
||||
void ManagedScriptingObject::SetManagedInstance(MonoObject* instance)
|
||||
{
|
||||
ASSERT(_gcHandle == 0);
|
||||
#if USE_NETCORE
|
||||
_gcHandle = (MGCHandle)instance;
|
||||
#else
|
||||
_gcHandle = MUtils::NewGCHandleWeakref(instance, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ManagedScriptingObject::OnManagedInstanceDeleted()
|
||||
{
|
||||
// Base
|
||||
@@ -508,302 +528,274 @@ PersistentScriptingObject::PersistentScriptingObject(const SpawnParams& params)
|
||||
{
|
||||
}
|
||||
|
||||
#if !COMPILE_WITHOUT_CSHARP
|
||||
|
||||
DEFINE_INTERNAL_CALL(MonoObject*) ObjectInternal_Create1(MonoReflectionType* type)
|
||||
{
|
||||
// Peek class for that type (handle generic class cases)
|
||||
if (!type)
|
||||
DebugLog::ThrowArgumentNull("type");
|
||||
MonoType* monoType = mono_reflection_type_get_type(type);
|
||||
const int32 monoTypeType = mono_type_get_type(monoType);
|
||||
if (monoTypeType == MONO_TYPE_GENERICINST)
|
||||
{
|
||||
LOG(Error, "Generic scripts are not supported.");
|
||||
return nullptr;
|
||||
}
|
||||
MonoClass* typeClass = mono_type_get_class(monoType);
|
||||
if (typeClass == nullptr)
|
||||
{
|
||||
LOG(Error, "Invalid type.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get the assembly with that class
|
||||
auto module = ManagedBinaryModule::FindModule(typeClass);
|
||||
if (module == nullptr)
|
||||
{
|
||||
LOG(Error, "Cannot find scripting assembly for type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to find the scripting type for this class
|
||||
int32 typeIndex;
|
||||
if (!module->ClassToTypeIndex.TryGet(typeClass, typeIndex))
|
||||
{
|
||||
LOG(Error, "Cannot spawn objects of type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return nullptr;
|
||||
}
|
||||
const ScriptingType& scriptingType = module->Types[typeIndex];
|
||||
|
||||
// Create unmanaged object
|
||||
const ScriptingObjectSpawnParams params(Guid::New(), ScriptingTypeHandle(module, typeIndex));
|
||||
ScriptingObject* obj = scriptingType.Script.Spawn(params);
|
||||
if (obj == nullptr)
|
||||
{
|
||||
LOG(Error, "Failed to spawn object of type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set default name for actors
|
||||
if (auto* actor = dynamic_cast<Actor*>(obj))
|
||||
{
|
||||
actor->SetName(String(mono_class_get_name(typeClass)));
|
||||
}
|
||||
|
||||
// Create managed object
|
||||
obj->CreateManaged();
|
||||
MonoObject* managedInstance = obj->GetManagedInstance();
|
||||
if (managedInstance == nullptr)
|
||||
{
|
||||
LOG(Error, "Cannot create managed instance for type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
Delete(obj);
|
||||
}
|
||||
|
||||
return managedInstance;
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(MonoObject*) ObjectInternal_Create2(MonoString* typeNameObj)
|
||||
{
|
||||
// Get typename
|
||||
if (typeNameObj == nullptr)
|
||||
DebugLog::ThrowArgumentNull("typeName");
|
||||
const StringAsANSI<> typeNameData((const Char*)mono_string_chars(typeNameObj), (int32)mono_string_length(typeNameObj));
|
||||
const StringAnsiView typeName(typeNameData.Get(), (int32)mono_string_length(typeNameObj));
|
||||
|
||||
// Try to find the scripting type for this typename
|
||||
const ScriptingTypeHandle type = Scripting::FindScriptingType(typeName);
|
||||
if (!type)
|
||||
{
|
||||
LOG(Error, "Cannot find scripting type for \'{0}\'.", String(typeName));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create unmanaged object
|
||||
const ScriptingObjectSpawnParams params(Guid::New(), type);
|
||||
ScriptingObject* obj = type.GetType().Script.Spawn(params);
|
||||
if (obj == nullptr)
|
||||
{
|
||||
LOG(Error, "Failed to spawn object of type \'{0}\'.", String(typeName));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create managed object
|
||||
obj->CreateManaged();
|
||||
MonoObject* managedInstance = obj->GetManagedInstance();
|
||||
if (managedInstance == nullptr)
|
||||
{
|
||||
LOG(Error, "Cannot create managed instance for type \'{0}\'.", String(typeName));
|
||||
Delete(obj);
|
||||
}
|
||||
|
||||
return managedInstance;
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) ObjectInternal_ManagedInstanceCreated(MonoObject* managedInstance)
|
||||
{
|
||||
MonoClass* typeClass = mono_object_get_class(managedInstance);
|
||||
|
||||
// Get the assembly with that class
|
||||
auto module = ManagedBinaryModule::FindModule(typeClass);
|
||||
if (module == nullptr)
|
||||
{
|
||||
LOG(Error, "Cannot find scripting assembly for type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find the scripting type for this class
|
||||
int32 typeIndex;
|
||||
if (!module->ClassToTypeIndex.TryGet(typeClass, typeIndex))
|
||||
{
|
||||
LOG(Error, "Cannot spawn objects of type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return;
|
||||
}
|
||||
const ScriptingType& scriptingType = module->Types[typeIndex];
|
||||
|
||||
// Create unmanaged object
|
||||
const ScriptingObjectSpawnParams params(Guid::New(), ScriptingTypeHandle(module, typeIndex));
|
||||
ScriptingObject* obj = scriptingType.Script.Spawn(params);
|
||||
if (obj == nullptr)
|
||||
{
|
||||
LOG(Error, "Failed to spawn object of type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Set default name for actors
|
||||
if (auto* actor = dynamic_cast<Actor*>(obj))
|
||||
{
|
||||
actor->SetName(String(mono_class_get_name(typeClass)));
|
||||
}
|
||||
|
||||
// Link created managed instance to the unmanaged object
|
||||
obj->SetManagedInstance(managedInstance);
|
||||
|
||||
MClass* monoClass = obj->GetClass();
|
||||
|
||||
// Set handle to unmanaged object
|
||||
const MField* monoUnmanagedPtrField = monoClass->GetField(ScriptingObject_unmanagedPtr);
|
||||
if (monoUnmanagedPtrField)
|
||||
{
|
||||
const void* value = obj;
|
||||
monoUnmanagedPtrField->SetValue(managedInstance, &value);
|
||||
}
|
||||
|
||||
// Set object id
|
||||
const MField* monoIdField = monoClass->GetField(ScriptingObject_id);
|
||||
if (monoIdField)
|
||||
{
|
||||
const Guid id = obj->GetID();
|
||||
monoIdField->SetValue(managedInstance, (void*)&id);
|
||||
}
|
||||
|
||||
// Register object
|
||||
if (!obj->IsRegistered())
|
||||
obj->RegisterObject();
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) ObjectInternal_ManagedInstanceDeleted(ScriptingObject* obj)
|
||||
{
|
||||
Scripting::OnManagedInstanceDeleted(obj);
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) ObjectInternal_Destroy(ScriptingObject* obj, float timeLeft)
|
||||
{
|
||||
// Use scaled game time for removing actors/scripts by the user (maybe expose it to the api?)
|
||||
const bool useGameTime = timeLeft > ZeroTolerance;
|
||||
|
||||
if (obj)
|
||||
obj->DeleteObject(timeLeft, useGameTime);
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(MonoString*) ObjectInternal_GetTypeName(ScriptingObject* obj)
|
||||
{
|
||||
INTERNAL_CALL_CHECK_RETURN(obj, nullptr);
|
||||
return MUtils::ToString(obj->GetType().Fullname);
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(MonoObject*) ObjectInternal_FindObject(Guid* id, MonoReflectionType* type)
|
||||
{
|
||||
if (!id->IsValid())
|
||||
return nullptr;
|
||||
auto klass = MUtils::GetClass(type);
|
||||
ScriptingObject* obj = Scripting::TryFindObject(*id);
|
||||
if (!obj)
|
||||
{
|
||||
if (!klass || klass == ScriptingObject::GetStaticClass()->GetNative() || mono_class_is_subclass_of(klass, Asset::GetStaticClass()->GetNative(), false) != 0)
|
||||
{
|
||||
obj = Content::LoadAsync<Asset>(*id);
|
||||
}
|
||||
}
|
||||
if (obj)
|
||||
{
|
||||
if (klass && !obj->Is(klass))
|
||||
{
|
||||
LOG(Warning, "Found scripting object with ID={0} of type {1} that doesn't match type {2}.", *id, String(obj->GetType().Fullname), String(MUtils::GetClassFullname(klass)));
|
||||
return nullptr;
|
||||
}
|
||||
return obj->GetOrCreateManagedInstance();
|
||||
}
|
||||
if (klass)
|
||||
LOG(Warning, "Unable to find scripting object with ID={0}. Required type {1}.", *id, String(MUtils::GetClassFullname(klass)));
|
||||
else
|
||||
LOG(Warning, "Unable to find scripting object with ID={0}", *id);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(MonoObject*) ObjectInternal_TryFindObject(Guid* id, MonoReflectionType* type)
|
||||
{
|
||||
ScriptingObject* obj = Scripting::TryFindObject(*id);
|
||||
if (obj && !obj->Is(MUtils::GetClass(type)))
|
||||
obj = nullptr;
|
||||
return obj ? obj->GetOrCreateManagedInstance() : nullptr;
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void) ObjectInternal_ChangeID(ScriptingObject* obj, Guid* id)
|
||||
{
|
||||
INTERNAL_CALL_CHECK(obj);
|
||||
obj->ChangeID(*id);
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(void*) ObjectInternal_GetUnmanagedInterface(ScriptingObject* obj, MonoReflectionType* type)
|
||||
{
|
||||
if (obj && type)
|
||||
{
|
||||
auto typeClass = MUtils::GetClass(type);
|
||||
const ScriptingTypeHandle interfaceType = ManagedBinaryModule::FindType(typeClass);
|
||||
if (interfaceType)
|
||||
{
|
||||
return ScriptingObject::ToInterface(obj, interfaceType);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DEFINE_INTERNAL_CALL(MonoObject*) ObjectInternal_FromUnmanagedPtr(ScriptingObject* obj)
|
||||
{
|
||||
MonoObject* result = nullptr;
|
||||
if (obj)
|
||||
result = obj->GetOrCreateManagedInstance();
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
class ScriptingObjectInternal
|
||||
{
|
||||
public:
|
||||
#if !COMPILE_WITHOUT_CSHARP
|
||||
|
||||
static MonoObject* Create1(MonoReflectionType* type)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Object::Internal_Create1")
|
||||
// Peek class for that type (handle generic class cases)
|
||||
if (!type)
|
||||
DebugLog::ThrowArgumentNull("type");
|
||||
MonoType* monoType = mono_reflection_type_get_type(type);
|
||||
const int32 monoTypeType = mono_type_get_type(monoType);
|
||||
if (monoTypeType == MONO_TYPE_GENERICINST)
|
||||
{
|
||||
LOG(Error, "Generic scripts are not supported.");
|
||||
return nullptr;
|
||||
}
|
||||
MonoClass* typeClass = mono_type_get_class(monoType);
|
||||
if (typeClass == nullptr)
|
||||
{
|
||||
LOG(Error, "Invalid type.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Get the assembly with that class
|
||||
auto module = ManagedBinaryModule::FindModule(typeClass);
|
||||
if (module == nullptr)
|
||||
{
|
||||
LOG(Error, "Cannot find scripting assembly for type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to find the scripting type for this class
|
||||
int32 typeIndex;
|
||||
if (!module->ClassToTypeIndex.TryGet(typeClass, typeIndex))
|
||||
{
|
||||
LOG(Error, "Cannot spawn objects of type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return nullptr;
|
||||
}
|
||||
const ScriptingType& scriptingType = module->Types[typeIndex];
|
||||
|
||||
// Create unmanaged object
|
||||
const ScriptingObjectSpawnParams params(Guid::New(), ScriptingTypeHandle(module, typeIndex));
|
||||
ScriptingObject* obj = scriptingType.Script.Spawn(params);
|
||||
if (obj == nullptr)
|
||||
{
|
||||
LOG(Error, "Failed to spawn object of type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set default name for actors
|
||||
if (auto* actor = dynamic_cast<Actor*>(obj))
|
||||
{
|
||||
actor->SetName(String(mono_class_get_name(typeClass)));
|
||||
}
|
||||
|
||||
// Create managed object
|
||||
obj->CreateManaged();
|
||||
MonoObject* managedInstance = obj->GetManagedInstance();
|
||||
if (managedInstance == nullptr)
|
||||
{
|
||||
LOG(Error, "Cannot create managed instance for type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
Delete(obj);
|
||||
}
|
||||
|
||||
return managedInstance;
|
||||
}
|
||||
|
||||
static MonoObject* Create2(MonoString* typeNameObj)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Object::Internal_Create2")
|
||||
// Get typename
|
||||
if (typeNameObj == nullptr)
|
||||
DebugLog::ThrowArgumentNull("typeName");
|
||||
const StringAsANSI<> typeNameData((const Char*)mono_string_chars(typeNameObj), (int32)mono_string_length(typeNameObj));
|
||||
const StringAnsiView typeName(typeNameData.Get(), (int32)mono_string_length(typeNameObj));
|
||||
|
||||
// Try to find the scripting type for this typename
|
||||
const ScriptingTypeHandle type = Scripting::FindScriptingType(typeName);
|
||||
if (!type)
|
||||
{
|
||||
LOG(Error, "Cannot find scripting type for \'{0}\'.", String(typeName));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create unmanaged object
|
||||
const ScriptingObjectSpawnParams params(Guid::New(), type);
|
||||
ScriptingObject* obj = type.GetType().Script.Spawn(params);
|
||||
if (obj == nullptr)
|
||||
{
|
||||
LOG(Error, "Failed to spawn object of type \'{0}\'.", String(typeName));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create managed object
|
||||
obj->CreateManaged();
|
||||
MonoObject* managedInstance = obj->GetManagedInstance();
|
||||
if (managedInstance == nullptr)
|
||||
{
|
||||
LOG(Error, "Cannot create managed instance for type \'{0}\'.", String(typeName));
|
||||
Delete(obj);
|
||||
}
|
||||
|
||||
return managedInstance;
|
||||
}
|
||||
|
||||
static void ManagedInstanceCreated(MonoObject* managedInstance)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Object::Internal_ManagedInstanceCreated")
|
||||
MonoClass* typeClass = mono_object_get_class(managedInstance);
|
||||
|
||||
// Get the assembly with that class
|
||||
auto module = ManagedBinaryModule::FindModule(typeClass);
|
||||
if (module == nullptr)
|
||||
{
|
||||
LOG(Error, "Cannot find scripting assembly for type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find the scripting type for this class
|
||||
int32 typeIndex;
|
||||
if (!module->ClassToTypeIndex.TryGet(typeClass, typeIndex))
|
||||
{
|
||||
LOG(Error, "Cannot spawn objects of type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return;
|
||||
}
|
||||
const ScriptingType& scriptingType = module->Types[typeIndex];
|
||||
|
||||
// Create unmanaged object
|
||||
const ScriptingObjectSpawnParams params(Guid::New(), ScriptingTypeHandle(module, typeIndex));
|
||||
ScriptingObject* obj = scriptingType.Script.Spawn(params);
|
||||
if (obj == nullptr)
|
||||
{
|
||||
LOG(Error, "Failed to spawn object of type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Set default name for actors
|
||||
if (auto* actor = dynamic_cast<Actor*>(obj))
|
||||
{
|
||||
actor->SetName(String(mono_class_get_name(typeClass)));
|
||||
}
|
||||
|
||||
// Link created managed instance to the unmanaged object
|
||||
if (auto* managedScriptingObject = dynamic_cast<ManagedScriptingObject*>(obj))
|
||||
{
|
||||
// Managed
|
||||
#if USE_NETCORE
|
||||
managedScriptingObject->_gcHandle = (MGCHandle)managedInstance;
|
||||
#else
|
||||
managedScriptingObject->_gcHandle = MUtils::NewGCHandleWeakref(managedInstance, false);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// Persistent
|
||||
#if USE_NETCORE
|
||||
obj->_gcHandle = (MGCHandle)managedInstance;
|
||||
#else
|
||||
obj->_gcHandle = MUtils::NewGCHandle(managedInstance, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
MClass* monoClass = obj->GetClass();
|
||||
|
||||
// Set handle to unmanaged object
|
||||
const MField* monoUnmanagedPtrField = monoClass->GetField(ScriptingObject_unmanagedPtr);
|
||||
if (monoUnmanagedPtrField)
|
||||
{
|
||||
const void* value = obj;
|
||||
monoUnmanagedPtrField->SetValue(managedInstance, &value);
|
||||
}
|
||||
|
||||
// Set object id
|
||||
const MField* monoIdField = monoClass->GetField(ScriptingObject_id);
|
||||
if (monoIdField)
|
||||
{
|
||||
monoIdField->SetValue(managedInstance, (void*)&obj->_id);
|
||||
}
|
||||
|
||||
// Register object
|
||||
if (!obj->IsRegistered())
|
||||
obj->RegisterObject();
|
||||
}
|
||||
|
||||
static void Destroy(ScriptingObject* obj, float timeLeft)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Object::Internal_Destroy")
|
||||
// Use scaled game time for removing actors/scripts by the user (maybe expose it to the api?)
|
||||
const bool useGameTime = timeLeft > ZeroTolerance;
|
||||
|
||||
if (obj)
|
||||
obj->DeleteObject(timeLeft, useGameTime);
|
||||
}
|
||||
|
||||
static MonoString* GetTypeName(ScriptingObject* obj)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Object::Internal_GetTypeName")
|
||||
INTERNAL_CALL_CHECK_RETURN(obj, nullptr);
|
||||
return MUtils::ToString(obj->GetType().Fullname);
|
||||
}
|
||||
|
||||
static MonoObject* FindObject(Guid* id, MonoReflectionType* type)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Object::Internal_FindObject")
|
||||
if (!id->IsValid())
|
||||
return nullptr;
|
||||
auto klass = MUtils::GetClass(type);
|
||||
ScriptingObject* obj = Scripting::TryFindObject(*id);
|
||||
if (!obj)
|
||||
{
|
||||
if (!klass || klass == ScriptingObject::GetStaticClass()->GetNative() || mono_class_is_subclass_of(klass, Asset::GetStaticClass()->GetNative(), false) != 0)
|
||||
{
|
||||
obj = Content::LoadAsync<Asset>(*id);
|
||||
}
|
||||
}
|
||||
if (obj)
|
||||
{
|
||||
if (klass && !obj->Is(klass))
|
||||
{
|
||||
LOG(Warning, "Found scripting object with ID={0} of type {1} that doesn't match type {2}.", *id, String(obj->GetType().Fullname), String(MUtils::GetClassFullname(klass)));
|
||||
return nullptr;
|
||||
}
|
||||
return obj->GetOrCreateManagedInstance();
|
||||
}
|
||||
if (klass)
|
||||
LOG(Warning, "Unable to find scripting object with ID={0}. Required type {1}.", *id, String(MUtils::GetClassFullname(klass)));
|
||||
else
|
||||
LOG(Warning, "Unable to find scripting object with ID={0}", *id);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static MonoObject* TryFindObject(Guid* id, MonoReflectionType* type)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Object::Internal_TryFindObject")
|
||||
ScriptingObject* obj = Scripting::TryFindObject(*id);
|
||||
if (obj && !obj->Is(MUtils::GetClass(type)))
|
||||
obj = nullptr;
|
||||
return obj ? obj->GetOrCreateManagedInstance() : nullptr;
|
||||
}
|
||||
|
||||
static void ChangeID(ScriptingObject* obj, Guid* id)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Object::Internal_ChangeID")
|
||||
INTERNAL_CALL_CHECK(obj);
|
||||
obj->ChangeID(*id);
|
||||
}
|
||||
|
||||
static void* GetUnmanagedInterface(ScriptingObject* obj, MonoReflectionType* type)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Object::Internal_GetUnmanagedInterface")
|
||||
if (obj && type)
|
||||
{
|
||||
auto typeClass = MUtils::GetClass(type);
|
||||
const ScriptingTypeHandle interfaceType = ManagedBinaryModule::FindType(typeClass);
|
||||
if (interfaceType)
|
||||
{
|
||||
return ScriptingObject::ToInterface(obj, interfaceType);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static MonoObject* FromUnmanagedPtr(ScriptingObject* obj)
|
||||
{
|
||||
SCRIPTING_EXPORT("FlaxEngine.Object::FromUnmanagedPtr")
|
||||
MonoObject* result = nullptr;
|
||||
if (obj)
|
||||
result = obj->GetOrCreateManagedInstance();
|
||||
return result;
|
||||
}
|
||||
|
||||
static void InitRuntime()
|
||||
{
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_Create1", &Create1);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_Create2", &Create2);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_ManagedInstanceCreated", &ManagedInstanceCreated);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_ManagedInstanceDeleted", &Scripting::OnManagedInstanceDeleted);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_Destroy", &Destroy);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_GetTypeName", &GetTypeName);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_FindObject", &FindObject);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_TryFindObject", &TryFindObject);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_ChangeID", &ChangeID);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_GetUnmanagedInterface", &GetUnmanagedInterface);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::FromUnmanagedPtr", &FromUnmanagedPtr);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_Create1", &ObjectInternal_Create1);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_Create2", &ObjectInternal_Create2);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_ManagedInstanceCreated", &ObjectInternal_ManagedInstanceCreated);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_ManagedInstanceDeleted", &ObjectInternal_ManagedInstanceDeleted);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_Destroy", &ObjectInternal_Destroy);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_GetTypeName", &ObjectInternal_GetTypeName);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_FindObject", &ObjectInternal_FindObject);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_TryFindObject", &ObjectInternal_TryFindObject);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_ChangeID", &ObjectInternal_ChangeID);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::Internal_GetUnmanagedInterface", &ObjectInternal_GetUnmanagedInterface);
|
||||
ADD_INTERNAL_CALL("FlaxEngine.Object::FromUnmanagedPtr", &ObjectInternal_FromUnmanagedPtr);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void InitRuntime()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static ScriptingObject* Spawn(const ScriptingObjectSpawnParams& params)
|
||||
{
|
||||
return New<ScriptingObject>(params);
|
||||
|
||||
@@ -14,19 +14,17 @@ API_CLASS(InBuild) class FLAXENGINE_API ScriptingObject : public Object
|
||||
{
|
||||
friend class Scripting;
|
||||
friend class BinaryModule;
|
||||
DECLARE_SCRIPTING_TYPE_NO_SPAWN(ScriptingObject);
|
||||
public:
|
||||
DECLARE_SCRIPTING_TYPE_NO_SPAWN(ScriptingObject);
|
||||
|
||||
public:
|
||||
typedef ScriptingObjectSpawnParams SpawnParams;
|
||||
|
||||
protected:
|
||||
|
||||
MGCHandle _gcHandle;
|
||||
ScriptingTypeHandle _type;
|
||||
Guid _id;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ScriptingObject"/> class.
|
||||
/// </summary>
|
||||
@@ -39,14 +37,15 @@ public:
|
||||
virtual ~ScriptingObject();
|
||||
|
||||
public:
|
||||
|
||||
// Spawns a new objects of the given type.
|
||||
static ScriptingObject* NewObject(const ScriptingTypeHandle& typeHandle);
|
||||
|
||||
template<typename T>
|
||||
static T* NewObject()
|
||||
{
|
||||
return (T*)NewObject(T::TypeInitializer);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T* NewObject(const ScriptingTypeHandle& typeHandle)
|
||||
{
|
||||
@@ -60,14 +59,12 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when object gets deleted.
|
||||
/// </summary>
|
||||
Delegate<ScriptingObject*> Deleted;
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Gets the managed instance object.
|
||||
/// </summary>
|
||||
@@ -116,15 +113,17 @@ public:
|
||||
MClass* GetClass() const;
|
||||
|
||||
public:
|
||||
|
||||
// Tries to cast native interface object to scripting object instance. Returns null if fails.
|
||||
static ScriptingObject* FromInterface(void* interfaceObj, const ScriptingTypeHandle& interfaceType);
|
||||
|
||||
template<typename T>
|
||||
static ScriptingObject* FromInterface(T* interfaceObj)
|
||||
{
|
||||
return FromInterface(interfaceObj, T::TypeInitializer);
|
||||
}
|
||||
|
||||
static void* ToInterface(ScriptingObject* obj, const ScriptingTypeHandle& interfaceType);
|
||||
|
||||
template<typename T>
|
||||
static T* ToInterface(ScriptingObject* obj)
|
||||
{
|
||||
@@ -184,7 +183,6 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Changes the object id (both managed and unmanaged). Warning! Use with caution as object ID is what it identifies it and change might cause issues.
|
||||
/// </summary>
|
||||
@@ -192,7 +190,7 @@ public:
|
||||
virtual void ChangeID(const Guid& newId);
|
||||
|
||||
public:
|
||||
|
||||
virtual void SetManagedInstance(MonoObject* instance);
|
||||
virtual void OnManagedInstanceDeleted();
|
||||
virtual void OnScriptingDispose();
|
||||
|
||||
@@ -200,7 +198,6 @@ public:
|
||||
virtual void DestroyManaged();
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this object is registered or not (can be found by the queries and used in a game).
|
||||
/// </summary>
|
||||
@@ -220,7 +217,6 @@ public:
|
||||
void UnregisterObject();
|
||||
|
||||
protected:
|
||||
|
||||
#if USE_MONO
|
||||
/// <summary>
|
||||
/// Create a new managed object.
|
||||
@@ -229,7 +225,6 @@ protected:
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
// [Object]
|
||||
void OnDeleteObject() override;
|
||||
String ToString() const override;
|
||||
@@ -243,7 +238,6 @@ public:
|
||||
API_CLASS(InBuild) class FLAXENGINE_API ManagedScriptingObject : public ScriptingObject
|
||||
{
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManagedScriptingObject"/> class.
|
||||
/// </summary>
|
||||
@@ -251,8 +245,8 @@ public:
|
||||
explicit ManagedScriptingObject(const SpawnParams& params);
|
||||
|
||||
public:
|
||||
|
||||
// [ScriptingObject]
|
||||
void SetManagedInstance(MonoObject* instance) override;
|
||||
void OnManagedInstanceDeleted() override;
|
||||
void OnScriptingDispose() override;
|
||||
bool CreateManaged() override;
|
||||
|
||||
Reference in New Issue
Block a user