using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.PlayerLoop; using XRLib; namespace Studio.Hierarchy { public class HierarchyTree { public event Action onAddEvent; public event Action onSelectEvent; public event Action onRemoveEvent; public event Action onDeselectEvent; public event Action> onDataUpdate; HashSet tempHashSet = new(); HashSet rootObjects = new(); List data = new List(); Dictionary twinToItem = new Dictionary(); TreeItem CreateItem(TwinObject to) { TreeItem item = new TreeItem(to); data.Add(item); twinToItem.Add(to, item); return item; } public bool isExist(TwinObject to) { return rootObjects.Contains(to); } public void Add(TwinObject to) { if (!rootObjects.Add(to)) return; var item = CreateItem(to); onAddEvent?.Invoke(item); } public void Remove(TwinObject to) { if (!rootObjects.Contains(to)) { return; } GetChilds(twinToItem[to]); foreach (var item in tempHashSet) { rootObjects.Remove(item.ToItem); item.parent?.RemoveChild(item); onRemoveEvent?.Invoke(item.ToItem); item.DestroyTreeItem(); data.Remove(item); twinToItem.Remove(item.ToItem); GameObject.Destroy(item.ToItem.gameObject); } tempHashSet.Clear(); onDataUpdate(data); } void GetChilds(TreeItem go) { tempHashSet.Add(go); foreach (var c in go.children) { GetChilds(c); } } public void Attach(TreeItem p, TreeItem t) { if (!data.Contains(p)) { Debug.LogError("Parent not found"); return; } if (!data.Contains(t)) { Debug.LogError("Child not found"); return; } if (p == t) { return; } GetChilds(t); foreach (var item in tempHashSet) { if (p.parent == item) { Debug.LogError("It is infinite"); tempHashSet.Clear(); return; } } t.parent?.RemoveChild(t); p.Add(t); t.parent = p; data.Remove(t); var index = data.IndexOf(p) + 1; if (index >= data.Count) { if (tempHashSet.Count > 1) { foreach (var item in tempHashSet) { data?.Remove(item); data.Add(item); } } else { data.Add(t); } } else { int i = 0; if (tempHashSet.Count > 1) { foreach (var item in tempHashSet) { data?.Remove(item); data.Insert(index + i, item); i++; } } else { data.Insert(index, t); } } tempHashSet.Clear(); onDataUpdate(data); } public void Dettach(TreeItem item) { if (!data.Contains(item)) { Debug.LogError("Not found"); return; } item.parent?.RemoveChild(item); item.parent = null; GetChilds(item); foreach (var i in tempHashSet) { data?.Remove(i); data.Add(i); } tempHashSet.Clear(); onDataUpdate(data); } internal void Select(TwinObject to) { onSelectEvent?.Invoke(twinToItem[to]); } public void Select(TreeItem ti) { onSelectEvent?.Invoke(ti); } internal void Deselect(TwinObject to) { onDeselectEvent?.Invoke(twinToItem[to]); } } }