From 3ad369501a33f3f9f39eebf40d697712ad13c8e5 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 11 Feb 2025 14:22:44 +0100 Subject: [PATCH] Add support for searching actors and scripts by interface #3199 --- Source/Engine/Level/Actor.cpp | 55 +++++++++++++++++++++++++++-------- Source/Engine/Level/Actor.h | 16 +++++----- Source/Engine/Level/Level.cpp | 22 ++++++++------ Source/Engine/Level/Level.h | 8 ++--- 4 files changed, 68 insertions(+), 33 deletions(-) diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp index f66974720..1db13145d 100644 --- a/Source/Engine/Level/Actor.cpp +++ b/Source/Engine/Level/Actor.cpp @@ -418,10 +418,21 @@ Actor* Actor::GetChild(const StringView& name) const Actor* Actor::GetChild(const MClass* type) const { CHECK_RETURN(type, nullptr); - for (auto child : Children) + if (type->IsInterface()) { - if (child->GetClass()->IsSubClassOf(type)) - return child; + for (auto child : Children) + { + if (child->GetClass()->HasInterface(type)) + return child; + } + } + else + { + for (auto child : Children) + { + if (child->GetClass()->IsSubClassOf(type)) + return child; + } } return nullptr; } @@ -429,9 +440,18 @@ Actor* Actor::GetChild(const MClass* type) const Array Actor::GetChildren(const MClass* type) const { Array result; - for (auto child : Children) - if (child->GetClass()->IsSubClassOf(type)) - result.Add(child); + if (type->IsInterface()) + { + for (auto child : Children) + if (child->GetClass()->HasInterface(type)) + result.Add(child); + } + else + { + for (auto child : Children) + if (child->GetClass()->IsSubClassOf(type)) + result.Add(child); + } return result; } @@ -1441,7 +1461,7 @@ Actor* Actor::FindActor(const MClass* type, bool activeOnly) const CHECK_RETURN(type, nullptr); if (activeOnly && !_isActive) return nullptr; - if (GetClass()->IsSubClassOf(type)) + if ((GetClass()->IsSubClassOf(type) || GetClass()->HasInterface(type))) return const_cast(this); for (auto child : Children) { @@ -1455,7 +1475,7 @@ Actor* Actor::FindActor(const MClass* type, bool activeOnly) const Actor* Actor::FindActor(const MClass* type, const StringView& name) const { CHECK_RETURN(type, nullptr); - if (GetClass()->IsSubClassOf(type) && _name == name) + if ((GetClass()->IsSubClassOf(type) || GetClass()->HasInterface(type)) && _name == name) return const_cast(this); for (auto child : Children) { @@ -1471,7 +1491,7 @@ Actor* Actor::FindActor(const MClass* type, const Tag& tag, bool activeOnly) con CHECK_RETURN(type, nullptr); if (activeOnly && !_isActive) return nullptr; - if (GetClass()->IsSubClassOf(type) && HasTag(tag)) + if ((GetClass()->IsSubClassOf(type) || GetClass()->HasInterface(type)) && HasTag(tag)) return const_cast(this); for (auto child : Children) { @@ -1485,10 +1505,21 @@ Actor* Actor::FindActor(const MClass* type, const Tag& tag, bool activeOnly) con Script* Actor::FindScript(const MClass* type) const { CHECK_RETURN(type, nullptr); - for (auto script : Scripts) + if (type->IsInterface()) { - if (script->GetClass()->IsSubClassOf(type) || script->GetClass()->HasInterface(type)) - return script; + for (const auto script : Scripts) + { + if (script->GetClass()->HasInterface(type)) + return script; + } + } + else + { + for (const auto script : Scripts) + { + if (script->GetClass()->IsSubClassOf(type)) + return script; + } } for (auto child : Children) { diff --git a/Source/Engine/Level/Actor.h b/Source/Engine/Level/Actor.h index a6d8659fa..4cc475d13 100644 --- a/Source/Engine/Level/Actor.h +++ b/Source/Engine/Level/Actor.h @@ -237,7 +237,7 @@ public: /// /// Gets the child actor of the given type. /// - /// Type of the actor to search for. Includes any actors derived from the type. + /// Type of the actor to search for. Includes any actors derived from the type. Supports interface types. /// The child actor or null. API_FUNCTION() Actor* GetChild(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type) const; @@ -270,7 +270,7 @@ public: /// /// Gets the child actors of the given type. /// - /// Type of the actor to search for. Includes any actors derived from the type. + /// Type of the actor to search for. Includes any actors derived from the type. Supports interface types. /// The child actors. API_FUNCTION() Array GetChildren(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type) const; @@ -315,7 +315,7 @@ public: /// /// Gets the script of the given type from this actor. /// - /// Type of the script to search for. Includes any scripts derived from the type. + /// Type of the script to search for. Includes any scripts derived from the type. Supports interface types. /// The script or null. API_FUNCTION() Script* GetScript(API_PARAM(Attributes="TypeReference(typeof(Script))") const MClass* type) const; @@ -332,7 +332,7 @@ public: /// /// Gets the scripts of the given type from this actor. /// - /// Type of the script to search for. Includes any scripts derived from the type. + /// Type of the script to search for. Includes any scripts derived from the type. Supports interface types. /// The scripts. API_FUNCTION() Array GetScripts(API_PARAM(Attributes="TypeReference(typeof(Script))") const MClass* type) const; @@ -778,7 +778,7 @@ public: /// /// Tries to find the actor of the given type in this actor hierarchy (checks this actor and all children hierarchy). /// - /// Type of the actor to search for. Includes any actors derived from the type. + /// Type of the actor to search for. Includes any actors derived from the type. Supports interface types. /// Finds only a active actor. /// Actor instance if found, null otherwise. API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, bool activeOnly = false) const; @@ -786,7 +786,7 @@ public: /// /// Tries to find the actor of the given type and name in this actor hierarchy (checks this actor and all children hierarchy). /// - /// Type of the actor to search for. Includes any actors derived from the type. + /// Type of the actor to search for. Includes any actors derived from the type. Supports interface types. /// The name of the actor. /// Actor instance if found, null otherwise. API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const StringView& name) const; @@ -794,7 +794,7 @@ public: /// /// Tries to find the actor of the given type and tag in this actor hierarchy. /// - /// Type of the actor to search for. Includes any actors derived from the type. + /// Type of the actor to search for. Includes any actors derived from the type. Supports interface types. /// The tag of the actor to search for. /// Finds only an active actor. /// Actor instance if found, null otherwise. @@ -835,7 +835,7 @@ public: /// /// Tries to find the script of the given type in this actor hierarchy (checks this actor and all children hierarchy). /// - /// Type of the actor to search for. Includes any actors derived from the type. + /// Type of the actor to search for. Includes any actors derived from the type. Supports interface types. /// Script instance if found, null otherwise. API_FUNCTION() Script* FindScript(API_PARAM(Attributes="TypeReference(typeof(Script))") const MClass* type) const; diff --git a/Source/Engine/Level/Level.cpp b/Source/Engine/Level/Level.cpp index f24a853e3..39db728bb 100644 --- a/Source/Engine/Level/Level.cpp +++ b/Source/Engine/Level/Level.cpp @@ -1451,7 +1451,7 @@ Actor* FindActorRecursiveByType(Actor* node, const MClass* type, const Tag& tag, CHECK_RETURN(type, nullptr); if (activeOnly && !node->GetIsActive()) return nullptr; - if (node->HasTag(tag) && node->GetClass()->IsSubClassOf(type)) + if (node->HasTag(tag) && (node->GetClass()->IsSubClassOf(type) || node->GetClass()->HasInterface(type))) return node; Actor* result = nullptr; for (Actor* child : node->Children) @@ -1583,23 +1583,27 @@ Script* Level::FindScript(const MClass* type) namespace { - void GetActors(const MClass* type, Actor* actor, bool activeOnly, Array& result) + void GetActors(const MClass* type, bool isInterface, Actor* actor, bool activeOnly, Array& result) { if (activeOnly && !actor->GetIsActive()) return; - if (actor->GetClass()->IsSubClassOf(type)) + if ((!isInterface && actor->GetClass()->IsSubClassOf(type)) || + (isInterface && actor->GetClass()->HasInterface(type))) result.Add(actor); for (auto child : actor->Children) - GetActors(type, child, activeOnly, result); + GetActors(type, isInterface, child, activeOnly, result); } - void GetScripts(const MClass* type, Actor* actor, Array& result) + void GetScripts(const MClass* type, bool isInterface, Actor* actor, Array& result) { for (auto script : actor->Scripts) - if (script->GetClass()->IsSubClassOf(type)) + { + if ((!isInterface && script->GetClass()->IsSubClassOf(type)) || + (isInterface && script->GetClass()->HasInterface(type))) result.Add(script); + } for (auto child : actor->Children) - GetScripts(type, child, result); + GetScripts(type, isInterface, child, result); } } @@ -1609,7 +1613,7 @@ Array Level::GetActors(const MClass* type, bool activeOnly) CHECK_RETURN(type, result); ScopeLock lock(ScenesLock); for (int32 i = 0; i < Scenes.Count(); i++) - ::GetActors(type, Scenes[i], activeOnly, result); + ::GetActors(type, type->IsInterface(), Scenes[i], activeOnly, result); return result; } @@ -1619,7 +1623,7 @@ Array Level::GetScripts(const MClass* type) CHECK_RETURN(type, result); ScopeLock lock(ScenesLock); for (int32 i = 0; i < Scenes.Count(); i++) - ::GetScripts(type, Scenes[i], result); + ::GetScripts(type, type->IsInterface(), Scenes[i], result); return result; } diff --git a/Source/Engine/Level/Level.h b/Source/Engine/Level/Level.h index b9c6b698a..c79abe784 100644 --- a/Source/Engine/Level/Level.h +++ b/Source/Engine/Level/Level.h @@ -360,7 +360,7 @@ public: /// /// Tries to find the actor of the given type in all the loaded scenes. /// - /// Type of the actor to search for. Includes any actors derived from the type. + /// Type of the actor to search for. Includes any actors derived from the type. Supports interface types. /// Finds only an active actor. /// Found actor or null. API_FUNCTION() static Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, bool activeOnly = false); @@ -368,7 +368,7 @@ public: /// /// Tries to find the actor of the given type and name in all the loaded scenes. /// - /// Type of the actor to search for. Includes any actors derived from the type. + /// Type of the actor to search for. Includes any actors derived from the type. Supports interface types. /// The name of the actor. /// Actor instance if found, null otherwise. API_FUNCTION() static Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const StringView& name); @@ -385,7 +385,7 @@ public: /// /// Tries to find the actor of the given type and tag in all the loaded scenes. /// - /// Type of the actor to search for. Includes any actors derived from the type. + /// Type of the actor to search for. Includes any actors derived from the type. Supports interface types. /// The tag of the actor to search for. /// Finds only an active actor. /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. @@ -446,7 +446,7 @@ public: /// /// Tries to find the script of the given type in all the loaded scenes. /// - /// Type of the script to search for. Includes any scripts derived from the type. + /// Type of the script to search for. Includes any scripts derived from the type. Supports interface types. /// Found script or null. API_FUNCTION() static Script* FindScript(API_PARAM(Attributes="TypeReference(typeof(Script))") const MClass* type);