// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. using System; using System.Collections.Generic; using FlaxEngine; namespace FlaxEditor.SceneGraph { /// /// Set of tools for processing. /// [HideInEditor] public static class SceneGraphTools { /// /// Delegate for scene graph action execution callback. /// /// The node. /// True if call deeper, otherwise skip calling node children. public delegate bool GraphExecuteCallbackDelegate(SceneGraphNode node); /// /// Executes the custom action on the graph nodes. /// /// The node /// The callback. public static void ExecuteOnGraph(this SceneGraphNode node, GraphExecuteCallbackDelegate callback) { for (int i = 0; i < node.ChildNodes.Count; i++) { if (callback(node.ChildNodes[i])) { ExecuteOnGraph(node.ChildNodes[i], callback); } } } /// /// Builds the array made of input nodes that are at the top level. The result collection contains only nodes that don't have parent nodes in the given collection. /// /// The scene graph node type. /// The nodes. /// The result. public static List BuildNodesParents(this List nodes) where T : SceneGraphNode { var list = new List(); BuildNodesParents(nodes, list); return list; } /// /// Builds the list made of input nodes that are at the top level. The result collection contains only nodes that don't have parent nodes in the given collection. /// /// The scene graph node type. /// The nodes. /// The result. public static void BuildNodesParents(this List nodes, List result) where T : SceneGraphNode { if (nodes == null || result == null) throw new ArgumentNullException(); result.Clear(); // Build solid part of the tree var fullTree = BuildAllNodes(nodes); for (var i = 0; i < nodes.Count; i++) { var target = nodes[i]; // If there is no target node parent in the solid tree list, // then it means it's a local root node and can be added to the results. if (!fullTree.Contains(target.ParentNode)) result.Add(target); } } /// /// Builds the array made of all nodes in the input list and child tree. The result collection contains all nodes in the tree. /// /// The nodes. /// The result. public static List BuildAllNodes(this List nodes) where T : SceneGraphNode { var list = new List(); BuildAllNodes(nodes, list); return list; } private static void FillTree(SceneGraphNode node, List result) { result.AddRange(node.ChildNodes); for (int i = 0; i < node.ChildNodes.Count; i++) { FillTree(node.ChildNodes[i], result); } } /// /// Builds the list made of all nodes in the input list and child tree. The result collection contains all nodes in the tree. /// /// The nodes. /// The result. public static void BuildAllNodes(this List nodes, List result) where T : SceneGraphNode { if (nodes == null || result == null) throw new ArgumentNullException(); result.Clear(); for (var i = 0; i < nodes.Count; i++) { var target = nodes[i]; // Check if has been already added if (result.Contains(target)) continue; // Add whole child tree to the results result.Add(target); FillTree(target, result); } } } }