148 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Collections.Generic;
 | 
						|
 | 
						|
namespace Engine.Core;
 | 
						|
 | 
						|
public abstract class ActiveBehaviourCollectorBase<T> : IBehaviourCollector<T> where T : class, IBehaviour
 | 
						|
{
 | 
						|
    protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = new(32);
 | 
						|
    protected readonly FastList<T> monitoringBehaviours = new(32);
 | 
						|
 | 
						|
    private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler delegateOnBehaviourAdded = null!;
 | 
						|
    private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler delegateOnBehaviourRemoved = null!;
 | 
						|
    private readonly Event<IActive, IActive.ActiveChangedArguments>.EventHandler delegateOnBehaviourStateChanged = null!;
 | 
						|
    private readonly Event<IUniverse, IUniverse.UniverseObjectRegisteredArguments>.EventHandler delegateOnUniverseObjectRegistered = null!;
 | 
						|
    private readonly Event<IUniverse, IUniverse.UniverseObjectUnRegisteredArguments>.EventHandler delegateOnUniverseObjectUnregistered = null!;
 | 
						|
 | 
						|
    public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourCollectedArguments> OnCollected { get; } = new();
 | 
						|
    public Event<IBehaviourCollector<T>, IBehaviourCollector<T>.BehaviourRemovedArguments> OnRemoved { get; } = new();
 | 
						|
    public Event<IHasUniverse> OnUniverseAssigned { get; } = new();
 | 
						|
    public Event<IAssignable>? OnUnassigned { get; } = new();
 | 
						|
 | 
						|
    public abstract int Count { get; }
 | 
						|
 | 
						|
    public abstract T this[Index index] { get; }
 | 
						|
    public IUniverse Universe { get; private set; } = null!;
 | 
						|
 | 
						|
    public bool Assign(IUniverse universe)
 | 
						|
    {
 | 
						|
        if (Universe is not null)
 | 
						|
            return false;
 | 
						|
 | 
						|
        foreach (IUniverseObject universeObject in universe)
 | 
						|
            OnUniverseObjectRegistered(universe, new(universeObject));
 | 
						|
 | 
						|
        universe.OnUniverseObjectRegistered.AddListener(delegateOnUniverseObjectRegistered);
 | 
						|
        universe.OnUniverseObjectUnRegistered.AddListener(delegateOnUniverseObjectUnregistered);
 | 
						|
 | 
						|
        Universe = universe;
 | 
						|
        OnUniverseAssigned?.Invoke(this);
 | 
						|
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    public bool Unassign()
 | 
						|
    {
 | 
						|
        if (Universe is null)
 | 
						|
            return false;
 | 
						|
 | 
						|
        foreach (IUniverseObject universeObject in Universe)
 | 
						|
            OnUniverseObjectUnregistered(Universe, new(universeObject));
 | 
						|
 | 
						|
        Universe.OnUniverseObjectRegistered.RemoveListener(delegateOnUniverseObjectRegistered);
 | 
						|
        Universe.OnUniverseObjectUnRegistered.RemoveListener(delegateOnUniverseObjectUnregistered);
 | 
						|
 | 
						|
        Universe = null!;
 | 
						|
        OnUnassigned?.Invoke(this);
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    protected abstract void AddBehaviour(T behaviour);
 | 
						|
    protected virtual void OnBehaviourAdd(IBehaviour behaviour) { }
 | 
						|
    private void OnBehaviourAdded(IBehaviourController controller, IBehaviourController.BehaviourAddedArguments args)
 | 
						|
    {
 | 
						|
        if (args.BehaviourAdded is not T tBehaviour)
 | 
						|
            return;
 | 
						|
 | 
						|
        monitoringBehaviours.Add(tBehaviour);
 | 
						|
        monitoringActiveToBehaviour.Add(tBehaviour, tBehaviour);
 | 
						|
        tBehaviour.OnActiveChanged.AddListener(delegateOnBehaviourStateChanged);
 | 
						|
        OnBehaviourStateChanged(tBehaviour, new(!tBehaviour.IsActive));
 | 
						|
    }
 | 
						|
 | 
						|
    protected abstract bool RemoveBehaviour(T behaviour);
 | 
						|
    protected virtual void OnBehaviourRemove(IBehaviour behaviour) { }
 | 
						|
    private void OnBehaviourRemoved(IBehaviourController controller, IBehaviourController.BehaviourRemovedArguments args)
 | 
						|
    {
 | 
						|
        if (args.BehaviourRemoved is not T tBehaviour)
 | 
						|
            return;
 | 
						|
 | 
						|
        if (!monitoringBehaviours.Remove(tBehaviour) || !monitoringActiveToBehaviour.Remove(tBehaviour))
 | 
						|
            return;
 | 
						|
 | 
						|
        tBehaviour.OnActiveChanged.RemoveListener(delegateOnBehaviourStateChanged);
 | 
						|
        if (!RemoveBehaviour(tBehaviour))
 | 
						|
            return;
 | 
						|
 | 
						|
        OnBehaviourRemove(tBehaviour);
 | 
						|
        OnRemoved?.Invoke(this, new(tBehaviour));
 | 
						|
    }
 | 
						|
    private void OnBehaviourStateChanged(IActive sender, IActive.ActiveChangedArguments args)
 | 
						|
    {
 | 
						|
        T behaviour = monitoringActiveToBehaviour[sender];
 | 
						|
        if (sender.IsActive)
 | 
						|
        {
 | 
						|
            AddBehaviour(behaviour);
 | 
						|
            OnBehaviourAdd(behaviour);
 | 
						|
            OnCollected?.Invoke(this, new(behaviour));
 | 
						|
        }
 | 
						|
        else if (RemoveBehaviour(behaviour))
 | 
						|
        {
 | 
						|
            OnBehaviourRemove(behaviour);
 | 
						|
            OnRemoved?.Invoke(this, new(behaviour));
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    private void OnUniverseObjectRegistered(IUniverse manager, IUniverse.UniverseObjectRegisteredArguments args)
 | 
						|
    {
 | 
						|
        IUniverseObject universeObject = args.UniverseObjectRegistered;
 | 
						|
 | 
						|
        universeObject.BehaviourController.OnBehaviourAdded.AddListener(delegateOnBehaviourAdded);
 | 
						|
        universeObject.BehaviourController.OnBehaviourRemoved.AddListener(delegateOnBehaviourRemoved);
 | 
						|
 | 
						|
        for (int i = 0; i < universeObject.BehaviourController.Count; i++)
 | 
						|
            OnBehaviourAdded(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
 | 
						|
    }
 | 
						|
 | 
						|
    private void OnUniverseObjectUnregistered(IUniverse manager, IUniverse.UniverseObjectUnRegisteredArguments args)
 | 
						|
    {
 | 
						|
        IUniverseObject universeObject = args.UniverseObjectUnregistered;
 | 
						|
 | 
						|
        universeObject.BehaviourController.OnBehaviourAdded.RemoveListener(delegateOnBehaviourAdded);
 | 
						|
        universeObject.BehaviourController.OnBehaviourRemoved.RemoveListener(delegateOnBehaviourRemoved);
 | 
						|
 | 
						|
        for (int i = 0; i < universeObject.BehaviourController.Count; i++)
 | 
						|
            OnBehaviourRemoved(universeObject.BehaviourController, new(universeObject.BehaviourController[i]));
 | 
						|
    }
 | 
						|
 | 
						|
    public ActiveBehaviourCollectorBase()
 | 
						|
    {
 | 
						|
        delegateOnBehaviourAdded = OnBehaviourAdded;
 | 
						|
        delegateOnBehaviourRemoved = OnBehaviourRemoved;
 | 
						|
        delegateOnBehaviourStateChanged = OnBehaviourStateChanged;
 | 
						|
        delegateOnUniverseObjectRegistered = OnUniverseObjectRegistered;
 | 
						|
        delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
 | 
						|
    }
 | 
						|
 | 
						|
    public ActiveBehaviourCollectorBase(IUniverse universe)
 | 
						|
    {
 | 
						|
        delegateOnBehaviourAdded = OnBehaviourAdded;
 | 
						|
        delegateOnBehaviourRemoved = OnBehaviourRemoved;
 | 
						|
        delegateOnBehaviourStateChanged = OnBehaviourStateChanged;
 | 
						|
        delegateOnUniverseObjectRegistered = OnUniverseObjectRegistered;
 | 
						|
        delegateOnUniverseObjectUnregistered = OnUniverseObjectUnregistered;
 | 
						|
 | 
						|
        Assign(universe);
 | 
						|
    }
 | 
						|
}
 |