154 lines
4.5 KiB
C#
154 lines
4.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Syntriax.Engine.Core;
|
|
|
|
[System.Diagnostics.DebuggerDisplay("Behaviour Count: {behaviours.Count}")]
|
|
public class BehaviourController : BaseEntity, IBehaviourController
|
|
{
|
|
public Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments> OnBehaviourAdded { get; } = new();
|
|
public Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments> OnBehaviourRemoved { get; } = new();
|
|
public Event<IHasUniverseObject> OnUniverseObjectAssigned { get; } = new();
|
|
|
|
private readonly List<IBehaviour> behaviours = new(Constants.BEHAVIOURS_SIZE_INITIAL);
|
|
|
|
private IUniverseObject _universeObject = null!;
|
|
|
|
public IUniverseObject UniverseObject => _universeObject;
|
|
public int Count => behaviours.Count;
|
|
public IBehaviour this[Index index] => behaviours[index];
|
|
|
|
public T AddBehaviour<T>(T behaviour) where T : class, IBehaviour
|
|
{
|
|
InsertBehaviourByPriority(behaviour);
|
|
|
|
behaviour.Assign(this);
|
|
|
|
if (IsInitialized)
|
|
behaviour.Initialize();
|
|
behaviour.OnPriorityChanged.AddListener(OnPriorityChange);
|
|
OnBehaviourAdded?.Invoke(this, new(behaviour));
|
|
return behaviour;
|
|
}
|
|
|
|
public T AddBehaviour<T>(params object?[]? args) where T : class, IBehaviour
|
|
{
|
|
T behaviour = Factory.BehaviourFactory.Instantiate<T>(args);
|
|
return AddBehaviour(behaviour);
|
|
}
|
|
|
|
public T? GetBehaviour<T>()
|
|
{
|
|
foreach (IBehaviour behaviourItem in behaviours)
|
|
if (behaviourItem is T result)
|
|
return result;
|
|
|
|
return default;
|
|
}
|
|
|
|
public IReadOnlyList<T> GetBehaviours<T>()
|
|
{
|
|
List<T>? behaviours = null;
|
|
foreach (IBehaviour behaviourItem in this.behaviours)
|
|
{
|
|
if (behaviourItem is not T behaviour)
|
|
continue;
|
|
|
|
behaviours ??= [];
|
|
behaviours.Add(behaviour);
|
|
}
|
|
|
|
return behaviours ?? Enumerable.Empty<T>().ToList();
|
|
}
|
|
|
|
public void GetBehaviours<T>(IList<T> results)
|
|
{
|
|
results.Clear();
|
|
foreach (IBehaviour behaviourItem in behaviours)
|
|
{
|
|
if (behaviourItem is not T behaviour)
|
|
continue;
|
|
|
|
results.Add(behaviour);
|
|
}
|
|
}
|
|
|
|
public void RemoveBehaviour<T>(bool removeAll = false) where T : class, IBehaviour
|
|
{
|
|
for (int i = behaviours.Count; i >= 0; i--)
|
|
{
|
|
if (behaviours[i] is not T behaviour)
|
|
continue;
|
|
|
|
RemoveBehaviour(behaviour);
|
|
|
|
if (!removeAll)
|
|
return;
|
|
}
|
|
}
|
|
|
|
public void RemoveBehaviour<T>(T behaviour) where T : class, IBehaviour
|
|
{
|
|
if (!behaviours.Contains(behaviour))
|
|
throw new Exception($"{behaviour.GetType().Name} does not exist in {UniverseObject.Name}'s {nameof(IBehaviourController)}.");
|
|
|
|
behaviour.OnPriorityChanged.RemoveListener(OnPriorityChange);
|
|
behaviour.Finalize();
|
|
behaviours.Remove(behaviour);
|
|
OnBehaviourRemoved?.Invoke(this, new(behaviour));
|
|
}
|
|
|
|
protected virtual void OnAssign(IUniverseObject universeObject) { }
|
|
public bool Assign(IUniverseObject universeObject)
|
|
{
|
|
if (UniverseObject is not null && UniverseObject.IsInitialized)
|
|
return false;
|
|
|
|
_universeObject = universeObject;
|
|
OnAssign(universeObject);
|
|
OnUniverseObjectAssigned?.Invoke(this);
|
|
return true;
|
|
}
|
|
|
|
protected override void InitializeInternal()
|
|
{
|
|
Debug.Assert.AssertUniverseObjectAssigned(this);
|
|
|
|
foreach (IBehaviour behaviour in behaviours)
|
|
behaviour.Initialize();
|
|
}
|
|
|
|
protected override void FinalizeInternal()
|
|
{
|
|
foreach (IBehaviour behaviour in behaviours)
|
|
behaviour.Finalize();
|
|
}
|
|
|
|
public BehaviourController() { }
|
|
public BehaviourController(IUniverseObject universeObject) => Assign(universeObject);
|
|
|
|
private void InsertBehaviourByPriority<T>(T behaviour) where T : class, IBehaviour
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < behaviours.Count; i++)
|
|
{
|
|
if (behaviours[i].Priority > behaviour.Priority)
|
|
continue;
|
|
|
|
behaviours.Insert(i, behaviour);
|
|
return;
|
|
}
|
|
|
|
if (i == 0 || i == behaviours.Count)
|
|
behaviours.Add(behaviour);
|
|
}
|
|
|
|
private void OnPriorityChange(IBehaviour sender, IBehaviour.PriorityChangedArguments arguments)
|
|
{
|
|
behaviours.Remove(sender);
|
|
InsertBehaviourByPriority(sender);
|
|
}
|
|
}
|