Compare commits
10 Commits
4c542df401
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
7c62440bba | |||
4bec7bce6e | |||
8d31372c24 | |||
a2e704916e | |||
c7d170fad9 | |||
9ccf7b754d | |||
e3d4899112 | |||
566c16d09c | |||
ae9d4f02ef | |||
e77772cbc2 |
@@ -1,67 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Engine.Core;
|
|
||||||
|
|
||||||
public class ActiveBehaviourCollectorSorted<T> : ActiveBehaviourCollector<T> where T : class, IBehaviour
|
|
||||||
{
|
|
||||||
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
|
||||||
|
|
||||||
private IComparer<T>? _sortBy = null;
|
|
||||||
public IComparer<T>? SortBy
|
|
||||||
{
|
|
||||||
get => _sortBy;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_sortBy = value;
|
|
||||||
|
|
||||||
if (value is not null)
|
|
||||||
activeBehaviours.Sort(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void AddBehaviour(T behaviour)
|
|
||||||
{
|
|
||||||
if (SortBy is null)
|
|
||||||
{
|
|
||||||
activeBehaviours.Add(behaviour);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int insertionIndex = activeBehaviours.BinarySearch(behaviour, SortBy);
|
|
||||||
|
|
||||||
if (insertionIndex < 0)
|
|
||||||
insertionIndex = ~insertionIndex;
|
|
||||||
|
|
||||||
activeBehaviours.Insert(insertionIndex, behaviour);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBehaviourAdd(IBehaviour behaviour)
|
|
||||||
{
|
|
||||||
behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBehaviourRemove(IBehaviour behaviour)
|
|
||||||
{
|
|
||||||
behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
|
||||||
{
|
|
||||||
T behaviour = (T)sender;
|
|
||||||
activeBehaviours.Remove(behaviour);
|
|
||||||
AddBehaviour(behaviour);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActiveBehaviourCollectorSorted()
|
|
||||||
{
|
|
||||||
delegateOnPriorityChanged = OnPriorityChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ActiveBehaviourCollectorSorted(IUniverse universe, Comparison<T> sortBy) : base(universe)
|
|
||||||
{
|
|
||||||
delegateOnPriorityChanged = OnPriorityChanged;
|
|
||||||
|
|
||||||
SortBy = Comparer<T>.Create(sortBy);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,67 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Engine.Core;
|
|
||||||
|
|
||||||
public class BehaviourCollectorSorted<T> : BehaviourCollector<T> where T : class
|
|
||||||
{
|
|
||||||
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
|
||||||
|
|
||||||
private IComparer<T>? _sortBy = null;
|
|
||||||
public IComparer<T>? SortBy
|
|
||||||
{
|
|
||||||
get => _sortBy;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_sortBy = value;
|
|
||||||
|
|
||||||
if (value is not null)
|
|
||||||
behaviours.Sort(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void AddBehaviour(T behaviour)
|
|
||||||
{
|
|
||||||
if (SortBy is null)
|
|
||||||
{
|
|
||||||
behaviours.Add(behaviour);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int insertionIndex = behaviours.BinarySearch(behaviour, SortBy);
|
|
||||||
|
|
||||||
if (insertionIndex < 0)
|
|
||||||
insertionIndex = ~insertionIndex;
|
|
||||||
|
|
||||||
behaviours.Insert(insertionIndex, behaviour);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBehaviourAdd(IBehaviour behaviour)
|
|
||||||
{
|
|
||||||
behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnBehaviourRemove(IBehaviour behaviour)
|
|
||||||
{
|
|
||||||
behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
|
||||||
{
|
|
||||||
T behaviour = (T)sender;
|
|
||||||
behaviours.Remove(behaviour);
|
|
||||||
AddBehaviour(behaviour);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BehaviourCollectorSorted()
|
|
||||||
{
|
|
||||||
delegateOnPriorityChanged = OnPriorityChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BehaviourCollectorSorted(IUniverse universe, Comparison<T> sortBy) : base(universe)
|
|
||||||
{
|
|
||||||
delegateOnPriorityChanged = OnPriorityChanged;
|
|
||||||
|
|
||||||
SortBy = Comparer<T>.Create(sortBy);
|
|
||||||
}
|
|
||||||
}
|
|
16
Engine.Core/Collectors/ActiveBehaviourCollector.cs
Normal file
16
Engine.Core/Collectors/ActiveBehaviourCollector.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
public class ActiveBehaviourCollector<T> : ActiveBehaviourCollectorBase<T> where T : class, IBehaviour
|
||||||
|
{
|
||||||
|
protected readonly FastList<T> activeBehaviours = new(32);
|
||||||
|
public override T this[Index index] => activeBehaviours[index];
|
||||||
|
public override int Count => activeBehaviours.Count;
|
||||||
|
|
||||||
|
public ActiveBehaviourCollector() { }
|
||||||
|
public ActiveBehaviourCollector(IUniverse universe) : base(universe) { }
|
||||||
|
|
||||||
|
protected override void AddBehaviour(T behaviour) => activeBehaviours.Add(behaviour);
|
||||||
|
protected override bool RemoveBehaviour(T tBehaviour) => activeBehaviours.Remove(tBehaviour);
|
||||||
|
}
|
@@ -3,12 +3,10 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : class, IBehaviour
|
public abstract class ActiveBehaviourCollectorBase<T> : IBehaviourCollector<T> where T : class, IBehaviour
|
||||||
{
|
{
|
||||||
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
|
protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = new(32);
|
||||||
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
|
protected readonly FastList<T> monitoringBehaviours = new(32);
|
||||||
public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
|
|
||||||
public Event<IAssignable>? OnUnassigned { get; } = new();
|
|
||||||
|
|
||||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
|
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
|
||||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
|
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
|
||||||
@@ -16,80 +14,16 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
|||||||
private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
|
private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
|
||||||
private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
|
private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
|
||||||
|
|
||||||
private readonly FastList<T> monitoringBehaviours = new(32);
|
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
|
||||||
protected readonly FastList<T> activeBehaviours = new(32);
|
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
|
||||||
protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = new(32);
|
public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
|
||||||
|
public Event<IAssignable>? OnUnassigned { get; } = new();
|
||||||
|
|
||||||
|
public abstract int Count { get; }
|
||||||
|
|
||||||
|
public abstract T this[Index index] { get; }
|
||||||
public IUniverse Universe { get; private set; } = null!;
|
public IUniverse Universe { get; private set; } = null!;
|
||||||
|
|
||||||
private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
|
|
||||||
{
|
|
||||||
IUniverseObject universeObject = args.UniverseObjectRegistered;
|
|
||||||
|
|
||||||
universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
|
|
||||||
universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
|
|
||||||
|
|
||||||
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
|
||||||
OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments args)
|
|
||||||
{
|
|
||||||
IUniverseObject universeObject = args.UniverseObjectUnregistered;
|
|
||||||
|
|
||||||
universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
|
|
||||||
universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
|
|
||||||
|
|
||||||
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
|
||||||
OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
|
||||||
private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
|
|
||||||
{
|
|
||||||
if (args.BehaviourAdded is not T tBehaviour)
|
|
||||||
return;
|
|
||||||
|
|
||||||
monitoringBehaviours.Add(tBehaviour);
|
|
||||||
monitoringActiveToBehaviour.Add(tBehaviour, tBehaviour);
|
|
||||||
tBehaviour.OnActiveChanged.AddListener(delegateOnBehaviourStateChanged);
|
|
||||||
OnBehaviourStateChanged(tBehaviour, new(!tBehaviour.IsActive));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void AddBehaviour(T behaviour) => activeBehaviours.Add(behaviour);
|
|
||||||
private void OnBehaviourStateChanged(IActive sender, IActive.ActiveChangedArguments args)
|
|
||||||
{
|
|
||||||
T behaviour = monitoringActiveToBehaviour[sender];
|
|
||||||
if (sender.IsActive)
|
|
||||||
{
|
|
||||||
AddBehaviour(behaviour);
|
|
||||||
OnBehaviourAdd(behaviour);
|
|
||||||
OnCollected?.Invoke(this, new(behaviour));
|
|
||||||
}
|
|
||||||
else if (activeBehaviours.Remove(behaviour))
|
|
||||||
{
|
|
||||||
OnBehaviourRemove(behaviour);
|
|
||||||
OnRemoved?.Invoke(this, new(behaviour));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
|
|
||||||
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
|
|
||||||
{
|
|
||||||
if (args.BehaviourRemoved is not T tBehaviour)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!monitoringBehaviours.Remove(tBehaviour) || !monitoringActiveToBehaviour.Remove(tBehaviour))
|
|
||||||
return;
|
|
||||||
|
|
||||||
tBehaviour.OnActiveChanged.RemoveListener(delegateOnBehaviourStateChanged);
|
|
||||||
if (activeBehaviours.Remove(tBehaviour))
|
|
||||||
{
|
|
||||||
OnBehaviourRemove(tBehaviour);
|
|
||||||
OnRemoved?.Invoke(this, new(tBehaviour));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Assign(IUniverse universe)
|
public bool Assign(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (Universe is not null)
|
if (Universe is not null)
|
||||||
@@ -123,10 +57,75 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Count => activeBehaviours.Count;
|
protected abstract void AddBehaviour(T behaviour);
|
||||||
public T this[Index index] => activeBehaviours[index];
|
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
||||||
|
private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
|
||||||
|
{
|
||||||
|
if (args.BehaviourAdded is not T tBehaviour)
|
||||||
|
return;
|
||||||
|
|
||||||
public ActiveBehaviourCollector()
|
monitoringBehaviours.Add(tBehaviour);
|
||||||
|
monitoringActiveToBehaviour.Add(tBehaviour, tBehaviour);
|
||||||
|
tBehaviour.OnActiveChanged.AddListener(delegateOnBehaviourStateChanged);
|
||||||
|
OnBehaviourStateChanged(tBehaviour, new(!tBehaviour.IsActive));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract bool RemoveBehaviour(T behaviour);
|
||||||
|
protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
|
||||||
|
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
|
||||||
|
{
|
||||||
|
if (args.BehaviourRemoved is not T tBehaviour)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!monitoringBehaviours.Remove(tBehaviour) || !monitoringActiveToBehaviour.Remove(tBehaviour))
|
||||||
|
return;
|
||||||
|
|
||||||
|
tBehaviour.OnActiveChanged.RemoveListener(delegateOnBehaviourStateChanged);
|
||||||
|
if (!RemoveBehaviour(tBehaviour))
|
||||||
|
return;
|
||||||
|
|
||||||
|
OnBehaviourRemove(tBehaviour);
|
||||||
|
OnRemoved?.Invoke(this, new(tBehaviour));
|
||||||
|
}
|
||||||
|
private void OnBehaviourStateChanged(IActive sender, IActive.ActiveChangedArguments args)
|
||||||
|
{
|
||||||
|
T behaviour = monitoringActiveToBehaviour[sender];
|
||||||
|
if (sender.IsActive)
|
||||||
|
{
|
||||||
|
AddBehaviour(behaviour);
|
||||||
|
OnBehaviourAdd(behaviour);
|
||||||
|
OnCollected?.Invoke(this, new(behaviour));
|
||||||
|
}
|
||||||
|
else if (RemoveBehaviour(behaviour))
|
||||||
|
{
|
||||||
|
OnBehaviourRemove(behaviour);
|
||||||
|
OnRemoved?.Invoke(this, new(behaviour));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
|
||||||
|
{
|
||||||
|
IUniverseObject universeObject = args.UniverseObjectRegistered;
|
||||||
|
|
||||||
|
universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
|
||||||
|
universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
|
||||||
|
|
||||||
|
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
||||||
|
OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments args)
|
||||||
|
{
|
||||||
|
IUniverseObject universeObject = args.UniverseObjectUnregistered;
|
||||||
|
|
||||||
|
universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
|
||||||
|
universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
|
||||||
|
|
||||||
|
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
||||||
|
OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveBehaviourCollectorBase()
|
||||||
{
|
{
|
||||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
||||||
@@ -135,7 +134,7 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
|||||||
delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
|
delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActiveBehaviourCollector(IUniverse universe)
|
public ActiveBehaviourCollectorBase(IUniverse universe)
|
||||||
{
|
{
|
||||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
104
Engine.Core/Collectors/ActiveBehaviourCollectorOrdered.cs
Normal file
104
Engine.Core/Collectors/ActiveBehaviourCollectorOrdered.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
public class ActiveBehaviourCollectorOrdered<TIndex, TItem> : ActiveBehaviourCollector<TItem> where TItem : class, IBehaviour where TIndex : IComparable
|
||||||
|
{
|
||||||
|
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
||||||
|
|
||||||
|
private readonly SortedDictionary<TIndex, FastList<TItem>> behaviours = null!;
|
||||||
|
|
||||||
|
private readonly Func<TItem, TIndex> getIndexFunc = null!;
|
||||||
|
private readonly IComparer<TIndex> sortBy = null!;
|
||||||
|
|
||||||
|
private int count = 0;
|
||||||
|
public override int Count => count;
|
||||||
|
|
||||||
|
public override TItem this[Index index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int actualIndex = index.IsFromEnd
|
||||||
|
? count - index.Value
|
||||||
|
: index.Value;
|
||||||
|
|
||||||
|
if (actualIndex < 0 || actualIndex >= count)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
|
||||||
|
int leftIndex = actualIndex;
|
||||||
|
foreach ((TIndex i, FastList<TItem> list) in behaviours)
|
||||||
|
{
|
||||||
|
if (leftIndex < list.Count)
|
||||||
|
return list[leftIndex];
|
||||||
|
leftIndex -= list.Count;
|
||||||
|
}
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool RemoveBehaviour(TItem tBehaviour)
|
||||||
|
{
|
||||||
|
TIndex index = getIndexFunc(tBehaviour);
|
||||||
|
if (!behaviours.TryGetValue(index, out FastList<TItem>? list))
|
||||||
|
throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector");
|
||||||
|
|
||||||
|
if (!list.Remove(tBehaviour))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
count--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AddBehaviour(TItem behaviour)
|
||||||
|
{
|
||||||
|
TIndex key = getIndexFunc(behaviour);
|
||||||
|
if (!behaviours.TryGetValue(key, out FastList<TItem>? list))
|
||||||
|
behaviours[key] = list = [];
|
||||||
|
|
||||||
|
count++;
|
||||||
|
list.Add(behaviour);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnBehaviourAdd(IBehaviour behaviour) => behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
||||||
|
protected override void OnBehaviourRemove(IBehaviour behaviour) => behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
||||||
|
|
||||||
|
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
||||||
|
{
|
||||||
|
TItem behaviour = (TItem)sender;
|
||||||
|
RemoveBehaviour(behaviour);
|
||||||
|
AddBehaviour(behaviour);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveBehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = Comparer<TIndex>.Create(sortBy);
|
||||||
|
behaviours = new(this.sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveBehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) : base(universe)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = Comparer<TIndex>.Create(sortBy);
|
||||||
|
behaviours = new(this.sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveBehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy)
|
||||||
|
{
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.sortBy = sortBy;
|
||||||
|
behaviours = new(sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActiveBehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) : base(universe)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = sortBy;
|
||||||
|
behaviours = new(sortBy);
|
||||||
|
}
|
||||||
|
}
|
17
Engine.Core/Collectors/BehaviourCollector.cs
Normal file
17
Engine.Core/Collectors/BehaviourCollector.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
public class BehaviourCollector<T> : BehaviourCollectorBase<T> where T : class
|
||||||
|
{
|
||||||
|
protected readonly FastList<T> behaviours = new(32);
|
||||||
|
|
||||||
|
public override T this[Index index] => behaviours[index];
|
||||||
|
public override int Count => behaviours.Count;
|
||||||
|
|
||||||
|
protected override void AddBehaviour(T behaviour) => behaviours.Add(behaviour);
|
||||||
|
protected override bool RemoveBehaviour(T tBehaviour) => behaviours.Remove(tBehaviour);
|
||||||
|
|
||||||
|
public BehaviourCollector() { }
|
||||||
|
public BehaviourCollector(IUniverse universe) : base(universe) { }
|
||||||
|
}
|
@@ -2,70 +2,24 @@ using System;
|
|||||||
|
|
||||||
namespace Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
public abstract class BehaviourCollectorBase<T> : IBehaviourCollector<T> where T : class
|
||||||
{
|
{
|
||||||
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
|
|
||||||
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
|
|
||||||
public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
|
|
||||||
public Event<IAssignable>? OnUnassigned { get; } = new();
|
|
||||||
|
|
||||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
|
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
|
||||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
|
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
|
||||||
private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
|
private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
|
||||||
private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
|
private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
|
||||||
|
|
||||||
protected readonly FastList<T> behaviours = new(32);
|
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
|
||||||
|
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
|
||||||
|
public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
|
||||||
|
public Event<IAssignable>? OnUnassigned { get; } = new();
|
||||||
|
|
||||||
public IUniverse Universe { get; private set; } = null!;
|
public IUniverse Universe { get; private set; } = null!;
|
||||||
|
|
||||||
private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
|
public abstract int Count { get; }
|
||||||
{
|
|
||||||
IUniverseObject universeObject = args.UniverseObjectRegistered;
|
|
||||||
|
|
||||||
universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
|
public abstract T this[Index index] { get; }
|
||||||
universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
|
|
||||||
|
|
||||||
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
|
||||||
OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments args)
|
|
||||||
{
|
|
||||||
IUniverseObject universeObject = args.UniverseObjectUnregistered;
|
|
||||||
|
|
||||||
universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
|
|
||||||
universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
|
|
||||||
|
|
||||||
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
|
||||||
OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void AddBehaviour(T behaviour) => behaviours.Add(behaviour);
|
|
||||||
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
|
||||||
private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
|
|
||||||
{
|
|
||||||
if (args.BehaviourAdded is not T tBehaviour)
|
|
||||||
return;
|
|
||||||
|
|
||||||
AddBehaviour(tBehaviour);
|
|
||||||
OnBehaviourAdd(args.BehaviourAdded);
|
|
||||||
OnCollected?.Invoke(this, new(tBehaviour));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
|
|
||||||
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
|
|
||||||
{
|
|
||||||
if (args.BehaviourRemoved is not T tBehaviour)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!behaviours.Remove(tBehaviour))
|
|
||||||
return;
|
|
||||||
|
|
||||||
OnBehaviourRemove(args.BehaviourRemoved);
|
|
||||||
OnRemoved?.Invoke(this, new(tBehaviour));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnAssign(IUniverse universe) { }
|
|
||||||
public bool Assign(IUniverse universe)
|
public bool Assign(IUniverse universe)
|
||||||
{
|
{
|
||||||
if (Universe is not null)
|
if (Universe is not null)
|
||||||
@@ -100,10 +54,57 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Count => behaviours.Count;
|
protected virtual void OnAssign(IUniverse universe) { }
|
||||||
public T this[Index index] => behaviours[index];
|
|
||||||
|
|
||||||
public BehaviourCollector()
|
protected abstract void AddBehaviour(T behaviour);
|
||||||
|
protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
|
||||||
|
private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
|
||||||
|
{
|
||||||
|
if (args.BehaviourAdded is not T tBehaviour)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AddBehaviour(tBehaviour);
|
||||||
|
OnBehaviourAdd(args.BehaviourAdded);
|
||||||
|
OnCollected?.Invoke(this, new(tBehaviour));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract bool RemoveBehaviour(T tBehaviour);
|
||||||
|
protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
|
||||||
|
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
|
||||||
|
{
|
||||||
|
if (args.BehaviourRemoved is not T tBehaviour)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!RemoveBehaviour(tBehaviour))
|
||||||
|
return;
|
||||||
|
|
||||||
|
OnBehaviourRemove(args.BehaviourRemoved);
|
||||||
|
OnRemoved?.Invoke(this, new(tBehaviour));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
|
||||||
|
{
|
||||||
|
IUniverseObject universeObject = args.UniverseObjectRegistered;
|
||||||
|
|
||||||
|
universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
|
||||||
|
universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
|
||||||
|
|
||||||
|
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
||||||
|
OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments args)
|
||||||
|
{
|
||||||
|
IUniverseObject universeObject = args.UniverseObjectUnregistered;
|
||||||
|
|
||||||
|
universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
|
||||||
|
universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
|
||||||
|
|
||||||
|
for (int i = 0; i < universeObject.BehaviourController.Count; i++)
|
||||||
|
OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BehaviourCollectorBase()
|
||||||
{
|
{
|
||||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
||||||
@@ -111,7 +112,7 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
|||||||
delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
|
delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BehaviourCollector(IUniverse universe)
|
public BehaviourCollectorBase(IUniverse universe)
|
||||||
{
|
{
|
||||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
104
Engine.Core/Collectors/BehaviourCollectorOrdered.cs
Normal file
104
Engine.Core/Collectors/BehaviourCollectorOrdered.cs
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
public class BehaviourCollectorOrdered<TIndex, TItem> : BehaviourCollectorBase<TItem> where TItem : class where TIndex : IComparable
|
||||||
|
{
|
||||||
|
private readonly Event<IBehaviour, IBehaviour.PriorityChangedArguments>.EventHandler delegateOnPriorityChanged = null!;
|
||||||
|
|
||||||
|
private readonly SortedDictionary<TIndex, FastList<TItem>> behaviours = null!;
|
||||||
|
|
||||||
|
private readonly Func<TItem, TIndex> getIndexFunc = null!;
|
||||||
|
private readonly IComparer<TIndex> sortBy = null!;
|
||||||
|
|
||||||
|
private int count = 0;
|
||||||
|
public override int Count => count;
|
||||||
|
|
||||||
|
public override TItem this[Index index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int actualIndex = index.IsFromEnd
|
||||||
|
? count - index.Value
|
||||||
|
: index.Value;
|
||||||
|
|
||||||
|
if (actualIndex < 0 || actualIndex >= count)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
|
||||||
|
int leftIndex = actualIndex;
|
||||||
|
foreach ((TIndex i, FastList<TItem> list) in behaviours)
|
||||||
|
{
|
||||||
|
if (leftIndex < list.Count)
|
||||||
|
return list[leftIndex];
|
||||||
|
leftIndex -= list.Count;
|
||||||
|
}
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool RemoveBehaviour(TItem tBehaviour)
|
||||||
|
{
|
||||||
|
TIndex index = getIndexFunc(tBehaviour);
|
||||||
|
if (!behaviours.TryGetValue(index, out FastList<TItem>? list))
|
||||||
|
throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector");
|
||||||
|
|
||||||
|
if (!list.Remove(tBehaviour))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
count--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AddBehaviour(TItem behaviour)
|
||||||
|
{
|
||||||
|
TIndex key = getIndexFunc(behaviour);
|
||||||
|
if (!behaviours.TryGetValue(key, out FastList<TItem>? list))
|
||||||
|
behaviours[key] = list = [];
|
||||||
|
|
||||||
|
count++;
|
||||||
|
list.Add(behaviour);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnBehaviourAdd(IBehaviour behaviour) => behaviour.OnPriorityChanged.AddListener(delegateOnPriorityChanged);
|
||||||
|
protected override void OnBehaviourRemove(IBehaviour behaviour) => behaviour.OnPriorityChanged.RemoveListener(delegateOnPriorityChanged);
|
||||||
|
|
||||||
|
private void OnPriorityChanged(IBehaviour sender, IBehaviour.PriorityChangedArguments args)
|
||||||
|
{
|
||||||
|
TItem behaviour = (TItem)sender;
|
||||||
|
RemoveBehaviour(behaviour);
|
||||||
|
AddBehaviour(behaviour);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = Comparer<TIndex>.Create(sortBy);
|
||||||
|
behaviours = new(this.sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy) : base(universe)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = Comparer<TIndex>.Create(sortBy);
|
||||||
|
behaviours = new(this.sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BehaviourCollectorOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy)
|
||||||
|
{
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.sortBy = sortBy;
|
||||||
|
behaviours = new(sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BehaviourCollectorOrdered(IUniverse universe, Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy) : base(universe)
|
||||||
|
{
|
||||||
|
delegateOnPriorityChanged = OnPriorityChanged;
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = sortBy;
|
||||||
|
behaviours = new(sortBy);
|
||||||
|
}
|
||||||
|
}
|
@@ -3,17 +3,30 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace Engine.Core;
|
namespace Engine.Core;
|
||||||
|
|
||||||
public class FastList<T> : IReadOnlyList<T>, IEnumerable<T> where T : notnull
|
public class FastList<T> : IList<T>, IReadOnlyList<T>, IEnumerable<T> where T : notnull
|
||||||
{
|
{
|
||||||
private readonly List<T> items = [];
|
private readonly List<T> items = [];
|
||||||
private readonly Dictionary<T, int> indexMap = [];
|
private readonly Dictionary<T, int> indexMap = [];
|
||||||
|
|
||||||
|
public bool IsReadOnly { get; set; } = false;
|
||||||
public int Count => items.Count;
|
public int Count => items.Count;
|
||||||
|
public T this[int index]
|
||||||
|
{
|
||||||
|
get => items[index];
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
public T this[int index] => items[index];
|
items[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Add(T item)
|
public void Add(T item)
|
||||||
{
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
indexMap[item] = items.Count;
|
indexMap[item] = items.Count;
|
||||||
items.Add(item);
|
items.Add(item);
|
||||||
}
|
}
|
||||||
@@ -21,6 +34,9 @@ public class FastList<T> : IReadOnlyList<T>, IEnumerable<T> where T : notnull
|
|||||||
public void RemoveAt(int i) => Remove(items[i], i);
|
public void RemoveAt(int i) => Remove(items[i], i);
|
||||||
public bool Remove(T item)
|
public bool Remove(T item)
|
||||||
{
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
if (!indexMap.TryGetValue(item, out int index))
|
if (!indexMap.TryGetValue(item, out int index))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -43,6 +59,9 @@ public class FastList<T> : IReadOnlyList<T>, IEnumerable<T> where T : notnull
|
|||||||
|
|
||||||
public void Insert(int index, T item)
|
public void Insert(int index, T item)
|
||||||
{
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
items.Insert(index, item);
|
items.Insert(index, item);
|
||||||
|
|
||||||
for (int i = index; i < items.Count; i++)
|
for (int i = index; i < items.Count; i++)
|
||||||
@@ -51,21 +70,30 @@ public class FastList<T> : IReadOnlyList<T>, IEnumerable<T> where T : notnull
|
|||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
items.Clear();
|
items.Clear();
|
||||||
indexMap.Clear();
|
indexMap.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Contains(T item) => indexMap.ContainsKey(item);
|
public bool Contains(T item) => indexMap.ContainsKey(item);
|
||||||
|
public int IndexOf(T item) => items.IndexOf(item);
|
||||||
public int BinarySearch(T item, IComparer<T>? comparer = null) => items.BinarySearch(item, comparer);
|
public int BinarySearch(T item, IComparer<T>? comparer = null) => items.BinarySearch(item, comparer);
|
||||||
|
|
||||||
public void Sort(IComparer<T> comparer)
|
public void Sort(IComparer<T> comparer)
|
||||||
{
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
items.Sort(comparer);
|
items.Sort(comparer);
|
||||||
|
|
||||||
for (int i = 0; i < items.Count; i++)
|
for (int i = 0; i < items.Count; i++)
|
||||||
indexMap[items[i]] = i;
|
indexMap[items[i]] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CopyTo(T[] array, int arrayIndex) => items.CopyTo(array, arrayIndex);
|
||||||
|
|
||||||
public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
|
public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
|
172
Engine.Core/Helpers/FastListOrdered.cs
Normal file
172
Engine.Core/Helpers/FastListOrdered.cs
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Engine.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TODO This is VEERY experimental, and doesn't work well with the indices access. Use with caution
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TIndex"></typeparam>
|
||||||
|
/// <typeparam name="TItem"></typeparam>
|
||||||
|
public class FastListOrdered<TIndex, TItem> : IList<TItem>, IReadOnlyList<TItem>, IEnumerable<TItem> where TItem : notnull where TIndex : IComparable
|
||||||
|
{
|
||||||
|
private readonly SortedDictionary<TIndex, FastList<TItem>> items = null!;
|
||||||
|
|
||||||
|
private readonly Func<TItem, TIndex> getIndexFunc = null!;
|
||||||
|
private readonly IComparer<TIndex> sortBy = null!;
|
||||||
|
|
||||||
|
private int count = 0;
|
||||||
|
public int Count => count;
|
||||||
|
|
||||||
|
public bool IsReadOnly { get; set; } = false;
|
||||||
|
|
||||||
|
public TItem this[int index]
|
||||||
|
{
|
||||||
|
get { (TIndex tIndex, int i) = GetAt(index); return items[tIndex][i]; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
(TIndex tIndex, int i) = GetAt(index); items[tIndex][i] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private (TIndex TIndex, int i) GetAt(Index index)
|
||||||
|
{
|
||||||
|
int actualIndex = index.IsFromEnd
|
||||||
|
? count - index.Value
|
||||||
|
: index.Value;
|
||||||
|
|
||||||
|
if (actualIndex < 0 || actualIndex >= count)
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
|
||||||
|
int leftIndex = actualIndex;
|
||||||
|
foreach ((TIndex i, FastList<TItem> list) in items)
|
||||||
|
{
|
||||||
|
if (leftIndex < list.Count)
|
||||||
|
return (i, leftIndex);
|
||||||
|
leftIndex -= list.Count;
|
||||||
|
}
|
||||||
|
throw new IndexOutOfRangeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int IndexOf(TItem item)
|
||||||
|
{
|
||||||
|
int indexCounter = 0;
|
||||||
|
foreach ((TIndex index, FastList<TItem> list) in items)
|
||||||
|
{
|
||||||
|
int i = list.IndexOf(item);
|
||||||
|
if (i != -1)
|
||||||
|
return indexCounter + i;
|
||||||
|
indexCounter += list.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(TItem item)
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
|
TIndex key = getIndexFunc(item);
|
||||||
|
if (!items.TryGetValue(key, out FastList<TItem>? list))
|
||||||
|
items[key] = list = [];
|
||||||
|
|
||||||
|
list.Add(item);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Insert(int index, TItem item)
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
|
TIndex tIndex = getIndexFunc(item);
|
||||||
|
if (!items.TryGetValue(tIndex, out FastList<TItem>? list))
|
||||||
|
items[tIndex] = list = [];
|
||||||
|
|
||||||
|
list.Insert(index, item);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(TItem item)
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
|
TIndex index = getIndexFunc(item);
|
||||||
|
if (!items.TryGetValue(index, out FastList<TItem>? list))
|
||||||
|
throw new Exceptions.NotFoundException($"Index of '{index}' is not found in the collector");
|
||||||
|
|
||||||
|
if (!list.Remove(item))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
count--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveAt(int index)
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
|
(TIndex tIndex, int i) = GetAt(index);
|
||||||
|
items[tIndex].RemoveAt(i);
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
throw new System.Data.ReadOnlyException();
|
||||||
|
|
||||||
|
foreach ((TIndex index, FastList<TItem> list) in items)
|
||||||
|
list.Clear();
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(TItem item)
|
||||||
|
{
|
||||||
|
foreach ((TIndex index, FastList<TItem> list) in items)
|
||||||
|
if (list.Contains(item))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(TItem[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
int indexCounter = 0;
|
||||||
|
|
||||||
|
foreach ((TIndex index, FastList<TItem> list) in items)
|
||||||
|
{
|
||||||
|
list.CopyTo(array, indexCounter);
|
||||||
|
indexCounter += list.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<TItem> GetEnumerator()
|
||||||
|
{
|
||||||
|
foreach ((TIndex index, FastList<TItem> list) in items)
|
||||||
|
foreach (TItem item in list)
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
|
public FastListOrdered(Func<TItem, TIndex> getIndexFunc, Comparison<TIndex> sortBy)
|
||||||
|
{
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = Comparer<TIndex>.Create(sortBy);
|
||||||
|
items = new(this.sortBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FastListOrdered(Func<TItem, TIndex> getIndexFunc, IComparer<TIndex> sortBy)
|
||||||
|
{
|
||||||
|
this.getIndexFunc = getIndexFunc;
|
||||||
|
this.sortBy = sortBy;
|
||||||
|
items = new(sortBy);
|
||||||
|
}
|
||||||
|
}
|
@@ -5,11 +5,12 @@ namespace Engine.Core;
|
|||||||
public class DrawManager : Behaviour
|
public class DrawManager : Behaviour
|
||||||
{
|
{
|
||||||
// We use Descending order because draw calls are running from last to first
|
// We use Descending order because draw calls are running from last to first
|
||||||
private static Comparer<IBehaviour> SortByDescendingPriority() => Comparer<IBehaviour>.Create((x, y) => y.Priority.CompareTo(x.Priority));
|
private static Comparer<int> SortByDescendingPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
|
||||||
|
private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
|
||||||
|
|
||||||
private readonly ActiveBehaviourCollectorSorted<IPreDraw> preDrawEntities = new() { SortBy = SortByDescendingPriority() };
|
private readonly ActiveBehaviourCollectorOrdered<int, IPreDraw> preDrawEntities = new(GetPriority(), SortByDescendingPriority());
|
||||||
private readonly ActiveBehaviourCollectorSorted<IDraw> drawEntities = new() { SortBy = SortByDescendingPriority() };
|
private readonly ActiveBehaviourCollectorOrdered<int, IDraw> drawEntities = new(GetPriority(), SortByDescendingPriority());
|
||||||
private readonly ActiveBehaviourCollectorSorted<IPostDraw> postDrawEntities = new() { SortBy = SortByDescendingPriority() };
|
private readonly ActiveBehaviourCollectorOrdered<int, IPostDraw> postDrawEntities = new(GetPriority(), SortByDescendingPriority());
|
||||||
|
|
||||||
private void OnPreDraw(IUniverse sender)
|
private void OnPreDraw(IUniverse sender)
|
||||||
{
|
{
|
||||||
|
@@ -5,10 +5,11 @@ namespace Engine.Core;
|
|||||||
public class UniverseEntranceManager : Behaviour
|
public class UniverseEntranceManager : Behaviour
|
||||||
{
|
{
|
||||||
// We use Ascending order because we are using reverse for loop to call them
|
// We use Ascending order because we are using reverse for loop to call them
|
||||||
private static Comparer<IBehaviour> SortByAscendingPriority() => Comparer<IBehaviour>.Create((x, y) => x.Priority.CompareTo(y.Priority));
|
private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
|
||||||
|
private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
|
||||||
|
|
||||||
private readonly ActiveBehaviourCollectorSorted<IEnterUniverse> enterUniverses = new() { SortBy = SortByAscendingPriority() };
|
private readonly ActiveBehaviourCollectorOrdered<int, IEnterUniverse> enterUniverses = new(GetPriority(), SortByAscendingPriority());
|
||||||
private readonly ActiveBehaviourCollectorSorted<IExitUniverse> exitUniverses = new() { SortBy = SortByAscendingPriority() };
|
private readonly ActiveBehaviourCollectorOrdered<int, IExitUniverse> exitUniverses = new(GetPriority(), SortByAscendingPriority());
|
||||||
|
|
||||||
private readonly List<IEnterUniverse> toCallEnterUniverses = new(32);
|
private readonly List<IEnterUniverse> toCallEnterUniverses = new(32);
|
||||||
private readonly List<IExitUniverse> toCallExitUniverses = new(32);
|
private readonly List<IExitUniverse> toCallExitUniverses = new(32);
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Engine.Core;
|
namespace Engine.Core;
|
||||||
@@ -6,13 +5,14 @@ namespace Engine.Core;
|
|||||||
public class UpdateManager : Behaviour
|
public class UpdateManager : Behaviour
|
||||||
{
|
{
|
||||||
// We use Ascending order because we are using reverse for loop to call them
|
// We use Ascending order because we are using reverse for loop to call them
|
||||||
private static Comparer<IBehaviour> SortByAscendingPriority() => Comparer<IBehaviour>.Create((x, y) => x.Priority.CompareTo(y.Priority));
|
private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
|
||||||
|
private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
|
||||||
|
|
||||||
private readonly ActiveBehaviourCollectorSorted<IFirstFrameUpdate> firstFrameUpdates = new() { SortBy = SortByAscendingPriority() };
|
private readonly ActiveBehaviourCollectorOrdered<int, IFirstFrameUpdate> firstFrameUpdates = new(GetPriority(), SortByAscendingPriority());
|
||||||
private readonly ActiveBehaviourCollector<ILastFrameUpdate> lastFrameUpdates = new();
|
private readonly ActiveBehaviourCollector<ILastFrameUpdate> lastFrameUpdates = new();
|
||||||
private readonly ActiveBehaviourCollectorSorted<IPreUpdate> preUpdateEntities = new() { SortBy = SortByAscendingPriority() };
|
private readonly ActiveBehaviourCollectorOrdered<int, IPreUpdate> preUpdateEntities = new(GetPriority(), SortByAscendingPriority());
|
||||||
private readonly ActiveBehaviourCollectorSorted<IUpdate> updateEntities = new() { SortBy = SortByAscendingPriority() };
|
private readonly ActiveBehaviourCollectorOrdered<int, IUpdate> updateEntities = new(GetPriority(), SortByAscendingPriority());
|
||||||
private readonly ActiveBehaviourCollectorSorted<IPostUpdate> postUpdateEntities = new() { SortBy = SortByAscendingPriority() };
|
private readonly ActiveBehaviourCollectorOrdered<int, IPostUpdate> postUpdateEntities = new(GetPriority(), SortByAscendingPriority());
|
||||||
|
|
||||||
private readonly List<IFirstFrameUpdate> toCallFirstFrameUpdates = new(32);
|
private readonly List<IFirstFrameUpdate> toCallFirstFrameUpdates = new(32);
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@ public class Universe : BaseEntity, IUniverse
|
|||||||
private readonly Event<IInitializable>.EventHandler delegateOnUniverseObjectFinalize = null!;
|
private readonly Event<IInitializable>.EventHandler delegateOnUniverseObjectFinalize = null!;
|
||||||
private readonly Event<IUniverseObject, IUniverseObject.ExitedUniverseArguments>.EventHandler delegateOnUniverseObjectExitedUniverse = null!;
|
private readonly Event<IUniverseObject, IUniverseObject.ExitedUniverseArguments>.EventHandler delegateOnUniverseObjectExitedUniverse = null!;
|
||||||
|
|
||||||
private readonly List<IUniverseObject> _universeObjects = new(Constants.UNIVERSE_OBJECTS_SIZE_INITIAL);
|
private readonly FastList<IUniverseObject> _universeObjects = new(Constants.UNIVERSE_OBJECTS_SIZE_INITIAL);
|
||||||
private float _timeScale = 1f;
|
private float _timeScale = 1f;
|
||||||
|
|
||||||
public Universe()
|
public Universe()
|
||||||
|
@@ -19,7 +19,7 @@ public class UniverseObject : BaseEntity, IUniverseObject
|
|||||||
private IUniverse _universe = null!;
|
private IUniverse _universe = null!;
|
||||||
private IBehaviourController _behaviourController = null!;
|
private IBehaviourController _behaviourController = null!;
|
||||||
private bool _isActive = false;
|
private bool _isActive = false;
|
||||||
private readonly List<IUniverseObject> _children = [];
|
private readonly FastList<IUniverseObject> _children = [];
|
||||||
private IUniverseObject? _parent = null;
|
private IUniverseObject? _parent = null;
|
||||||
|
|
||||||
public IReadOnlyList<IUniverseObject> Children => _children;
|
public IReadOnlyList<IUniverseObject> Children => _children;
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using Engine.Core;
|
using Engine.Core;
|
||||||
|
|
||||||
namespace Engine.Integration.MonoGame;
|
namespace Engine.Integration.MonoGame;
|
||||||
@@ -6,9 +7,10 @@ namespace Engine.Integration.MonoGame;
|
|||||||
public class LoadContentManager : Behaviour, IFirstFrameUpdate
|
public class LoadContentManager : Behaviour, IFirstFrameUpdate
|
||||||
{
|
{
|
||||||
// We use Ascending order because we are using reverse for loop to call them
|
// We use Ascending order because we are using reverse for loop to call them
|
||||||
private static Comparer<IBehaviour> SortByAscendingPriority() => Comparer<IBehaviour>.Create((x, y) => x.Priority.CompareTo(y.Priority));
|
private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
|
||||||
|
private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
|
||||||
|
|
||||||
private readonly ActiveBehaviourCollectorSorted<ILoadContent> loadContents = new() { SortBy = SortByAscendingPriority() };
|
private readonly ActiveBehaviourCollectorOrdered<int, ILoadContent> loadContents = new(GetPriority(), SortByAscendingPriority());
|
||||||
private readonly List<ILoadContent> toCallLoadContents = new(32);
|
private readonly List<ILoadContent> toCallLoadContents = new(32);
|
||||||
|
|
||||||
private MonoGameWindowContainer monoGameWindowContainer = null!;
|
private MonoGameWindowContainer monoGameWindowContainer = null!;
|
||||||
|
@@ -6,12 +6,13 @@ namespace Engine.Integration.MonoGame;
|
|||||||
|
|
||||||
public class SpriteBatcher : BehaviourBase, IFirstFrameUpdate, IDraw
|
public class SpriteBatcher : BehaviourBase, IFirstFrameUpdate, IDraw
|
||||||
{
|
{
|
||||||
private static Comparer<IBehaviour> SortByPriority() => Comparer<IBehaviour>.Create((x, y) => y.Priority.CompareTo(x.Priority));
|
private static Comparer<int> SortByPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
|
||||||
|
private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
|
||||||
|
|
||||||
private ISpriteBatch spriteBatch = null!;
|
private ISpriteBatch spriteBatch = null!;
|
||||||
private MonoGameCamera2D camera2D = null!;
|
private MonoGameCamera2D camera2D = null!;
|
||||||
|
|
||||||
private readonly ActiveBehaviourCollectorSorted<IDrawableSprite> drawableSprites = new() { SortBy = SortByPriority() };
|
private readonly ActiveBehaviourCollectorOrdered<int, IDrawableSprite> drawableSprites = new(GetPriority(), SortByPriority());
|
||||||
|
|
||||||
public void FirstActiveFrame()
|
public void FirstActiveFrame()
|
||||||
{
|
{
|
||||||
|
@@ -8,11 +8,13 @@ namespace Engine.Integration.MonoGame;
|
|||||||
|
|
||||||
public class TriangleBatcher : BehaviourBase, ITriangleBatch, IFirstFrameUpdate, IDraw
|
public class TriangleBatcher : BehaviourBase, ITriangleBatch, IFirstFrameUpdate, IDraw
|
||||||
{
|
{
|
||||||
private static Comparer<IBehaviour> SortByAscendingPriority() => Comparer<IBehaviour>.Create((x, y) => x.Priority.CompareTo(y.Priority));
|
private static Comparer<int> SortByAscendingPriority() => Comparer<int>.Create((x, y) => x.CompareTo(y));
|
||||||
|
private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
|
||||||
|
|
||||||
private TriangleBatch triangleBatch = null!;
|
private TriangleBatch triangleBatch = null!;
|
||||||
private MonoGameCamera2D camera2D = null!;
|
private MonoGameCamera2D camera2D = null!;
|
||||||
private readonly ActiveBehaviourCollectorSorted<IDrawableTriangle> drawableShapes = new() { SortBy = SortByAscendingPriority() };
|
|
||||||
|
private readonly ActiveBehaviourCollectorOrdered<int, IDrawableTriangle> drawableShapes = new(GetPriority(), SortByAscendingPriority());
|
||||||
|
|
||||||
public void FirstActiveFrame()
|
public void FirstActiveFrame()
|
||||||
{
|
{
|
||||||
|
@@ -17,11 +17,12 @@ public class PhysicsEngine2D : Behaviour, IPreUpdate, IPhysicsEngine2D
|
|||||||
protected readonly ICollisionResolver2D collisionResolver = null!;
|
protected readonly ICollisionResolver2D collisionResolver = null!;
|
||||||
protected readonly IRaycastResolver2D raycastResolver = null!;
|
protected readonly IRaycastResolver2D raycastResolver = null!;
|
||||||
|
|
||||||
private static Comparer<IBehaviour> SortByPriority() => Comparer<IBehaviour>.Create((x, y) => y.Priority.CompareTo(x.Priority));
|
private static Comparer<int> SortByPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
|
||||||
protected ActiveBehaviourCollectorSorted<IPrePhysicsUpdate> physicsPreUpdateCollector = new() { SortBy = SortByPriority() };
|
private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
|
||||||
protected ActiveBehaviourCollectorSorted<IPhysicsUpdate> physicsUpdateCollector = new() { SortBy = SortByPriority() };
|
protected ActiveBehaviourCollectorOrdered<int, IPrePhysicsUpdate> physicsPreUpdateCollector = new(GetPriority(), SortByPriority());
|
||||||
protected ActiveBehaviourCollectorSorted<IPhysicsIteration> physicsIterationCollector = new() { SortBy = SortByPriority() };
|
protected ActiveBehaviourCollectorOrdered<int, IPhysicsUpdate> physicsUpdateCollector = new(GetPriority(), SortByPriority());
|
||||||
protected ActiveBehaviourCollectorSorted<IPostPhysicsUpdate> physicsPostUpdateCollector = new() { SortBy = SortByPriority() };
|
protected ActiveBehaviourCollectorOrdered<int, IPhysicsIteration> physicsIterationCollector = new(GetPriority(), SortByPriority());
|
||||||
|
protected ActiveBehaviourCollectorOrdered<int, IPostPhysicsUpdate> physicsPostUpdateCollector = new(GetPriority(), SortByPriority());
|
||||||
protected BehaviourCollector<IRigidBody2D> rigidBodyCollector = new();
|
protected BehaviourCollector<IRigidBody2D> rigidBodyCollector = new();
|
||||||
protected BehaviourCollector<ICollider2D> colliderCollector = new();
|
protected BehaviourCollector<ICollider2D> colliderCollector = new();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user