using System; using System.Collections; using System.Collections.Generic; using UnityEngine; namespace UVC.Linq { public static partial class GameObjectExtensions { /// Ãà(ºÎ¸ð, ÀÚ½Ä, Àڽĵé, Á¶»ó/ÀÚ¼Õ, ÀÌÀü ÇüÁ¦/ÀÌÈÄ ÇüÁ¦ °´Ã¼)À» ±â¹ÝÀ¸·Î °ÔÀÓ °´Ã¼¸¦ ¼øÈ¸ÇÕ´Ï´Ù. /// ÀÌ GameObjectÀÇ ºÎ¸ð GameObject¸¦ °¡Á®¿É´Ï´Ù. ÀÌ GameObject¿¡ ºÎ¸ð°¡ ¾øÀ¸¸é nullÀ» ¹ÝȯÇÕ´Ï´Ù. public static GameObject Parent(this GameObject origin) { if (origin == null) return null; var parentTransform = origin.transform.parent; if (parentTransform == null) return null; return parentTransform.gameObject; } /// ÁöÁ¤µÈ À̸§À» °¡Áø ù ¹øÂ° ÀÚ½Ä GameObject¸¦ °¡Á®¿É´Ï´Ù. ÁöÁ¤µÈ À̸§À» °¡Áø GameObject°¡ ¾øÀ¸¸é nullÀ» ¹ÝȯÇÕ´Ï´Ù. public static GameObject Child(this GameObject origin, string name) { if (origin == null) return null; var child = origin.transform.Find(name); // transform.find´Â ºñȰ¼º °´Ã¼¸¦ °¡Á®¿Ã ¼ö ÀÖ½À´Ï´Ù. if (child == null) return null; return child.gameObject; } /// ÀÚ½Ä GameObjectÀÇ Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public static ChildrenEnumerable Children(this GameObject origin) { return new ChildrenEnumerable(origin, false); } /// ÀÌ GameObject¿Í ÀÚ½Ä GameObject¸¦ Æ÷ÇÔÇÏ´Â GameObject Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public static ChildrenEnumerable ChildrenAndSelf(this GameObject origin) { return new ChildrenEnumerable(origin, true); } /// ÀÌ GameObjectÀÇ Á¶»ó GameObject Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public static AncestorsEnumerable Ancestors(this GameObject origin) { return new AncestorsEnumerable(origin, false); } /// ÀÌ ¿ä¼Ò¿Í ÀÌ GameObjectÀÇ Á¶»óÀ» Æ÷ÇÔÇÏ´Â GameObject Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public static AncestorsEnumerable AncestorsAndSelf(this GameObject origin) { return new AncestorsEnumerable(origin, true); } /// ÀÚ¼Õ GameObjectÀÇ Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public static DescendantsEnumerable Descendants(this GameObject origin, Func descendIntoChildren = null) { return new DescendantsEnumerable(origin, false, descendIntoChildren); } /// ÀÌ GameObject¿Í ÀÌ GameObjectÀÇ ¸ðµç ÀÚ¼Õ GameObject¸¦ Æ÷ÇÔÇÏ´Â GameObject Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public static DescendantsEnumerable DescendantsAndSelf(this GameObject origin, Func descendIntoChildren = null) { return new DescendantsEnumerable(origin, true, descendIntoChildren); } /// ÀÌ GameObject ÀÌÀüÀÇ ÇüÁ¦ GameObject Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public static BeforeSelfEnumerable BeforeSelf(this GameObject origin) { return new BeforeSelfEnumerable(origin, false); } /// ÀÌ GameObject¿Í ÀÌ GameObject ÀÌÀüÀÇ ÇüÁ¦ GameObject¸¦ Æ÷ÇÔÇÏ´Â GameObject Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public static BeforeSelfEnumerable BeforeSelfAndSelf(this GameObject origin) { return new BeforeSelfEnumerable(origin, true); } /// ÀÌ GameObject ÀÌÈÄÀÇ ÇüÁ¦ GameObject Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public static AfterSelfEnumerable AfterSelf(this GameObject origin) { return new AfterSelfEnumerable(origin, false); } /// ÀÌ GameObject¿Í ÀÌ GameObject ÀÌÈÄÀÇ ÇüÁ¦ GameObject¸¦ Æ÷ÇÔÇÏ´Â GameObject Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public static AfterSelfEnumerable AfterSelfAndSelf(this GameObject origin) { return new AfterSelfEnumerable(origin, true); } // ¼öµ¿ ±¸Á¶Ã¼ ¿­°ÅÀÚ¸¦ ±¸ÇöÇÕ´Ï´Ù. public struct ChildrenEnumerable : IEnumerable { readonly GameObject origin; readonly bool withSelf; public ChildrenEnumerable(GameObject origin, bool withSelf) { this.origin = origin; this.withSelf = withSelf; } /// ¼Ò½º Ä÷º¼Ç¿¡¼­ ÁöÁ¤µÈ ÄÄÆ÷³ÍÆ®ÀÇ Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public OfComponentEnumerable OfComponent() where T : Component { return new OfComponentEnumerable(ref this); } /// ¼Ò½º Ä÷º¼ÇÀÇ ¸ðµç GameObject¸¦ ¾ÈÀüÇϰÔ(null È®ÀÎ) ÆÄ±«ÇÕ´Ï´Ù. /// ¿¡µðÅÍ ¸ðµåÀÎ °æ¿ì trueÀ̰ųª !Application.isPlayingÀ» Àü´ÞÇØ¾ß ÇÕ´Ï´Ù. /// parent = null·Î ¼³Á¤ÇÕ´Ï´Ù. public void Destroy(bool useDestroyImmediate = false, bool detachParent = false) { var e = GetEnumerator(); while (e.MoveNext()) { e.Current.Destroy(useDestroyImmediate, false); } if (detachParent) { origin.transform.DetachChildren(); if (withSelf) { #if !(UNITY_4_0 || UNITY_4_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_4 || UNITY_4_5) origin.transform.SetParent(null); #else origin.transform.parent = null; #endif } } } /// ¼Ò½º Ä÷º¼ÇÀÇ ¸ðµç GameObject¸¦ ¾ÈÀüÇϰÔ(null È®ÀÎ) ÆÄ±«ÇÕ´Ï´Ù. /// ¿¡µðÅÍ ¸ðµåÀÎ °æ¿ì trueÀ̰ųª !Application.isPlayingÀ» Àü´ÞÇØ¾ß ÇÕ´Ï´Ù. public void Destroy(Func predicate, bool useDestroyImmediate = false) { var e = GetEnumerator(); while (e.MoveNext()) { var item = e.Current; if (predicate(item)) { item.Destroy(useDestroyImmediate, false); } } } public Enumerator GetEnumerator() { // GetEnumerator ½ÃÁ¡¿¡¸¸ GameObject°¡ ÆÄ±«µÇ¾ú´ÂÁö È®ÀÎÇÕ´Ï´Ù. return (origin == null) ? new Enumerator(null, withSelf, false) : new Enumerator(origin.transform, withSelf, true); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #region LINQ int GetChildrenSize() { return origin.transform.childCount + (withSelf ? 1 : 0); } public void ForEach(Action action) { var e = this.GetEnumerator(); while (e.MoveNext()) { action(e.Current); } } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(ref GameObject[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (array.Length == index) { var newSize = (index == 0) ? GetChildrenSize() : index * 2; Array.Resize(ref array, newSize); } array[index++] = item; } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func filter, ref GameObject[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (!filter(item)) continue; if (array.Length == index) { var newSize = (index == 0) ? GetChildrenSize() : index * 2; Array.Resize(ref array, newSize); } array[index++] = item; } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (array.Length == index) { var newSize = (index == 0) ? GetChildrenSize() : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(item); } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func filter, Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (!filter(item)) continue; if (array.Length == index) { var newSize = (index == 0) ? GetChildrenSize() : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(item); } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func let, Func filter, Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; var state = let(item); if (!filter(state)) continue; if (array.Length == index) { var newSize = (index == 0) ? GetChildrenSize() : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(state); } return index; } public GameObject[] ToArray() { var array = new GameObject[GetChildrenSize()]; var len = ToArrayNonAlloc(ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public GameObject[] ToArray(Func filter) { var array = new GameObject[GetChildrenSize()]; var len = ToArrayNonAlloc(filter, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func selector) { var array = new T[GetChildrenSize()]; var len = ToArrayNonAlloc(selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func filter, Func selector) { var array = new T[GetChildrenSize()]; var len = ToArrayNonAlloc(filter, selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func let, Func filter, Func selector) { var array = new T[GetChildrenSize()]; var len = ToArrayNonAlloc(let, filter, selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public GameObject First() { var e = this.GetEnumerator(); if (e.MoveNext()) { return e.Current; } else { throw new InvalidOperationException("½ÃÄö½º°¡ ºñ¾î ÀÖ½À´Ï´Ù."); } } public GameObject FirstOrDefault() { var e = this.GetEnumerator(); return (e.MoveNext()) ? e.Current : null; } #endregion public struct Enumerator : IEnumerator { readonly int childCount; // childCount´Â GetEnumerator°¡ È£ÃâµÉ ¶§ °íÁ¤µË´Ï´Ù. readonly Transform originTransform; readonly bool canRun; bool withSelf; int currentIndex; GameObject current; internal Enumerator(Transform originTransform, bool withSelf, bool canRun) { this.originTransform = originTransform; this.withSelf = withSelf; this.childCount = canRun ? originTransform.childCount : 0; this.currentIndex = -1; this.canRun = canRun; this.current = null; } public bool MoveNext() { if (!canRun) return false; if (withSelf) { current = originTransform.gameObject; withSelf = false; return true; } currentIndex++; if (currentIndex < childCount) { var child = originTransform.GetChild(currentIndex); current = child.gameObject; return true; } return false; } public GameObject Current { get { return current; } } object IEnumerator.Current { get { return current; } } public void Dispose() { } public void Reset() { throw new NotSupportedException(); } } public struct OfComponentEnumerable : IEnumerable where T : Component { ChildrenEnumerable parent; public OfComponentEnumerable(ref ChildrenEnumerable parent) { this.parent = parent; } public OfComponentEnumerator GetEnumerator() { return new OfComponentEnumerator(ref this.parent); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #region LINQ public void ForEach(Action action) { var e = this.GetEnumerator(); while (e.MoveNext()) { action(e.Current); } } public T First() { var e = this.GetEnumerator(); if (e.MoveNext()) { return e.Current; } else { throw new InvalidOperationException("½ÃÄö½º°¡ ºñ¾î ÀÖ½À´Ï´Ù."); } } public T FirstOrDefault() { var e = this.GetEnumerator(); return (e.MoveNext()) ? e.Current : null; } public T[] ToArray() { var array = new T[parent.GetChildrenSize()]; var len = ToArrayNonAlloc(ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(ref T[] array) { var index = 0; var e = this.GetEnumerator(); while (e.MoveNext()) { if (array.Length == index) { var newSize = (index == 0) ? parent.GetChildrenSize() : index * 2; Array.Resize(ref array, newSize); } array[index++] = e.Current; } return index; } #endregion } public struct OfComponentEnumerator : IEnumerator where T : Component { Enumerator enumerator; // ¿­°ÅÀÚ´Â º¯°æ °¡´ÉÇÕ´Ï´Ù. T current; #if UNITY_EDITOR static List componentCache = new List(); // UNITY_EDITOR¿¡¼­ ÇÒ´ç ¾øÀ½À» À§ÇÔ #endif public OfComponentEnumerator(ref ChildrenEnumerable parent) { this.enumerator = parent.GetEnumerator(); this.current = default(T); } public bool MoveNext() { while (enumerator.MoveNext()) { #if UNITY_EDITOR enumerator.Current.GetComponents(componentCache); if (componentCache.Count != 0) { current = componentCache[0]; componentCache.Clear(); return true; } #else var component = enumerator.Current.GetComponent(); if (component != null) { current = component; return true; } #endif } return false; } public T Current { get { return current; } } object IEnumerator.Current { get { return current; } } public void Dispose() { } public void Reset() { throw new NotSupportedException(); } } } public struct AncestorsEnumerable : IEnumerable { readonly GameObject origin; readonly bool withSelf; public AncestorsEnumerable(GameObject origin, bool withSelf) { this.origin = origin; this.withSelf = withSelf; } /// ¼Ò½º Ä÷º¼Ç¿¡¼­ ÁöÁ¤µÈ ÄÄÆ÷³ÍÆ®ÀÇ Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public OfComponentEnumerable OfComponent() where T : Component { return new OfComponentEnumerable(ref this); } /// ¼Ò½º Ä÷º¼ÇÀÇ ¸ðµç GameObject¸¦ ¾ÈÀüÇϰÔ(null È®ÀÎ) ÆÄ±«ÇÕ´Ï´Ù. /// ¿¡µðÅÍ ¸ðµåÀÎ °æ¿ì trueÀ̰ųª !Application.isPlayingÀ» Àü´ÞÇØ¾ß ÇÕ´Ï´Ù. public void Destroy(bool useDestroyImmediate = false) { var e = GetEnumerator(); while (e.MoveNext()) { e.Current.Destroy(useDestroyImmediate, false); } } /// ¼Ò½º Ä÷º¼ÇÀÇ ¸ðµç GameObject¸¦ ¾ÈÀüÇϰÔ(null È®ÀÎ) ÆÄ±«ÇÕ´Ï´Ù. /// ¿¡µðÅÍ ¸ðµåÀÎ °æ¿ì trueÀ̰ųª !Application.isPlayingÀ» Àü´ÞÇØ¾ß ÇÕ´Ï´Ù. public void Destroy(Func predicate, bool useDestroyImmediate = false) { var e = GetEnumerator(); while (e.MoveNext()) { var item = e.Current; if (predicate(item)) { item.Destroy(useDestroyImmediate, false); } } } public Enumerator GetEnumerator() { // GetEnumerator ½ÃÁ¡¿¡¸¸ GameObject°¡ ÆÄ±«µÇ¾ú´ÂÁö È®ÀÎÇÕ´Ï´Ù. return (origin == null) ? new Enumerator(null, null, withSelf, false) : new Enumerator(origin, origin.transform, withSelf, true); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #region LINQ public void ForEach(Action action) { var e = this.GetEnumerator(); while (e.MoveNext()) { action(e.Current); } } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(ref GameObject[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = item; } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func filter, ref GameObject[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (!filter(item)) continue; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = item; } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(item); } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func filter, Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (!filter(item)) continue; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(item); } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func let, Func filter, Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; var state = let(item); if (!filter(state)) continue; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(state); } return index; } public GameObject[] ToArray() { var array = new GameObject[4]; var len = ToArrayNonAlloc(ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public GameObject[] ToArray(Func filter) { var array = new GameObject[4]; var len = ToArrayNonAlloc(filter, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func filter, Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(filter, selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func let, Func filter, Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(let, filter, selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public GameObject First() { var e = this.GetEnumerator(); if (e.MoveNext()) { return e.Current; } else { throw new InvalidOperationException("½ÃÄö½º°¡ ºñ¾î ÀÖ½À´Ï´Ù."); } } public GameObject FirstOrDefault() { var e = this.GetEnumerator(); return (e.MoveNext()) ? e.Current : null; } #endregion public struct Enumerator : IEnumerator { readonly bool canRun; GameObject current; Transform currentTransform; bool withSelf; internal Enumerator(GameObject origin, Transform originTransform, bool withSelf, bool canRun) { this.current = origin; this.currentTransform = originTransform; this.withSelf = withSelf; this.canRun = canRun; } public bool MoveNext() { if (!canRun) return false; if (withSelf) { // withSelf, origin ¹× originTransform »ç¿ë withSelf = false; return true; } var parentTransform = currentTransform.parent; if (parentTransform != null) { current = parentTransform.gameObject; currentTransform = parentTransform; return true; } return false; } public GameObject Current { get { return current; } } object IEnumerator.Current { get { return current; } } public void Dispose() { } public void Reset() { throw new NotSupportedException(); } } public struct OfComponentEnumerable : IEnumerable where T : Component { AncestorsEnumerable parent; public OfComponentEnumerable(ref AncestorsEnumerable parent) { this.parent = parent; } public OfComponentEnumerator GetEnumerator() { return new OfComponentEnumerator(ref parent); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #region LINQ public void ForEach(Action action) { var e = this.GetEnumerator(); while (e.MoveNext()) { action(e.Current); } } public T First() { var e = this.GetEnumerator(); if (e.MoveNext()) { return e.Current; } else { throw new InvalidOperationException("½ÃÄö½º°¡ ºñ¾î ÀÖ½À´Ï´Ù."); } } public T FirstOrDefault() { var e = this.GetEnumerator(); return (e.MoveNext()) ? e.Current : null; } public T[] ToArray() { var array = new T[4]; var len = ToArrayNonAlloc(ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(ref T[] array) { var index = 0; var e = this.GetEnumerator(); while (e.MoveNext()) { if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = e.Current; } return index; } #endregion } public struct OfComponentEnumerator : IEnumerator where T : Component { Enumerator enumerator; // ¿­°ÅÀÚ´Â º¯°æ °¡´ÉÇÕ´Ï´Ù. T current; #if UNITY_EDITOR static List componentCache = new List(); // UNITY_EDITOR¿¡¼­ ÇÒ´ç ¾øÀ½À» À§ÇÔ #endif public OfComponentEnumerator(ref AncestorsEnumerable parent) { this.enumerator = parent.GetEnumerator(); this.current = default(T); } public bool MoveNext() { while (enumerator.MoveNext()) { #if UNITY_EDITOR enumerator.Current.GetComponents(componentCache); if (componentCache.Count != 0) { current = componentCache[0]; componentCache.Clear(); return true; } #else var component = enumerator.Current.GetComponent(); if (component != null) { current = component; return true; } #endif } return false; } public T Current { get { return current; } } object IEnumerator.Current { get { return current; } } public void Dispose() { } public void Reset() { throw new NotSupportedException(); } } } public struct DescendantsEnumerable : IEnumerable { static readonly Func alwaysTrue = _ => true; readonly GameObject origin; readonly bool withSelf; readonly Func descendIntoChildren; public DescendantsEnumerable(GameObject origin, bool withSelf, Func descendIntoChildren) { this.origin = origin; this.withSelf = withSelf; this.descendIntoChildren = descendIntoChildren ?? alwaysTrue; } /// ¼Ò½º Ä÷º¼Ç¿¡¼­ ÁöÁ¤µÈ ÄÄÆ÷³ÍÆ®ÀÇ Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public OfComponentEnumerable OfComponent() where T : Component { return new OfComponentEnumerable(ref this); } /// ¼Ò½º Ä÷º¼ÇÀÇ ¸ðµç GameObject¸¦ ¾ÈÀüÇϰÔ(null È®ÀÎ) ÆÄ±«ÇÕ´Ï´Ù. /// ¿¡µðÅÍ ¸ðµåÀÎ °æ¿ì trueÀ̰ųª !Application.isPlayingÀ» Àü´ÞÇØ¾ß ÇÕ´Ï´Ù. public void Destroy(bool useDestroyImmediate = false) { var e = GetEnumerator(); while (e.MoveNext()) { e.Current.Destroy(useDestroyImmediate, false); } } /// ¼Ò½º Ä÷º¼ÇÀÇ ¸ðµç GameObject¸¦ ¾ÈÀüÇϰÔ(null È®ÀÎ) ÆÄ±«ÇÕ´Ï´Ù. /// ¿¡µðÅÍ ¸ðµåÀÎ °æ¿ì trueÀ̰ųª !Application.isPlayingÀ» Àü´ÞÇØ¾ß ÇÕ´Ï´Ù. public void Destroy(Func predicate, bool useDestroyImmediate = false) { var e = GetEnumerator(); while (e.MoveNext()) { var item = e.Current; if (predicate(item)) { item.Destroy(useDestroyImmediate, false); } } } public Enumerator GetEnumerator() { // GetEnumerator ½ÃÁ¡¿¡¸¸ GameObject°¡ ÆÄ±«µÇ¾ú´ÂÁö È®ÀÎÇÕ´Ï´Ù. if (origin == null) { return new Enumerator(null, withSelf, false, null, descendIntoChildren); } InternalUnsafeRefStack refStack; if (InternalUnsafeRefStack.RefStackPool.Count != 0) { refStack = InternalUnsafeRefStack.RefStackPool.Dequeue(); refStack.Reset(); } else { refStack = new InternalUnsafeRefStack(6); } return new Enumerator(origin.transform, withSelf, true, refStack, descendIntoChildren); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #region LINQ void ResizeArray(ref int index, ref T[] array) { if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } } void DescendantsCore(ref Transform transform, ref Action action) { if (!descendIntoChildren(transform)) return; var childCount = transform.childCount; for (int i = 0; i < childCount; i++) { var child = transform.GetChild(i); action(child.gameObject); DescendantsCore(ref child, ref action); } } void DescendantsCore(ref Transform transform, ref int index, ref GameObject[] array) { if (!descendIntoChildren(transform)) return; var childCount = transform.childCount; for (int i = 0; i < childCount; i++) { var child = transform.GetChild(i); ResizeArray(ref index, ref array); array[index++] = child.gameObject; DescendantsCore(ref child, ref index, ref array); } } void DescendantsCore(ref Func filter, ref Transform transform, ref int index, ref GameObject[] array) { if (!descendIntoChildren(transform)) return; var childCount = transform.childCount; for (int i = 0; i < childCount; i++) { var child = transform.GetChild(i); var childGameObject = child.gameObject; if (filter(childGameObject)) { ResizeArray(ref index, ref array); array[index++] = childGameObject; } DescendantsCore(ref filter, ref child, ref index, ref array); } } void DescendantsCore(ref Func selector, ref Transform transform, ref int index, ref T[] array) { if (!descendIntoChildren(transform)) return; var childCount = transform.childCount; for (int i = 0; i < childCount; i++) { var child = transform.GetChild(i); ResizeArray(ref index, ref array); array[index++] = selector(child.gameObject); DescendantsCore(ref selector, ref child, ref index, ref array); } } void DescendantsCore(ref Func filter, ref Func selector, ref Transform transform, ref int index, ref T[] array) { if (!descendIntoChildren(transform)) return; var childCount = transform.childCount; for (int i = 0; i < childCount; i++) { var child = transform.GetChild(i); var childGameObject = child.gameObject; if (filter(childGameObject)) { ResizeArray(ref index, ref array); array[index++] = selector(childGameObject); } DescendantsCore(ref filter, ref selector, ref child, ref index, ref array); } } void DescendantsCore(ref Func let, ref Func filter, ref Func selector, ref Transform transform, ref int index, ref T[] array) { if (!descendIntoChildren(transform)) return; var childCount = transform.childCount; for (int i = 0; i < childCount; i++) { var child = transform.GetChild(i); var state = let(child.gameObject); if (filter(state)) { ResizeArray(ref index, ref array); array[index++] = selector(state); } DescendantsCore(ref let, ref filter, ref selector, ref child, ref index, ref array); } } /// ¼º´É ÃÖÀûÈ­¸¦ À§ÇØ ³»ºÎ ¹Ýº¹±â¸¦ »ç¿ëÇÕ´Ï´Ù. /// public void ForEach(Action action) { if (withSelf) { action(origin); } var originTransform = origin.transform; DescendantsCore(ref originTransform, ref action); } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(ref GameObject[] array) { var index = 0; if (withSelf) { ResizeArray(ref index, ref array); array[index++] = origin; } var originTransform = origin.transform; DescendantsCore(ref originTransform, ref index, ref array); return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func filter, ref GameObject[] array) { var index = 0; if (withSelf && filter(origin)) { ResizeArray(ref index, ref array); array[index++] = origin; } var originTransform = origin.transform; DescendantsCore(ref filter, ref originTransform, ref index, ref array); return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func selector, ref T[] array) { var index = 0; if (withSelf) { ResizeArray(ref index, ref array); array[index++] = selector(origin); } var originTransform = origin.transform; DescendantsCore(ref selector, ref originTransform, ref index, ref array); return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func filter, Func selector, ref T[] array) { var index = 0; if (withSelf && filter(origin)) { ResizeArray(ref index, ref array); array[index++] = selector(origin); } var originTransform = origin.transform; DescendantsCore(ref filter, ref selector, ref originTransform, ref index, ref array); return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func let, Func filter, Func selector, ref T[] array) { var index = 0; if (withSelf) { var state = let(origin); if (filter(state)) { ResizeArray(ref index, ref array); array[index++] = selector(state); } } var originTransform = origin.transform; DescendantsCore(ref let, ref filter, ref selector, ref originTransform, ref index, ref array); return index; } public GameObject[] ToArray() { var array = new GameObject[4]; var len = ToArrayNonAlloc(ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public GameObject[] ToArray(Func filter) { var array = new GameObject[4]; var len = ToArrayNonAlloc(filter, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func filter, Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(filter, selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func let, Func filter, Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(let, filter, selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public GameObject First() { var e = this.GetEnumerator(); try { if (e.MoveNext()) { return e.Current; } else { throw new InvalidOperationException("½ÃÄö½º°¡ ºñ¾î ÀÖ½À´Ï´Ù."); } } finally { e.Dispose(); } } public GameObject FirstOrDefault() { var e = this.GetEnumerator(); try { return (e.MoveNext()) ? e.Current : null; } finally { e.Dispose(); } } #endregion internal class InternalUnsafeRefStack { public static Queue RefStackPool = new Queue(); public int size = 0; public Enumerator[] array; // Pop = this.array[--size]; public InternalUnsafeRefStack(int initialStackDepth) { array = new GameObjectExtensions.DescendantsEnumerable.Enumerator[initialStackDepth]; } public void Push(ref Enumerator e) { if (size == array.Length) { Array.Resize(ref array, array.Length * 2); } array[size++] = e; } public void Reset() { size = 0; } } public struct Enumerator : IEnumerator { readonly int childCount; // childCount´Â GetEnumerator°¡ È£ÃâµÉ ¶§ °íÁ¤µË´Ï´Ù. readonly Transform originTransform; bool canRun; bool withSelf; int currentIndex; GameObject current; InternalUnsafeRefStack sharedStack; Func descendIntoChildren; internal Enumerator(Transform originTransform, bool withSelf, bool canRun, InternalUnsafeRefStack sharedStack, Func descendIntoChildren) { this.originTransform = originTransform; this.withSelf = withSelf; this.childCount = canRun ? originTransform.childCount : 0; this.currentIndex = -1; this.canRun = canRun; this.current = null; this.sharedStack = sharedStack; this.descendIntoChildren = descendIntoChildren; } public bool MoveNext() { if (!canRun) return false; while (sharedStack.size != 0) { if (sharedStack.array[sharedStack.size - 1].MoveNextCore(true, out current)) { return true; } } if (!withSelf && !descendIntoChildren(originTransform)) { // Àç»ç¿ë canRun = false; InternalUnsafeRefStack.RefStackPool.Enqueue(sharedStack); return false; } if (MoveNextCore(false, out current)) { return true; } else { // Àç»ç¿ë canRun = false; InternalUnsafeRefStack.RefStackPool.Enqueue(sharedStack); return false; } } bool MoveNextCore(bool peek, out GameObject current) { if (withSelf) { current = originTransform.gameObject; withSelf = false; return true; } ++currentIndex; if (currentIndex < childCount) { var item = originTransform.GetChild(currentIndex); if (descendIntoChildren(item)) { var childEnumerator = new Enumerator(item, true, true, sharedStack, descendIntoChildren); sharedStack.Push(ref childEnumerator); return sharedStack.array[sharedStack.size - 1].MoveNextCore(true, out current); } else { current = item.gameObject; return true; } } if (peek) { sharedStack.size--; // Pop } current = null; return false; } public GameObject Current { get { return current; } } object IEnumerator.Current { get { return current; } } public void Dispose() { if (canRun) { canRun = false; InternalUnsafeRefStack.RefStackPool.Enqueue(sharedStack); } } public void Reset() { throw new NotSupportedException(); } } public struct OfComponentEnumerable : IEnumerable where T : Component { DescendantsEnumerable parent; public OfComponentEnumerable(ref DescendantsEnumerable parent) { this.parent = parent; } public OfComponentEnumerator GetEnumerator() { return new OfComponentEnumerator(ref parent); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #region LINQ public T First() { var e = this.GetEnumerator(); try { if (e.MoveNext()) { return e.Current; } else { throw new InvalidOperationException("½ÃÄö½º°¡ ºñ¾î ÀÖ½À´Ï´Ù."); } } finally { e.Dispose(); } } public T FirstOrDefault() { var e = this.GetEnumerator(); try { return (e.MoveNext()) ? e.Current : null; } finally { e.Dispose(); } } /// ¼º´É ÃÖÀûÈ­¸¦ À§ÇØ ³»ºÎ ¹Ýº¹±â¸¦ »ç¿ëÇÕ´Ï´Ù. public void ForEach(Action action) { if (parent.withSelf) { T component = default(T); #if UNITY_EDITOR parent.origin.GetComponents(componentCache); if (componentCache.Count != 0) { component = componentCache[0]; componentCache.Clear(); } #else component = parent.origin.GetComponent(); #endif if (component != null) { action(component); } } var originTransform = parent.origin.transform; OfComponentDescendantsCore(ref originTransform, ref action); } public T[] ToArray() { var array = new T[4]; var len = ToArrayNonAlloc(ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } #if UNITY_EDITOR static List componentCache = new List(); // UNITY_EDITOR¿¡¼­ ÇÒ´ç ¾øÀ½À» À§ÇÔ #endif void OfComponentDescendantsCore(ref Transform transform, ref Action action) { if (!parent.descendIntoChildren(transform)) return; var childCount = transform.childCount; for (int i = 0; i < childCount; i++) { var child = transform.GetChild(i); T component = default(T); #if UNITY_EDITOR child.GetComponents(componentCache); if (componentCache.Count != 0) { component = componentCache[0]; componentCache.Clear(); } #else component = child.GetComponent(); #endif if (component != null) { action(component); } OfComponentDescendantsCore(ref child, ref action); } } void OfComponentDescendantsCore(ref Transform transform, ref int index, ref T[] array) { if (!parent.descendIntoChildren(transform)) return; var childCount = transform.childCount; for (int i = 0; i < childCount; i++) { var child = transform.GetChild(i); T component = default(T); #if UNITY_EDITOR child.GetComponents(componentCache); if (componentCache.Count != 0) { component = componentCache[0]; componentCache.Clear(); } #else component = child.GetComponent(); #endif if (component != null) { if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = component; } OfComponentDescendantsCore(ref child, ref index, ref array); } } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(ref T[] array) { var index = 0; if (parent.withSelf) { T component = default(T); #if UNITY_EDITOR parent.origin.GetComponents(componentCache); if (componentCache.Count != 0) { component = componentCache[0]; componentCache.Clear(); } #else component = parent.origin.GetComponent(); #endif if (component != null) { if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = component; } } var originTransform = parent.origin.transform; OfComponentDescendantsCore(ref originTransform, ref index, ref array); return index; } #endregion } public struct OfComponentEnumerator : IEnumerator where T : Component { Enumerator enumerator; // ¿­°ÅÀÚ´Â º¯°æ °¡´ÉÇÕ´Ï´Ù. T current; #if UNITY_EDITOR static List componentCache = new List(); // UNITY_EDITOR¿¡¼­ ÇÒ´ç ¾øÀ½À» À§ÇÔ #endif public OfComponentEnumerator(ref DescendantsEnumerable parent) { this.enumerator = parent.GetEnumerator(); this.current = default(T); } public bool MoveNext() { while (enumerator.MoveNext()) { #if UNITY_EDITOR enumerator.Current.GetComponents(componentCache); if (componentCache.Count != 0) { current = componentCache[0]; componentCache.Clear(); return true; } #else var component = enumerator.Current.GetComponent(); if (component != null) { current = component; return true; } #endif } return false; } public T Current { get { return current; } } object IEnumerator.Current { get { return current; } } public void Dispose() { enumerator.Dispose(); } public void Reset() { throw new NotSupportedException(); } } } public struct BeforeSelfEnumerable : IEnumerable { readonly GameObject origin; readonly bool withSelf; public BeforeSelfEnumerable(GameObject origin, bool withSelf) { this.origin = origin; this.withSelf = withSelf; } /// ¼Ò½º Ä÷º¼Ç¿¡¼­ ÁöÁ¤µÈ ÄÄÆ÷³ÍÆ®ÀÇ Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public OfComponentEnumerable OfComponent() where T : Component { return new OfComponentEnumerable(ref this); } /// ¼Ò½º Ä÷º¼ÇÀÇ ¸ðµç GameObject¸¦ ¾ÈÀüÇϰÔ(null È®ÀÎ) ÆÄ±«ÇÕ´Ï´Ù. /// ¿¡µðÅÍ ¸ðµåÀÎ °æ¿ì trueÀ̰ųª !Application.isPlayingÀ» Àü´ÞÇØ¾ß ÇÕ´Ï´Ù. public void Destroy(bool useDestroyImmediate = false) { var e = GetEnumerator(); while (e.MoveNext()) { e.Current.Destroy(useDestroyImmediate, false); } } /// ¼Ò½º Ä÷º¼ÇÀÇ ¸ðµç GameObject¸¦ ¾ÈÀüÇϰÔ(null È®ÀÎ) ÆÄ±«ÇÕ´Ï´Ù. /// ¿¡µðÅÍ ¸ðµåÀÎ °æ¿ì trueÀ̰ųª !Application.isPlayingÀ» Àü´ÞÇØ¾ß ÇÕ´Ï´Ù. public void Destroy(Func predicate, bool useDestroyImmediate = false) { var e = GetEnumerator(); while (e.MoveNext()) { var item = e.Current; if (predicate(item)) { item.Destroy(useDestroyImmediate, false); } } } public Enumerator GetEnumerator() { // GetEnumerator ½ÃÁ¡¿¡¸¸ GameObject°¡ ÆÄ±«µÇ¾ú´ÂÁö È®ÀÎÇÕ´Ï´Ù. return (origin == null) ? new Enumerator(null, withSelf, false) : new Enumerator(origin.transform, withSelf, true); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #region LINQ public void ForEach(Action action) { var e = this.GetEnumerator(); while (e.MoveNext()) { action(e.Current); } } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(ref GameObject[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = item; } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func filter, ref GameObject[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (!filter(item)) continue; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = item; } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(item); } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func filter, Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (!filter(item)) continue; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(item); } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func let, Func filter, Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; var state = let(item); if (!filter(state)) continue; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(state); } return index; } public GameObject[] ToArray() { var array = new GameObject[4]; var len = ToArrayNonAlloc(ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public GameObject[] ToArray(Func filter) { var array = new GameObject[4]; var len = ToArrayNonAlloc(filter, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func filter, Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(filter, selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func let, Func filter, Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(let, filter, selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public GameObject First() { var e = this.GetEnumerator(); if (e.MoveNext()) { return e.Current; } else { throw new InvalidOperationException("½ÃÄö½º°¡ ºñ¾î ÀÖ½À´Ï´Ù."); } } public GameObject FirstOrDefault() { var e = this.GetEnumerator(); return (e.MoveNext()) ? e.Current : null; } #endregion public struct Enumerator : IEnumerator { readonly int childCount; // childCount´Â GetEnumerator°¡ È£ÃâµÉ ¶§ °íÁ¤µË´Ï´Ù. readonly Transform originTransform; bool canRun; bool withSelf; int currentIndex; GameObject current; Transform parent; internal Enumerator(Transform originTransform, bool withSelf, bool canRun) { this.originTransform = originTransform; this.withSelf = withSelf; this.currentIndex = -1; this.canRun = canRun; this.current = null; this.parent = originTransform.parent; this.childCount = (parent != null) ? parent.childCount : 0; } public bool MoveNext() { if (!canRun) return false; if (parent == null) goto RETURN_SELF; currentIndex++; if (currentIndex < childCount) { var item = parent.GetChild(currentIndex); if (item == originTransform) { goto RETURN_SELF; } current = item.gameObject; return true; } RETURN_SELF: if (withSelf) { current = originTransform.gameObject; withSelf = false; canRun = false; // Àڽſ¡°Ô µµ´ÞÇßÀ¸¹Ç·Î ½ÇÇà ¿Ï·á. return true; } return false; } public GameObject Current { get { return current; } } object IEnumerator.Current { get { return current; } } public void Dispose() { } public void Reset() { throw new NotSupportedException(); } } public struct OfComponentEnumerable : IEnumerable where T : Component { BeforeSelfEnumerable parent; public OfComponentEnumerable(ref BeforeSelfEnumerable parent) { this.parent = parent; } public OfComponentEnumerator GetEnumerator() { return new OfComponentEnumerator(ref parent); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #region LINQ public void ForEach(Action action) { var e = this.GetEnumerator(); while (e.MoveNext()) { action(e.Current); } } public T First() { var e = this.GetEnumerator(); if (e.MoveNext()) { return e.Current; } else { throw new InvalidOperationException("½ÃÄö½º°¡ ºñ¾î ÀÖ½À´Ï´Ù."); } } public T FirstOrDefault() { var e = this.GetEnumerator(); return (e.MoveNext()) ? e.Current : null; } public T[] ToArray() { var array = new T[4]; var len = ToArrayNonAlloc(ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(ref T[] array) { var index = 0; var e = this.GetEnumerator(); while (e.MoveNext()) { if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = e.Current; } return index; } #endregion } public struct OfComponentEnumerator : IEnumerator where T : Component { Enumerator enumerator; // ¿­°ÅÀÚ´Â º¯°æ °¡´ÉÇÕ´Ï´Ù. T current; #if UNITY_EDITOR static List componentCache = new List(); // UNITY_EDITOR¿¡¼­ ÇÒ´ç ¾øÀ½À» À§ÇÔ #endif public OfComponentEnumerator(ref BeforeSelfEnumerable parent) { this.enumerator = parent.GetEnumerator(); this.current = default(T); } public bool MoveNext() { while (enumerator.MoveNext()) { #if UNITY_EDITOR enumerator.Current.GetComponents(componentCache); if (componentCache.Count != 0) { current = componentCache[0]; componentCache.Clear(); return true; } #else var component = enumerator.Current.GetComponent(); if (component != null) { current = component; return true; } #endif } return false; } public T Current { get { return current; } } object IEnumerator.Current { get { return current; } } public void Dispose() { } public void Reset() { throw new NotSupportedException(); } } } public struct AfterSelfEnumerable : IEnumerable { readonly GameObject origin; readonly bool withSelf; public AfterSelfEnumerable(GameObject origin, bool withSelf) { this.origin = origin; this.withSelf = withSelf; } /// ¼Ò½º Ä÷º¼Ç¿¡¼­ ÁöÁ¤µÈ ÄÄÆ÷³ÍÆ®ÀÇ Ä÷º¼ÇÀ» ¹ÝȯÇÕ´Ï´Ù. public OfComponentEnumerable OfComponent() where T : Component { return new OfComponentEnumerable(ref this); } /// ¼Ò½º Ä÷º¼ÇÀÇ ¸ðµç GameObject¸¦ ¾ÈÀüÇϰÔ(null È®ÀÎ) ÆÄ±«ÇÕ´Ï´Ù. /// ¿¡µðÅÍ ¸ðµåÀÎ °æ¿ì trueÀ̰ųª !Application.isPlayingÀ» Àü´ÞÇØ¾ß ÇÕ´Ï´Ù. public void Destroy(bool useDestroyImmediate = false) { var e = GetEnumerator(); while (e.MoveNext()) { e.Current.Destroy(useDestroyImmediate, false); } } /// ¼Ò½º Ä÷º¼ÇÀÇ ¸ðµç GameObject¸¦ ¾ÈÀüÇϰÔ(null È®ÀÎ) ÆÄ±«ÇÕ´Ï´Ù. /// ¿¡µðÅÍ ¸ðµåÀÎ °æ¿ì trueÀ̰ųª !Application.isPlayingÀ» Àü´ÞÇØ¾ß ÇÕ´Ï´Ù. public void Destroy(Func predicate, bool useDestroyImmediate = false) { var e = GetEnumerator(); while (e.MoveNext()) { var item = e.Current; if (predicate(item)) { item.Destroy(useDestroyImmediate, false); } } } public Enumerator GetEnumerator() { // GetEnumerator ½ÃÁ¡¿¡¸¸ GameObject°¡ ÆÄ±«µÇ¾ú´ÂÁö È®ÀÎÇÕ´Ï´Ù. return (origin == null) ? new Enumerator(null, withSelf, false) : new Enumerator(origin.transform, withSelf, true); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #region LINQ public void ForEach(Action action) { var e = this.GetEnumerator(); while (e.MoveNext()) { action(e.Current); } } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(ref GameObject[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = item; } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func filter, ref GameObject[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (!filter(item)) continue; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = item; } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(item); } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func filter, Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; if (!filter(item)) continue; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(item); } return index; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(Func let, Func filter, Func selector, ref T[] array) { var index = 0; var e = this.GetEnumerator(); // Dispose¸¦ È£ÃâÇÒ Çʿ䰡 ¾ø½À´Ï´Ù. while (e.MoveNext()) { var item = e.Current; var state = let(item); if (!filter(state)) continue; if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = selector(state); } return index; } public GameObject[] ToArray() { var array = new GameObject[4]; var len = ToArrayNonAlloc(ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public GameObject[] ToArray(Func filter) { var array = new GameObject[4]; var len = ToArrayNonAlloc(filter, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func filter, Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(filter, selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public T[] ToArray(Func let, Func filter, Func selector) { var array = new T[4]; var len = ToArrayNonAlloc(let, filter, selector, ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } public GameObject First() { var e = this.GetEnumerator(); if (e.MoveNext()) { return e.Current; } else { throw new InvalidOperationException("½ÃÄö½º°¡ ºñ¾î ÀÖ½À´Ï´Ù."); } } public GameObject FirstOrDefault() { var e = this.GetEnumerator(); return (e.MoveNext()) ? e.Current : null; } #endregion public struct Enumerator : IEnumerator { readonly int childCount; // childCount´Â GetEnumerator°¡ È£ÃâµÉ ¶§ °íÁ¤µË´Ï´Ù. readonly Transform originTransform; readonly bool canRun; bool withSelf; int currentIndex; GameObject current; Transform parent; internal Enumerator(Transform originTransform, bool withSelf, bool canRun) { this.originTransform = originTransform; this.withSelf = withSelf; this.currentIndex = (originTransform != null) ? originTransform.GetSiblingIndex() + 1 : 0; this.canRun = canRun; this.current = null; this.parent = originTransform.parent; this.childCount = (parent != null) ? parent.childCount : 0; } public bool MoveNext() { if (!canRun) return false; if (withSelf) { current = originTransform.gameObject; withSelf = false; return true; } if (currentIndex < childCount) { current = parent.GetChild(currentIndex).gameObject; currentIndex++; return true; } return false; } public GameObject Current { get { return current; } } object IEnumerator.Current { get { return current; } } public void Dispose() { } public void Reset() { throw new NotSupportedException(); } } public struct OfComponentEnumerable : IEnumerable where T : Component { AfterSelfEnumerable parent; public OfComponentEnumerable(ref AfterSelfEnumerable parent) { this.parent = parent; } public OfComponentEnumerator GetEnumerator() { return new OfComponentEnumerator(ref this.parent); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #region LINQ public void ForEach(Action action) { var e = this.GetEnumerator(); while (e.MoveNext()) { action(e.Current); } } public T First() { var e = this.GetEnumerator(); if (e.MoveNext()) { return e.Current; } else { throw new InvalidOperationException("½ÃÄö½º°¡ ºñ¾î ÀÖ½À´Ï´Ù."); } } public T FirstOrDefault() { var e = this.GetEnumerator(); return (e.MoveNext()) ? e.Current : null; } public T[] ToArray() { var array = new T[4]; var len = ToArrayNonAlloc(ref array); if (array.Length != len) { Array.Resize(ref array, len); } return array; } /// ¿ä¼Ò¸¦ ¹öÆÛ¿¡ ÀúÀåÇϰí Å©±â¸¦ ¹ÝȯÇÕ´Ï´Ù. ¹è¿­Àº ÀÚµ¿À¸·Î È®ÀåµË´Ï´Ù. public int ToArrayNonAlloc(ref T[] array) { var index = 0; var e = this.GetEnumerator(); while (e.MoveNext()) { if (array.Length == index) { var newSize = (index == 0) ? 4 : index * 2; Array.Resize(ref array, newSize); } array[index++] = e.Current; } return index; } #endregion } public struct OfComponentEnumerator : IEnumerator where T : Component { Enumerator enumerator; // ¿­°ÅÀÚ´Â º¯°æ °¡´ÉÇÕ´Ï´Ù. T current; #if UNITY_EDITOR static List componentCache = new List(); // UNITY_EDITOR¿¡¼­ ÇÒ´ç ¾øÀ½À» À§ÇÔ #endif public OfComponentEnumerator(ref AfterSelfEnumerable parent) { this.enumerator = parent.GetEnumerator(); this.current = default(T); } public bool MoveNext() { while (enumerator.MoveNext()) { #if UNITY_EDITOR enumerator.Current.GetComponents(componentCache); if (componentCache.Count != 0) { current = componentCache[0]; componentCache.Clear(); return true; } #else var component = enumerator.Current.GetComponent(); if (component != null) { current = component; return true; } #endif } return false; } public T Current { get { return current; } } object IEnumerator.Current { get { return current; } } public void Dispose() { } public void Reset() { throw new NotSupportedException(); } } } } }