105 lines
3.5 KiB
C#
105 lines
3.5 KiB
C#
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);
|
|
}
|
|
}
|