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(); }
}
}
}
}