using System; using System.Collections; using System.Collections.Generic; using Syntriax.Engine.Core.Abstract; namespace Syntriax.Engine.Core; public class BehaviourCollector : IAssignableGameManager, IEnumerable { public event IAssignable.OnUnassignedDelegate? OnUnassigned = null; public event IAssignableGameManager.OnGameManagerAssignedDelegate? OnGameManagerAssigned = null; public event OnCollectedDelegate? OnCollected = null; public event OnRemovedDelegate? OnRemoved = null; private readonly List _behaviours = new(32); public IReadOnlyList Behaviours => _behaviours; public IGameManager GameManager { get; private set; } = null!; public T this[Index index] => _behaviours[index]; public BehaviourCollector() { } public BehaviourCollector(IGameManager gameManager) => Assign(gameManager); private void OnGameObjectRegistered(IGameManager manager, IGameObject gameObject) { gameObject.BehaviourController.OnBehaviourAdded += OnBehaviourAdded; gameObject.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved; } private void OnGameObjectUnregistered(IGameManager manager, IGameObject gameObject) { gameObject.BehaviourController.OnBehaviourAdded -= OnBehaviourAdded; gameObject.BehaviourController.OnBehaviourRemoved -= OnBehaviourRemoved; foreach (IBehaviour item in gameObject.BehaviourController) OnBehaviourRemoved(gameObject.BehaviourController, item); } private void OnBehaviourAdded(IBehaviourController controller, IBehaviour behaviour) { if (behaviour is not T tBehaviour) return; _behaviours.Add(tBehaviour); OnCollected?.Invoke(this, tBehaviour); } private void OnBehaviourRemoved(IBehaviourController controller, IBehaviour behaviour) { if (behaviour is not T tBehaviour) return; if (!_behaviours.Remove(tBehaviour)) return; OnRemoved?.Invoke(this, tBehaviour); } public bool Assign(IGameManager gameManager) { if (GameManager is not null) return false; foreach (IGameObject gameObject in gameManager) { OnGameObjectRegistered(gameManager, gameObject); foreach (IBehaviour behaviour in gameObject.BehaviourController) OnBehaviourAdded(gameObject.BehaviourController, behaviour); } gameManager.OnGameObjectRegistered += OnGameObjectRegistered; gameManager.OnGameObjectUnRegistered += OnGameObjectUnregistered; GameManager = gameManager; OnGameManagerAssigned?.Invoke(this); return true; } public bool Unassign() { if (GameManager is null) return false; foreach (IGameObject gameObject in GameManager) { OnGameObjectUnregistered(GameManager, gameObject); foreach (IBehaviour behaviour in gameObject.BehaviourController) OnBehaviourRemoved(gameObject.BehaviourController, behaviour); } GameManager.OnGameObjectRegistered -= OnGameObjectRegistered; GameManager.OnGameObjectUnRegistered -= OnGameObjectUnregistered; GameManager = null!; OnUnassigned?.Invoke(this); return true; } public IEnumerator GetEnumerator() => _behaviours.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _behaviours.GetEnumerator(); public delegate void OnCollectedDelegate(BehaviourCollector sender, T behaviourCollected); public delegate void OnRemovedDelegate(BehaviourCollector sender, T behaviourRemoved); }