using System; using System.Collections; using System.Collections.Generic; using Syntriax.Engine.Core.Abstract; namespace Syntriax.Engine.Core; public class BehaviourCollector : IBehaviourCollector where T : class { public event IAssignable.UnassignEventHandler? OnUnassigned = null; public event IHasUniverse.UniverseAssignedEventHandler? OnUniverseAssigned = null; public event IBehaviourCollector.CollectedEventHandler? OnCollected = null; public event IBehaviourCollector.RemovedEventHandler? OnRemoved = null; protected readonly List behaviours = new(32); public IReadOnlyList Behaviours => behaviours; public IUniverse Universe { get; private set; } = null!; public T this[Index index] => behaviours[index]; public BehaviourCollector() { } public BehaviourCollector(IUniverse universe) => Assign(universe); private void OnUniverseObjectRegistered(IUniverse manager, IUniverseObject universeObject) { universeObject.BehaviourController.OnBehaviourAdded += OnBehaviourAdded; universeObject.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved; foreach (IBehaviour item in universeObject.BehaviourController) OnBehaviourAdded(universeObject.BehaviourController, item); } private void OnUniverseObjectUnregistered(IUniverse manager, IUniverseObject universeObject) { universeObject.BehaviourController.OnBehaviourAdded -= OnBehaviourAdded; universeObject.BehaviourController.OnBehaviourRemoved -= OnBehaviourRemoved; foreach (IBehaviour item in universeObject.BehaviourController) OnBehaviourRemoved(universeObject.BehaviourController, item); } protected virtual void OnBehaviourAdd(IBehaviour behaviour) { } private void OnBehaviourAdded(IBehaviourController controller, IBehaviour behaviour) { if (behaviour is not T tBehaviour) return; behaviours.Add(tBehaviour); OnBehaviourAdd(behaviour); OnCollected?.InvokeSafe(this, tBehaviour); } protected virtual void OnBehaviourRemove(IBehaviour behaviour) { } private void OnBehaviourRemoved(IBehaviourController controller, IBehaviour behaviour) { if (behaviour is not T tBehaviour) return; if (!behaviours.Remove(tBehaviour)) return; OnBehaviourRemove(behaviour); OnRemoved?.InvokeSafe(this, 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, universeObject); universe.OnUniverseObjectRegistered += OnUniverseObjectRegistered; universe.OnUniverseObjectUnRegistered += OnUniverseObjectUnregistered; Universe = universe; OnAssign(universe); OnUniverseAssigned?.InvokeSafe(this); return true; } public bool Unassign() { if (Universe is null) return false; foreach (IUniverseObject universeObject in Universe.UniverseObjects) OnUniverseObjectUnregistered(Universe, universeObject); Universe.OnUniverseObjectRegistered -= OnUniverseObjectRegistered; Universe.OnUniverseObjectUnRegistered -= OnUniverseObjectUnregistered; Universe = null!; OnUnassigned?.InvokeSafe(this); return true; } public IEnumerator GetEnumerator() => behaviours.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => behaviours.GetEnumerator(); }