Last active
January 13, 2021 01:56
-
-
Save techanon/379e22c964118f044974c7bb38e6ada4 to your computer and use it in GitHub Desktop.
Type-agnostic transform depth-search algorithm for any component within Udon, just change 'MyComponent' the type you are looking for.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UdonSharp; | |
using UnityEngine; | |
using VRC.SDKBase; | |
using VRC.Udon; | |
public class GetMyComponents : UdonSharpBehaviour | |
{ | |
public GameObject[] roots; | |
[HideInInspector] public MyComponent[] comps; | |
void Start() { | |
var i = 0; | |
var _comps = traverseAllFor(typeof(MyComponent), roots); | |
// traverse methods always return Component[], loop and cast. | |
comps = new MyComponent[_comps.Length]; | |
for (i = 0; i < _comps.Length; i++) { | |
comps[i] = (MyComponent) _comps[i]; | |
} | |
// additional initialization here | |
} | |
// Your other stuff for the class can go here | |
private Component[] traverseAllFor(System.Type T, GameObject[] objects) | |
{ | |
var elements = new Component[objects.Length]; | |
var index = 0; | |
log("Searching nodes for " + T); | |
foreach (GameObject obj in objects) | |
{ | |
if (obj == null) continue; | |
log("Traversing node " + obj.name); | |
Component[] found = traverseFor(T, obj.transform); | |
foreach (Component element in found) | |
{ | |
if (element == null) continue; | |
// check if next index exceeds bounds, expand if so | |
if (index >= elements.Length) | |
elements = expand(elements, 16); | |
elements[index] = element; | |
index++; | |
} | |
} | |
// remove excess nulls | |
var clean = new Component[index]; | |
for (int i = 0; i < clean.Length; i++) { | |
clean[i] = elements[i]; | |
} | |
elements = clean; | |
log("Total found: " + elements.Length); | |
return elements; | |
} | |
private Component[] traverseFor(System.Type T, Transform root) | |
{ | |
Component[] elements = new Component[16]; | |
Component[] stack = new Component[16]; | |
stack[0] = root; | |
var found = 0; | |
while (stack[0] != null) | |
{ | |
var cur = (Transform)pop(stack); | |
// log("Gathering elements within node " + cur.name); | |
if (cur != null) | |
{ | |
var t = cur.GetComponent(T); | |
if (t != null) | |
{ | |
found++; | |
elements = push(elements, t); | |
} | |
// add all children to stack in reverse order | |
for (int i = cur.childCount - 1; i >= 0; i--) | |
stack = push(stack, cur.GetChild(i)); | |
} | |
} | |
if (found > 0) log("Found " + found + " matching component(s)"); | |
return elements; | |
} | |
private Component[] push(Component[] stack, Component n) | |
{ | |
var added = false; | |
for (int i = 0; i < stack.Length; i++) | |
{ | |
if (stack[i] == null) | |
{ | |
stack[i] = n; | |
added = true; | |
break; | |
} | |
} | |
// unable to add due to stackoverflow, expand stack and retry | |
if (!added) | |
{ | |
stack = expand(stack, 16); | |
for (int i = 0; i < stack.Length; i++) | |
{ | |
if (stack[i] == null) | |
{ | |
stack[i] = n; | |
added = true; | |
break; | |
} | |
} | |
} | |
return stack; | |
} | |
private Component pop(Component[] stack) | |
{ | |
// find first non-null entry in the stack, remove and return. | |
var last = -1; | |
for (int i = 0; i < stack.Length; i++) | |
{ | |
var item = stack[i]; | |
if (item != null) last = i; | |
if (item == null) break; | |
} | |
if (last == -1) return null; | |
var t = stack[last]; | |
stack[last] = null; | |
return t; | |
} | |
private Component[] expand(Component[] arr, int add) | |
{ | |
// expand beyond size of self if children are found | |
var newArray = new Component[arr.Length + add]; | |
var index = 0; | |
for (int i = 0; i < arr.Length; i++) | |
{ | |
if (arr[i] == null) continue; | |
newArray[index] = arr[i]; | |
index++; | |
} | |
return newArray; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment