using System; using System.Collections; using System.Collections.Generic; using Syntriax.Engine.Core.Abstract; using Syntriax.Engine.Core.Exceptions; using Syntriax.Engine.Core.Factory; namespace Syntriax.Engine.Core; [System.Diagnostics.DebuggerDisplay("GameObject Count: {_gameObjects.Count}")] public class GameManager : BaseEntity, IGameManager { public Action? OnGameObjectRegistered { get; set; } = null; public Action? OnGameObjectUnRegistered { get; set; } = null; private readonly List _gameObjects = new(Constants.GAME_OBJECTS_SIZE_INITIAL); private GameObjectFactory _gameObjectFactory = null!; private GameObjectFactory GameObjectFactory { get { if (_gameObjectFactory is null) _gameObjectFactory = new GameObjectFactory(); return _gameObjectFactory; } } public IReadOnlyList GameObjects => _gameObjects; public override IStateEnable StateEnable { get { if (base.StateEnable is null) { Assign(new StateEnableFactory().Instantiate(this)); if (base.StateEnable is null) throw NotAssignedException.From(this, base.StateEnable); } return base.StateEnable; } } public void RegisterGameObject(IGameObject gameObject) { if (_gameObjects.Contains(gameObject)) throw new Exception($"{nameof(IGameObject)} named {gameObject.Name} is already registered to the {nameof(GameManager)}."); Register(gameObject); } public T InstantiateGameObject(params object?[]? args) where T : class, IGameObject { T gameObject = GameObjectFactory.Instantiate(args); Register(gameObject); return gameObject; } public IGameObject RemoveGameObject(IGameObject gameObject) { if (!_gameObjects.Contains(gameObject)) throw new Exception($"{nameof(IGameObject)} named {gameObject.Name} is not registered to the {nameof(GameManager)}."); Unregister(gameObject); return gameObject; } protected override void InitializeInternal() { base.InitializeInternal(); NotAssignedException.Check(this, StateEnable); foreach (var gameObject in GameObjects) gameObject.Initialize(); } protected override void FinalizeInternal() { base.FinalizeInternal(); for (int i = GameObjects.Count; i >= 0; i--) GameObjects[i].Finalize(); } public void Update(EngineTime time) { Time.SetTime(time); foreach (var gameObject in GameObjects) gameObject.BehaviourController.Update(); } public void PreDraw() { foreach (var gameObject in GameObjects) gameObject.BehaviourController.UpdatePreDraw(); } ///////////////////////////////////////////////////////////////// private void Register(IGameObject gameObject) { gameObject.Assign(this); gameObject.OnFinalized += OnGameObjectFinalize; _gameObjects.Add(gameObject); OnGameObjectRegistered?.Invoke(this, gameObject); } private void Unregister(IGameObject gameObject) { gameObject.OnFinalized -= OnGameObjectFinalize; _gameObjects.Remove(gameObject); OnGameObjectUnRegistered?.Invoke(this, gameObject); } private void OnGameObjectFinalize(IInitialize initialize) { if (initialize is IGameObject gameObject) Unregister(gameObject); } ///////////////////////////////////////////////////////////////// public IEnumerator GetEnumerator() => _gameObjects.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _gameObjects.GetEnumerator(); }