Add GetComponentsInChildren<T>() to SceneContainer
Facts
FindComponents, FindNodes and FindNodesWhereComponent traverse the (sub-)graph passed. All methods work on IEnumerable<SceneNode> as well as directly on SceneNode instances.
GetComponent searches the components list of the given node and does not traverse the given node's child list.
To find a componen of a certain type in a node specified by a certain serach criterion (e. g. the node's name) in the entire scene a rather complicated call chain is necessary:
_scene.Children?.FindNodes( n => n.Name == "NodeInQuestion").FirstOrDefault()?.GetComponent<TComponentInQuestion>()
TODO
- Remove
GetComponentInChildrenentirely (mark it obsolete first) as it imlements the same behavior asFindComponents<> - Implement
FindNodeByName(string nodeName)as extension method forSceneContainerandSceneNode. Example[_scene|node].FindNodeByName("WhatNode")?.GetComponent<TCompTypeToLookFor>()
Is this correct @ASPePeX?
var res = _rocketScene.Children[0].GetComponentsInChildren<Transform>(); // works
res = _rocketScene.GetComponentsInChildren<Transform>(); // not available
Therefore, if one would want to get every component inside the root children list, one currently would have to write:
var res = new List<Transform>();
for(var i = 0; i < _rocketScene.Children.Count; i++)
{
res.AddRange(_rocketScene.Children[i].GetComponentsInChildren<Transform>());
}
Proposal: implement _rocketScene.GetComponentsInChildren<T>()
EDIT: And RemoveComponentsInChildren accordingly.
Doesn't [FindComponents] (https://github.com/FUSEEProjectTeam/Fusee/blob/master/src/Engine/Core/Scene/SceneExtensions.cs#L36) do the job already? Or is GetComponentsInChildren meant to NOT work recursively.
We could enhance FindComponents to take a recursion depth parameter (initalized to -1 meaning to recurse as deep as the hierarchy is) OR at least implement GetComponentsInChildren using the same pattern as FindComponents is implemented: There are two such extension methods:
- One directly extending SceneNode (https://github.com/FUSEEProjectTeam/Fusee/blob/master/src/Engine/Core/Scene/SceneExtensions.cs#L25)
- One extending
(this IEnumerable<SceneNode> roots, ...(https://github.com/FUSEEProjectTeam/Fusee/blob/master/src/Engine/Core/Scene/SceneExtensions.cs#L63)
This way you could call the method on single nodes as well as on the Children property of both, a scene and a node.
Doesn't [FindComponents]
Yeah, it indeed does!
My guess is, that it's much more convenient (and easier to understand) to write _scene.GetComponentsInChildren<Transform>() than _scene.Children.FindComponents(c => c is Transform);.
So the proposal to enhance the function GetComponentInChildren via 2. (this IEnumerable<SceneNode> roots, ... is a good idea. Knowing that we just add convenience and a little code overlap.
Using the FindComponents flavors implemented
here: https://github.com/FUSEEProjectTeam/Fusee/blob/master/src/Engine/Core/Scene/SceneExtensions.cs#L51
and here: https://github.com/FUSEEProjectTeam/Fusee/blob/master/src/Engine/Core/Scene/SceneExtensions.cs#L63
you could write _scene.Children.FindComponents<Transform>(c => true). We could provide the match lambda used here as a default parameter in the FindComponents versions taking the TComponentToFind generic argument.
We could provide the match lambda
👍
One more thing, what's the meaning of GetComponents vs. FindComponents. It seems clear for GetLight and consortia, but in this case, I'm not quite sure what we want to express. It could as well be FindComponentsInChildren so a user would know, that FindComponents does the same job as FindComponentsInChildren but from another starting point, couldn't it?
FindComponentsis recursive and traverses the given node(s) and their children