using System; using System.Collections.Generic; namespace Syntriax.Engine.Core; public class BehaviourCollector : IBehaviourCollector where T : class { 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 cachedOnBehaviourAdded = null!; private readonly Event.EventHandler cachedOnBehaviourRemoved = null!; private readonly Event.EventHandler cachedOnUniverseObjectRegistered = null!; private readonly Event.EventHandler cachedOnUniverseObjectUnregistered = null!; protected readonly List behaviours = new(32); public IUniverse Universe { get; private set; } = null!; private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments arguments) { IUniverseObject universeObject = arguments.UniverseObjectRegistered; universeObject.BehaviourController.OnBehaviourAdded.AddListener(cachedOnBehaviourAdded); universeObject.BehaviourController.OnBehaviourRemoved.AddListener(cachedOnBehaviourRemoved); for (int i = 0; i < universeObject.BehaviourController.Count; i++) OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i])); } private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments arguments) { IUniverseObject universeObject = arguments.UniverseObjectUnregistered; universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(cachedOnBehaviourAdded); universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(cachedOnBehaviourRemoved); 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 arguments) { if (arguments.BehaviourAdded is not T tBehaviour) return; behaviours.Add(tBehaviour); OnBehaviourAdd(arguments.BehaviourAdded); OnCollected?.Invoke(this, new(tBehaviour)); } protected virtual void OnBehaviourRemove(IBehaviour behaviour) { } private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments arguments) { if (arguments.BehaviourRemoved is not T tBehaviour) return; if (!behaviours.Remove(tBehaviour)) return; OnBehaviourRemove(arguments.BehaviourRemoved); OnRemoved?.Invoke(this, new(tBehaviour)); } protected virtual void OnAssign(IUniverse universe) { } 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(cachedOnUniverseObjectRegistered); universe.OnUniverseObjectUnRegistered.AddListener(cachedOnUniverseObjectUnregistered); Universe = universe; OnAssign(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(cachedOnUniverseObjectRegistered); Universe.OnUniverseObjectUnRegistered.RemoveListener(cachedOnUniverseObjectUnregistered); Universe = null!; OnUnassigned?.Invoke(this); return true; } public int Count => behaviours.Count; public T this[Index index] => behaviours[index]; public BehaviourCollector() { cachedOnBehaviourAdded = OnBehaviourAdded; cachedOnBehaviourRemoved = OnBehaviourRemoved; cachedOnUniverseObjectRegistered = OnUniverseObjectRegistered; cachedOnUniverseObjectUnregistered = OnUniverseObjectUnregistered; } }