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.");
return nullptr;
}
asset->RegisterObject();
// Call initializer function
asset->InitAsVirtual();
@@ -1041,6 +1042,7 @@ Asset* Content::LoadAsync(const Guid& id, const ScriptingTypeHandle& type)
LOAD_FAILED();
}
#endif
result->RegisterObject();
// Register asset
AssetsLocker.Lock();

View File

@@ -956,10 +956,12 @@ bool Level::loadScene(rapidjson_flax::Value& data, int32 engineBuild, Scene** ou
objects[i] = obj;
if (obj)
{
obj->RegisterObject();
if (!obj->IsRegistered())
obj->RegisterObject();
#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)
obj->CreateManaged();
if (!obj->GetManagedInstance())
obj->CreateManaged();
#endif
}
else

View File

@@ -796,6 +796,17 @@ ScriptingObject* ManagedBinaryModule::ManagedObjectSpawn(const ScriptingObjectSp
// Mark as managed type
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;
}

View File

@@ -412,7 +412,8 @@ void ScriptingObject::DestroyManaged()
void ScriptingObject::RegisterObject()
{
ASSERT(!IsRegistered());
if (IsRegistered())
return;
Flags |= ObjectFlags::IsRegistered;
Scripting::RegisterObject(this);
}
@@ -532,10 +533,6 @@ bool ManagedScriptingObject::CreateManaged()
}
#endif
// Ensure to be registered
if (!IsRegistered())
RegisterObject();
return false;
}
@@ -598,8 +595,7 @@ DEFINE_INTERNAL_CALL(MObject*) ObjectInternal_Create1(MTypeObject* type)
}
// Create managed object
obj->CreateManaged();
MObject* managedInstance = obj->GetManagedInstance();
MObject* managedInstance = obj->GetOrCreateManagedInstance();
if (managedInstance == nullptr)
{
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
obj->CreateManaged();
MObject* managedInstance = obj->GetManagedInstance();
MObject* managedInstance = obj->GetOrCreateManagedInstance();
if (managedInstance == nullptr)
{
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];
// 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);
if (obj == nullptr)
{
@@ -675,9 +671,6 @@ DEFINE_INTERNAL_CALL(void) ObjectInternal_ManagedInstanceCreated(MObject* manage
return;
}
// Link created managed instance to the unmanaged object
obj->SetManagedInstance(managedInstance);
// Set default name for actors
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);
// Register object
if (!obj->IsRegistered())
obj->RegisterObject();
obj->RegisterObject();
}
DEFINE_INTERNAL_CALL(void) ObjectInternal_ManagedInstanceDeleted(ScriptingObject* obj)

View File

@@ -355,9 +355,15 @@ struct ScriptingObjectSpawnParams
/// </summary>
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)
: ID(id)
, Type(typeHandle)
, Managed(nullptr)
{
}
};