Align Unity-style object and hierarchy scripting APIs
This commit is contained in:
@@ -109,18 +109,8 @@ MonoScriptRuntime* GetActiveMonoScriptRuntime() {
|
||||
return dynamic_cast<MonoScriptRuntime*>(ScriptEngine::Get().GetRuntime());
|
||||
}
|
||||
|
||||
ManagedComponentTypeInfo ResolveManagedComponentTypeInfo(MonoReflectionType* reflectionType) {
|
||||
ManagedComponentTypeInfo ResolveManagedComponentTypeInfo(MonoClass* monoClass) {
|
||||
ManagedComponentTypeInfo typeInfo;
|
||||
if (!reflectionType) {
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
MonoType* monoType = mono_reflection_type_get_type(reflectionType);
|
||||
if (!monoType) {
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
MonoClass* monoClass = mono_class_from_mono_type(monoType);
|
||||
if (!monoClass) {
|
||||
return typeInfo;
|
||||
}
|
||||
@@ -163,6 +153,19 @@ ManagedComponentTypeInfo ResolveManagedComponentTypeInfo(MonoReflectionType* ref
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
ManagedComponentTypeInfo ResolveManagedComponentTypeInfo(MonoReflectionType* reflectionType) {
|
||||
if (!reflectionType) {
|
||||
return {};
|
||||
}
|
||||
|
||||
MonoType* monoType = mono_reflection_type_get_type(reflectionType);
|
||||
if (!monoType) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return ResolveManagedComponentTypeInfo(mono_class_from_mono_type(monoType));
|
||||
}
|
||||
|
||||
Components::GameObject* FindGameObjectByUUIDRecursive(Components::GameObject* gameObject, uint64_t uuid) {
|
||||
if (!gameObject) {
|
||||
return nullptr;
|
||||
@@ -231,28 +234,32 @@ ScriptComponent* FindScriptComponentByUUID(uint64_t scriptComponentUUID) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool HasNativeComponent(Components::GameObject* gameObject, ManagedComponentKind componentKind) {
|
||||
Components::Component* FindNativeComponent(Components::GameObject* gameObject, ManagedComponentKind componentKind) {
|
||||
if (!gameObject) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (componentKind) {
|
||||
case ManagedComponentKind::Transform:
|
||||
return gameObject->GetTransform() != nullptr;
|
||||
return gameObject->GetTransform();
|
||||
case ManagedComponentKind::Camera:
|
||||
return gameObject->GetComponent<Components::CameraComponent>() != nullptr;
|
||||
return gameObject->GetComponent<Components::CameraComponent>();
|
||||
case ManagedComponentKind::Light:
|
||||
return gameObject->GetComponent<Components::LightComponent>() != nullptr;
|
||||
return gameObject->GetComponent<Components::LightComponent>();
|
||||
case ManagedComponentKind::MeshFilter:
|
||||
return gameObject->GetComponent<Components::MeshFilterComponent>() != nullptr;
|
||||
return gameObject->GetComponent<Components::MeshFilterComponent>();
|
||||
case ManagedComponentKind::MeshRenderer:
|
||||
return gameObject->GetComponent<Components::MeshRendererComponent>() != nullptr;
|
||||
return gameObject->GetComponent<Components::MeshRendererComponent>();
|
||||
case ManagedComponentKind::Script:
|
||||
case ManagedComponentKind::Unknown:
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool HasNativeComponent(Components::GameObject* gameObject, ManagedComponentKind componentKind) {
|
||||
return FindNativeComponent(gameObject, componentKind) != nullptr;
|
||||
}
|
||||
|
||||
Components::Component* AddOrGetNativeComponent(Components::GameObject* gameObject, ManagedComponentKind componentKind) {
|
||||
@@ -309,6 +316,87 @@ ScriptComponent* FindMatchingScriptComponent(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScriptComponent* FindMatchingScriptComponentInChildren(
|
||||
Components::GameObject* gameObject,
|
||||
const ManagedComponentTypeInfo& typeInfo) {
|
||||
if (!gameObject) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (ScriptComponent* component = FindMatchingScriptComponent(gameObject, typeInfo)) {
|
||||
return component;
|
||||
}
|
||||
|
||||
for (Components::GameObject* child : gameObject->GetChildren()) {
|
||||
if (ScriptComponent* component = FindMatchingScriptComponentInChildren(child, typeInfo)) {
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScriptComponent* FindMatchingScriptComponentInParent(
|
||||
Components::GameObject* gameObject,
|
||||
const ManagedComponentTypeInfo& typeInfo) {
|
||||
while (gameObject) {
|
||||
if (ScriptComponent* component = FindMatchingScriptComponent(gameObject, typeInfo)) {
|
||||
return component;
|
||||
}
|
||||
|
||||
gameObject = gameObject->GetParent();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Components::Component* FindNativeComponentInChildren(
|
||||
Components::GameObject* gameObject,
|
||||
ManagedComponentKind componentKind) {
|
||||
if (!gameObject) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (Components::Component* component = FindNativeComponent(gameObject, componentKind)) {
|
||||
return component;
|
||||
}
|
||||
|
||||
for (Components::GameObject* child : gameObject->GetChildren()) {
|
||||
if (Components::Component* component = FindNativeComponentInChildren(child, componentKind)) {
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Components::Component* FindNativeComponentInParent(
|
||||
Components::GameObject* gameObject,
|
||||
ManagedComponentKind componentKind) {
|
||||
while (gameObject) {
|
||||
if (Components::Component* component = FindNativeComponent(gameObject, componentKind)) {
|
||||
return component;
|
||||
}
|
||||
|
||||
gameObject = gameObject->GetParent();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool DestroyNativeComponentInstance(Components::GameObject* gameObject, Components::Component* component) {
|
||||
if (!gameObject || !component || component == gameObject->GetTransform()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (component->IsEnabled() && gameObject->IsActiveInHierarchy()) {
|
||||
component->OnDisable();
|
||||
}
|
||||
|
||||
component->OnDestroy();
|
||||
return gameObject->RemoveComponent(component);
|
||||
}
|
||||
|
||||
Components::CameraComponent* FindCameraComponent(uint64_t gameObjectUUID) {
|
||||
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
|
||||
return gameObject ? gameObject->GetComponent<Components::CameraComponent>() : nullptr;
|
||||
@@ -520,6 +608,72 @@ MonoObject* InternalCall_GameObject_GetComponent(uint64_t gameObjectUUID, MonoRe
|
||||
return runtime->CreateManagedComponentWrapper(typeInfo.monoClass, gameObjectUUID);
|
||||
}
|
||||
|
||||
MonoObject* InternalCall_GameObject_GetComponentInChildren(uint64_t gameObjectUUID, MonoReflectionType* componentType) {
|
||||
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
|
||||
if (!gameObject) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MonoScriptRuntime* runtime = GetActiveMonoScriptRuntime();
|
||||
if (!runtime) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ManagedComponentTypeInfo typeInfo = ResolveManagedComponentTypeInfo(componentType);
|
||||
if (typeInfo.kind == ManagedComponentKind::Script) {
|
||||
ScriptComponent* component = FindMatchingScriptComponentInChildren(gameObject, typeInfo);
|
||||
if (!component) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!runtime->HasManagedInstance(component)) {
|
||||
ScriptEngine::Get().OnScriptComponentEnabled(component);
|
||||
}
|
||||
|
||||
return runtime->GetManagedInstanceObject(component);
|
||||
}
|
||||
|
||||
Components::Component* component = FindNativeComponentInChildren(gameObject, typeInfo.kind);
|
||||
if (!component || !typeInfo.monoClass) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return runtime->CreateManagedComponentWrapper(typeInfo.monoClass, component->GetGameObject()->GetUUID());
|
||||
}
|
||||
|
||||
MonoObject* InternalCall_GameObject_GetComponentInParent(uint64_t gameObjectUUID, MonoReflectionType* componentType) {
|
||||
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
|
||||
if (!gameObject) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MonoScriptRuntime* runtime = GetActiveMonoScriptRuntime();
|
||||
if (!runtime) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ManagedComponentTypeInfo typeInfo = ResolveManagedComponentTypeInfo(componentType);
|
||||
if (typeInfo.kind == ManagedComponentKind::Script) {
|
||||
ScriptComponent* component = FindMatchingScriptComponentInParent(gameObject, typeInfo);
|
||||
if (!component) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!runtime->HasManagedInstance(component)) {
|
||||
ScriptEngine::Get().OnScriptComponentEnabled(component);
|
||||
}
|
||||
|
||||
return runtime->GetManagedInstanceObject(component);
|
||||
}
|
||||
|
||||
Components::Component* component = FindNativeComponentInParent(gameObject, typeInfo.kind);
|
||||
if (!component || !typeInfo.monoClass) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return runtime->CreateManagedComponentWrapper(typeInfo.monoClass, component->GetGameObject()->GetUUID());
|
||||
}
|
||||
|
||||
MonoObject* InternalCall_GameObject_AddComponent(uint64_t gameObjectUUID, MonoReflectionType* componentType) {
|
||||
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
|
||||
if (!gameObject) {
|
||||
@@ -588,6 +742,15 @@ void InternalCall_GameObject_Destroy(uint64_t gameObjectUUID) {
|
||||
scene->DestroyGameObject(gameObject);
|
||||
}
|
||||
|
||||
void InternalCall_Object_Destroy(MonoObject* object) {
|
||||
MonoScriptRuntime* runtime = GetActiveMonoScriptRuntime();
|
||||
if (!runtime || !object) {
|
||||
return;
|
||||
}
|
||||
|
||||
runtime->DestroyManagedObject(object);
|
||||
}
|
||||
|
||||
mono_bool InternalCall_Behaviour_GetEnabled(uint64_t scriptComponentUUID) {
|
||||
ScriptComponent* component = FindScriptComponentByUUID(scriptComponentUUID);
|
||||
return (component && component->IsEnabled()) ? 1 : 0;
|
||||
@@ -1241,10 +1404,13 @@ void RegisterInternalCalls() {
|
||||
mono_add_internal_call("XCEngine.InternalCalls::GameObject_SetActive", reinterpret_cast<const void*>(&InternalCall_GameObject_SetActive));
|
||||
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_GetComponentInChildren", reinterpret_cast<const void*>(&InternalCall_GameObject_GetComponentInChildren));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::GameObject_GetComponentInParent", reinterpret_cast<const void*>(&InternalCall_GameObject_GetComponentInParent));
|
||||
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::Object_Destroy", reinterpret_cast<const void*>(&InternalCall_Object_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));
|
||||
@@ -2224,6 +2390,73 @@ MonoObject* MonoScriptRuntime::CreateManagedGameObject(uint64_t gameObjectUUID)
|
||||
return managedObject;
|
||||
}
|
||||
|
||||
bool MonoScriptRuntime::DestroyManagedObject(MonoObject* managedObject) {
|
||||
if (!m_initialized || !managedObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SetCurrentDomain();
|
||||
|
||||
MonoClass* monoClass = mono_object_get_class(managedObject);
|
||||
if (!monoClass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (monoClass == m_gameObjectClass) {
|
||||
uint64_t gameObjectUUID = 0;
|
||||
mono_field_get_value(managedObject, m_managedGameObjectUUIDField, &gameObjectUUID);
|
||||
|
||||
Components::Scene* scene = GetInternalCallScene();
|
||||
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
|
||||
if (!scene || !gameObject || gameObject->GetScene() != scene) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scene->DestroyGameObject(gameObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (monoClass != m_componentClass && !mono_class_is_subclass_of(monoClass, m_componentClass, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t gameObjectUUID = 0;
|
||||
mono_field_get_value(managedObject, m_gameObjectUUIDField, &gameObjectUUID);
|
||||
|
||||
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
|
||||
if (!gameObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (monoClass == m_behaviourClass || mono_class_is_subclass_of(monoClass, m_behaviourClass, false)) {
|
||||
uint64_t scriptComponentUUID = 0;
|
||||
mono_field_get_value(managedObject, m_scriptComponentUUIDField, &scriptComponentUUID);
|
||||
|
||||
if (scriptComponentUUID != 0) {
|
||||
ScriptComponent* component = FindScriptComponentByUUID(scriptComponentUUID);
|
||||
return DestroyNativeComponentInstance(gameObject, component);
|
||||
}
|
||||
}
|
||||
|
||||
const ManagedComponentTypeInfo typeInfo = ResolveManagedComponentTypeInfo(monoClass);
|
||||
switch (typeInfo.kind) {
|
||||
case ManagedComponentKind::Camera:
|
||||
return DestroyNativeComponentInstance(gameObject, gameObject->GetComponent<Components::CameraComponent>());
|
||||
case ManagedComponentKind::Light:
|
||||
return DestroyNativeComponentInstance(gameObject, gameObject->GetComponent<Components::LightComponent>());
|
||||
case ManagedComponentKind::MeshFilter:
|
||||
return DestroyNativeComponentInstance(gameObject, gameObject->GetComponent<Components::MeshFilterComponent>());
|
||||
case ManagedComponentKind::MeshRenderer:
|
||||
return DestroyNativeComponentInstance(gameObject, gameObject->GetComponent<Components::MeshRendererComponent>());
|
||||
case ManagedComponentKind::Transform:
|
||||
case ManagedComponentKind::Script:
|
||||
case ManagedComponentKind::Unknown:
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MonoScriptRuntime::TryExtractGameObjectReference(
|
||||
MonoObject* managedObject,
|
||||
GameObjectReference& outReference) const {
|
||||
|
||||
Reference in New Issue
Block a user