using System; using System.Collections.Generic; using UnityEngine; namespace UVC.Linq { public static partial class GameObjectExtensions { /// 소스 컬렉션에 있는 모든 GameObject의 조상을 포함하는 GameObject 컬렉션을 반환합니다. public static IEnumerable Ancestors(this IEnumerable source) { foreach (var item in source) { var e = item.Ancestors().GetEnumerator(); while (e.MoveNext()) { yield return e.Current; } } } /// 소스 컬렉션의 모든 GameObject와 이들의 조상 GameObject를 포함하는 컬렉션을 반환합니다. public static IEnumerable AncestorsAndSelf(this IEnumerable source) { foreach (var item in source) { var e = item.AncestorsAndSelf().GetEnumerator(); while (e.MoveNext()) { yield return e.Current; } } } /// 소스 컬렉션에 있는 모든 GameObject의 자손 GameObject를 포함하는 컬렉션을 반환합니다. /// 자식 객체를 순회할지 결정하는 조건 함수입니다. null이면 모든 자식을 순회합니다. public static IEnumerable Descendants(this IEnumerable source, Func descendIntoChildren = null) { foreach (var item in source) { var e = item.Descendants(descendIntoChildren).GetEnumerator(); while (e.MoveNext()) { yield return e.Current; } } } /// 소스 컬렉션의 모든 GameObject와 이들의 자손 GameObject를 포함하는 컬렉션을 반환합니다. public static IEnumerable DescendantsAndSelf(this IEnumerable source, Func descendIntoChildren = null) { foreach (var item in source) { var e = item.DescendantsAndSelf(descendIntoChildren).GetEnumerator(); while (e.MoveNext()) { yield return e.Current; } } } /// 소스 컬렉션에 있는 모든 GameObject의 자식 GameObject를 포함하는 컬렉션을 반환합니다. public static IEnumerable Children(this IEnumerable source) { foreach (var item in source) { var e = item.Children().GetEnumerator(); while (e.MoveNext()) { yield return e.Current; } } } /// 소스 컬렉션의 모든 GameObject와 이들의 자식 GameObject를 포함하는 컬렉션을 반환합니다. public static IEnumerable ChildrenAndSelf(this IEnumerable source) { foreach (var item in source) { var e = item.ChildrenAndSelf().GetEnumerator(); while (e.MoveNext()) { yield return e.Current; } } } /// 소스 컬렉션에 있는 모든 GameObject를 안전하게(null 체크 포함) 파괴합니다. /// 에디터 모드에서는 true로 설정하거나 !Application.isPlaying을 전달하세요. /// 부모를 null로 설정합니다. public static void Destroy(this IEnumerable source, bool useDestroyImmediate = false, bool detachParent = false) { if (detachParent) { var l = new List(source); // avoid halloween problem var e = l.GetEnumerator(); // get struct enumerator for avoid unity's compiler bug(avoid boxing) while (e.MoveNext()) { e.Current.Destroy(useDestroyImmediate, true); } } else { foreach (var item in source) { item.Destroy(useDestroyImmediate, false); // doesn't detach. } } } /// 소스 컬렉션에서 지정된 컴포넌트 타입의 컬렉션을 반환합니다. /// 검색할 컴포넌트의 타입입니다. /// 에디터 모드에서는 메모리 할당을 최소화하기 위한 캐시 메커니즘을 사용합니다. public static IEnumerable OfComponent(this IEnumerable source) where T : UnityEngine.Component { foreach (var item in source) { #if UNITY_EDITOR var cache = ComponentCache.Instance; item.GetComponents(cache); if (cache.Count != 0) { var component = cache[0]; cache.Clear(); yield return component; } #else var component = item.GetComponent(); if (component != null) { yield return component; } #endif } } #if UNITY_EDITOR class ComponentCache { public static readonly List Instance = new List(); // for no allocate on UNITY_EDITOR } #endif /// 요소를 버퍼에 저장하고, 크기를 반환합니다. 배열은 자동으로 확장됩니다. /// 저장할 요소들의 소스 컬렉션입니다. /// 요소를 저장할 배열 참조입니다. 필요에 따라 크기가 조정됩니다. /// 배열에 저장된 요소의 수를 반환합니다. public static int ToArrayNonAlloc(this IEnumerable source, ref T[] array) { var index = 0; foreach (var item in source) { if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = item; } return index; } } }