Compare commits
17 Commits
a4b83679b1
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
8d31372c24 | |||
a2e704916e | |||
c7d170fad9 | |||
9ccf7b754d | |||
e3d4899112 | |||
566c16d09c | |||
ae9d4f02ef | |||
e77772cbc2 | |||
4c542df401 | |||
28ca343b43 | |||
651b0614c4 | |||
f47488c6f1 | |||
6d159330a1 | |||
8e314f3269 | |||
f5a7077570 | |||
746d29fb7a | |||
cf68f6ca6f |
@@ -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);
|
||||
}
|
||||
}
|
@@ -10,7 +10,7 @@ public class BehaviourController : BaseEntity, IBehaviourController
|
||||
public Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments> OnBehaviourRemoved { get; } = new();
|
||||
public Event<IHasUniverseObject> OnUniverseObjectAssigned { get; } = new();
|
||||
|
||||
private readonly List<IBehaviour> behaviours = new(Constants.BEHAVIOURS_SIZE_INITIAL);
|
||||
private readonly FastList<IBehaviour> behaviours = new(Constants.BEHAVIOURS_SIZE_INITIAL);
|
||||
|
||||
private IUniverseObject _universeObject = null!;
|
||||
|
||||
|
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;
|
||||
|
||||
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();
|
||||
public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
|
||||
public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
|
||||
public Event<IAssignable>? OnUnassigned { get; } = new();
|
||||
protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = new(32);
|
||||
protected readonly FastList<T> monitoringBehaviours = new(32);
|
||||
|
||||
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = 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.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
|
||||
|
||||
private readonly List<T> monitoringBehaviours = new(32);
|
||||
protected readonly List<T> activeBehaviours = new(32);
|
||||
protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = 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 abstract int Count { get; }
|
||||
|
||||
public abstract T this[Index index] { get; }
|
||||
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)
|
||||
{
|
||||
if (Universe is not null)
|
||||
@@ -123,10 +57,75 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
||||
return true;
|
||||
}
|
||||
|
||||
public int Count => activeBehaviours.Count;
|
||||
public T this[Index index] => activeBehaviours[index];
|
||||
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;
|
||||
|
||||
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;
|
||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
||||
@@ -135,7 +134,7 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
||||
delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
|
||||
}
|
||||
|
||||
public ActiveBehaviourCollector(IUniverse universe)
|
||||
public ActiveBehaviourCollectorBase(IUniverse universe)
|
||||
{
|
||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||
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) { }
|
||||
}
|
@@ -1,72 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
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.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
|
||||
private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
|
||||
private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
|
||||
|
||||
protected readonly List<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!;
|
||||
|
||||
private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
|
||||
{
|
||||
IUniverseObject universeObject = args.UniverseObjectRegistered;
|
||||
public abstract int Count { get; }
|
||||
|
||||
universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
|
||||
universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
|
||||
public abstract T this[Index index] { get; }
|
||||
|
||||
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)
|
||||
{
|
||||
if (Universe is not null)
|
||||
@@ -101,10 +54,57 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
||||
return true;
|
||||
}
|
||||
|
||||
public int Count => behaviours.Count;
|
||||
public T this[Index index] => behaviours[index];
|
||||
protected virtual void OnAssign(IUniverse universe) { }
|
||||
|
||||
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;
|
||||
delegateOnBehaviourRemoved = OnBehaviourRemoved;
|
||||
@@ -112,7 +112,7 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
||||
delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
|
||||
}
|
||||
|
||||
public BehaviourCollector(IUniverse universe)
|
||||
public BehaviourCollectorBase(IUniverse universe)
|
||||
{
|
||||
delegateOnBehaviourAdded = OnBehaviourAdded;
|
||||
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);
|
||||
}
|
||||
}
|
78
Engine.Core/Helpers/FastList.cs
Normal file
78
Engine.Core/Helpers/FastList.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Engine.Core;
|
||||
|
||||
public class FastList<T> : IList<T>, IReadOnlyList<T>, IEnumerable<T> where T : notnull
|
||||
{
|
||||
private readonly List<T> items = [];
|
||||
private readonly Dictionary<T, int> indexMap = [];
|
||||
|
||||
public int Count => items.Count;
|
||||
|
||||
public bool IsReadOnly { get; set; } = false;
|
||||
public T this[int index] { get => items[index]; set => items[index] = value; }
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
indexMap[item] = items.Count;
|
||||
items.Add(item);
|
||||
}
|
||||
|
||||
public void RemoveAt(int i) => Remove(items[i], i);
|
||||
public bool Remove(T item)
|
||||
{
|
||||
if (!indexMap.TryGetValue(item, out int index))
|
||||
return false;
|
||||
|
||||
Remove(item, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void Remove(T item, int index)
|
||||
{
|
||||
int lastIndex = items.Count - 1;
|
||||
T lastItem = items[lastIndex];
|
||||
|
||||
items[index] = lastItem;
|
||||
indexMap[lastItem] = index;
|
||||
|
||||
items.RemoveAt(lastIndex);
|
||||
indexMap.Remove(item);
|
||||
}
|
||||
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
items.Insert(index, item);
|
||||
|
||||
for (int i = index; i < items.Count; i++)
|
||||
indexMap[items[i]] = i;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
items.Clear();
|
||||
indexMap.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(T item) => indexMap.ContainsKey(item);
|
||||
|
||||
public int BinarySearch(T item, IComparer<T>? comparer = null) => items.BinarySearch(item, comparer);
|
||||
public void Sort(IComparer<T> comparer)
|
||||
{
|
||||
items.Sort(comparer);
|
||||
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
indexMap[items[i]] = i;
|
||||
}
|
||||
|
||||
public int IndexOf(T item) => items.IndexOf(item);
|
||||
public void CopyTo(T[] array, int arrayIndex) => items.CopyTo(array, arrayIndex);
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
public FastList() { }
|
||||
public FastList(int count) { items.Capacity = count; }
|
||||
}
|
@@ -10,22 +10,25 @@ public class Pool<T> : IPool<T>
|
||||
|
||||
private readonly Func<T> generator = null!;
|
||||
private readonly Queue<T> queue = new();
|
||||
private readonly HashSet<T> queuedHashes = [];
|
||||
|
||||
public T Get()
|
||||
{
|
||||
if (!queue.TryDequeue(out T? result))
|
||||
result = generator();
|
||||
|
||||
queuedHashes.Remove(result);
|
||||
OnRemoved?.Invoke(this, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Return(T item)
|
||||
{
|
||||
if (queue.Contains(item))
|
||||
if (queuedHashes.Contains(item))
|
||||
return;
|
||||
|
||||
queue.Enqueue(item);
|
||||
queuedHashes.Add(item);
|
||||
OnReturned?.Invoke(this, item);
|
||||
}
|
||||
|
||||
|
@@ -5,11 +5,12 @@ namespace Engine.Core;
|
||||
public class DrawManager : Behaviour
|
||||
{
|
||||
// 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 ActiveBehaviourCollectorSorted<IDraw> drawEntities = new() { SortBy = SortByDescendingPriority() };
|
||||
private readonly ActiveBehaviourCollectorSorted<IPostDraw> postDrawEntities = new() { SortBy = SortByDescendingPriority() };
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IPreDraw> preDrawEntities = new(GetPriority(), SortByDescendingPriority());
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IDraw> drawEntities = new(GetPriority(), SortByDescendingPriority());
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IPostDraw> postDrawEntities = new(GetPriority(), SortByDescendingPriority());
|
||||
|
||||
private void OnPreDraw(IUniverse sender)
|
||||
{
|
||||
|
@@ -5,10 +5,11 @@ namespace Engine.Core;
|
||||
public class UniverseEntranceManager : Behaviour
|
||||
{
|
||||
// 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 ActiveBehaviourCollectorSorted<IExitUniverse> exitUniverses = new() { SortBy = SortByAscendingPriority() };
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IEnterUniverse> enterUniverses = new(GetPriority(), SortByAscendingPriority());
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IExitUniverse> exitUniverses = new(GetPriority(), SortByAscendingPriority());
|
||||
|
||||
private readonly List<IEnterUniverse> toCallEnterUniverses = new(32);
|
||||
private readonly List<IExitUniverse> toCallExitUniverses = new(32);
|
||||
@@ -39,8 +40,9 @@ public class UniverseEntranceManager : Behaviour
|
||||
{
|
||||
for (int i = toCallExitUniverses.Count - 1; i >= 0; i--)
|
||||
{
|
||||
toCallExitUniverses[i].ExitUniverse(Universe);
|
||||
IExitUniverse exitUniverse = toCallExitUniverses[i];
|
||||
toCallExitUniverses.RemoveAt(i);
|
||||
exitUniverse.ExitUniverse(Universe);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,8 +50,9 @@ public class UniverseEntranceManager : Behaviour
|
||||
{
|
||||
for (int i = toCallEnterUniverses.Count - 1; i >= 0; i--)
|
||||
{
|
||||
toCallEnterUniverses[i].EnterUniverse(Universe);
|
||||
IEnterUniverse enterUniverse = toCallEnterUniverses[i];
|
||||
toCallEnterUniverses.RemoveAt(i);
|
||||
enterUniverse.EnterUniverse(Universe);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -5,13 +5,14 @@ namespace Engine.Core;
|
||||
public class UpdateManager : Behaviour
|
||||
{
|
||||
// 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 ActiveBehaviourCollectorSorted<IPreUpdate> preUpdateEntities = new() { SortBy = SortByAscendingPriority() };
|
||||
private readonly ActiveBehaviourCollectorSorted<IUpdate> updateEntities = new() { SortBy = SortByAscendingPriority() };
|
||||
private readonly ActiveBehaviourCollectorSorted<IPostUpdate> postUpdateEntities = new() { SortBy = SortByAscendingPriority() };
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IPreUpdate> preUpdateEntities = new(GetPriority(), SortByAscendingPriority());
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IUpdate> updateEntities = new(GetPriority(), SortByAscendingPriority());
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IPostUpdate> postUpdateEntities = new(GetPriority(), SortByAscendingPriority());
|
||||
|
||||
private readonly List<IFirstFrameUpdate> toCallFirstFrameUpdates = new(32);
|
||||
|
||||
@@ -23,6 +24,7 @@ public class UpdateManager : Behaviour
|
||||
updateEntities.Assign(universe);
|
||||
postUpdateEntities.Assign(universe);
|
||||
|
||||
universe.OnPreUpdate.AddListener(OnFirstUpdate, int.MaxValue);
|
||||
universe.OnPreUpdate.AddListener(OnPreUpdate);
|
||||
universe.OnUpdate.AddListener(OnUpdate);
|
||||
universe.OnPostUpdate.AddListener(OnPostUpdate);
|
||||
@@ -36,19 +38,23 @@ public class UpdateManager : Behaviour
|
||||
updateEntities.Unassign();
|
||||
postUpdateEntities.Unassign();
|
||||
|
||||
universe.OnPreUpdate.RemoveListener(OnFirstUpdate);
|
||||
universe.OnPreUpdate.RemoveListener(OnPreUpdate);
|
||||
universe.OnUpdate.RemoveListener(OnUpdate);
|
||||
universe.OnPostUpdate.RemoveListener(OnPostUpdate);
|
||||
}
|
||||
|
||||
private void OnPreUpdate(IUniverse sender, IUniverse.UpdateArguments args)
|
||||
private void OnFirstUpdate(IUniverse sender, IUniverse.UpdateArguments args)
|
||||
{
|
||||
for (int i = toCallFirstFrameUpdates.Count - 1; i >= 0; i--)
|
||||
{
|
||||
toCallFirstFrameUpdates[i].FirstActiveFrame();
|
||||
toCallFirstFrameUpdates.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPreUpdate(IUniverse sender, IUniverse.UpdateArguments args)
|
||||
{
|
||||
for (int i = preUpdateEntities.Count - 1; i >= 0; i--)
|
||||
preUpdateEntities[i].PreUpdate();
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ public class Universe : BaseEntity, IUniverse
|
||||
private readonly Event<IInitializable>.EventHandler delegateOnUniverseObjectFinalize = 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;
|
||||
|
||||
public Universe()
|
||||
|
@@ -19,7 +19,7 @@ public class UniverseObject : BaseEntity, IUniverseObject
|
||||
private IUniverse _universe = null!;
|
||||
private IBehaviourController _behaviourController = null!;
|
||||
private bool _isActive = false;
|
||||
private readonly List<IUniverseObject> _children = [];
|
||||
private readonly FastList<IUniverseObject> _children = [];
|
||||
private IUniverseObject? _parent = null;
|
||||
|
||||
public IReadOnlyList<IUniverseObject> Children => _children;
|
||||
|
@@ -10,11 +10,11 @@ namespace Engine.Integration.MonoGame;
|
||||
|
||||
public class KeyboardInputs : Behaviour, IButtonInputs<Keys>, IUpdate
|
||||
{
|
||||
public Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments> OnAnyButtonPressed { get; } = new();
|
||||
public Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments> OnAnyButtonReleased { get; } = new();
|
||||
public IButtonInputs<Keys>.InputEvent OnAnyButtonPressed { get; } = new();
|
||||
public IButtonInputs<Keys>.InputEvent OnAnyButtonReleased { get; } = new();
|
||||
|
||||
private readonly Dictionary<Keys, Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>> OnPressed = new(256);
|
||||
private readonly Dictionary<Keys, Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>> OnReleased = new(256);
|
||||
private readonly Dictionary<Keys, IButtonInputs<Keys>.InputEvent> OnPressed = new(256);
|
||||
private readonly Dictionary<Keys, IButtonInputs<Keys>.InputEvent> OnReleased = new(256);
|
||||
|
||||
private int cachePressedCurrentlyCount = 0;
|
||||
private readonly Keys[] cachePressedCurrently = new Keys[256];
|
||||
@@ -22,9 +22,9 @@ public class KeyboardInputs : Behaviour, IButtonInputs<Keys>, IUpdate
|
||||
private int cachePressedPreviouslyCount = 0;
|
||||
private readonly Keys[] cachePressedPreviously = new Keys[256];
|
||||
|
||||
public void RegisterOnPress(Keys key, Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>.EventHandler callback)
|
||||
public void RegisterOnPress(Keys key, IButtonInputs<Keys>.InputEvent.EventHandler callback)
|
||||
{
|
||||
if (!OnPressed.TryGetValue(key, out Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>? delegateCallback))
|
||||
if (!OnPressed.TryGetValue(key, out IButtonInputs<Keys>.InputEvent? delegateCallback))
|
||||
{
|
||||
delegateCallback = new();
|
||||
OnPressed.Add(key, delegateCallback);
|
||||
@@ -33,15 +33,15 @@ public class KeyboardInputs : Behaviour, IButtonInputs<Keys>, IUpdate
|
||||
delegateCallback.AddListener(callback);
|
||||
}
|
||||
|
||||
public void UnregisterOnPress(Keys key, Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>.EventHandler callback)
|
||||
public void UnregisterOnPress(Keys key, IButtonInputs<Keys>.InputEvent.EventHandler callback)
|
||||
{
|
||||
if (OnPressed.TryGetValue(key, out Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>? delegateCallback))
|
||||
if (OnPressed.TryGetValue(key, out IButtonInputs<Keys>.InputEvent? delegateCallback))
|
||||
delegateCallback.RemoveListener(callback);
|
||||
}
|
||||
|
||||
public void RegisterOnRelease(Keys key, Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>.EventHandler callback)
|
||||
public void RegisterOnRelease(Keys key, IButtonInputs<Keys>.InputEvent.EventHandler callback)
|
||||
{
|
||||
if (!OnReleased.TryGetValue(key, out Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>? delegateCallback))
|
||||
if (!OnReleased.TryGetValue(key, out IButtonInputs<Keys>.InputEvent? delegateCallback))
|
||||
{
|
||||
delegateCallback = new();
|
||||
OnReleased.Add(key, delegateCallback);
|
||||
@@ -50,9 +50,9 @@ public class KeyboardInputs : Behaviour, IButtonInputs<Keys>, IUpdate
|
||||
delegateCallback.AddListener(callback);
|
||||
}
|
||||
|
||||
public void UnregisterOnRelease(Keys key, Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>.EventHandler callback)
|
||||
public void UnregisterOnRelease(Keys key, IButtonInputs<Keys>.InputEvent.EventHandler callback)
|
||||
{
|
||||
if (OnReleased.TryGetValue(key, out Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>? delegateCallback))
|
||||
if (OnReleased.TryGetValue(key, out IButtonInputs<Keys>.InputEvent? delegateCallback))
|
||||
delegateCallback.RemoveListener(callback);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public class KeyboardInputs : Behaviour, IButtonInputs<Keys>, IUpdate
|
||||
if (WasPressed(currentlyPressedKey))
|
||||
continue;
|
||||
|
||||
if (OnPressed.TryGetValue(currentlyPressedKey, out Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>? callback))
|
||||
if (OnPressed.TryGetValue(currentlyPressedKey, out IButtonInputs<Keys>.InputEvent? callback))
|
||||
callback?.Invoke(this, new(currentlyPressedKey));
|
||||
|
||||
OnAnyButtonPressed?.Invoke(this, new(currentlyPressedKey));
|
||||
@@ -82,7 +82,7 @@ public class KeyboardInputs : Behaviour, IButtonInputs<Keys>, IUpdate
|
||||
if (IsPressed(previouslyPressedKey))
|
||||
continue;
|
||||
|
||||
if (OnReleased.TryGetValue(previouslyPressedKey, out Event<IButtonInputs<Keys>, IButtonInputs<Keys>.ButtonCallbackArguments>? callback))
|
||||
if (OnReleased.TryGetValue(previouslyPressedKey, out IButtonInputs<Keys>.InputEvent? callback))
|
||||
callback?.Invoke(this, new(previouslyPressedKey));
|
||||
|
||||
OnAnyButtonReleased?.Invoke(this, new(previouslyPressedKey));
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Engine.Core;
|
||||
|
||||
namespace Engine.Integration.MonoGame;
|
||||
@@ -6,9 +7,10 @@ namespace Engine.Integration.MonoGame;
|
||||
public class LoadContentManager : Behaviour, IFirstFrameUpdate
|
||||
{
|
||||
// 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 MonoGameWindowContainer monoGameWindowContainer = null!;
|
||||
|
@@ -6,12 +6,13 @@ namespace Engine.Integration.MonoGame;
|
||||
|
||||
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 MonoGameCamera2D camera2D = null!;
|
||||
|
||||
private readonly ActiveBehaviourCollectorSorted<IDrawableSprite> drawableSprites = new() { SortBy = SortByPriority() };
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IDrawableSprite> drawableSprites = new(GetPriority(), SortByPriority());
|
||||
|
||||
public void FirstActiveFrame()
|
||||
{
|
||||
|
@@ -8,11 +8,13 @@ namespace Engine.Integration.MonoGame;
|
||||
|
||||
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 MonoGameCamera2D camera2D = null!;
|
||||
private readonly ActiveBehaviourCollectorSorted<IDrawableTriangle> drawableShapes = new() { SortBy = SortByAscendingPriority() };
|
||||
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IDrawableTriangle> drawableShapes = new(GetPriority(), SortByAscendingPriority());
|
||||
|
||||
public void FirstActiveFrame()
|
||||
{
|
||||
|
@@ -58,6 +58,9 @@ public class TriangleBatch : ITriangleBatch
|
||||
|
||||
private void Flush()
|
||||
{
|
||||
if (verticesIndex == 0)
|
||||
return;
|
||||
|
||||
graphicsDevice.RasterizerState = rasterizerState;
|
||||
basicEffect.Projection = _projection;
|
||||
basicEffect.View = _view;
|
||||
|
@@ -17,11 +17,12 @@ public class PhysicsEngine2D : Behaviour, IPreUpdate, IPhysicsEngine2D
|
||||
protected readonly ICollisionResolver2D collisionResolver = null!;
|
||||
protected readonly IRaycastResolver2D raycastResolver = null!;
|
||||
|
||||
private static Comparer<IBehaviour> SortByPriority() => Comparer<IBehaviour>.Create((x, y) => y.Priority.CompareTo(x.Priority));
|
||||
protected ActiveBehaviourCollectorSorted<IPrePhysicsUpdate> physicsPreUpdateCollector = new() { SortBy = SortByPriority() };
|
||||
protected ActiveBehaviourCollectorSorted<IPhysicsUpdate> physicsUpdateCollector = new() { SortBy = SortByPriority() };
|
||||
protected ActiveBehaviourCollectorSorted<IPhysicsIteration> physicsIterationCollector = new() { SortBy = SortByPriority() };
|
||||
protected ActiveBehaviourCollectorSorted<IPostPhysicsUpdate> physicsPostUpdateCollector = new() { SortBy = SortByPriority() };
|
||||
private static Comparer<int> SortByPriority() => Comparer<int>.Create((x, y) => y.CompareTo(x));
|
||||
private static System.Func<IBehaviour, int> GetPriority() => (b) => b.Priority;
|
||||
protected ActiveBehaviourCollectorOrdered<int, IPrePhysicsUpdate> physicsPreUpdateCollector = new(GetPriority(), SortByPriority());
|
||||
protected ActiveBehaviourCollectorOrdered<int, IPhysicsUpdate> physicsUpdateCollector = new(GetPriority(), SortByPriority());
|
||||
protected ActiveBehaviourCollectorOrdered<int, IPhysicsIteration> physicsIterationCollector = new(GetPriority(), SortByPriority());
|
||||
protected ActiveBehaviourCollectorOrdered<int, IPostPhysicsUpdate> physicsPostUpdateCollector = new(GetPriority(), SortByPriority());
|
||||
protected BehaviourCollector<IRigidBody2D> rigidBodyCollector = new();
|
||||
protected BehaviourCollector<ICollider2D> colliderCollector = new();
|
||||
|
||||
|
1
Engine.Serializers/YamlDotNet
Submodule
1
Engine.Serializers/YamlDotNet
Submodule
Submodule Engine.Serializers/YamlDotNet added at 62048d7abe
@@ -4,15 +4,17 @@ namespace Engine.Systems.Input;
|
||||
|
||||
public interface IButtonInputs<T> : IHasStateEnable
|
||||
{
|
||||
Event<IButtonInputs<T>, ButtonCallbackArguments> OnAnyButtonPressed { get; }
|
||||
Event<IButtonInputs<T>, ButtonCallbackArguments> OnAnyButtonReleased { get; }
|
||||
InputEvent OnAnyButtonPressed { get; }
|
||||
InputEvent OnAnyButtonReleased { get; }
|
||||
|
||||
void RegisterOnPress(T button, Event<IButtonInputs<T>, ButtonCallbackArguments>.EventHandler callback);
|
||||
void UnregisterOnPress(T button, Event<IButtonInputs<T>, ButtonCallbackArguments>.EventHandler callback);
|
||||
void RegisterOnRelease(T button, Event<IButtonInputs<T>, ButtonCallbackArguments>.EventHandler callback);
|
||||
void UnregisterOnRelease(T button, Event<IButtonInputs<T>, ButtonCallbackArguments>.EventHandler callback);
|
||||
void RegisterOnPress(T button, InputEvent.EventHandler callback);
|
||||
void UnregisterOnPress(T button, InputEvent.EventHandler callback);
|
||||
void RegisterOnRelease(T button, InputEvent.EventHandler callback);
|
||||
void UnregisterOnRelease(T button, InputEvent.EventHandler callback);
|
||||
|
||||
bool IsPressed(T button);
|
||||
|
||||
readonly record struct ButtonCallbackArguments(T Button);
|
||||
|
||||
class InputEvent : Event<IButtonInputs<T>, ButtonCallbackArguments>;
|
||||
}
|
||||
|
@@ -16,22 +16,3 @@ public interface INetworkCommunicator
|
||||
INetworkCommunicator SubscribeToPackets<T>(Event<IConnection, T>.EventHandler callback);
|
||||
INetworkCommunicator UnsubscribeFromPackets<T>(Event<IConnection, T>.EventHandler callback);
|
||||
}
|
||||
|
||||
public interface INetworkCommunicatorClient : INetworkCommunicator
|
||||
{
|
||||
INetworkCommunicatorClient Connect(string address, int port, string? password = null);
|
||||
|
||||
INetworkCommunicatorClient SendToServer<T>(T packet, PacketDelivery packetDelivery = PacketDelivery.ReliableInOrder) where T : class, new();
|
||||
}
|
||||
|
||||
public interface INetworkCommunicatorServer : INetworkCommunicator
|
||||
{
|
||||
string Password { get; }
|
||||
int MaxConnectionCount { get; }
|
||||
int Port { get; }
|
||||
|
||||
INetworkCommunicatorServer Start(int port, int maxConnectionCount, string? password = null);
|
||||
|
||||
INetworkCommunicatorServer SendToClient<T>(IConnection connection, T packet, PacketDelivery packetDelivery = PacketDelivery.ReliableInOrder) where T : class, new();
|
||||
INetworkCommunicatorServer SendToAll<T>(T packet, PacketDelivery packetDelivery = PacketDelivery.ReliableInOrder) where T : class, new();
|
||||
}
|
||||
|
@@ -0,0 +1,8 @@
|
||||
namespace Engine.Systems.Network;
|
||||
|
||||
public interface INetworkCommunicatorClient : INetworkCommunicator
|
||||
{
|
||||
INetworkCommunicatorClient Connect(string address, int port, string? password = null);
|
||||
|
||||
INetworkCommunicatorClient SendToServer<T>(T packet, PacketDelivery packetDelivery = PacketDelivery.ReliableInOrder) where T : class, new();
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
namespace Engine.Systems.Network;
|
||||
|
||||
public interface INetworkCommunicatorServer : INetworkCommunicator
|
||||
{
|
||||
string Password { get; }
|
||||
int MaxConnectionCount { get; }
|
||||
int Port { get; }
|
||||
|
||||
INetworkCommunicatorServer Start(int port, int maxConnectionCount, string? password = null);
|
||||
|
||||
INetworkCommunicatorServer SendToClient<T>(IConnection connection, T packet, PacketDelivery packetDelivery = PacketDelivery.ReliableInOrder) where T : class, new();
|
||||
INetworkCommunicatorServer SendToAll<T>(T packet, PacketDelivery packetDelivery = PacketDelivery.ReliableInOrder) where T : class, new();
|
||||
}
|
27
Engine.Systems/Network/TypeHasher.cs
Normal file
27
Engine.Systems/Network/TypeHasher.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
namespace Engine.Systems.Network;
|
||||
|
||||
public static class TypeHasher<T>
|
||||
{
|
||||
private static long _fnv1a = 0;
|
||||
public static long FNV1a
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_fnv1a == 0)
|
||||
unchecked
|
||||
{
|
||||
const long fnvPrime = 1099511628211;
|
||||
_fnv1a = 1469598103934665603;
|
||||
|
||||
string typeName = typeof(T).FullName ?? typeof(T).Name;
|
||||
foreach (char c in typeName)
|
||||
{
|
||||
_fnv1a ^= c;
|
||||
_fnv1a *= fnvPrime;
|
||||
}
|
||||
}
|
||||
|
||||
return _fnv1a;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,10 +1,24 @@
|
||||
using System;
|
||||
using Engine.Core;
|
||||
|
||||
namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenAABBExtensions
|
||||
{
|
||||
public static ITween TweenAABB(this AABB initialAABB, ITweenManager tweenManager, float duration, AABB targetAABB, Action<AABB> setMethod)
|
||||
=> tweenManager.StartTween(duration, t => setMethod?.Invoke(new AABB(initialAABB.LowerBoundary.Lerp(targetAABB.LowerBoundary, t), initialAABB.UpperBoundary.Lerp(targetAABB.UpperBoundary, t))));
|
||||
private static readonly BoxedPool<AABB> boxedAABBPool = new(2);
|
||||
|
||||
public static ITween TweenAABB(this AABB initialAABB, ITweenManager tweenManager, float duration, AABB targetAABB, System.Action<AABB> setMethod)
|
||||
{
|
||||
Boxed<AABB> boxedInitial = boxedAABBPool.Get(initialAABB);
|
||||
Boxed<AABB> boxedTarget = boxedAABBPool.Get(targetAABB);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(new AABB(boxedInitial.Value.LowerBoundary.Lerp(boxedTarget.Value.LowerBoundary, t), boxedInitial.Value.UpperBoundary.Lerp(boxedTarget.Value.UpperBoundary, t))));
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedAABBPool.Return(boxedInitial);
|
||||
boxedAABBPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
||||
|
@@ -4,9 +4,21 @@ namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenCamera2DExtensions
|
||||
{
|
||||
private static readonly BoxedPool<float> boxedFloatPool = new(2);
|
||||
|
||||
public static ITween TweenZoom(this ICamera2D camera2D, ITweenManager tweenManager, float duration, float targetZoom)
|
||||
{
|
||||
float initialZoom = camera2D.Zoom;
|
||||
return tweenManager.StartTween(duration, t => camera2D.Zoom = initialZoom.Lerp(targetZoom, t));
|
||||
Boxed<float> boxedInitial = boxedFloatPool.Get(camera2D.Zoom);
|
||||
Boxed<float> boxedTarget = boxedFloatPool.Get(targetZoom);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration, t => camera2D.Zoom = boxedInitial.Value.Lerp(boxedTarget.Value, t));
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedFloatPool.Return(boxedInitial);
|
||||
boxedFloatPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
||||
|
@@ -4,13 +4,28 @@ namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenCircleExtensions
|
||||
{
|
||||
private static readonly BoxedPool<Circle> boxedCirclePool = new(2);
|
||||
|
||||
public static ITween TweenCircle(this Circle initialCircle, ITweenManager tweenManager, float duration, Circle targetCircle, System.Action<Circle> setMethod)
|
||||
=> tweenManager.StartTween(duration,
|
||||
{
|
||||
Boxed<Circle> boxedInitial = boxedCirclePool.Get(initialCircle);
|
||||
Boxed<Circle> boxedTarget = boxedCirclePool.Get(targetCircle);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration,
|
||||
t => setMethod?.Invoke(
|
||||
new Circle(
|
||||
initialCircle.Center.Lerp(targetCircle.Center, t),
|
||||
initialCircle.Diameter.Lerp(targetCircle.Diameter, t)
|
||||
boxedInitial.Value.Center.Lerp(boxedTarget.Value.Center, t),
|
||||
boxedInitial.Value.Diameter.Lerp(boxedTarget.Value.Diameter, t)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedCirclePool.Return(boxedInitial);
|
||||
boxedCirclePool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,9 @@ namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenColorExtensions
|
||||
{
|
||||
private static readonly BoxedPool<ColorHSV> boxedColorHSVPool = new(2);
|
||||
private static readonly BoxedPool<ColorHSVA> boxedColorHSVAPool = new(2);
|
||||
|
||||
public static ITween TweenColor(this ColorRGB initialColorRGB, ITweenManager tweenManager, float duration, ColorRGB targetColorRGB, System.Action<ColorRGB> setMethod)
|
||||
=> TweenColor((ColorHSV)initialColorRGB, tweenManager, duration, (ColorHSV)targetColorRGB, color => setMethod?.Invoke(color));
|
||||
|
||||
@@ -11,8 +14,34 @@ public static class TweenColorExtensions
|
||||
=> TweenColor((ColorHSVA)initialColorRGBA, tweenManager, duration, (ColorHSVA)targetColorRGBA, color => setMethod?.Invoke(color));
|
||||
|
||||
public static ITween TweenColor(this ColorHSV initialColorHSV, ITweenManager tweenManager, float duration, ColorHSV targetColorHSV, System.Action<ColorHSV> setMethod)
|
||||
=> tweenManager.StartTween(duration, t => setMethod?.Invoke(initialColorHSV.Lerp(targetColorHSV, t)));
|
||||
{
|
||||
Boxed<ColorHSV> boxedInitial = boxedColorHSVPool.Get(initialColorHSV);
|
||||
Boxed<ColorHSV> boxedTarget = boxedColorHSVPool.Get(targetColorHSV);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(boxedInitial.Value.Lerp(boxedTarget.Value, t)));
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedColorHSVPool.Return(boxedInitial);
|
||||
boxedColorHSVPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
|
||||
public static ITween TweenColor(this ColorHSVA initialColorHSVA, ITweenManager tweenManager, float duration, ColorHSVA targetColorHSVA, System.Action<ColorHSVA> setMethod)
|
||||
=> tweenManager.StartTween(duration, t => setMethod?.Invoke(initialColorHSVA.Lerp(targetColorHSVA, t)));
|
||||
{
|
||||
Boxed<ColorHSVA> boxedInitial = boxedColorHSVAPool.Get(initialColorHSVA);
|
||||
Boxed<ColorHSVA> boxedTarget = boxedColorHSVAPool.Get(targetColorHSVA);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(boxedInitial.Value.Lerp(boxedTarget.Value, t)));
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedColorHSVAPool.Return(boxedInitial);
|
||||
boxedColorHSVAPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
||||
|
@@ -4,13 +4,28 @@ namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenLine2DEquationExtensions
|
||||
{
|
||||
private static readonly BoxedPool<Line2DEquation> boxedLine2DEquationPool = new(2);
|
||||
|
||||
public static ITween TweenLine2DEquation(this Line2DEquation initialLine2DEquation, ITweenManager tweenManager, float duration, Line2DEquation targetLine2DEquation, System.Action<Line2DEquation> setMethod)
|
||||
=> tweenManager.StartTween(duration,
|
||||
{
|
||||
Boxed<Line2DEquation> boxedInitial = boxedLine2DEquationPool.Get(initialLine2DEquation);
|
||||
Boxed<Line2DEquation> boxedTarget = boxedLine2DEquationPool.Get(targetLine2DEquation);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration,
|
||||
t => setMethod?.Invoke(
|
||||
new Line2DEquation(
|
||||
initialLine2DEquation.Slope.Lerp(targetLine2DEquation.Slope, t),
|
||||
initialLine2DEquation.OffsetY.Lerp(targetLine2DEquation.OffsetY, t)
|
||||
boxedInitial.Value.Slope.Lerp(boxedTarget.Value.Slope, t),
|
||||
boxedInitial.Value.OffsetY.Lerp(boxedTarget.Value.OffsetY, t)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedLine2DEquationPool.Return(boxedInitial);
|
||||
boxedLine2DEquationPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
||||
|
@@ -4,13 +4,28 @@ namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenLine2DExtensions
|
||||
{
|
||||
private static readonly BoxedPool<Line2D> boxedLine2DPool = new(2);
|
||||
|
||||
public static ITween TweenLine2D(this Line2D initialLine2D, ITweenManager tweenManager, float duration, Line2D targetLine2D, System.Action<Line2D> setMethod)
|
||||
=> tweenManager.StartTween(duration,
|
||||
{
|
||||
Boxed<Line2D> boxedInitial = boxedLine2DPool.Get(initialLine2D);
|
||||
Boxed<Line2D> boxedTarget = boxedLine2DPool.Get(targetLine2D);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration,
|
||||
t => setMethod?.Invoke(
|
||||
new Line2D(
|
||||
initialLine2D.From.Lerp(targetLine2D.From, t),
|
||||
initialLine2D.To.Lerp(targetLine2D.To, t)
|
||||
boxedInitial.Value.From.Lerp(boxedTarget.Value.From, t),
|
||||
boxedInitial.Value.To.Lerp(boxedTarget.Value.To, t)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedLine2DPool.Return(boxedInitial);
|
||||
boxedLine2DPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,41 @@
|
||||
using Engine.Core;
|
||||
|
||||
namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenPrimitiveExtensions
|
||||
{
|
||||
private static readonly BoxedPool<float> boxedFloatPool = new(2);
|
||||
private static readonly BoxedPool<int> boxedIntPool = new(2);
|
||||
|
||||
public static ITween TweenFloat(this float initialFloat, ITweenManager tweenManager, float duration, float targetFloat, System.Action<float> setMethod)
|
||||
{
|
||||
Boxed<float> boxedInitial = boxedFloatPool.Get(initialFloat);
|
||||
Boxed<float> boxedTarget = boxedFloatPool.Get(targetFloat);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(boxedInitial.Value.Lerp(boxedTarget.Value, t)));
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedFloatPool.Return(boxedInitial);
|
||||
boxedFloatPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
|
||||
public static ITween TweenInt(this int initialInt, ITweenManager tweenManager, float duration, int targetInt, System.Action<float> setMethod)
|
||||
{
|
||||
Boxed<int> boxedInitial = boxedIntPool.Get(initialInt);
|
||||
Boxed<int> boxedTarget = boxedIntPool.Get(targetInt);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(boxedInitial.Value + (boxedTarget.Value - boxedInitial.Value) * t));
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedIntPool.Return(boxedInitial);
|
||||
boxedIntPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
@@ -1,17 +1,31 @@
|
||||
using System;
|
||||
using Engine.Core;
|
||||
|
||||
namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenProjection1DExtensions
|
||||
{
|
||||
public static ITween TweenProjection1D(this Projection1D initialProjection1D, ITweenManager tweenManager, float duration, Projection1D targetProjection1D, Action<Projection1D> setMethod)
|
||||
=> tweenManager.StartTween(duration,
|
||||
private static readonly BoxedPool<Projection1D> boxedProjection1DPool = new(2);
|
||||
|
||||
public static ITween TweenProjection1D(this Projection1D initialProjection1D, ITweenManager tweenManager, float duration, Projection1D targetProjection1D, System.Action<Projection1D> setMethod)
|
||||
{
|
||||
Boxed<Projection1D> boxedInitial = boxedProjection1DPool.Get(initialProjection1D);
|
||||
Boxed<Projection1D> boxedTarget = boxedProjection1DPool.Get(targetProjection1D);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration,
|
||||
t => setMethod?.Invoke(
|
||||
new Projection1D(
|
||||
initialProjection1D.Min.Lerp(targetProjection1D.Min, t),
|
||||
initialProjection1D.Max.Lerp(targetProjection1D.Max, t)
|
||||
boxedInitial.Value.Min.Lerp(boxedTarget.Value.Min, t),
|
||||
boxedInitial.Value.Max.Lerp(boxedTarget.Value.Max, t)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedProjection1DPool.Return(boxedInitial);
|
||||
boxedProjection1DPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,24 @@
|
||||
using System;
|
||||
using Engine.Core;
|
||||
|
||||
namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenQuaternionExtensions
|
||||
{
|
||||
public static ITween TweenQuaternion(this Quaternion initialQuaternion, ITweenManager tweenManager, float duration, Quaternion targetQuaternion, Action<Quaternion> setMethod)
|
||||
=> tweenManager.StartTween(duration, t => setMethod?.Invoke(initialQuaternion.SLerp(targetQuaternion, t)));
|
||||
private static readonly BoxedPool<Quaternion> boxedQuaternionPool = new(2);
|
||||
|
||||
public static ITween TweenQuaternion(this Quaternion initialQuaternion, ITweenManager tweenManager, float duration, Quaternion targetQuaternion, System.Action<Quaternion> setMethod)
|
||||
{
|
||||
Boxed<Quaternion> boxedInitial = boxedQuaternionPool.Get(initialQuaternion);
|
||||
Boxed<Quaternion> boxedTarget = boxedQuaternionPool.Get(targetQuaternion);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(boxedInitial.Value.SLerp(boxedTarget.Value, t)));
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedQuaternionPool.Return(boxedInitial);
|
||||
boxedQuaternionPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
||||
|
@@ -5,40 +5,23 @@ namespace Engine.Systems.Tween;
|
||||
public static class TweenTransform2DExtensions
|
||||
{
|
||||
public static ITween TweenPosition(this ITransform2D transform2D, ITweenManager tweenManager, float duration, Vector2D targetPosition)
|
||||
{
|
||||
Vector2D initialPosition = transform2D.Position;
|
||||
return tweenManager.StartTween(duration, t => transform2D.Position = initialPosition.Lerp(targetPosition, t));
|
||||
}
|
||||
=> transform2D.Position.TweenVector2D(tweenManager, duration, targetPosition, x => transform2D.Position = x);
|
||||
|
||||
public static ITween TweenScale(this ITransform2D transform2D, ITweenManager tweenManager, float duration, Vector2D targetScale)
|
||||
{
|
||||
Vector2D initialScale = transform2D.Scale;
|
||||
return tweenManager.StartTween(duration, t => transform2D.Scale = initialScale.Lerp(targetScale, t));
|
||||
}
|
||||
=> transform2D.Scale.TweenVector2D(tweenManager, duration, targetScale, x => transform2D.Scale = x);
|
||||
|
||||
public static ITween TweenRotation(this ITransform2D transform2D, ITweenManager tweenManager, float duration, float targetRotation)
|
||||
{
|
||||
float initialRotation = transform2D.Rotation;
|
||||
return tweenManager.StartTween(duration, t => transform2D.Rotation = initialRotation.Lerp(targetRotation, t));
|
||||
}
|
||||
=> transform2D.Rotation.TweenFloat(tweenManager, duration, targetRotation, x => transform2D.Rotation = x);
|
||||
|
||||
public static ITween TweenLocalPosition(this ITransform2D transform2D, ITweenManager tweenManager, float duration, Vector2D targetLocalPosition)
|
||||
{
|
||||
Vector2D initialLocalPosition = transform2D.LocalPosition;
|
||||
return tweenManager.StartTween(duration, t => transform2D.LocalPosition = initialLocalPosition.Lerp(targetLocalPosition, t));
|
||||
}
|
||||
=> transform2D.LocalPosition.TweenVector2D(tweenManager, duration, targetLocalPosition, x => transform2D.LocalPosition = x);
|
||||
|
||||
public static ITween TweenLocalScale(this ITransform2D transform2D, ITweenManager tweenManager, float duration, Vector2D targetLocalScale)
|
||||
{
|
||||
Vector2D initialLocalScale = transform2D.LocalScale;
|
||||
return tweenManager.StartTween(duration, t => transform2D.LocalScale = initialLocalScale.Lerp(targetLocalScale, t));
|
||||
}
|
||||
=> transform2D.LocalScale.TweenVector2D(tweenManager, duration, targetLocalScale, x => transform2D.LocalScale = x);
|
||||
|
||||
public static ITween TweenLocalRotation(this ITransform2D transform2D, ITweenManager tweenManager, float duration, float targetLocalRotation)
|
||||
{
|
||||
float initialLocalRotation = transform2D.LocalRotation;
|
||||
return tweenManager.StartTween(duration, t => transform2D.LocalRotation = initialLocalRotation.Lerp(targetLocalRotation, t));
|
||||
}
|
||||
=> transform2D.LocalRotation.TweenFloat(tweenManager, duration, targetLocalRotation, x => transform2D.LocalRotation = x);
|
||||
|
||||
public static ITween TweenPositionAdditive(this ITransform2D transform2D, ITweenManager tweenManager, float duration, Vector2D additivePosition)
|
||||
{
|
||||
Vector2D progressedPosition = Vector2D.Zero;
|
||||
|
@@ -1,18 +1,31 @@
|
||||
using System;
|
||||
using Engine.Core;
|
||||
|
||||
namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenTriangleExtensions
|
||||
{
|
||||
public static ITween TweenTriangle(this Triangle initialTriangle, ITweenManager tweenManager, float duration, Triangle targetTriangle, Action<Triangle> setMethod)
|
||||
=> tweenManager.StartTween(duration,
|
||||
t => setMethod?.Invoke(
|
||||
private static readonly BoxedPool<Triangle> boxedTrianglePool = new(2);
|
||||
|
||||
public static ITween TweenTriangle(this Triangle initialTriangle, ITweenManager tweenManager, float duration, Triangle targetTriangle, System.Action<Triangle> setMethod)
|
||||
{
|
||||
Boxed<Triangle> boxedInitial = boxedTrianglePool.Get(initialTriangle);
|
||||
Boxed<Triangle> boxedTarget = boxedTrianglePool.Get(targetTriangle);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(
|
||||
new Triangle(
|
||||
initialTriangle.A.Lerp(targetTriangle.A, t),
|
||||
initialTriangle.B.Lerp(targetTriangle.B, t),
|
||||
initialTriangle.C.Lerp(targetTriangle.C, t)
|
||||
boxedInitial.Value.A.Lerp(boxedTarget.Value.A, t),
|
||||
boxedInitial.Value.B.Lerp(boxedTarget.Value.B, t),
|
||||
boxedInitial.Value.C.Lerp(boxedTarget.Value.C, t)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedTrianglePool.Return(boxedInitial);
|
||||
boxedTrianglePool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,21 @@ namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenVector2DExtensions
|
||||
{
|
||||
private static readonly BoxedPool<Vector2D> boxedVector2DPool = new(2);
|
||||
|
||||
public static ITween TweenVector2D(this Vector2D initialVector2D, ITweenManager tweenManager, float duration, Vector2D targetVector2D, System.Action<Vector2D> setMethod)
|
||||
=> tweenManager.StartTween(duration, t => setMethod?.Invoke(initialVector2D.Lerp(targetVector2D, t)));
|
||||
{
|
||||
Boxed<Vector2D> boxedInitial = boxedVector2DPool.Get(initialVector2D);
|
||||
Boxed<Vector2D> boxedTarget = boxedVector2DPool.Get(targetVector2D);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(boxedInitial.Value.Lerp(boxedTarget.Value, t)));
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedVector2DPool.Return(boxedInitial);
|
||||
boxedVector2DPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,21 @@ namespace Engine.Systems.Tween;
|
||||
|
||||
public static class TweenVector3DExtensions
|
||||
{
|
||||
private static readonly BoxedPool<Vector3D> boxedVector3DPool = new(2);
|
||||
|
||||
public static ITween TweenVector3D(this Vector3D initialVector3D, ITweenManager tweenManager, float duration, Vector3D targetVector3D, System.Action<Vector3D> setMethod)
|
||||
=> tweenManager.StartTween(duration, t => setMethod?.Invoke(initialVector3D.Lerp(targetVector3D, t)));
|
||||
{
|
||||
Boxed<Vector3D> boxedInitial = boxedVector3DPool.Get(initialVector3D);
|
||||
Boxed<Vector3D> boxedTarget = boxedVector3DPool.Get(targetVector3D);
|
||||
|
||||
ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(boxedInitial.Value.Lerp(boxedTarget.Value, t)));
|
||||
|
||||
tween.OnComplete(() =>
|
||||
{
|
||||
boxedVector3DPool.Return(boxedInitial);
|
||||
boxedVector3DPool.Return(boxedTarget);
|
||||
});
|
||||
|
||||
return tween;
|
||||
}
|
||||
}
|
||||
|
12
Engine.Systems/Tween/Helpers/Boxed.cs
Normal file
12
Engine.Systems/Tween/Helpers/Boxed.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Engine.Core;
|
||||
|
||||
namespace Engine.Systems.Tween;
|
||||
|
||||
public class Boxed<T> where T : struct
|
||||
{
|
||||
public Event<Boxed<T>, BoxedValueChangedArguments> OnValueChanged { get; } = new();
|
||||
|
||||
public T Value { get; set; } = default;
|
||||
|
||||
public readonly record struct BoxedValueChangedArguments(T PreviousValue, T CurrentValue);
|
||||
}
|
14
Engine.Systems/Tween/Helpers/BoxedPool.cs
Normal file
14
Engine.Systems/Tween/Helpers/BoxedPool.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Engine.Core;
|
||||
|
||||
namespace Engine.Systems.Tween;
|
||||
|
||||
public class BoxedPool<T>(int initialCapacity = 1) : Pool<Boxed<T>>(() => new(), initialCapacity) where T : struct;
|
||||
public static class BoxedPoolExtensions
|
||||
{
|
||||
public static Boxed<T> Get<T>(this BoxedPool<T> boxedPool, T value) where T : struct
|
||||
{
|
||||
Boxed<T> boxed = boxedPool.Get();
|
||||
boxed.Value = value;
|
||||
return boxed;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user