diff --git a/Engine.Core/ActiveBehaviourCollector.cs b/Engine.Core/ActiveBehaviourCollector.cs index 533ff47..f138a59 100644 --- a/Engine.Core/ActiveBehaviourCollector.cs +++ b/Engine.Core/ActiveBehaviourCollector.cs @@ -56,12 +56,13 @@ public class ActiveBehaviourCollector : IBehaviourCollector where T : clas 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) { - activeBehaviours.Add(behaviour); + AddBehaviour(behaviour); OnBehaviourAdd(behaviour); OnCollected?.Invoke(this, new(behaviour)); } diff --git a/Engine.Core/ActiveBehaviourCollectorSorted.cs b/Engine.Core/ActiveBehaviourCollectorSorted.cs index e1622ff..292f6b5 100644 --- a/Engine.Core/ActiveBehaviourCollectorSorted.cs +++ b/Engine.Core/ActiveBehaviourCollectorSorted.cs @@ -1,11 +1,14 @@ using System; +using System.Collections.Generic; namespace Syntriax.Engine.Core; public class ActiveBehaviourCollectorSorted : ActiveBehaviourCollector where T : class, IBehaviour { - private Comparison? _sortBy = null; - public Comparison? SortBy + private readonly Event.EventHandler delegateOnPriorityChanged = null!; + + private IComparer? _sortBy = null; + public IComparer? SortBy { get => _sortBy; set @@ -17,12 +20,48 @@ public class ActiveBehaviourCollectorSorted : ActiveBehaviourCollector whe } } - protected override void OnBehaviourAdd(IBehaviour behaviour) + protected override void AddBehaviour(T behaviour) { - if (SortBy is not null) - activeBehaviours.Sort(SortBy); + if (SortBy is null) + { + activeBehaviours.Add(behaviour); + return; + } + + int insertionIndex = activeBehaviours.BinarySearch(behaviour, SortBy); + + if (insertionIndex < 0) + insertionIndex = ~insertionIndex; + + activeBehaviours.Insert(insertionIndex, behaviour); } - public ActiveBehaviourCollectorSorted() { } - public ActiveBehaviourCollectorSorted(IUniverse universe, Comparison sortBy) : base(universe) => SortBy = sortBy; + 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 sortBy) : base(universe) + { + delegateOnPriorityChanged = OnPriorityChanged; + + SortBy = Comparer.Create(sortBy); + } } diff --git a/Engine.Core/BehaviourCollector.cs b/Engine.Core/BehaviourCollector.cs index ae04f3a..19d8782 100644 --- a/Engine.Core/BehaviourCollector.cs +++ b/Engine.Core/BehaviourCollector.cs @@ -41,13 +41,14 @@ public class BehaviourCollector : IBehaviourCollector where T : class 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; - behaviours.Add(tBehaviour); + AddBehaviour(tBehaviour); OnBehaviourAdd(args.BehaviourAdded); OnCollected?.Invoke(this, new(tBehaviour)); } diff --git a/Engine.Core/BehaviourCollectorSorted.cs b/Engine.Core/BehaviourCollectorSorted.cs index 6f93f76..35effbc 100644 --- a/Engine.Core/BehaviourCollectorSorted.cs +++ b/Engine.Core/BehaviourCollectorSorted.cs @@ -1,11 +1,14 @@ using System; +using System.Collections.Generic; namespace Syntriax.Engine.Core; public class BehaviourCollectorSorted : BehaviourCollector where T : class { - private Comparison? _sortBy = null; - public Comparison? SortBy + private readonly Event.EventHandler delegateOnPriorityChanged = null!; + + private IComparer? _sortBy = null; + public IComparer? SortBy { get => _sortBy; set @@ -17,12 +20,48 @@ public class BehaviourCollectorSorted : BehaviourCollector where T : class } } - protected override void OnBehaviourAdd(IBehaviour behaviour) + protected override void AddBehaviour(T behaviour) { - if (SortBy is not null) - behaviours.Sort(SortBy); + if (SortBy is null) + { + behaviours.Add(behaviour); + return; + } + + int insertionIndex = behaviours.BinarySearch(behaviour, SortBy); + + if (insertionIndex < 0) + insertionIndex = ~insertionIndex; + + behaviours.Insert(insertionIndex, behaviour); } - public BehaviourCollectorSorted() { } - public BehaviourCollectorSorted(IUniverse universe, Comparison sortBy) : base(universe) => SortBy = sortBy; + 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 sortBy) : base(universe) + { + delegateOnPriorityChanged = OnPriorityChanged; + + SortBy = Comparer.Create(sortBy); + } } diff --git a/Engine.Core/Systems/DrawManager.cs b/Engine.Core/Systems/DrawManager.cs index 53f5267..4045c23 100644 --- a/Engine.Core/Systems/DrawManager.cs +++ b/Engine.Core/Systems/DrawManager.cs @@ -1,8 +1,10 @@ +using System.Collections.Generic; + namespace Syntriax.Engine.Core; public class DrawManager : UniverseObject { - private static System.Comparison SortByPriority() => (x, y) => y.Priority.CompareTo(x.Priority); + private static Comparer SortByPriority() => Comparer.Create((x, y) => y.Priority.CompareTo(x.Priority)); private readonly ActiveBehaviourCollectorSorted preDrawEntities = new() { SortBy = SortByPriority() }; private readonly ActiveBehaviourCollectorSorted drawEntities = new() { SortBy = SortByPriority() }; diff --git a/Engine.Core/Systems/UpdateManager.cs b/Engine.Core/Systems/UpdateManager.cs index 470f1c6..2b204dd 100644 --- a/Engine.Core/Systems/UpdateManager.cs +++ b/Engine.Core/Systems/UpdateManager.cs @@ -4,7 +4,7 @@ namespace Syntriax.Engine.Core; public class UpdateManager : UniverseObject { - private static System.Comparison SortByPriority() => (x, y) => y.Priority.CompareTo(x.Priority); + private static Comparer SortByPriority() => Comparer.Create((x, y) => y.Priority.CompareTo(x.Priority)); private readonly ActiveBehaviourCollectorSorted firstFrameUpdates = new() { SortBy = SortByPriority() }; private readonly ActiveBehaviourCollectorSorted preUpdateEntities = new() { SortBy = SortByPriority() }; diff --git a/Engine.Physics2D/PhysicsEngine2D.cs b/Engine.Physics2D/PhysicsEngine2D.cs index 355d0ca..3a378a6 100644 --- a/Engine.Physics2D/PhysicsEngine2D.cs +++ b/Engine.Physics2D/PhysicsEngine2D.cs @@ -1,3 +1,5 @@ +using System.Collections; +using System.Collections.Generic; using Syntriax.Engine.Core; namespace Syntriax.Engine.Physics2D; @@ -16,7 +18,7 @@ public class PhysicsEngine2D : UniverseObject, IPhysicsEngine2D protected readonly ICollisionDetector2D collisionDetector = null!; protected readonly ICollisionResolver2D collisionResolver = null!; - private static System.Comparison SortByPriority() => (x, y) => y.Priority.CompareTo(x.Priority); + private static Comparer SortByPriority() => Comparer.Create((x, y) => y.Priority.CompareTo(x.Priority)); protected ActiveBehaviourCollectorSorted physicsPreUpdateCollector = new() { SortBy = SortByPriority() }; protected ActiveBehaviourCollectorSorted physicsUpdateCollector = new() { SortBy = SortByPriority() }; protected ActiveBehaviourCollectorSorted physicsPostUpdateCollector = new() { SortBy = SortByPriority() };