Syntriax.Engine/Engine.Core/GameManager.cs

200 lines
6.8 KiB
C#

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 event IGameManager.OnUpdateDelegate? OnUpdate = null;
public event IGameManager.OnPreDawDelegate? OnPreDraw = null;
public event IGameManager.OnGameObjectRegisteredDelegate? OnGameObjectRegistered = null;
public event IGameManager.OnGameObjectUnRegisteredDelegate? OnGameObjectUnRegistered = null;
public event IGameManager.OnHierarchyObjectRegisteredDelegate? OnHierarchyObjectRegistered = null;
public event IGameManager.OnHierarchyObjectUnRegisteredDelegate? OnHierarchyObjectUnRegistered = null;
private readonly List<IGameObject> _gameObjects = new(Constants.GAME_OBJECTS_SIZE_INITIAL);
private readonly List<IHierarchyObject> _hierarchyObjects = 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<IGameObject> GameObjects => _gameObjects;
public IReadOnlyList<IHierarchyObject> HierarchyObjects => _hierarchyObjects;
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 Register(IHierarchyObject hierarchyObject)
{
if (_hierarchyObjects.Contains(hierarchyObject))
throw new Exception($"{nameof(IHierarchyObject)} named {hierarchyObject.Name} is already registered to the {nameof(GameManager)}.");
if (hierarchyObject is IGameObject gameObject)
Register(gameObject);
else
{
if (!hierarchyObject.Initialize())
throw new Exception($"{nameof(hierarchyObject)} can't be initialized");
_hierarchyObjects.Add(hierarchyObject);
hierarchyObject.EnterHierarchy(this);
OnHierarchyObjectRegistered?.Invoke(this, hierarchyObject);
}
}
public T InstantiateGameObject<T>(params object?[]? args) where T : class, IGameObject
{
T gameObject = GameObjectFactory.Instantiate<T>(args);
Register(gameObject);
return gameObject;
}
public void Remove(IHierarchyObject hierarchyObject)
{
if (!_hierarchyObjects.Contains(hierarchyObject))
throw new Exception($"{nameof(IHierarchyObject)} named {hierarchyObject.Name} is not registered to the {nameof(GameManager)}.");
if (hierarchyObject is IGameObject gameObject)
Unregister(gameObject);
else
{
_hierarchyObjects.Remove(hierarchyObject);
hierarchyObject.ExitHierarchy();
if (!hierarchyObject.Finalize())
throw new Exception($"{nameof(hierarchyObject)} can't be finalized");
OnHierarchyObjectUnRegistered?.Invoke(this, hierarchyObject);
}
}
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);
for (int i = 0; i < GameObjects.Count; i++)
GameObjects[i].BehaviourController.Update();
OnUpdate?.Invoke(this, time);
}
public void PreDraw()
{
for (int i = 0; i < GameObjects.Count; i++)
GameObjects[i].BehaviourController.UpdatePreDraw();
OnPreDraw?.Invoke(this);
}
/////////////////////////////////////////////////////////////////
private void Register(IGameObject gameObject)
{
if (_gameObjects.Contains(gameObject))
throw new Exception($"{nameof(IGameObject)} named {gameObject.Name} is already registered to the {nameof(GameManager)}.");
gameObject.OnFinalized += OnGameObjectFinalize;
gameObject.OnExitedHierarchy += OnGameObjectExitedHierarchy;
foreach (ITransform child in gameObject.Transform.Children)
Register(child.GameObject);
if (!gameObject.Initialize())
throw new Exception($"{nameof(gameObject)} can't be initialized");
_gameObjects.Add(gameObject);
_hierarchyObjects.Add(gameObject);
if (!gameObject.EnterHierarchy(this))
throw new Exception($"{nameof(gameObject)} can't enter the hierarchy");
OnHierarchyObjectRegistered?.Invoke(this, gameObject);
OnGameObjectRegistered?.Invoke(this, gameObject);
}
private void Unregister(IGameObject gameObject)
{
if (!_gameObjects.Contains(gameObject))
throw new Exception($"{nameof(IGameObject)} named {gameObject.Name} is not registered to the {nameof(GameManager)}.");
gameObject.OnFinalized -= OnGameObjectFinalize;
gameObject.OnExitedHierarchy -= OnGameObjectExitedHierarchy;
foreach (ITransform child in gameObject.Transform.Children)
Unregister(child.GameObject);
_gameObjects.Remove(gameObject);
_hierarchyObjects.Remove(gameObject);
if (!gameObject.ExitHierarchy())
throw new Exception($"{nameof(gameObject)} can't exit the hierarchy");
if (!gameObject.Finalize())
throw new Exception($"{nameof(gameObject)} can't be finalized");
OnHierarchyObjectUnRegistered?.Invoke(this, gameObject);
OnGameObjectUnRegistered?.Invoke(this, gameObject);
}
private void OnGameObjectFinalize(IInitialize initialize)
{
if (initialize is IGameObject gameObject)
Unregister(gameObject);
}
private void OnGameObjectExitedHierarchy(IHierarchyObject sender, IGameManager gameManager)
{
if (sender is IGameObject gameObject)
Unregister(gameObject);
}
/////////////////////////////////////////////////////////////////
public IEnumerator<IGameObject> GetEnumerator() => _gameObjects.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _gameObjects.GetEnumerator();
}