apply formatting

This commit is contained in:
2024-12-11 07:29:30 +03:00
parent 00fec5e053
commit 44bb459c1b
54 changed files with 2326 additions and 1558 deletions

View File

@@ -5,136 +5,156 @@ using Engine.Util;
namespace Engine.Scene;
public class Hierarchy<T> : IEnumerable<T>
where T : class
where T : class
{
private readonly Dictionary<NullableObject<T>, IList<T>> _childrenLookup = new();
private readonly Dictionary<T, T?> _parentLookup = new();
private readonly Dictionary<NullableObject<T>, IList<T>> _childrenLookup = new();
private readonly Dictionary<T, T?> _parentLookup = new();
private readonly ConcurrentQueue<Action> _hierarchyActions = new();
private readonly ConcurrentQueue<Action> _hierarchyActions = new();
public Hierarchy()
public Hierarchy()
{
_childrenLookup.Add(new NullableObject<T>(), new List<T>());
}
internal void ProcessChanges()
{
while (_hierarchyActions.TryDequeue(out var action))
{
_childrenLookup.Add(new NullableObject<T>(), new List<T>());
action();
}
}
public void Add(T parObj)
{
_hierarchyActions.Enqueue(() =>
{
if (_parentLookup.ContainsKey(parObj))
{
throw new ArgumentException("Object is already added to hierarchy");
}
_childrenLookup.Add(parObj, new List<T>());
_parentLookup.Add(parObj, null);
_childrenLookup[null].Add(parObj);
});
}
public void Remove(T parObj)
{
foreach (var child in GetChildren(parObj))
{
Remove(child);
}
internal void ProcessChanges()
_hierarchyActions.Enqueue(() =>
{
while (_hierarchyActions.TryDequeue(out var action))
action();
var parent = GetParent(parObj);
_childrenLookup[parent].Remove(parObj);
_parentLookup.Remove(parObj);
_childrenLookup.Remove(parObj);
});
}
public void AddChild(T parEnt, T parChild)
{
SetParent(parChild, parEnt);
}
private void SetParent(T parChild, T? parEnt)
{
if (parChild.Equals(parEnt))
{
throw new InvalidOperationException("Child cannot be parent");
}
public void Add(T obj)
_hierarchyActions.Enqueue(() =>
{
_hierarchyActions.Enqueue(() =>
{
if (_parentLookup.ContainsKey(obj))
throw new ArgumentException("Object is already added to hierarchy");
if (IsInHierarchy(parChild, parEnt))
{
throw new InvalidOperationException("Parent is a child of child");
}
_childrenLookup.Add(obj, new List<T>());
_parentLookup.Add(obj, null);
_childrenLookup[null].Add(obj);
});
var oldParent = GetParent(parChild);
_childrenLookup[oldParent].Remove(parChild);
_childrenLookup[parEnt].Add(parChild);
_parentLookup[parChild] = parEnt;
});
}
public bool Contains(T parObj)
{
return _parentLookup.ContainsKey(parObj) && _childrenLookup.ContainsKey(parObj);
}
public T? GetParent(T parChild)
{
return _parentLookup.TryGetValue(parChild, out var parent)
? parent
: throw new InvalidOperationException($"Child {parChild} is not in hierarchy");
}
public IEnumerable<T> GetChildren(T? parObj = null)
{
return _childrenLookup.TryGetValue(parObj, out IList<T>? children) ? children : Enumerable.Empty<T>();
}
public bool IsInHierarchy(T? parAncestor, T? parChild)
{
if (parChild == null) // if child is null (root), then it is not in hierarchy, as root can not have a parent
{
return false;
}
public void Remove(T obj)
if (parAncestor == null) // if ancestor is null (root), then child is not in hierarchy, as root is not a parent
{
foreach (var child in GetChildren(obj))
Remove(child);
_hierarchyActions.Enqueue(() =>
{
var parent = GetParent(obj);
_childrenLookup[parent].Remove(obj);
_parentLookup.Remove(obj);
_childrenLookup.Remove(obj);
});
return false;
}
public void AddChild(T parent, T child)
if (parAncestor.Equals(parChild))
{
SetParent(child, parent);
return true;
}
private void SetParent(T child, T? parent)
var parent = GetParent(parChild);
if (parent == null)
{
if (child.Equals(parent))
throw new InvalidOperationException("Child cannot be parent");
_hierarchyActions.Enqueue(() =>
{
if (IsInHierarchy(child, parent))
throw new InvalidOperationException("Parent is a child of child");
var oldParent = GetParent(child);
_childrenLookup[oldParent].Remove(child);
_childrenLookup[parent].Add(child);
_parentLookup[child] = parent;
});
return false;
}
public bool Contains(T obj)
if (parAncestor.Equals(parent))
{
return _parentLookup.ContainsKey(obj) && _childrenLookup.ContainsKey(obj);
return true;
}
public T? GetParent(T child)
return IsInHierarchy(parAncestor, parent);
}
public IEnumerable<T> GetAllChildren(T? parObj = null)
{
IEnumerable<T>? children = GetChildren(parObj);
foreach (var child in children)
{
return _parentLookup.TryGetValue(child, out var parent)
? parent
: throw new InvalidOperationException($"Child {child} is not in hierarchy");
yield return child;
foreach (var descendant in GetAllChildren(child))
{
yield return descendant;
}
}
}
public IEnumerable<T> GetChildren(T? obj = null)
{
return _childrenLookup.TryGetValue(obj, out var children) ? children : Enumerable.Empty<T>();
}
public IEnumerator<T> GetEnumerator()
{
return _parentLookup.Keys.GetEnumerator();
}
public bool IsInHierarchy(T? ancestor, T? child)
{
if (child == null) // if child is null (root), then it is not in hierarchy, as root can not have a parent
return false;
if (ancestor == null) // if ancestor is null (root), then child is not in hierarchy, as root is not a parent
return false;
if (ancestor.Equals(child))
return true;
var parent = GetParent(child);
if (parent == null)
return false;
if (ancestor.Equals(parent))
return true;
return IsInHierarchy(ancestor, parent);
}
public IEnumerable<T> GetAllChildren(T? obj = null)
{
var children = GetChildren(obj);
foreach (var child in children)
{
yield return child;
foreach (var descendant in GetAllChildren(child))
{
yield return descendant;
}
}
}
public IEnumerator<T> GetEnumerator()
{
return _parentLookup.Keys.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}