Syntriax.Engine/Engine.Core/GameManager.cs

147 lines
4.8 KiB
C#

using System;
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("HierarchyObject Count: {_hierarchyObjects.Count}")]
public class GameManager : BaseEntity, IGameManager
{
public event IGameManager.UpdateEventHandler? OnUpdate = null;
public event IGameManager.PreDawEventHandler? OnPreDraw = null;
public event IGameManager.HierarchyObjectRegisteredEventHandler? OnHierarchyObjectRegistered = null;
public event IGameManager.HierarchyObjectUnRegisteredEventHandler? OnHierarchyObjectUnRegistered = null;
private readonly List<IHierarchyObject> _hierarchyObjects = new(Constants.GAME_OBJECTS_SIZE_INITIAL);
private HierarchyObjectFactory _hierarchyObjectFactory = null!;
private HierarchyObjectFactory HierarchyObjectFactory
{
get
{
_hierarchyObjectFactory ??= new HierarchyObjectFactory();
return _hierarchyObjectFactory;
}
}
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)}.");
hierarchyObject.OnFinalized += OnHierarchyObjectFinalize;
hierarchyObject.OnExitedHierarchy += OnHierarchyObjectExitedHierarchy;
if (!hierarchyObject.Initialize())
throw new Exception($"{hierarchyObject.Name} can't be initialized");
foreach (IHierarchyObject child in hierarchyObject.Children)
Register(child);
_hierarchyObjects.Add(hierarchyObject);
if (!hierarchyObject.EnterHierarchy(this))
throw new Exception($"{hierarchyObject.Name} can't enter the hierarchy");
OnHierarchyObjectRegistered?.Invoke(this, hierarchyObject);
}
public T InstantiateHierarchyObject<T>(params object?[]? args) where T : class, IHierarchyObject
{
T hierarchyObject = HierarchyObjectFactory.Instantiate<T>(args);
Register(hierarchyObject);
return hierarchyObject;
}
public void Remove(IHierarchyObject hierarchyObject)
{
if (!_hierarchyObjects.Contains(hierarchyObject))
throw new Exception($"{nameof(IHierarchyObject)} named {hierarchyObject.Name} is not registered to the {nameof(GameManager)}.");
hierarchyObject.OnFinalized -= OnHierarchyObjectFinalize;
hierarchyObject.OnExitedHierarchy -= OnHierarchyObjectExitedHierarchy;
foreach (IHierarchyObject child in hierarchyObject.Children)
Remove(child);
_hierarchyObjects.Remove(hierarchyObject);
if (!hierarchyObject.ExitHierarchy())
throw new Exception($"{hierarchyObject.Name} can't exit the hierarchy");
if (!hierarchyObject.Finalize())
throw new Exception($"{hierarchyObject.Name} can't be finalized");
OnHierarchyObjectUnRegistered?.Invoke(this, hierarchyObject);
}
protected override void InitializeInternal()
{
base.InitializeInternal();
NotAssignedException.Check(this, StateEnable);
foreach (IHierarchyObject hierarchyObject in HierarchyObjects)
hierarchyObject.Initialize();
}
protected override void FinalizeInternal()
{
base.FinalizeInternal();
for (int i = HierarchyObjects.Count; i >= 0; i--)
HierarchyObjects[i].Finalize();
}
public void Update(EngineTime time)
{
Time.SetTime(time);
for (int i = 0; i < HierarchyObjects.Count; i++)
HierarchyObjects[i].BehaviourController.Update();
OnUpdate?.Invoke(this, time);
}
public void PreDraw()
{
for (int i = 0; i < HierarchyObjects.Count; i++)
HierarchyObjects[i].BehaviourController.UpdatePreDraw();
OnPreDraw?.Invoke(this);
}
/////////////////////////////////////////////////////////////////
private void OnHierarchyObjectFinalize(IInitializable initializable)
{
if (initializable is IHierarchyObject hierarchyObject)
Remove(hierarchyObject);
}
private void OnHierarchyObjectExitedHierarchy(IHierarchyObject sender, IGameManager gameManager)
{
if (sender is IHierarchyObject hierarchyObject)
Remove(hierarchyObject);
}
}