All delegate events are refactored to use the Event<TSender> and Event<TSender, TArgument> for performance issues regarding delegate events creating garbage, also this gives us better control on event invocation since C# Delegates did also create unnecessary garbage during Delegate.DynamicInvoke
97 lines
3.7 KiB
C#
97 lines
3.7 KiB
C#
namespace Syntriax.Engine.Core;
|
|
|
|
[System.Diagnostics.DebuggerDisplay("{GetType().Name, nq}, Priority: {Priority}, Initialized: {Initialized}")]
|
|
public abstract class BehaviourBase : BaseEntity, IBehaviour
|
|
{
|
|
public Event<IBehaviour, IBehaviour.PriorityChangedArguments> OnPriorityChanged { get; } = new();
|
|
public Event<IActive, IActive.ActiveChangedArguments> OnActiveChanged { get; } = new();
|
|
public Event<IHasBehaviourController> OnBehaviourControllerAssigned { get; } = new();
|
|
|
|
private readonly Event<IHasUniverseObject>.EventHandler delegateOnUniverseObjectAssigned = null!;
|
|
private readonly Event<IActive, IActive.ActiveChangedArguments>.EventHandler delegateOnUniverseObjectActiveChanged = null!;
|
|
private readonly Event<IStateEnable, IStateEnable.EnabledChangedArguments>.EventHandler delegateOnStateEnabledChanged = null!;
|
|
|
|
private IBehaviourController _behaviourController = null!;
|
|
public IBehaviourController BehaviourController => _behaviourController;
|
|
|
|
private int _priority = 0;
|
|
public int Priority
|
|
{
|
|
get => _priority;
|
|
set
|
|
{
|
|
if (value == _priority)
|
|
return;
|
|
|
|
int previousPriority = _priority;
|
|
_priority = value;
|
|
OnPriorityChanged?.Invoke(this, new(previousPriority));
|
|
}
|
|
}
|
|
|
|
private bool _isActive = false;
|
|
public bool IsActive => _isActive;
|
|
|
|
protected virtual void OnAssign(IBehaviourController behaviourController) { }
|
|
public bool Assign(IBehaviourController behaviourController)
|
|
{
|
|
if (IsInitialized)
|
|
return false;
|
|
|
|
_behaviourController = behaviourController;
|
|
OnAssign(behaviourController);
|
|
behaviourController.OnUniverseObjectAssigned.AddListener(delegateOnUniverseObjectAssigned);
|
|
if (behaviourController.UniverseObject is not null)
|
|
OnUniverseObjectAssigned(behaviourController);
|
|
OnBehaviourControllerAssigned?.Invoke(this);
|
|
return true;
|
|
}
|
|
|
|
private void OnUniverseObjectAssigned(IHasUniverseObject sender)
|
|
{
|
|
sender.UniverseObject.OnActiveChanged.AddListener(delegateOnUniverseObjectActiveChanged);
|
|
UpdateActive();
|
|
}
|
|
|
|
protected override void OnAssign(IStateEnable stateEnable)
|
|
{
|
|
base.OnAssign(stateEnable);
|
|
|
|
stateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
|
|
}
|
|
|
|
protected override void UnassignInternal()
|
|
{
|
|
BehaviourController.UniverseObject.OnActiveChanged.RemoveListener(delegateOnUniverseObjectActiveChanged);
|
|
StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
|
|
BehaviourController.OnUniverseObjectAssigned.RemoveListener(delegateOnUniverseObjectAssigned);
|
|
base.UnassignInternal();
|
|
_behaviourController = null!;
|
|
}
|
|
|
|
protected override void InitializeInternal()
|
|
{
|
|
Debug.Assert.AssertBehaviourControllerAssigned(this);
|
|
Debug.Assert.AssertStateEnableAssigned(this);
|
|
}
|
|
|
|
private void OnStateEnabledChanged(IStateEnable sender, IStateEnable.EnabledChangedArguments args) => UpdateActive();
|
|
private void OnUniverseObjectActiveChanged(IActive sender, IActive.ActiveChangedArguments args) => UpdateActive();
|
|
|
|
private void UpdateActive()
|
|
{
|
|
bool previousActive = IsActive;
|
|
_isActive = StateEnable.Enabled && _behaviourController.UniverseObject.IsActive;
|
|
|
|
if (previousActive != IsActive)
|
|
OnActiveChanged?.Invoke(this, new(previousActive));
|
|
}
|
|
|
|
protected BehaviourBase()
|
|
{
|
|
delegateOnUniverseObjectAssigned = OnUniverseObjectAssigned;
|
|
delegateOnUniverseObjectActiveChanged = OnUniverseObjectActiveChanged;
|
|
delegateOnStateEnabledChanged = OnStateEnabledChanged;
|
|
}
|
|
}
|