Syntriax.Engine/Engine.Core/GameManager.cs

142 lines
5.1 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core;
[System.Diagnostics.DebuggerDisplay("HierarchyObject Count: {_hierarchyObjects.Count}")]
public class GameManager : BaseEntity, IGameManager
{
public event IGameManager.UpdateEventHandler? OnPreUpdate = null;
public event IGameManager.UpdateEventHandler? OnUpdate = null;
public event IGameManager.PreDrawEventHandler? 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 float _timeScale = 1f;
public IReadOnlyList<IHierarchyObject> HierarchyObjects => _hierarchyObjects;
public EngineTime Time { get; private set; } = new();
public EngineTime UnscaledTime { get; private set; } = new();
public float TimeScale
{
get => _timeScale;
set => _timeScale = value.Max(0f);
}
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");
for (int i = 0; i < hierarchyObject.Children.Count; i++)
Register(hierarchyObject.Children[i]);
_hierarchyObjects.Add(hierarchyObject);
if (!hierarchyObject.EnterHierarchy(this))
throw new Exception($"{hierarchyObject.Name} can't enter the hierarchy");
OnHierarchyObjectRegistered?.InvokeSafe(this, hierarchyObject);
}
public T InstantiateHierarchyObject<T>(params object?[]? args) where T : class, IHierarchyObject
{
T hierarchyObject = Factory.HierarchyObjectFactory.Instantiate<T>(args);
Register(hierarchyObject);
return hierarchyObject;
}
public void Remove(IHierarchyObject hierarchyObject)
{
hierarchyObject.SetParent(null);
RemoveIncursive(hierarchyObject);
}
private void RemoveIncursive(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;
for (int i = hierarchyObject.Children.Count - 1; i >= 0; i--)
Remove(hierarchyObject.Children[i]);
_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?.InvokeSafe(this, hierarchyObject);
}
protected override void InitializeInternal()
{
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 engineTime)
{
Debug.AssertHelpers.AssertInitialized(this);
UnscaledTime = engineTime;
Time = new(TimeSpan.FromTicks((long)(Time.TimeSinceStart.Ticks + engineTime.DeltaSpan.Ticks * TimeScale)), TimeSpan.FromTicks((long)(engineTime.DeltaSpan.Ticks * TimeScale)));
OnPreUpdate?.InvokeSafe(this, Time);
for (int i = 0; i < HierarchyObjects.Count; i++)
HierarchyObjects[i].BehaviourController.Update();
OnUpdate?.InvokeSafe(this, Time);
}
public void PreDraw()
{
Debug.AssertHelpers.AssertInitialized(this);
for (int i = 0; i < HierarchyObjects.Count; i++)
HierarchyObjects[i].BehaviourController.UpdatePreDraw();
OnPreDraw?.InvokeSafe(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);
}
public IEnumerator<IHierarchyObject> GetEnumerator() => _hierarchyObjects.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _hierarchyObjects.GetEnumerator();
}