2023-11-23 22:07:49 +03:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
2024-01-24 18:40:12 +03:00
|
|
|
using System.Linq;
|
2023-11-23 22:07:49 +03:00
|
|
|
|
|
|
|
using Syntriax.Engine.Core.Abstract;
|
|
|
|
|
|
|
|
namespace Syntriax.Engine.Core;
|
|
|
|
|
2024-01-27 21:05:56 +03:00
|
|
|
[System.Diagnostics.DebuggerDisplay("Behaviour Count: {behaviours.Count}")]
|
2023-11-23 22:07:49 +03:00
|
|
|
public class BehaviourController : IBehaviourController
|
|
|
|
{
|
2024-01-22 22:45:40 +03:00
|
|
|
public Action<IBehaviourController>? OnPreUpdate { get; set; }
|
|
|
|
public Action<IBehaviourController>? OnUpdate { get; set; } = null;
|
|
|
|
public Action<IBehaviourController>? OnPreDraw { get; set; } = null;
|
2023-11-23 22:07:49 +03:00
|
|
|
|
|
|
|
public Action<IBehaviourController, IBehaviour>? OnBehaviourAdded { get; set; } = null;
|
|
|
|
public Action<IBehaviourController, IBehaviour>? OnBehaviourRemoved { get; set; } = null;
|
2023-11-24 17:03:21 +03:00
|
|
|
public Action<IAssignable>? OnUnassigned { get; set; } = null;
|
2023-11-23 22:07:49 +03:00
|
|
|
public Action<IAssignableGameObject>? OnGameObjectAssigned { get; set; } = null;
|
|
|
|
|
|
|
|
|
|
|
|
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.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 bool TryGetBehaviour<T>([NotNullWhen(returnValue: true)] out T? behaviour)
|
|
|
|
{
|
|
|
|
foreach (var behaviourItem in behaviours)
|
|
|
|
{
|
|
|
|
if (behaviourItem is not T result)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
behaviour = result;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
behaviour = default;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-11-30 17:54:32 +03:00
|
|
|
public IList<T> GetBehaviours<T>()
|
2023-11-23 22:07:49 +03:00
|
|
|
{
|
2024-01-24 18:40:12 +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;
|
|
|
|
|
2024-01-24 18:40:12 +03:00
|
|
|
behaviours ??= [];
|
2023-11-23 22:07:49 +03:00
|
|
|
behaviours.Add(behaviour);
|
|
|
|
}
|
|
|
|
|
2024-01-24 18:40:12 +03:00
|
|
|
return behaviours ?? Enumerable.Empty<T>().ToList();
|
2023-11-23 22:07:49 +03:00
|
|
|
}
|
|
|
|
|
2023-11-30 17:54:32 +03:00
|
|
|
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;
|
|
|
|
|
2023-11-30 17:54:32 +03:00
|
|
|
RemoveBehaviour(behaviour);
|
2023-11-23 22:07:49 +03:00
|
|
|
|
|
|
|
if (!removeAll)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-30 17:54:32 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-01-22 22:45:40 +03:00
|
|
|
public void Update()
|
2023-11-23 22:07:49 +03:00
|
|
|
{
|
|
|
|
if (!GameObject.StateEnable.Enabled)
|
|
|
|
return;
|
|
|
|
|
2024-01-22 22:45:40 +03:00
|
|
|
OnPreUpdate?.Invoke(this);
|
|
|
|
OnUpdate?.Invoke(this);
|
2023-11-23 22:07:49 +03:00
|
|
|
}
|
2023-11-30 10:39:40 +03:00
|
|
|
|
2024-01-22 22:45:40 +03:00
|
|
|
public void UpdatePreDraw()
|
2023-11-23 22:07:49 +03:00
|
|
|
{
|
|
|
|
if (!GameObject.StateEnable.Enabled)
|
|
|
|
return;
|
|
|
|
|
2024-01-22 22:45:40 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnPriorityChange(IBehaviour behaviour)
|
|
|
|
{
|
|
|
|
behaviours.Remove(behaviour);
|
|
|
|
InsertBehaviourByPriority(behaviour);
|
|
|
|
}
|
|
|
|
}
|