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(); }