From d4c6288b38cc838d2c4217c079f59ec228854a52 Mon Sep 17 00:00:00 2001 From: Syntriax Date: Tue, 1 Apr 2025 12:19:58 +0300 Subject: [PATCH] feat: added behaviour collector for active behaviours only --- Engine.Core/ActiveBehaviourCollector.cs | 123 ++++++++++++++++++ Engine.Core/ActiveBehaviourCollectorSorted.cs | 19 +++ 2 files changed, 142 insertions(+) create mode 100644 Engine.Core/ActiveBehaviourCollector.cs create mode 100644 Engine.Core/ActiveBehaviourCollectorSorted.cs diff --git a/Engine.Core/ActiveBehaviourCollector.cs b/Engine.Core/ActiveBehaviourCollector.cs new file mode 100644 index 0000000..70e48d8 --- /dev/null +++ b/Engine.Core/ActiveBehaviourCollector.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +using Syntriax.Engine.Core.Abstract; + +namespace Syntriax.Engine.Core; + +public class ActiveBehaviourCollector : IBehaviourCollector where T : class, IBehaviour +{ + public event IAssignable.UnassignEventHandler? OnUnassigned = null; + public event IHasGameManager.GameManagerAssignedEventHandler? OnGameManagerAssigned = null; + + public event IBehaviourCollector.CollectedEventHandler? OnCollected = null; + public event IBehaviourCollector.RemovedEventHandler? OnRemoved = null; + + private readonly List monitoringBehaviours = new(32); + protected readonly List activeBehaviours = new(32); + protected readonly Dictionary monitoringStateToBehaviour = new(32); + + public IReadOnlyList Behaviours => activeBehaviours; + public IGameManager GameManager { get; private set; } = null!; + + public T this[Index index] => activeBehaviours[index]; + + public ActiveBehaviourCollector() { } + public ActiveBehaviourCollector(IGameManager gameManager) => Assign(gameManager); + + private void OnHierarchyObjectRegistered(IGameManager manager, IHierarchyObject hierarchyObject) + { + hierarchyObject.BehaviourController.OnBehaviourAdded += OnBehaviourAdded; + hierarchyObject.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved; + + foreach (IBehaviour item in hierarchyObject.BehaviourController) + OnBehaviourAdded(hierarchyObject.BehaviourController, item); + } + + private void OnHierarchyObjectUnregistered(IGameManager manager, IHierarchyObject hierarchyObject) + { + hierarchyObject.BehaviourController.OnBehaviourAdded -= OnBehaviourAdded; + hierarchyObject.BehaviourController.OnBehaviourRemoved -= OnBehaviourRemoved; + + foreach (IBehaviour item in hierarchyObject.BehaviourController) + OnBehaviourRemoved(hierarchyObject.BehaviourController, item); + } + + protected virtual void OnBehaviourAdd(IBehaviour behaviour) { } + private void OnBehaviourAdded(IBehaviourController controller, IBehaviour behaviour) + { + if (behaviour is not T tBehaviour) + return; + + monitoringBehaviours.Add(tBehaviour); + monitoringStateToBehaviour.Add(tBehaviour.StateEnable, tBehaviour); + tBehaviour.StateEnable.OnEnabledChanged += OnBehaviourStateChanged; + OnBehaviourStateChanged(tBehaviour.StateEnable, !tBehaviour.StateEnable.Enabled); + } + + private void OnBehaviourStateChanged(IStateEnable sender, bool previousState) + { + T behaviour = monitoringStateToBehaviour[sender]; + if (sender.Enabled) + { + activeBehaviours.Add(behaviour); + OnBehaviourAdd(behaviour); + OnCollected?.Invoke(this, behaviour); + } + else if (activeBehaviours.Contains(behaviour)) + { + activeBehaviours.Remove(behaviour); + OnBehaviourRemove(behaviour); + OnRemoved?.Invoke(this, behaviour); + } + } + + protected virtual void OnBehaviourRemove(IBehaviour behaviour) { } + private void OnBehaviourRemoved(IBehaviourController controller, IBehaviour behaviour) + { + if (behaviour is not T tBehaviour) + return; + + if (!monitoringBehaviours.Remove(tBehaviour) || !monitoringStateToBehaviour.Remove(tBehaviour.StateEnable)) + return; + + tBehaviour.StateEnable.OnEnabledChanged -= OnBehaviourStateChanged; + } + + public bool Assign(IGameManager gameManager) + { + if (GameManager is not null) + return false; + + foreach (IHierarchyObject hierarchyObject in gameManager.HierarchyObjects) + OnHierarchyObjectRegistered(gameManager, hierarchyObject); + + gameManager.OnHierarchyObjectRegistered += OnHierarchyObjectRegistered; + gameManager.OnHierarchyObjectUnRegistered += OnHierarchyObjectUnregistered; + + GameManager = gameManager; + OnGameManagerAssigned?.Invoke(this); + + return true; + } + + public bool Unassign() + { + if (GameManager is null) + return false; + + foreach (IHierarchyObject hierarchyObject in GameManager.HierarchyObjects) + OnHierarchyObjectUnregistered(GameManager, hierarchyObject); + + GameManager.OnHierarchyObjectRegistered -= OnHierarchyObjectRegistered; + GameManager.OnHierarchyObjectUnRegistered -= OnHierarchyObjectUnregistered; + + GameManager = null!; + OnUnassigned?.Invoke(this); + return true; + } + + public IEnumerator GetEnumerator() => activeBehaviours.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => activeBehaviours.GetEnumerator(); +} diff --git a/Engine.Core/ActiveBehaviourCollectorSorted.cs b/Engine.Core/ActiveBehaviourCollectorSorted.cs new file mode 100644 index 0000000..e6807c2 --- /dev/null +++ b/Engine.Core/ActiveBehaviourCollectorSorted.cs @@ -0,0 +1,19 @@ +using System; + +using Syntriax.Engine.Core.Abstract; + +namespace Syntriax.Engine.Core; + +public class ActiveBehaviourCollectorSorted : ActiveBehaviourCollector where T : class, IBehaviour +{ + public Comparison? SortBy { get; set; } = null; + + protected override void OnBehaviourAdd(IBehaviour behaviour) + { + if (SortBy is not null) + activeBehaviours.Sort(SortBy); + } + + public ActiveBehaviourCollectorSorted() { } + public ActiveBehaviourCollectorSorted(IGameManager gameManager) : base(gameManager) { } +}