Original Behaviour was using old methods for detecting entering/exiting universe, they are now all under the same hood and the original is kept for UniverseEntranceManager because it needs to enter the universe without itself. The internal behaviour kept under a subnamespace of "Core.Internal" for the purpose that it might come in handy for other use cases.
104 lines
4.1 KiB
C#
104 lines
4.1 KiB
C#
namespace Engine.Core;
|
|
|
|
[System.Diagnostics.DebuggerDisplay("{GetType().Name, nq}, Priority: {Priority}, Initialized: {Initialized}")]
|
|
public abstract class Behaviour : 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!;
|
|
|
|
public IUniverse Universe => BehaviourController.UniverseObject.Universe;
|
|
public IUniverseObject UniverseObject => BehaviourController.UniverseObject;
|
|
|
|
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);
|
|
behaviourController.StateEnable.OnEnabledChanged.AddListener(delegateOnStateEnabledChanged);
|
|
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);
|
|
BehaviourController.StateEnable.OnEnabledChanged.RemoveListener(delegateOnStateEnabledChanged);
|
|
base.UnassignInternal();
|
|
_behaviourController = null!;
|
|
}
|
|
|
|
protected override void InitializeInternal()
|
|
{
|
|
Debug.Assert.AssertBehaviourControllerAssigned(this);
|
|
Debug.Assert.AssertStateEnableAssigned(this);
|
|
|
|
UpdateActive();
|
|
}
|
|
|
|
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.StateEnable.Enabled && _behaviourController.UniverseObject.IsActive;
|
|
|
|
if (previousActive != IsActive)
|
|
OnActiveChanged?.Invoke(this, new(previousActive));
|
|
}
|
|
|
|
protected Behaviour()
|
|
{
|
|
delegateOnUniverseObjectAssigned = OnUniverseObjectAssigned;
|
|
delegateOnUniverseObjectActiveChanged = OnUniverseObjectActiveChanged;
|
|
delegateOnStateEnabledChanged = OnStateEnabledChanged;
|
|
}
|
|
}
|