diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp index 67d84b81d..08fb77223 100644 --- a/Source/Engine/Level/Actor.cpp +++ b/Source/Engine/Level/Actor.cpp @@ -1337,6 +1337,20 @@ Actor* Actor::FindActor(const MClass* type, const StringView& name) const return nullptr; } +Actor* Actor::FindActor(const MClass* type, const Tag& tag) const +{ + CHECK_RETURN(type, nullptr); + if (GetClass()->IsSubClassOf(type) && HasTag(tag)) + return const_cast(this); + for (auto child : Children) + { + const auto actor = child->FindActor(type, tag); + if (actor) + return actor; + } + return nullptr; +} + Script* Actor::FindScript(const MClass* type) const { CHECK_RETURN(type, nullptr); diff --git a/Source/Engine/Level/Actor.cs b/Source/Engine/Level/Actor.cs index 957d09c7a..661b350cb 100644 --- a/Source/Engine/Level/Actor.cs +++ b/Source/Engine/Level/Actor.cs @@ -269,6 +269,17 @@ namespace FlaxEngine { return FindActor(typeof(T), name) as T; } + + /// + /// Tries to find actor of the given type and tag in this actor hierarchy (checks this actor and all children hierarchy). + /// + /// A tag on the object. + /// Type of the object. + /// Actor instance if found, null otherwise. + public T FindActor(Tag tag) where T : Actor + { + return FindActor(typeof(T), tag) as T; + } /// /// Searches for all actors of a specific type in this actor children list. diff --git a/Source/Engine/Level/Actor.h b/Source/Engine/Level/Actor.h index fb9fb0848..510bc9eb8 100644 --- a/Source/Engine/Level/Actor.h +++ b/Source/Engine/Level/Actor.h @@ -739,6 +739,14 @@ public: /// Actor instance if found, null otherwise. API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const StringView& name) const; + /// + /// 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. + /// The tag of the actor to search for. + /// Actor instance if found, null otherwise. + API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const Tag& tag) const; + /// /// Tries to find the actor of the given type in this actor hierarchy (checks this actor and all children hierarchy). /// @@ -759,6 +767,17 @@ public: { return (T*)FindActor(T::GetStaticClass(), name); } + + /// + /// Tries to find the actor of the given type and tag in this actor hierarchy (checks this actor and all children hierarchy). + /// + /// The tag of the actor to search for. + /// Actor instance if found, null otherwise. + template + FORCE_INLINE T* FindActor(const Tag& tag) const + { + return (T*)FindActor(T::GetStaticClass(), tag); + } /// /// Tries to find the script of the given type in this actor hierarchy (checks this actor and all children hierarchy). diff --git a/Source/Engine/Level/Level.cpp b/Source/Engine/Level/Level.cpp index ab8a9bbfe..587d20331 100644 --- a/Source/Engine/Level/Level.cpp +++ b/Source/Engine/Level/Level.cpp @@ -726,116 +726,6 @@ int32 Level::GetLayerIndex(const StringView& layer) return result; } -Actor* FindActorRecursive(Actor* node, const Tag& tag) -{ - if (node->HasTag(tag)) - return node; - Actor* result = nullptr; - for (Actor* child : node->Children) - { - result = FindActorRecursive(child, tag); - if (result) - break; - } - return result; -} - -void FindActorsRecursive(Actor* node, const Tag& tag, const bool activeOnly, Array& result) -{ - if (activeOnly && !node->GetIsActive()) - return; - if (node->HasTag(tag)) - result.Add(node); - for (Actor* child : node->Children) - FindActorsRecursive(child, tag, activeOnly, result); -} - -void FindActorsRecursiveByParentTags(Actor* node, const Array& tags, const bool activeOnly, Array& result) -{ - if (activeOnly && !node->GetIsActive()) - return; - for (Tag tag : tags) - { - if (node->HasTag(tag)) - { - result.Add(node); - break; - } - } - for (Actor* child : node->Children) - FindActorsRecursiveByParentTags(child, tags, activeOnly, result); -} - -Actor* Level::FindActor(const Tag& tag, Actor* root) -{ - PROFILE_CPU(); - if (root) - return FindActorRecursive(root, tag); - Actor* result = nullptr; - for (Scene* scene : Scenes) - { - result = FindActorRecursive(scene, tag); - if (result) - break; - } - return result; -} - -void FindActorRecursive(Actor* node, const Tag& tag, Array& result) -{ - if (node->HasTag(tag)) - result.Add(node); - for (Actor* child : node->Children) - FindActorRecursive(child, tag, result); -} - -Array Level::FindActors(const Tag& tag, const bool activeOnly, Actor* root) -{ - PROFILE_CPU(); - Array result; - if (root) - { - FindActorsRecursive(root, tag, activeOnly, result); - } - else - { - ScopeLock lock(ScenesLock); - for (Scene* scene : Scenes) - FindActorsRecursive(scene, tag, activeOnly, result); - } - return result; -} - -Array Level::FindActorsByParentTag(const Tag& parentTag, const bool activeOnly, Actor* root) -{ - PROFILE_CPU(); - Array result; - const Array subTags = Tags::GetSubTags(parentTag); - - if (subTags.Count() == 0) - { - return result; - } - if (subTags.Count() == 1) - { - result = FindActors(subTags[0], activeOnly, root); - return result; - } - - if (root) - { - FindActorsRecursiveByParentTags(root, subTags, activeOnly, result); - } - else - { - ScopeLock lock(ScenesLock); - for (Scene* scene : Scenes) - FindActorsRecursiveByParentTags(scene, subTags, activeOnly, result); - } - - return result; -} - void Level::callActorEvent(ActorEventType eventType, Actor* a, Actor* b) { PROFILE_CPU(); @@ -1505,6 +1395,143 @@ Actor* Level::FindActor(const MClass* type, const StringView& name) return result; } +Actor* FindActorRecursive(Actor* node, const Tag& tag) +{ + if (node->HasTag(tag)) + return node; + Actor* result = nullptr; + for (Actor* child : node->Children) + { + result = FindActorRecursive(child, tag); + if (result) + break; + } + return result; +} + +Actor* FindActorRecursiveByType(Actor* node, const MClass* type, const Tag& tag) +{ + CHECK_RETURN(type, nullptr); + if (node->HasTag(tag) && node->GetClass()->IsSubClassOf(type)) + return node; + Actor* result = nullptr; + for (Actor* child : node->Children) + { + result = FindActorRecursiveByType(child, type, tag); + if (result) + break; + } + return result; +} + +void FindActorsRecursive(Actor* node, const Tag& tag, const bool activeOnly, Array& result) +{ + if (activeOnly && !node->GetIsActive()) + return; + if (node->HasTag(tag)) + result.Add(node); + for (Actor* child : node->Children) + FindActorsRecursive(child, tag, activeOnly, result); +} + +void FindActorsRecursiveByParentTags(Actor* node, const Array& tags, const bool activeOnly, Array& result) +{ + if (activeOnly && !node->GetIsActive()) + return; + for (Tag tag : tags) + { + if (node->HasTag(tag)) + { + result.Add(node); + break; + } + } + for (Actor* child : node->Children) + FindActorsRecursiveByParentTags(child, tags, activeOnly, result); +} + +Actor* Level::FindActor(const Tag& tag, Actor* root) +{ + PROFILE_CPU(); + if (root) + return FindActorRecursive(root, tag); + Actor* result = nullptr; + for (Scene* scene : Scenes) + { + result = FindActorRecursive(scene, tag); + if (result) + break; + } + return result; +} + +Actor* Level::FindActor(const MClass* type, const Tag& tag, Actor* root) +{ + CHECK_RETURN(type, nullptr); + if (root) + return FindActorRecursiveByType(root, type, tag); + Actor* result = nullptr; + ScopeLock lock(ScenesLock); + for (int32 i = 0; result == nullptr && i < Scenes.Count(); i++) + result = Scenes[i]->FindActor(type, tag); + return result; +} + +void FindActorRecursive(Actor* node, const Tag& tag, Array& result) +{ + if (node->HasTag(tag)) + result.Add(node); + for (Actor* child : node->Children) + FindActorRecursive(child, tag, result); +} + +Array Level::FindActors(const Tag& tag, const bool activeOnly, Actor* root) +{ + PROFILE_CPU(); + Array result; + if (root) + { + FindActorsRecursive(root, tag, activeOnly, result); + } + else + { + ScopeLock lock(ScenesLock); + for (Scene* scene : Scenes) + FindActorsRecursive(scene, tag, activeOnly, result); + } + return result; +} + +Array Level::FindActorsByParentTag(const Tag& parentTag, const bool activeOnly, Actor* root) +{ + PROFILE_CPU(); + Array result; + const Array subTags = Tags::GetSubTags(parentTag); + + if (subTags.Count() == 0) + { + return result; + } + if (subTags.Count() == 1) + { + result = FindActors(subTags[0], activeOnly, root); + return result; + } + + if (root) + { + FindActorsRecursiveByParentTags(root, subTags, activeOnly, result); + } + else + { + ScopeLock lock(ScenesLock); + for (Scene* scene : Scenes) + FindActorsRecursiveByParentTags(scene, subTags, activeOnly, result); + } + + return result; +} + Script* Level::FindScript(const MClass* type) { CHECK_RETURN(type, nullptr); diff --git a/Source/Engine/Level/Level.cs b/Source/Engine/Level/Level.cs index c38b287ca..1e8524f2c 100644 --- a/Source/Engine/Level/Level.cs +++ b/Source/Engine/Level/Level.cs @@ -77,6 +77,18 @@ namespace FlaxEngine { return FindActor(typeof(T), name) as T; } + + /// + /// Tries to find actor of the given type and tag in a root actor or all loaded scenes. + /// + /// A tag on the object. + /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. + /// Type of the object. + /// Found actor or null. + public static T FindActor(Tag tag, Actor root = null) where T : Actor + { + return FindActor(typeof(T), tag, root) as T; + } /// /// Tries to find actor with the given ID in all loaded scenes. It's very fast O(1) lookup. diff --git a/Source/Engine/Level/Level.h b/Source/Engine/Level/Level.h index 9a041bda9..1f0acda2d 100644 --- a/Source/Engine/Level/Level.h +++ b/Source/Engine/Level/Level.h @@ -371,6 +371,41 @@ public: /// Actor instance if found, null otherwise. API_FUNCTION() static Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const StringView& name); + /// + /// Tries to find the actor with the given tag (returns the first one found). + /// + /// The tag of the actor to search for. + /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. + /// Found actor or null. + API_FUNCTION() static Actor* FindActor(const Tag& tag, Actor* root = nullptr); + + /// + /// 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. + /// The tag of the actor to search for. + /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. + /// Actor instance if found, null otherwise. + API_FUNCTION() static Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const Tag& tag, Actor* root = nullptr); + + /// + /// Tries to find the actors with the given tag (returns all found). + /// + /// The tag of the actor to search for. + /// Find only active actors. + /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. + /// Found actors or empty if none. + API_FUNCTION() static Array FindActors(const Tag& tag, const bool activeOnly = false, Actor* root = nullptr); + + /// + /// Search actors using a parent parentTag. + /// + /// The tag to search actors with subtags belonging to this tag + /// Find only active actors. + /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. + /// Returns all actors that have subtags belonging to the given parent parentTag + API_FUNCTION() static Array FindActorsByParentTag(const Tag& parentTag, const bool activeOnly = false, Actor* root = nullptr); + /// /// Tries to find the actor of the given type in all the loaded scenes. /// @@ -392,6 +427,18 @@ public: return (T*)FindActor(T::GetStaticClass(), name); } + /// + /// Tries to find the actor of the given type and tag in a root actor or all the loaded scenes. + /// The tag of the actor to search for. + /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. + /// + /// Actor instance if found, null otherwise. + template + FORCE_INLINE static T* FindActor(const Tag& tag, Actor* root = nullptr) + { + return (T*)FindActor(T::GetStaticClass(), tag, root); + } + /// /// Tries to find the script of the given type in all the loaded scenes. /// @@ -481,33 +528,6 @@ public: /// API_FUNCTION() static int32 GetLayerIndex(const StringView& layer); -public: - /// - /// Tries to find the actor with the given tag (returns the first one found). - /// - /// The tag of the actor to search for. - /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. - /// Found actor or null. - API_FUNCTION() static Actor* FindActor(const Tag& tag, Actor* root = nullptr); - - /// - /// Tries to find the actors with the given tag (returns all found). - /// - /// The tag of the actor to search for. - /// Find only active actors. - /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. - /// Found actors or empty if none. - API_FUNCTION() static Array FindActors(const Tag& tag, const bool activeOnly = false, Actor* root = nullptr); - - /// - /// Search actors using a parent parentTag. - /// - /// The tag to search actors with subtags belonging to this tag - /// Find only active actors. - /// The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes. - /// Returns all actors that have subtags belonging to the given parent parentTag - API_FUNCTION() static Array FindActorsByParentTag(const Tag& parentTag, const bool activeOnly = false, Actor* root = nullptr); - private: // Actor API enum class ActorEventType