Syntriax.Engine/Engine.Core/BehaviourController.cs

181 lines
5.0 KiB
C#
Raw Normal View History

2023-11-23 22:07:49 +03:00
using System;
using System.Collections;
2023-11-23 22:07:49 +03:00
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
2023-11-23 22:07:49 +03:00
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core;
[System.Diagnostics.DebuggerDisplay("Behaviour Count: {behaviours.Count}")]
2023-11-23 22:07:49 +03:00
public class BehaviourController : IBehaviourController
{
2024-07-15 01:13:39 +03:00
public event IBehaviourController.OnPreUpdateDelegate? OnPreUpdate = null;
public event IBehaviourController.OnUpdateDelegate? OnUpdate = null;
public event IBehaviourController.OnPreDrawDelegate? OnPreDraw = null;
2023-11-23 22:07:49 +03:00
2024-07-15 01:13:39 +03:00
public event IBehaviourController.OnBehaviourAddedDelegate? OnBehaviourAdded = null;
public event IBehaviourController.OnBehaviourRemovedDelegate? OnBehaviourRemoved = null;
public event IAssignable.OnUnassignedDelegate? OnUnassigned;
public event IAssignableGameObject.OnGameObjectAssignedDelegate? OnGameObjectAssigned = null;
2023-11-23 22:07:49 +03:00
private readonly IList<IBehaviour> behaviours = new List<IBehaviour>(Constants.BEHAVIOURS_SIZE_INITIAL);
private IGameObject _gameObject = null!;
public IGameObject GameObject => _gameObject;
public T AddBehaviour<T>(T behaviour) where T : class, IBehaviour
{
InsertBehaviourByPriority(behaviour);
behaviour.Assign(this);
behaviour.Assign(GameObject.StateEnable);
2023-11-23 22:07:49 +03:00
behaviour.Initialize();
behaviour.OnPriorityChanged += OnPriorityChange;
OnBehaviourAdded?.Invoke(this, behaviour);
return behaviour;
}
public T AddBehaviour<T>(params object?[]? args) where T : class, IBehaviour
=> AddBehaviour(new Factory.BehaviourFactory().Instantiate<T>(_gameObject, args));
public T? GetBehaviour<T>()
2023-11-23 22:07:49 +03:00
{
foreach (var behaviourItem in behaviours)
if (behaviourItem is T result)
return result;
2023-11-23 22:07:49 +03:00
return default;
}
2023-11-23 22:07:49 +03:00
public bool TryGetBehaviour<T>([NotNullWhen(returnValue: true)] out T? behaviour)
{
behaviour = GetBehaviour<T>();
return behaviour is not null;
2023-11-23 22:07:49 +03:00
}
public IList<T> GetBehaviours<T>()
2023-11-23 22:07:49 +03:00
{
List<T>? behaviours = null;
2023-11-23 22:07:49 +03:00
foreach (var behaviourItem in this.behaviours)
{
if (behaviourItem is not T behaviour)
continue;
behaviours ??= [];
2023-11-23 22:07:49 +03:00
behaviours.Add(behaviour);
}
return behaviours ?? Enumerable.Empty<T>().ToList();
2023-11-23 22:07:49 +03:00
}
public void GetBehaviours<T>(List<T> behaviors)
{
behaviors.Clear();
foreach (var behaviourItem in behaviours)
{
if (behaviourItem is not T _)
continue;
behaviours.Add(behaviourItem);
}
}
public void RemoveBehaviour<T>(bool removeAll = false) where T : class, IBehaviour
2023-11-23 22:07:49 +03:00
{
for (int i = behaviours.Count; i >= 0; i--)
{
if (behaviours[i] is not T behaviour)
continue;
RemoveBehaviour(behaviour);
2023-11-23 22:07:49 +03:00
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 {GameObject.Name}'s {nameof(IBehaviourController)}.");
behaviour.OnPriorityChanged -= OnPriorityChange;
behaviour.Finalize();
behaviours.Remove(behaviour);
OnBehaviourRemoved?.Invoke(this, behaviour);
}
2023-11-23 22:07:49 +03:00
public bool Assign(IGameObject gameObject)
{
2023-11-24 17:20:43 +03:00
if (GameObject is not null && GameObject.Initialized)
2023-11-23 22:07:49 +03:00
return false;
_gameObject = gameObject;
OnGameObjectAssigned?.Invoke(this);
return true;
}
2023-11-24 17:03:21 +03:00
public bool Unassign()
{
2023-11-24 17:20:43 +03:00
if (GameObject is not null && GameObject.Initialized)
2023-11-24 17:03:21 +03:00
return false;
_gameObject = null!;
OnUnassigned?.Invoke(this);
return true;
}
public void Update()
2023-11-23 22:07:49 +03:00
{
if (!GameObject.StateEnable.Enabled)
return;
OnPreUpdate?.Invoke(this);
OnUpdate?.Invoke(this);
2023-11-23 22:07:49 +03:00
}
public void UpdatePreDraw()
2023-11-23 22:07:49 +03:00
{
if (!GameObject.StateEnable.Enabled)
return;
OnPreDraw?.Invoke(this);
2023-11-23 22:07:49 +03:00
}
public BehaviourController() { }
public BehaviourController(IGameObject gameObject) => Assign(gameObject);
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);
}
2024-07-15 01:13:39 +03:00
private void OnPriorityChange(IBehaviour sender, int previousPriority)
2023-11-23 22:07:49 +03:00
{
2024-07-15 01:13:39 +03:00
behaviours.Remove(sender);
InsertBehaviourByPriority(sender);
2023-11-23 22:07:49 +03:00
}
public IEnumerator<IBehaviour> GetEnumerator() => behaviours.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => behaviours.GetEnumerator();
2023-11-23 22:07:49 +03:00
}