// MIT License - Copyright (c) 2024 wallstop // Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE namespace WallstopStudios.UnityHelpers.Core.Helper { using System.Collections.Generic; using UnityEngine; using Utils; public static partial class Helpers { public static List IterateOverAllParentComponentsRecursively( this Component component, List buffer, bool includeSelf = false ) { buffer.Clear(); if (component == null) { return buffer; } using PooledResource> bufferResource = Buffers.List.Get( out List internalBuffer ); if (includeSelf) { component.GetComponents(internalBuffer); buffer.AddRange(internalBuffer); } Transform parent = component.transform.parent; while (parent != null) { parent.GetComponents(internalBuffer); buffer.AddRange(internalBuffer); parent = parent.parent; } return buffer; } public static IEnumerable IterateOverAllParentComponentsRecursively( this Component component, bool includeSelf = false ) { if (component == null) { yield break; } using PooledResource> bufferResource = Buffers.List.Get(out List buffer); using PooledResource> transformResource = Buffers.List.Get( out List transforms ); foreach (Transform parent in component.IterateOverAllParents(transforms, includeSelf)) { parent.GetComponents(buffer); foreach (T c in buffer) { yield return c; } } } public static List IterateOverAllChildComponentsRecursively( this Component component, List buffer, bool includeSelf = false ) { buffer.Clear(); if (component == null) { return buffer; } using PooledResource> internalBufferResource = Buffers.List.Get( out List internalBuffer ); if (includeSelf) { component.GetComponents(internalBuffer); buffer.AddRange(internalBuffer); } Transform transform = component.transform; for (int i = 0; i < transform.childCount; ++i) { Transform child = transform.GetChild(i); child.GetComponentsInChildren(true, internalBuffer); buffer.AddRange(internalBuffer); } return buffer; } public static IEnumerable IterateOverAllChildComponentsRecursively( this Component component, bool includeSelf = false ) { if (component == null) { yield break; } using PooledResource> bufferResource = Buffers.List.Get(out List buffer); if (includeSelf) { component.GetComponents(buffer); foreach (T c in buffer) { yield return c; } } Transform transform = component.transform; for (int i = 0; i < transform.childCount; ++i) { Transform child = transform.GetChild(i); child.GetComponentsInChildren(true, buffer); foreach (T c in buffer) { yield return c; } } } public static IEnumerable IterateOverAllChildren( this Component component, bool includeSelf = false ) { if (component == null) { yield break; } Transform transform = component.transform; if (includeSelf) { yield return transform; } for (int i = 0; i < transform.childCount; ++i) { yield return transform.GetChild(i); } } public static List IterateOverAllChildren( this Component component, List buffer, bool includeSelf = false ) { buffer.Clear(); if (component == null) { return buffer; } Transform transform = component.transform; if (includeSelf) { buffer.Add(transform); } for (int i = 0; i < transform.childCount; ++i) { buffer.Add(transform.GetChild(i)); } return buffer; } public static IEnumerable IterateOverAllParents( this Component component, bool includeSelf = false ) { if (component == null) { yield break; } Transform transform = component.transform; if (includeSelf) { yield return transform; } Transform parent = transform.parent; while (parent != null) { yield return parent; parent = parent.parent; } } public static List IterateOverAllParents( this Component component, List buffer, bool includeSelf = false ) { buffer.Clear(); if (component == null) { return buffer; } Transform transform = component.transform; if (includeSelf) { buffer.Add(transform); } Transform parent = transform.parent; while (parent != null) { buffer.Add(parent); parent = parent.parent; } return buffer; } public static IEnumerable IterateOverAllChildrenRecursively( this Component component, bool includeSelf = false ) { if (component == null) { yield break; } Transform transform = component.transform; if (includeSelf) { yield return transform; } using PooledResource> transformResource = Buffers.List.Get( out List transforms ); for (int i = 0; i < transform.childCount; ++i) { foreach ( Transform child in transform .GetChild(i) .IterateOverAllChildrenRecursively(transforms, includeSelf: true) ) { yield return child; } } } public static List IterateOverAllChildrenRecursively( this Component component, List buffer, bool includeSelf = false ) { buffer.Clear(); if (component == null) { return buffer; } Transform transform = component.transform; if (includeSelf) { buffer.Add(transform); } return transform.InternalIterateOverAllChildrenRecursively(buffer); } private static List InternalIterateOverAllChildrenRecursively( this Transform transform, List buffer ) { for (int i = 0; i < transform.childCount; ++i) { Transform child = transform.GetChild(i); buffer.Add(child); child.InternalIterateOverAllChildrenRecursively(buffer); } return buffer; } public static IEnumerable IterateOverAllChildrenRecursivelyBreadthFirst( this Component component, bool includeSelf = false ) { if (component == null) { yield break; } Transform transform = component.transform; if (includeSelf) { yield return transform; } using PooledResource> queueResource = Buffers.Queue.Get( out Queue iteration ); iteration.Enqueue(transform); while (iteration.TryDequeue(out Transform current)) { for (int i = 0; i < current.childCount; ++i) { Transform childTransform = current.GetChild(i); iteration.Enqueue(childTransform); yield return childTransform; } } } public static List IterateOverAllChildrenRecursivelyBreadthFirst( this Component component, List buffer, bool includeSelf = false ) { return component.IterateOverAllChildrenRecursivelyBreadthFirst( buffer, includeSelf, maxDepth: 0 ); } public static List IterateOverAllChildrenRecursivelyBreadthFirst( this Component component, List buffer, bool includeSelf, int maxDepth ) { buffer.Clear(); if (component == null) { return buffer; } Transform transform = component.transform; if (includeSelf) { buffer.Add(transform); } if (maxDepth == 0) { maxDepth = int.MaxValue; } using PooledResource> iterationResource = Buffers<( Transform, int )>.Queue.Get(); Queue<(Transform transform, int depth)> iteration = iterationResource.resource; iteration.Enqueue((transform, 0)); while (iteration.TryDequeue(out (Transform current, int depth) item)) { for (int i = 0; i < item.current.childCount; ++i) { Transform childTransform = item.current.GetChild(i); int childDepth = item.depth + 1; if (childDepth <= maxDepth) { buffer.Add(childTransform); iteration.Enqueue((childTransform, childDepth)); } } } return buffer; } } }