diff --git a/Engine.Core/Collectors/ActiveBehaviourCollector.cs b/Engine.Core/Collectors/ActiveBehaviourCollector.cs index f6a5fc0..dfe9a2f 100644 --- a/Engine.Core/Collectors/ActiveBehaviourCollector.cs +++ b/Engine.Core/Collectors/ActiveBehaviourCollector.cs @@ -1,148 +1,16 @@ using System; -using System.Collections.Generic; namespace Engine.Core; -public class ActiveBehaviourCollector : IBehaviourCollector where T : class, IBehaviour +public class ActiveBehaviourCollector : ActiveBehaviourCollectorBase where T : class, IBehaviour { - public Event, IBehaviourCollector.BehaviourCollectedArguments> OnCollected { get; } = new(); - public Event, IBehaviourCollector.BehaviourRemovedArguments> OnRemoved { get; } = new(); - public Event OnUniverseAssigned { get; } = new(); - public Event? OnUnassigned { get; } = new(); - - private readonly Event.EventHandler delegateOnBehaviourAdded = null!; - private readonly Event.EventHandler delegateOnBehaviourRemoved = null!; - private readonly Event.EventHandler delegateOnBehaviourStateChanged = null!; - private readonly Event.EventHandler delegateOnUniverseObjectRegistered = null!; - private readonly Event.EventHandler delegateOnUniverseObjectUnregistered = null!; - - private readonly FastList monitoringBehaviours = new(32); protected readonly FastList activeBehaviours = new(32); - protected readonly Dictionary monitoringActiveToBehaviour = new(32); + public override T this[Index index] => activeBehaviours[index]; + public override int Count => activeBehaviours.Count; - public IUniverse Universe { get; private set; } = null!; + public ActiveBehaviourCollector() { } + public ActiveBehaviourCollector(IUniverse universe) : base(universe) { } - 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) - return false; - - foreach (IUniverseObject universeObject in universe.UniverseObjects) - OnUniverseObjectRegistered(universe, new(universeObject)); - - universe.OnUniverseObjectRegistered.AddListener(delegateOnUniverseObjectRegistered); - universe.OnUniverseObjectUnRegistered.AddListener(delegateOnUniverseObjectUnregistered); - - Universe = universe; - OnUniverseAssigned?.Invoke(this); - - return true; - } - - public bool Unassign() - { - if (Universe is null) - return false; - - foreach (IUniverseObject universeObject in Universe.UniverseObjects) - OnUniverseObjectUnregistered(Universe, new(universeObject)); - - Universe.OnUniverseObjectRegistered.RemoveListener(delegateOnUniverseObjectRegistered); - Universe.OnUniverseObjectUnRegistered.RemoveListener(delegateOnUniverseObjectUnregistered); - - Universe = null!; - OnUnassigned?.Invoke(this); - return true; - } - - public int Count => activeBehaviours.Count; - public T this[Index index] => activeBehaviours[index]; - - public ActiveBehaviourCollector() - { - delegateOnBehaviourAdded = OnBehaviourAdded; - delegateOnBehaviourRemoved = OnBehaviourRemoved; - delegateOnBehaviourStateChanged = OnBehaviourStateChanged; - delegateOnUniverseObjectRegistered = OnUniverseObjectRegistered; - delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered; - } - - public ActiveBehaviourCollector(IUniverse universe) - { - delegateOnBehaviourAdded = OnBehaviourAdded; - delegateOnBehaviourRemoved = OnBehaviourRemoved; - delegateOnBehaviourStateChanged = OnBehaviourStateChanged; - delegateOnUniverseObjectRegistered = OnUniverseObjectRegistered; - delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered; - - Assign(universe); - } + protected override void AddBehaviour(T behaviour) => activeBehaviours.Add(behaviour); + protected override bool RemoveBehaviour(T tBehaviour) => activeBehaviours.Remove(tBehaviour); } diff --git a/Engine.Core/Collectors/ActiveBehaviourCollectorBase.cs b/Engine.Core/Collectors/ActiveBehaviourCollectorBase.cs new file mode 100644 index 0000000..f389a61 --- /dev/null +++ b/Engine.Core/Collectors/ActiveBehaviourCollectorBase.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; + +namespace Engine.Core; + +public abstract class ActiveBehaviourCollectorBase : IBehaviourCollector where T : class, IBehaviour +{ + protected readonly Dictionary monitoringActiveToBehaviour = new(32); + protected readonly FastList monitoringBehaviours = new(32); + + private readonly Event.EventHandler delegateOnBehaviourAdded = null!; + private readonly Event.EventHandler delegateOnBehaviourRemoved = null!; + private readonly Event.EventHandler delegateOnBehaviourStateChanged = null!; + private readonly Event.EventHandler delegateOnUniverseObjectRegistered = null!; + private readonly Event.EventHandler delegateOnUniverseObjectUnregistered = null!; + + public Event, IBehaviourCollector.BehaviourCollectedArguments> OnCollected { get; } = new(); + public Event, IBehaviourCollector.BehaviourRemovedArguments> OnRemoved { get; } = new(); + public Event OnUniverseAssigned { get; } = new(); + public Event? OnUnassigned { get; } = new(); + + public abstract int Count { get; } + + public abstract T this[Index index] { get; } + public IUniverse Universe { get; private set; } = null!; + + public bool Assign(IUniverse universe) + { + if (Universe is not null) + return false; + + foreach (IUniverseObject universeObject in universe.UniverseObjects) + OnUniverseObjectRegistered(universe, new(universeObject)); + + universe.OnUniverseObjectRegistered.AddListener(delegateOnUniverseObjectRegistered); + universe.OnUniverseObjectUnRegistered.AddListener(delegateOnUniverseObjectUnregistered); + + Universe = universe; + OnUniverseAssigned?.Invoke(this); + + return true; + } + + public bool Unassign() + { + if (Universe is null) + return false; + + foreach (IUniverseObject universeObject in Universe.UniverseObjects) + OnUniverseObjectUnregistered(Universe, new(universeObject)); + + Universe.OnUniverseObjectRegistered.RemoveListener(delegateOnUniverseObjectRegistered); + Universe.OnUniverseObjectUnRegistered.RemoveListener(delegateOnUniverseObjectUnregistered); + + Universe = null!; + OnUnassigned?.Invoke(this); + return true; + } + + 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; + + 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; + delegateOnBehaviourStateChanged = OnBehaviourStateChanged; + delegateOnUniverseObjectRegistered = OnUniverseObjectRegistered; + delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered; + } + + public ActiveBehaviourCollectorBase(IUniverse universe) + { + delegateOnBehaviourAdded = OnBehaviourAdded; + delegateOnBehaviourRemoved = OnBehaviourRemoved; + delegateOnBehaviourStateChanged = OnBehaviourStateChanged; + delegateOnUniverseObjectRegistered = OnUniverseObjectRegistered; + delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered; + + Assign(universe); + } +}