feat(scripting): add runtime gameobject lifecycle api
This commit is contained in:
@@ -354,6 +354,49 @@ uint64_t InternalCall_GameObject_AddComponent(uint64_t gameObjectUUID, MonoRefle
|
||||
return AddOrGetNativeComponent(gameObject, ResolveManagedComponentKind(componentType)) ? gameObjectUUID : 0;
|
||||
}
|
||||
|
||||
uint64_t InternalCall_GameObject_Find(MonoString* name) {
|
||||
Components::Scene* scene = GetInternalCallScene();
|
||||
if (!scene) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Components::GameObject* gameObject = scene->Find(MonoStringToUtf8(name));
|
||||
return gameObject ? gameObject->GetUUID() : 0;
|
||||
}
|
||||
|
||||
uint64_t InternalCall_GameObject_Create(MonoString* name, uint64_t parentGameObjectUUID) {
|
||||
Components::Scene* scene = GetInternalCallScene();
|
||||
if (!scene) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Components::GameObject* parent = nullptr;
|
||||
if (parentGameObjectUUID != 0) {
|
||||
parent = FindGameObjectByUUID(parentGameObjectUUID);
|
||||
if (!parent || parent->GetScene() != scene) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string objectName = MonoStringToUtf8(name);
|
||||
if (objectName.empty()) {
|
||||
objectName = "GameObject";
|
||||
}
|
||||
|
||||
Components::GameObject* created = scene->CreateGameObject(objectName, parent);
|
||||
return created ? created->GetUUID() : 0;
|
||||
}
|
||||
|
||||
void InternalCall_GameObject_Destroy(uint64_t gameObjectUUID) {
|
||||
Components::Scene* scene = GetInternalCallScene();
|
||||
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
|
||||
if (!scene || !gameObject || gameObject->GetScene() != scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
scene->DestroyGameObject(gameObject);
|
||||
}
|
||||
|
||||
mono_bool InternalCall_Behaviour_GetEnabled(uint64_t scriptComponentUUID) {
|
||||
ScriptComponent* component = FindScriptComponentByUUID(scriptComponentUUID);
|
||||
return (component && component->IsEnabled()) ? 1 : 0;
|
||||
@@ -992,6 +1035,9 @@ void RegisterInternalCalls() {
|
||||
mono_add_internal_call("XCEngine.InternalCalls::GameObject_HasComponent", reinterpret_cast<const void*>(&InternalCall_GameObject_HasComponent));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::GameObject_GetComponent", reinterpret_cast<const void*>(&InternalCall_GameObject_GetComponent));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::GameObject_AddComponent", reinterpret_cast<const void*>(&InternalCall_GameObject_AddComponent));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::GameObject_Find", reinterpret_cast<const void*>(&InternalCall_GameObject_Find));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::GameObject_Create", reinterpret_cast<const void*>(&InternalCall_GameObject_Create));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::GameObject_Destroy", reinterpret_cast<const void*>(&InternalCall_GameObject_Destroy));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Behaviour_GetEnabled", reinterpret_cast<const void*>(&InternalCall_Behaviour_GetEnabled));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Behaviour_SetEnabled", reinterpret_cast<const void*>(&InternalCall_Behaviour_SetEnabled));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Transform_GetLocalPosition", reinterpret_cast<const void*>(&InternalCall_Transform_GetLocalPosition));
|
||||
|
||||
@@ -24,14 +24,22 @@ ScriptComponent::ScriptComponent()
|
||||
}
|
||||
|
||||
void ScriptComponent::SetScriptClass(const std::string& namespaceName, const std::string& className) {
|
||||
const bool hadScriptClass = HasScriptClass();
|
||||
m_namespaceName = namespaceName;
|
||||
m_className = className;
|
||||
if (!hadScriptClass && HasScriptClass()) {
|
||||
ScriptEngine::Get().OnScriptComponentEnabled(this);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptComponent::SetScriptClass(const std::string& assemblyName, const std::string& namespaceName, const std::string& className) {
|
||||
const bool hadScriptClass = HasScriptClass();
|
||||
m_assemblyName = assemblyName;
|
||||
m_namespaceName = namespaceName;
|
||||
m_className = className;
|
||||
if (!hadScriptClass && HasScriptClass()) {
|
||||
ScriptEngine::Get().OnScriptComponentEnabled(this);
|
||||
}
|
||||
}
|
||||
|
||||
std::string ScriptComponent::GetFullClassName() const {
|
||||
|
||||
@@ -28,6 +28,10 @@ void ScriptEngine::OnRuntimeStart(Components::Scene* scene) {
|
||||
m_runtimeScene = scene;
|
||||
m_runtimeRunning = true;
|
||||
m_runtime->OnRuntimeStart(scene);
|
||||
m_runtimeSceneCreatedSubscription = scene->OnGameObjectCreated().Subscribe(
|
||||
[this](Components::GameObject* gameObject) {
|
||||
HandleGameObjectCreated(gameObject);
|
||||
});
|
||||
|
||||
for (Components::GameObject* root : scene->GetRootGameObjects()) {
|
||||
CollectScriptComponents(root);
|
||||
@@ -49,6 +53,12 @@ void ScriptEngine::OnRuntimeStart(Components::Scene* scene) {
|
||||
}
|
||||
|
||||
void ScriptEngine::OnRuntimeStop() {
|
||||
if (m_runtimeScene && m_runtimeSceneCreatedSubscription != 0) {
|
||||
m_runtimeScene->OnGameObjectCreated().Unsubscribe(m_runtimeSceneCreatedSubscription);
|
||||
m_runtimeScene->OnGameObjectCreated().ProcessUnsubscribes();
|
||||
m_runtimeSceneCreatedSubscription = 0;
|
||||
}
|
||||
|
||||
if (!m_runtimeRunning) {
|
||||
m_runtimeScene = nullptr;
|
||||
m_scriptStates.clear();
|
||||
@@ -209,6 +219,34 @@ void ScriptEngine::CollectScriptComponents(Components::GameObject* gameObject) {
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::EnsureTrackedScriptsReady(Components::GameObject* gameObject) {
|
||||
if (!gameObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ScriptComponent* component : gameObject->GetComponents<ScriptComponent>()) {
|
||||
ScriptInstanceState* state = FindState(component);
|
||||
if (!state || !ShouldScriptRun(*state)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EnsureScriptReady(*state, true);
|
||||
}
|
||||
|
||||
for (Components::GameObject* child : gameObject->GetChildren()) {
|
||||
EnsureTrackedScriptsReady(child);
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::HandleGameObjectCreated(Components::GameObject* gameObject) {
|
||||
if (!m_runtimeRunning || !gameObject || gameObject->GetScene() != m_runtimeScene) {
|
||||
return;
|
||||
}
|
||||
|
||||
CollectScriptComponents(gameObject);
|
||||
EnsureTrackedScriptsReady(gameObject);
|
||||
}
|
||||
|
||||
ScriptEngine::ScriptInstanceState* ScriptEngine::TrackScriptComponent(ScriptComponent* component) {
|
||||
if (!component || !component->GetGameObject()) {
|
||||
return nullptr;
|
||||
|
||||
Reference in New Issue
Block a user