Development Merge 2025.04.01 #1
19
Engine.Core/Abstract/IActive.cs
Normal file
19
Engine.Core/Abstract/IActive.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace Syntriax.Engine.Core.Abstract;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an entity which can be active or not.
|
||||
/// </summary>
|
||||
public interface IActive
|
||||
{
|
||||
/// <summary>
|
||||
/// Event triggered when the <see cref="IsActive"/> state of the <see cref="IActive"/> changes.
|
||||
/// </summary>
|
||||
event ActiveChangedEventHandler? OnActiveChanged;
|
||||
|
||||
/// <summary>
|
||||
/// The value indicating whether the <see cref="IActive"/> is enabled.
|
||||
/// </summary>
|
||||
bool IsActive { get; }
|
||||
|
||||
delegate void ActiveChangedEventHandler(IActive sender, bool previousState);
|
||||
}
|
@ -3,7 +3,7 @@ namespace Syntriax.Engine.Core.Abstract;
|
||||
/// <summary>
|
||||
/// Represents a behaviour that any object in the game might use to interact with itself or other objects.
|
||||
/// </summary>
|
||||
public interface IBehaviour : IEntity, IHasBehaviourController, IHasStateEnable
|
||||
public interface IBehaviour : IEntity, IActive, IHasBehaviourController, IHasStateEnable
|
||||
{
|
||||
/// <summary>
|
||||
/// Event triggered when the priority of the <see cref="IBehaviour"/> changes.
|
||||
@ -15,10 +15,5 @@ public interface IBehaviour : IEntity, IHasBehaviourController, IHasStateEnable
|
||||
/// </summary>
|
||||
int Priority { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The value indicating whether the <see cref="IBehaviour"/> is active.
|
||||
/// </summary>
|
||||
bool IsActive { get; }
|
||||
|
||||
delegate void PriorityChangedEventHandler(IBehaviour sender, int previousPriority);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ namespace Syntriax.Engine.Core.Abstract;
|
||||
/// This interface allows for tracking the object's presence in the hierarchy and provides events
|
||||
/// for notifying when the see enters or exits the hierarchy.
|
||||
/// </summary>
|
||||
public interface IHierarchyObject : IEntity, INameable, IHasBehaviourController, IEnumerable<IHierarchyObject>
|
||||
public interface IHierarchyObject : IEntity, IActive, INameable, IHasBehaviourController, IEnumerable<IHierarchyObject>
|
||||
{
|
||||
/// <summary>
|
||||
/// Event triggered when the <see cref="IHierarchyObject"/> enters the hierarchy.
|
||||
|
@ -8,12 +8,12 @@ public interface IStateEnable : IHasEntity
|
||||
/// <summary>
|
||||
/// Event triggered when the <see cref="Enabled"/> state of the <see cref="IStateEnable"/> changes.
|
||||
/// </summary>
|
||||
event NameChangedEventHandler? OnEnabledChanged;
|
||||
event EnabledChangedEventHandler? OnEnabledChanged;
|
||||
|
||||
/// <summary>
|
||||
/// The value indicating whether the <see cref="IStateEnable"/> is enabled.
|
||||
/// </summary>
|
||||
bool Enabled { get; set; }
|
||||
|
||||
delegate void NameChangedEventHandler(IStateEnable sender, bool previousState);
|
||||
delegate void EnabledChangedEventHandler(IStateEnable sender, bool previousState);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
||||
|
||||
private readonly List<T> monitoringBehaviours = new(32);
|
||||
protected readonly List<T> activeBehaviours = new(32);
|
||||
protected readonly Dictionary<IStateEnable, T> monitoringStateToBehaviour = new(32);
|
||||
protected readonly Dictionary<IActive, T> monitoringActiveToBehaviour = new(32);
|
||||
|
||||
public IReadOnlyList<T> Behaviours => activeBehaviours;
|
||||
public IGameManager GameManager { get; private set; } = null!;
|
||||
@ -51,23 +51,22 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
||||
return;
|
||||
|
||||
monitoringBehaviours.Add(tBehaviour);
|
||||
monitoringStateToBehaviour.Add(tBehaviour.StateEnable, tBehaviour);
|
||||
tBehaviour.StateEnable.OnEnabledChanged += OnBehaviourStateChanged;
|
||||
OnBehaviourStateChanged(tBehaviour.StateEnable, !tBehaviour.StateEnable.Enabled);
|
||||
monitoringActiveToBehaviour.Add(tBehaviour, tBehaviour);
|
||||
tBehaviour.OnActiveChanged += OnBehaviourStateChanged;
|
||||
OnBehaviourStateChanged(tBehaviour, !tBehaviour.IsActive);
|
||||
}
|
||||
|
||||
private void OnBehaviourStateChanged(IStateEnable sender, bool previousState)
|
||||
private void OnBehaviourStateChanged(IActive sender, bool previousState)
|
||||
{
|
||||
T behaviour = monitoringStateToBehaviour[sender];
|
||||
if (sender.Enabled)
|
||||
T behaviour = monitoringActiveToBehaviour[sender];
|
||||
if (sender.IsActive)
|
||||
{
|
||||
activeBehaviours.Add(behaviour);
|
||||
OnBehaviourAdd(behaviour);
|
||||
OnCollected?.Invoke(this, behaviour);
|
||||
}
|
||||
else if (activeBehaviours.Contains(behaviour))
|
||||
else if (activeBehaviours.Remove(behaviour))
|
||||
{
|
||||
activeBehaviours.Remove(behaviour);
|
||||
OnBehaviourRemove(behaviour);
|
||||
OnRemoved?.Invoke(this, behaviour);
|
||||
}
|
||||
@ -79,10 +78,15 @@ public class ActiveBehaviourCollector<T> : IBehaviourCollector<T> where T : clas
|
||||
if (behaviour is not T tBehaviour)
|
||||
return;
|
||||
|
||||
if (!monitoringBehaviours.Remove(tBehaviour) || !monitoringStateToBehaviour.Remove(tBehaviour.StateEnable))
|
||||
if (!monitoringBehaviours.Remove(tBehaviour) || !monitoringActiveToBehaviour.Remove(tBehaviour))
|
||||
return;
|
||||
|
||||
tBehaviour.StateEnable.OnEnabledChanged -= OnBehaviourStateChanged;
|
||||
tBehaviour.OnActiveChanged -= OnBehaviourStateChanged;
|
||||
if (activeBehaviours.Remove(tBehaviour))
|
||||
{
|
||||
OnBehaviourRemove(tBehaviour);
|
||||
OnRemoved?.Invoke(this, tBehaviour);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Assign(IGameManager gameManager)
|
||||
|
@ -19,8 +19,6 @@ public abstract class BaseEntity : IEntity
|
||||
|
||||
public virtual IStateEnable StateEnable => _stateEnable;
|
||||
|
||||
public virtual bool IsActive => StateEnable.Enabled;
|
||||
|
||||
public string Id
|
||||
{
|
||||
get => _id;
|
||||
@ -55,6 +53,7 @@ public abstract class BaseEntity : IEntity
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnAssign(IStateEnable stateEnable) { }
|
||||
public bool Assign(IStateEnable stateEnable)
|
||||
{
|
||||
if (IsInitialized)
|
||||
@ -62,6 +61,7 @@ public abstract class BaseEntity : IEntity
|
||||
|
||||
_stateEnable = stateEnable;
|
||||
_stateEnable.Assign(this);
|
||||
OnAssign(stateEnable);
|
||||
OnStateEnableAssigned?.Invoke(this);
|
||||
return true;
|
||||
}
|
@ -7,17 +7,14 @@ namespace Syntriax.Engine.Core;
|
||||
public abstract class BehaviourBase : BaseEntity, IBehaviour
|
||||
{
|
||||
public event IHasBehaviourController.BehaviourControllerAssignedEventHandler? OnBehaviourControllerAssigned = null;
|
||||
|
||||
public event IBehaviour.PriorityChangedEventHandler? OnPriorityChanged = null;
|
||||
public event IActive.ActiveChangedEventHandler? OnActiveChanged = null;
|
||||
|
||||
private IBehaviourController _behaviourController = null!;
|
||||
|
||||
private int _priority = 0;
|
||||
|
||||
public IBehaviourController BehaviourController => _behaviourController;
|
||||
|
||||
public override bool IsActive => base.IsActive && BehaviourController.HierarchyObject.StateEnable.Enabled;
|
||||
|
||||
private int _priority = 0;
|
||||
public int Priority
|
||||
{
|
||||
get => _priority;
|
||||
@ -32,18 +29,40 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsActive { get; private set; } = false;
|
||||
|
||||
protected virtual void OnAssign(IBehaviourController behaviourController) { }
|
||||
public bool Assign(IBehaviourController behaviourController)
|
||||
{
|
||||
if (IsInitialized)
|
||||
return false;
|
||||
|
||||
_behaviourController = behaviourController;
|
||||
OnAssign(behaviourController);
|
||||
behaviourController.OnHierarchyObjectAssigned += OnHierarchyObjectAssigned;
|
||||
if (behaviourController.HierarchyObject is not null)
|
||||
OnHierarchyObjectAssigned(behaviourController);
|
||||
OnBehaviourControllerAssigned?.Invoke(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnHierarchyObjectAssigned(IHasHierarchyObject sender)
|
||||
{
|
||||
sender.HierarchyObject.OnActiveChanged += OnHierarchyObjectActiveChanged;
|
||||
UpdateActive();
|
||||
}
|
||||
|
||||
protected override void OnAssign(IStateEnable stateEnable)
|
||||
{
|
||||
base.OnAssign(stateEnable);
|
||||
|
||||
stateEnable.OnEnabledChanged += OnStateEnabledChanged;
|
||||
}
|
||||
|
||||
protected override void UnassignInternal()
|
||||
{
|
||||
StateEnable.OnEnabledChanged -= OnStateEnabledChanged;
|
||||
BehaviourController.OnHierarchyObjectAssigned -= OnHierarchyObjectAssigned;
|
||||
base.UnassignInternal();
|
||||
_behaviourController = null!;
|
||||
}
|
||||
@ -54,4 +73,16 @@ public abstract class BehaviourBase : BaseEntity, IBehaviour
|
||||
NotAssignedException.Check(this, _behaviourController);
|
||||
NotAssignedException.Check(this, StateEnable);
|
||||
}
|
||||
|
||||
private void OnStateEnabledChanged(IStateEnable sender, bool previousState) => UpdateActive();
|
||||
private void OnHierarchyObjectActiveChanged(IActive sender, bool previousState) => UpdateActive();
|
||||
|
||||
private void UpdateActive()
|
||||
{
|
||||
bool previousActive = IsActive;
|
||||
IsActive = StateEnable.Enabled && _behaviourController.HierarchyObject.IsActive;
|
||||
|
||||
if (previousActive != IsActive)
|
||||
OnActiveChanged?.Invoke(this, previousActive);
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
||||
OnRemoved?.Invoke(this, tBehaviour);
|
||||
}
|
||||
|
||||
protected virtual void OnAssign(IGameManager gameManager) { }
|
||||
public bool Assign(IGameManager gameManager)
|
||||
{
|
||||
if (GameManager is not null)
|
||||
@ -78,6 +79,7 @@ public class BehaviourCollector<T> : IBehaviourCollector<T> where T : class
|
||||
gameManager.OnHierarchyObjectUnRegistered += OnHierarchyObjectUnregistered;
|
||||
|
||||
GameManager = gameManager;
|
||||
OnAssign(gameManager);
|
||||
OnGameManagerAssigned?.Invoke(this);
|
||||
|
||||
return true;
|
||||
|
@ -124,12 +124,14 @@ public class BehaviourController : IBehaviourController
|
||||
OnBehaviourRemoved?.Invoke(this, behaviour);
|
||||
}
|
||||
|
||||
protected virtual void OnAssign(IHierarchyObject hierarchyObject) { }
|
||||
public bool Assign(IHierarchyObject hierarchyObject)
|
||||
{
|
||||
if (HierarchyObject is not null && HierarchyObject.IsInitialized)
|
||||
return false;
|
||||
|
||||
_hierarchyObject = hierarchyObject;
|
||||
OnAssign(hierarchyObject);
|
||||
OnHierarchyObjectAssigned?.Invoke(this);
|
||||
return true;
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ public class BehaviourFactory
|
||||
if (!stateEnable.Assign(behaviour))
|
||||
throw AssignException.From(stateEnable, behaviour);
|
||||
|
||||
if (!behaviour.Assign(hierarchyObject.BehaviourController))
|
||||
throw AssignException.From(behaviour, hierarchyObject.BehaviourController);
|
||||
if (!behaviour.Assign(stateEnable))
|
||||
throw AssignException.From(behaviour, stateEnable);
|
||||
if (!behaviour.Assign(hierarchyObject.BehaviourController))
|
||||
throw AssignException.From(behaviour, hierarchyObject.BehaviourController);
|
||||
|
||||
return behaviour;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ public class HierarchyObject : BaseEntity, IHierarchyObject
|
||||
public event IHierarchyObject.ChildrenRemovedEventHandler? OnChildrenRemoved = null;
|
||||
public event IHasBehaviourController.BehaviourControllerAssignedEventHandler? OnBehaviourControllerAssigned = null;
|
||||
public event INameable.NameChangedEventHandler? OnNameChanged = null;
|
||||
public event IActive.ActiveChangedEventHandler? OnActiveChanged = null;
|
||||
|
||||
private string _name = nameof(HierarchyObject);
|
||||
private IGameManager _gameManager = null!;
|
||||
@ -41,6 +42,8 @@ public class HierarchyObject : BaseEntity, IHierarchyObject
|
||||
|
||||
public IBehaviourController BehaviourController => _behaviourController;
|
||||
|
||||
public bool IsActive { get; private set; } = false;
|
||||
|
||||
protected virtual void OnEnteringHierarchy(IGameManager gameManager) { }
|
||||
bool IHierarchyObject.EnterHierarchy(IGameManager gameManager)
|
||||
{
|
||||
@ -48,6 +51,7 @@ public class HierarchyObject : BaseEntity, IHierarchyObject
|
||||
return false;
|
||||
|
||||
_gameManager = gameManager;
|
||||
UpdateActive();
|
||||
OnEnteringHierarchy(gameManager);
|
||||
OnEnteredHierarchy?.Invoke(this, gameManager);
|
||||
return true;
|
||||
@ -75,6 +79,7 @@ public class HierarchyObject : BaseEntity, IHierarchyObject
|
||||
{
|
||||
previousParent.RemoveChild(this);
|
||||
previousParent.OnParentChanged -= NotifyChildrenOnParentChange;
|
||||
previousParent.OnActiveChanged -= OnParentActiveChanged;
|
||||
}
|
||||
|
||||
Parent = parent;
|
||||
@ -83,8 +88,10 @@ public class HierarchyObject : BaseEntity, IHierarchyObject
|
||||
{
|
||||
parent.AddChild(this);
|
||||
parent.OnParentChanged += NotifyChildrenOnParentChange;
|
||||
parent.OnActiveChanged += OnParentActiveChanged;
|
||||
}
|
||||
|
||||
UpdateActive();
|
||||
OnParentChanged?.Invoke(this, previousParent, parent);
|
||||
}
|
||||
|
||||
@ -115,16 +122,43 @@ public class HierarchyObject : BaseEntity, IHierarchyObject
|
||||
child.SetParent(this);
|
||||
}
|
||||
|
||||
protected virtual void OnAssign(IBehaviourController behaviourController) { }
|
||||
public bool Assign(IBehaviourController behaviourController)
|
||||
{
|
||||
if (IsInitialized)
|
||||
return false;
|
||||
|
||||
_behaviourController = behaviourController;
|
||||
OnAssign(behaviourController);
|
||||
OnBehaviourControllerAssigned?.Invoke(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnAssign(IStateEnable stateEnable)
|
||||
{
|
||||
base.OnAssign(stateEnable);
|
||||
|
||||
stateEnable.OnEnabledChanged += OnStateEnabledChanged;
|
||||
}
|
||||
|
||||
private void OnParentActiveChanged(IActive sender, bool previousState) => UpdateActive();
|
||||
private void OnStateEnabledChanged(IStateEnable senfder, bool previousState) => UpdateActive();
|
||||
|
||||
private void UpdateActive()
|
||||
{
|
||||
bool previousActive = IsActive;
|
||||
IsActive = StateEnable.Enabled && (Parent?.IsActive ?? true);
|
||||
|
||||
if (previousActive != IsActive)
|
||||
OnActiveChanged?.Invoke(this, previousActive);
|
||||
}
|
||||
|
||||
protected override void UnassignInternal()
|
||||
{
|
||||
base.UnassignInternal();
|
||||
StateEnable.OnEnabledChanged -= OnStateEnabledChanged;
|
||||
}
|
||||
|
||||
protected override void InitializeInternal()
|
||||
{
|
||||
base.InitializeInternal();
|
||||
|
@ -6,7 +6,7 @@ public class StateEnable : IStateEnable
|
||||
{
|
||||
public event IAssignable.UnassignEventHandler? OnUnassigned = null;
|
||||
public event IHasEntity.EntityAssignedEventHandler? OnEntityAssigned = null;
|
||||
public event IStateEnable.NameChangedEventHandler? OnEnabledChanged = null;
|
||||
public event IStateEnable.EnabledChangedEventHandler? OnEnabledChanged = null;
|
||||
|
||||
private bool _enabled = true;
|
||||
private IEntity _entity = null!;
|
||||
@ -27,12 +27,14 @@ public class StateEnable : IStateEnable
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnAssign(IEntity entity) { }
|
||||
public bool Assign(IEntity entity)
|
||||
{
|
||||
if (_entity is not null && _entity.IsInitialized)
|
||||
return false;
|
||||
|
||||
_entity = entity;
|
||||
OnAssign(entity);
|
||||
OnEntityAssigned?.Invoke(this);
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user