using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Microsoft.Xna.Framework; using Syntriax.Engine.Core.Abstract; namespace Syntriax.Engine.Core; public class BehaviourController : IBehaviourController { public Action? OnUpdate { get; set; } = null; public Action? OnPreDraw { get; set; } = null; public Action? OnBehaviourAdded { get; set; } = null; public Action? OnBehaviourRemoved { get; set; } = null; public Action? OnUnassigned { get; set; } = null; public Action? OnGameObjectAssigned { get; set; } = null; private readonly IList behaviours = new List(Constants.BEHAVIOURS_SIZE_INITIAL); private IGameObject _gameObject = null!; public IGameObject GameObject => _gameObject; public T AddBehaviour(T behaviour) where T : class, IBehaviour { InsertBehaviourByPriority(behaviour); behaviour.Initialize(); behaviour.OnPriorityChanged += OnPriorityChange; OnBehaviourAdded?.Invoke(this, behaviour); return behaviour; } public T AddBehaviour(params object?[]? args) where T : class, IBehaviour => AddBehaviour(new Factory.BehaviourFactory().Instantiate(_gameObject, args)); public bool TryGetBehaviour([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; } public IList GetBehaviours() where T : IBehaviour { IList behaviours = new List(); foreach (var behaviourItem in this.behaviours) { if (behaviourItem is not T behaviour) continue; behaviours ??= new List(); behaviours.Add(behaviour); } return behaviours; } public void RemoveBehaviour(bool removeAll = false) where T : IBehaviour { for (int i = behaviours.Count; i >= 0; i--) { if (behaviours[i] is not T behaviour) continue; behaviour.OnPriorityChanged -= OnPriorityChange; behaviour.Finalize(); behaviours.RemoveAt(i); OnBehaviourRemoved?.Invoke(this, behaviour); if (!removeAll) return; } } public bool Assign(IGameObject gameObject) { if (GameObject.Initialized) return false; _gameObject = gameObject; OnGameObjectAssigned?.Invoke(this); return true; } public bool Unassign() { if (GameObject.Initialized) return false; _gameObject = null!; OnUnassigned?.Invoke(this); return true; } public void Update(GameTime gameTime) { if (!GameObject.StateEnable.Enabled) return; OnUpdate?.Invoke(this, gameTime); } public void UpdatePreDraw(GameTime gameTime) { if (!GameObject.StateEnable.Enabled) return; OnPreDraw?.Invoke(this, gameTime); } public BehaviourController() { } public BehaviourController(IGameObject gameObject) => Assign(gameObject); private void InsertBehaviourByPriority(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); } }