Add Unity-style GetComponents scripting API
This commit is contained in:
@@ -262,6 +262,15 @@ bool HasNativeComponent(Components::GameObject* gameObject, ManagedComponentKind
|
||||
return FindNativeComponent(gameObject, componentKind) != nullptr;
|
||||
}
|
||||
|
||||
bool IsMatchingScriptComponent(const ScriptComponent* component, const ManagedComponentTypeInfo& typeInfo) {
|
||||
return component
|
||||
&& component->HasScriptClass()
|
||||
&& typeInfo.kind == ManagedComponentKind::Script
|
||||
&& component->GetAssemblyName() == typeInfo.assemblyName
|
||||
&& component->GetNamespaceName() == typeInfo.namespaceName
|
||||
&& component->GetClassName() == typeInfo.className;
|
||||
}
|
||||
|
||||
Components::Component* AddOrGetNativeComponent(Components::GameObject* gameObject, ManagedComponentKind componentKind) {
|
||||
if (!gameObject) {
|
||||
return nullptr;
|
||||
@@ -302,13 +311,7 @@ ScriptComponent* FindMatchingScriptComponent(
|
||||
}
|
||||
|
||||
for (ScriptComponent* component : gameObject->GetComponents<ScriptComponent>()) {
|
||||
if (!component || !component->HasScriptClass()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (component->GetAssemblyName() == typeInfo.assemblyName
|
||||
&& component->GetNamespaceName() == typeInfo.namespaceName
|
||||
&& component->GetClassName() == typeInfo.className) {
|
||||
if (IsMatchingScriptComponent(component, typeInfo)) {
|
||||
return component;
|
||||
}
|
||||
}
|
||||
@@ -423,6 +426,28 @@ Components::Space ResolveManagedSpace(int32_t value) {
|
||||
: Components::Space::Self;
|
||||
}
|
||||
|
||||
MonoArray* CreateManagedComponentArray(MonoClass* componentClass, const std::vector<MonoObject*>& components) {
|
||||
if (!componentClass) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MonoDomain* domain = mono_domain_get();
|
||||
if (!domain) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MonoArray* array = mono_array_new(domain, componentClass, static_cast<uintptr_t>(components.size()));
|
||||
if (!array) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (uintptr_t index = 0; index < components.size(); ++index) {
|
||||
mono_array_setref(array, index, components[index]);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
void InternalCall_Debug_Log(MonoString* message) {
|
||||
XCEngine::Debug::Logger::Get().Info(
|
||||
XCEngine::Debug::LogCategory::Scripting,
|
||||
@@ -608,6 +633,74 @@ MonoObject* InternalCall_GameObject_GetComponent(uint64_t gameObjectUUID, MonoRe
|
||||
return runtime->CreateManagedComponentWrapper(typeInfo.monoClass, gameObjectUUID);
|
||||
}
|
||||
|
||||
MonoArray* InternalCall_GameObject_GetComponents(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.monoClass) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<MonoObject*> managedComponents;
|
||||
auto appendNativeComponents = [&](const auto& nativeComponents) {
|
||||
for (const auto* component : nativeComponents) {
|
||||
if (!component || !component->GetGameObject()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MonoObject* managedObject =
|
||||
runtime->CreateManagedComponentWrapper(typeInfo.monoClass, component->GetGameObject()->GetUUID())) {
|
||||
managedComponents.push_back(managedObject);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
switch (typeInfo.kind) {
|
||||
case ManagedComponentKind::Script:
|
||||
for (ScriptComponent* component : gameObject->GetComponents<ScriptComponent>()) {
|
||||
if (!IsMatchingScriptComponent(component, typeInfo)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!runtime->HasManagedInstance(component)) {
|
||||
ScriptEngine::Get().OnScriptComponentEnabled(component);
|
||||
}
|
||||
|
||||
if (MonoObject* managedObject = runtime->GetManagedInstanceObject(component)) {
|
||||
managedComponents.push_back(managedObject);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ManagedComponentKind::Transform:
|
||||
appendNativeComponents(gameObject->GetComponents<Components::TransformComponent>());
|
||||
break;
|
||||
case ManagedComponentKind::Camera:
|
||||
appendNativeComponents(gameObject->GetComponents<Components::CameraComponent>());
|
||||
break;
|
||||
case ManagedComponentKind::Light:
|
||||
appendNativeComponents(gameObject->GetComponents<Components::LightComponent>());
|
||||
break;
|
||||
case ManagedComponentKind::MeshFilter:
|
||||
appendNativeComponents(gameObject->GetComponents<Components::MeshFilterComponent>());
|
||||
break;
|
||||
case ManagedComponentKind::MeshRenderer:
|
||||
appendNativeComponents(gameObject->GetComponents<Components::MeshRendererComponent>());
|
||||
break;
|
||||
case ManagedComponentKind::Unknown:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return CreateManagedComponentArray(typeInfo.monoClass, managedComponents);
|
||||
}
|
||||
|
||||
MonoObject* InternalCall_GameObject_GetComponentInChildren(uint64_t gameObjectUUID, MonoReflectionType* componentType) {
|
||||
Components::GameObject* gameObject = FindGameObjectByUUID(gameObjectUUID);
|
||||
if (!gameObject) {
|
||||
@@ -1404,6 +1497,7 @@ 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_GetComponents", reinterpret_cast<const void*>(&InternalCall_GameObject_GetComponents));
|
||||
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));
|
||||
|
||||
Reference in New Issue
Block a user