Fix objects creation to ensure managed object ctor is always executed

#3245
This commit is contained in:
Wojtek Figat
2025-03-03 19:12:29 +01:00
parent 3200fc1570
commit e82bb639ed
5 changed files with 30 additions and 17 deletions

View File

@@ -874,6 +874,7 @@ Asset* Content::CreateVirtualAsset(const ScriptingTypeHandle& type)
LOG(Error, "Cannot create virtual asset object."); LOG(Error, "Cannot create virtual asset object.");
return nullptr; return nullptr;
} }
asset->RegisterObject();
// Call initializer function // Call initializer function
asset->InitAsVirtual(); asset->InitAsVirtual();
@@ -1041,6 +1042,7 @@ Asset* Content::LoadAsync(const Guid& id, const ScriptingTypeHandle& type)
LOAD_FAILED(); LOAD_FAILED();
} }
#endif #endif
result->RegisterObject();
// Register asset // Register asset
AssetsLocker.Lock(); AssetsLocker.Lock();

View File

@@ -956,10 +956,12 @@ bool Level::loadScene(rapidjson_flax::Value& data, int32 engineBuild, Scene** ou
objects[i] = obj; objects[i] = obj;
if (obj) if (obj)
{ {
obj->RegisterObject(); if (!obj->IsRegistered())
obj->RegisterObject();
#if USE_EDITOR #if USE_EDITOR
// Auto-create C# objects for all actors in Editor during scene load when running in async (so main thread already has all of them) // Auto-create C# objects for all actors in Editor during scene load when running in async (so main thread already has all of them)
obj->CreateManaged(); if (!obj->GetManagedInstance())
obj->CreateManaged();
#endif #endif
} }
else else

View File

@@ -796,6 +796,17 @@ ScriptingObject* ManagedBinaryModule::ManagedObjectSpawn(const ScriptingObjectSp
// Mark as managed type // Mark as managed type
object->Flags |= ObjectFlags::IsManagedType; object->Flags |= ObjectFlags::IsManagedType;
// Initialize managed instance
if (params.Managed)
{
object->SetManagedInstance((MObject*)params.Managed);
}
else
{
// Invoke managed ctor (to match C++ logic)
object->CreateManaged();
}
return object; return object;
} }

View File

@@ -412,7 +412,8 @@ void ScriptingObject::DestroyManaged()
void ScriptingObject::RegisterObject() void ScriptingObject::RegisterObject()
{ {
ASSERT(!IsRegistered()); if (IsRegistered())
return;
Flags |= ObjectFlags::IsRegistered; Flags |= ObjectFlags::IsRegistered;
Scripting::RegisterObject(this); Scripting::RegisterObject(this);
} }
@@ -532,10 +533,6 @@ bool ManagedScriptingObject::CreateManaged()
} }
#endif #endif
// Ensure to be registered
if (!IsRegistered())
RegisterObject();
return false; return false;
} }
@@ -598,8 +595,7 @@ DEFINE_INTERNAL_CALL(MObject*) ObjectInternal_Create1(MTypeObject* type)
} }
// Create managed object // Create managed object
obj->CreateManaged(); MObject* managedInstance = obj->GetOrCreateManagedInstance();
MObject* managedInstance = obj->GetManagedInstance();
if (managedInstance == nullptr) if (managedInstance == nullptr)
{ {
LOG(Error, "Cannot create managed instance for type \'{0}\'.", String(typeClass->GetFullName())); LOG(Error, "Cannot create managed instance for type \'{0}\'.", String(typeClass->GetFullName()));
@@ -636,8 +632,7 @@ DEFINE_INTERNAL_CALL(MObject*) ObjectInternal_Create2(MString* typeNameObj)
} }
// Create managed object // Create managed object
obj->CreateManaged(); MObject* managedInstance = obj->GetOrCreateManagedInstance();
MObject* managedInstance = obj->GetManagedInstance();
if (managedInstance == nullptr) if (managedInstance == nullptr)
{ {
LOG(Error, "Cannot create managed instance for type \'{0}\'.", String(typeName)); LOG(Error, "Cannot create managed instance for type \'{0}\'.", String(typeName));
@@ -667,7 +662,8 @@ DEFINE_INTERNAL_CALL(void) ObjectInternal_ManagedInstanceCreated(MObject* manage
const ScriptingType& scriptingType = module->Types[typeIndex]; const ScriptingType& scriptingType = module->Types[typeIndex];
// Create unmanaged object // Create unmanaged object
const ScriptingObjectSpawnParams params(Guid::New(), ScriptingTypeHandle(module, typeIndex)); ScriptingObjectSpawnParams params(Guid::New(), ScriptingTypeHandle(module, typeIndex));
params.Managed = managedInstance; // Link created managed instance to the unmanaged object
ScriptingObject* obj = scriptingType.Script.Spawn(params); ScriptingObject* obj = scriptingType.Script.Spawn(params);
if (obj == nullptr) if (obj == nullptr)
{ {
@@ -675,9 +671,6 @@ DEFINE_INTERNAL_CALL(void) ObjectInternal_ManagedInstanceCreated(MObject* manage
return; return;
} }
// Link created managed instance to the unmanaged object
obj->SetManagedInstance(managedInstance);
// Set default name for actors // Set default name for actors
if (auto* actor = dynamic_cast<Actor*>(obj)) if (auto* actor = dynamic_cast<Actor*>(obj))
{ {
@@ -689,8 +682,7 @@ DEFINE_INTERNAL_CALL(void) ObjectInternal_ManagedInstanceCreated(MObject* manage
MCore::ScriptingObject::SetInternalValues(klass, managedInstance, obj, &id); MCore::ScriptingObject::SetInternalValues(klass, managedInstance, obj, &id);
// Register object // Register object
if (!obj->IsRegistered()) obj->RegisterObject();
obj->RegisterObject();
} }
DEFINE_INTERNAL_CALL(void) ObjectInternal_ManagedInstanceDeleted(ScriptingObject* obj) DEFINE_INTERNAL_CALL(void) ObjectInternal_ManagedInstanceDeleted(ScriptingObject* obj)

View File

@@ -355,9 +355,15 @@ struct ScriptingObjectSpawnParams
/// </summary> /// </summary>
const ScriptingTypeHandle Type; const ScriptingTypeHandle Type;
/// <summary>
/// Optional C# object instance to use for unmanaged object.
/// </summary>
void* Managed;
FORCE_INLINE ScriptingObjectSpawnParams(const Guid& id, const ScriptingTypeHandle& typeHandle) FORCE_INLINE ScriptingObjectSpawnParams(const Guid& id, const ScriptingTypeHandle& typeHandle)
: ID(id) : ID(id)
, Type(typeHandle) , Type(typeHandle)
, Managed(nullptr)
{ {
} }
}; };