Add support for searching actors and scripts by interface

#3199
This commit is contained in:
Wojtek Figat
2025-02-11 14:22:44 +01:00
parent b0fe4373b0
commit 3ad369501a
4 changed files with 68 additions and 33 deletions

View File

@@ -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*> Actor::GetChildren(const MClass* type) const
{
Array<Actor*> 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<Actor*>(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<Actor*>(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<Actor*>(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)
{

View File

@@ -237,7 +237,7 @@ public:
/// <summary>
/// Gets the child actor of the given type.
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type. Supports interface types.</param>
/// <returns>The child actor or null.</returns>
API_FUNCTION() Actor* GetChild(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type) const;
@@ -270,7 +270,7 @@ public:
/// <summary>
/// Gets the child actors of the given type.
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type. Supports interface types.</param>
/// <returns>The child actors.</returns>
API_FUNCTION() Array<Actor*> GetChildren(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type) const;
@@ -315,7 +315,7 @@ public:
/// <summary>
/// Gets the script of the given type from this actor.
/// </summary>
/// <param name="type">Type of the script to search for. Includes any scripts derived from the type.</param>
/// <param name="type">Type of the script to search for. Includes any scripts derived from the type. Supports interface types.</param>
/// <returns>The script or null.</returns>
API_FUNCTION() Script* GetScript(API_PARAM(Attributes="TypeReference(typeof(Script))") const MClass* type) const;
@@ -332,7 +332,7 @@ public:
/// <summary>
/// Gets the scripts of the given type from this actor.
/// </summary>
/// <param name="type">Type of the script to search for. Includes any scripts derived from the type.</param>
/// <param name="type">Type of the script to search for. Includes any scripts derived from the type. Supports interface types.</param>
/// <returns>The scripts.</returns>
API_FUNCTION() Array<Script*> GetScripts(API_PARAM(Attributes="TypeReference(typeof(Script))") const MClass* type) const;
@@ -778,7 +778,7 @@ public:
/// <summary>
/// Tries to find the actor of the given type in this actor hierarchy (checks this actor and all children hierarchy).
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type. Supports interface types.</param>
/// <param name="activeOnly">Finds only a active actor.</param>
/// <returns>Actor instance if found, null otherwise.</returns>
API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, bool activeOnly = false) const;
@@ -786,7 +786,7 @@ public:
/// <summary>
/// Tries to find the actor of the given type and name in this actor hierarchy (checks this actor and all children hierarchy).
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type. Supports interface types.</param>
/// <param name="name">The name of the actor.</param>
/// <returns>Actor instance if found, null otherwise.</returns>
API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const StringView& name) const;
@@ -794,7 +794,7 @@ public:
/// <summary>
/// Tries to find the actor of the given type and tag in this actor hierarchy.
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type. Supports interface types.</param>
/// <param name="tag">The tag of the actor to search for.</param>
/// <param name="activeOnly">Finds only an active actor.</param>
/// <returns>Actor instance if found, null otherwise.</returns>
@@ -835,7 +835,7 @@ public:
/// <summary>
/// Tries to find the script of the given type in this actor hierarchy (checks this actor and all children hierarchy).
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type. Supports interface types.</param>
/// <returns>Script instance if found, null otherwise.</returns>
API_FUNCTION() Script* FindScript(API_PARAM(Attributes="TypeReference(typeof(Script))") const MClass* type) const;

View File

@@ -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<Actor*>& result)
void GetActors(const MClass* type, bool isInterface, Actor* actor, bool activeOnly, Array<Actor*>& 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<Script*>& result)
void GetScripts(const MClass* type, bool isInterface, Actor* actor, Array<Script*>& 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<Actor*> 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<Script*> 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;
}

View File

@@ -360,7 +360,7 @@ public:
/// <summary>
/// Tries to find the actor of the given type in all the loaded scenes.
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type. Supports interface types.</param>
/// <param name="activeOnly">Finds only an active actor.</param>
/// <returns>Found actor or null.</returns>
API_FUNCTION() static Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, bool activeOnly = false);
@@ -368,7 +368,7 @@ public:
/// <summary>
/// Tries to find the actor of the given type and name in all the loaded scenes.
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type. Supports interface types.</param>
/// <param name="name">The name of the actor.</param>
/// <returns>Actor instance if found, null otherwise.</returns>
API_FUNCTION() static Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const StringView& name);
@@ -385,7 +385,7 @@ public:
/// <summary>
/// Tries to find the actor of the given type and tag in all the loaded scenes.
/// </summary>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type.</param>
/// <param name="type">Type of the actor to search for. Includes any actors derived from the type. Supports interface types.</param>
/// <param name="tag">The tag of the actor to search for.</param>
/// <param name="activeOnly">Finds only an active actor.</param>
/// <param name="root">The custom root actor to start searching from (hierarchical), otherwise null to search all loaded scenes.</param>
@@ -446,7 +446,7 @@ public:
/// <summary>
/// Tries to find the script of the given type in all the loaded scenes.
/// </summary>
/// <param name="type">Type of the script to search for. Includes any scripts derived from the type.</param>
/// <param name="type">Type of the script to search for. Includes any scripts derived from the type. Supports interface types.</param>
/// <returns>Found script or null.</returns>
API_FUNCTION() static Script* FindScript(API_PARAM(Attributes="TypeReference(typeof(Script))") const MClass* type);