180 lines
4.7 KiB
C#
180 lines
4.7 KiB
C#
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<TreeItem> onAddEvent;
|
|
public event Action<TreeItem> onSelectEvent;
|
|
public event Action<TwinObject> onRemoveEvent;
|
|
public event Action<TreeItem> onDeselectEvent;
|
|
public event Action<List<TreeItem>> onDataUpdate;
|
|
|
|
HashSet<TreeItem> tempHashSet = new();
|
|
|
|
HashSet<TwinObject> rootObjects = new();
|
|
List<TreeItem> data = new List<TreeItem>();
|
|
Dictionary<TwinObject, TreeItem> twinToItem = new Dictionary<TwinObject, TreeItem>();
|
|
|
|
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]);
|
|
}
|
|
}
|
|
}
|