343 lines
12 KiB
C#
343 lines
12 KiB
C#
using System;
|
|
using System.Buffers;
|
|
using System.Collections.Generic;
|
|
|
|
namespace AlicizaX
|
|
{
|
|
public static class ModuleSystem
|
|
{
|
|
internal const int DesignModuleCount = 32;
|
|
|
|
private static readonly Dictionary<Type, IModule> _moduleMaps = new Dictionary<Type, IModule>(DesignModuleCount);
|
|
private static readonly GameFrameworkLinkedList<IModule> _modules = new GameFrameworkLinkedList<IModule>();
|
|
|
|
private static readonly GameFrameworkLinkedList<IModuleUpdate> _updateModules = new GameFrameworkLinkedList<IModuleUpdate>();
|
|
private static readonly IModuleUpdate[] _updateExecuteArray = new IModuleUpdate[DesignModuleCount];
|
|
|
|
private static readonly GameFrameworkLinkedList<IModuleLateUpdate> _lateUpdateModules = new GameFrameworkLinkedList<IModuleLateUpdate>();
|
|
private static readonly IModuleLateUpdate[] _lateUpdateExecuteArray = new IModuleLateUpdate[DesignModuleCount];
|
|
|
|
private static readonly GameFrameworkLinkedList<IModuleFixedUpdate> _fixedUpdateModules = new GameFrameworkLinkedList<IModuleFixedUpdate>();
|
|
private static readonly IModuleFixedUpdate[] _fixedUpdateExecuteArray = new IModuleFixedUpdate[DesignModuleCount];
|
|
|
|
private static readonly GameFrameworkLinkedList<IModuleDrawGizmos> _gizmosUpdateModules = new GameFrameworkLinkedList<IModuleDrawGizmos>();
|
|
private static readonly IModuleDrawGizmos[] _gizmosUpdateExecuteArray = new IModuleDrawGizmos[DesignModuleCount];
|
|
|
|
|
|
private static readonly GameFrameworkLinkedList<IModuleGUI> _guiUpdateModules = new GameFrameworkLinkedList<IModuleGUI>();
|
|
private static readonly IModuleGUI[] _guiUpdateExecuteArray = new IModuleGUI[DesignModuleCount];
|
|
|
|
private static bool _isExecuteListDirty;
|
|
private static bool _isLateExecuteListDirty;
|
|
private static bool _isFixedExecuteListDirty;
|
|
private static bool _isGizmosExecuteListDirty;
|
|
private static bool _isGUIExecuteListDirty;
|
|
|
|
internal static void Dispose()
|
|
{
|
|
_updateModules.Clear();
|
|
Array.Clear(_updateExecuteArray, 0, _updateExecuteArray.Length);
|
|
|
|
_lateUpdateModules.Clear();
|
|
Array.Clear(_lateUpdateExecuteArray, 0, _lateUpdateExecuteArray.Length);
|
|
|
|
_fixedUpdateModules.Clear();
|
|
Array.Clear(_fixedUpdateExecuteArray, 0, _fixedUpdateExecuteArray.Length);
|
|
|
|
_gizmosUpdateModules.Clear();
|
|
Array.Clear(_gizmosUpdateExecuteArray, 0, _gizmosUpdateExecuteArray.Length);
|
|
|
|
|
|
_guiUpdateModules.Clear();
|
|
Array.Clear(_guiUpdateExecuteArray, 0, _guiUpdateExecuteArray.Length);
|
|
|
|
for (LinkedListNode<IModule> current = _modules.Last; current != null; current = current.Previous)
|
|
{
|
|
current.Value.Dispose();
|
|
}
|
|
|
|
_modules.Clear();
|
|
_moduleMaps.Clear();
|
|
}
|
|
|
|
#region Public Manager
|
|
|
|
public static T RegisterManager<T>() where T : AManager, new()
|
|
{
|
|
T manager = new T();
|
|
if (manager is IModuleAwake awakeManager)
|
|
{
|
|
awakeManager.Awake();
|
|
}
|
|
|
|
AddManager(manager);
|
|
return manager;
|
|
}
|
|
|
|
private static void AddManager(AManager manager)
|
|
{
|
|
Type type = manager.GetType();
|
|
_moduleMaps[type] = manager;
|
|
_modules.AddLast(manager);
|
|
manager.Register();
|
|
CheckSystemLife(manager);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public System
|
|
|
|
public static T RegisterModule<T>(Type implType)
|
|
{
|
|
return (T)RegisterModule(typeof(T), implType);
|
|
}
|
|
|
|
public static IModule RegisterModule(Type interfaceType, Type implType)
|
|
{
|
|
if (!interfaceType.IsInterface)
|
|
{
|
|
throw new GameFrameworkException(Utility.Text.Format("You must register module by interface, but '{0}' is not.", interfaceType.FullName));
|
|
}
|
|
|
|
if (!implType.IsClass || implType.IsInterface || implType.IsAbstract)
|
|
{
|
|
throw new GameFrameworkException(Utility.Text.Format("You must register module by Class and not Interface and Abstract, but '{0}' is not.", implType.FullName));
|
|
}
|
|
|
|
if (!typeof(IModule).IsAssignableFrom(interfaceType))
|
|
{
|
|
throw new GameFrameworkException(Utility.Text.Format("You must register module by Class and not Interface and Abstract, but '{0}' is not.", implType.FullName));
|
|
}
|
|
|
|
if (GetModule(interfaceType) != null)
|
|
{
|
|
Log.Error("Already Register {0}", interfaceType.FullName);
|
|
return default;
|
|
}
|
|
|
|
return SetModuleInstance(interfaceType, implType);
|
|
}
|
|
|
|
public static T GetModule<T>() where T : class
|
|
{
|
|
Type interfaceType = typeof(T);
|
|
|
|
if (!interfaceType.IsInterface)
|
|
{
|
|
throw new GameFrameworkException(Utility.Text.Format("You must get module by interface, but '{0}' is not.", interfaceType.FullName));
|
|
}
|
|
|
|
return GetModule(interfaceType) as T;
|
|
}
|
|
|
|
public static IModule GetModule(Type moduleType)
|
|
{
|
|
if (_moduleMaps.TryGetValue(moduleType, out var ret))
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
return default;
|
|
}
|
|
|
|
private static IModule SetModuleInstance(Type interfaceType, Type implType)
|
|
{
|
|
IModule module = (IModule)Activator.CreateInstance(implType);
|
|
|
|
_moduleMaps[interfaceType] = module;
|
|
_modules.AddLast(module);
|
|
|
|
if (module is IModuleAwake awakeSystem)
|
|
{
|
|
awakeSystem.Awake();
|
|
}
|
|
|
|
CheckSystemLife(module);
|
|
return module;
|
|
}
|
|
|
|
#endregion
|
|
|
|
private static void CheckSystemLife(IModule module)
|
|
{
|
|
if (module is IModuleUpdate updateSystem)
|
|
{
|
|
BindSystemLife<IModuleUpdate>(updateSystem, _updateModules, ref _isExecuteListDirty);
|
|
}
|
|
|
|
if (module is IModuleLateUpdate lateUpdate)
|
|
{
|
|
BindSystemLife<IModuleLateUpdate>(lateUpdate, _lateUpdateModules, ref _isLateExecuteListDirty);
|
|
}
|
|
|
|
if (module is IModuleFixedUpdate fixedUpdate)
|
|
{
|
|
BindSystemLife<IModuleFixedUpdate>(fixedUpdate, _fixedUpdateModules, ref _isFixedExecuteListDirty);
|
|
}
|
|
|
|
if (module is IModuleDrawGizmos drawGizmosUpdate)
|
|
{
|
|
BindSystemLife<IModuleDrawGizmos>(drawGizmosUpdate, _gizmosUpdateModules, ref _isGizmosExecuteListDirty);
|
|
}
|
|
|
|
if (module is IModuleGUI guiUpdate)
|
|
{
|
|
BindSystemLife<IModuleGUI>(guiUpdate, _guiUpdateModules, ref _isGUIExecuteListDirty);
|
|
}
|
|
}
|
|
|
|
internal static void BindSystemLife<T>(T system, GameFrameworkLinkedList<T> updateModule, ref bool executeDirty) where T : IExecuteSystem
|
|
{
|
|
LinkedListNode<T> currentUpdate = updateModule.First;
|
|
while (currentUpdate != null)
|
|
{
|
|
if (system.Priority > currentUpdate.Value.Priority)
|
|
{
|
|
break;
|
|
}
|
|
|
|
currentUpdate = currentUpdate.Next;
|
|
}
|
|
|
|
if (currentUpdate != null)
|
|
{
|
|
updateModule.AddBefore(currentUpdate, system);
|
|
}
|
|
else
|
|
{
|
|
updateModule.AddLast(system);
|
|
}
|
|
|
|
executeDirty = true;
|
|
}
|
|
|
|
#region BuildExecuteList
|
|
|
|
private static void BuildExecuteList()
|
|
{
|
|
if (_isExecuteListDirty)
|
|
{
|
|
_isExecuteListDirty = false;
|
|
Array.Clear(_updateExecuteArray, 0, _updateExecuteArray.Length);
|
|
int index = 0;
|
|
foreach (var module in _updateModules)
|
|
{
|
|
_updateExecuteArray[index++] = module;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void BuildLateExecuteList()
|
|
{
|
|
if (_isLateExecuteListDirty)
|
|
{
|
|
_isLateExecuteListDirty = false;
|
|
Array.Clear(_lateUpdateExecuteArray, 0, _lateUpdateExecuteArray.Length);
|
|
int index = 0;
|
|
foreach (var module in _lateUpdateModules)
|
|
{
|
|
_lateUpdateExecuteArray[index++] = module;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void BuildFixedExecuteList()
|
|
{
|
|
if (_isFixedExecuteListDirty)
|
|
{
|
|
_isFixedExecuteListDirty = false;
|
|
Array.Clear(_fixedUpdateExecuteArray, 0, _fixedUpdateExecuteArray.Length);
|
|
int index = 0;
|
|
foreach (var module in _fixedUpdateModules)
|
|
{
|
|
_fixedUpdateExecuteArray[index++] = module;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void BuildGizmosExecuteList()
|
|
{
|
|
if (_isGizmosExecuteListDirty)
|
|
{
|
|
_isGizmosExecuteListDirty = false;
|
|
Array.Clear(_gizmosUpdateExecuteArray, 0, _gizmosUpdateExecuteArray.Length);
|
|
int index = 0;
|
|
foreach (var module in _gizmosUpdateModules)
|
|
{
|
|
_gizmosUpdateExecuteArray[index++] = module;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void BuildGUIExecuteList()
|
|
{
|
|
if (_isGUIExecuteListDirty)
|
|
{
|
|
_isGUIExecuteListDirty = false;
|
|
Array.Clear(_guiUpdateExecuteArray, 0, _guiUpdateExecuteArray.Length);
|
|
int index = 0;
|
|
foreach (var module in _guiUpdateModules)
|
|
{
|
|
_guiUpdateExecuteArray[index++] = module;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RunExecuteList
|
|
|
|
internal static void UpdateExecuteList(float elapseSeconds, float realElapseSeconds)
|
|
{
|
|
BuildExecuteList();
|
|
int executeCount = _updateExecuteArray.Length;
|
|
for (int i = 0; i < executeCount; i++)
|
|
{
|
|
_updateExecuteArray[i]?.Update(elapseSeconds, realElapseSeconds);
|
|
}
|
|
}
|
|
|
|
internal static void UpdateLateExecuteList()
|
|
{
|
|
BuildLateExecuteList();
|
|
int executeCount = _lateUpdateExecuteArray.Length;
|
|
for (int i = 0; i < executeCount; i++)
|
|
{
|
|
_lateUpdateExecuteArray[i]?.LateUpdate();
|
|
}
|
|
}
|
|
|
|
internal static void UpdateFixedExecuteList()
|
|
{
|
|
BuildFixedExecuteList();
|
|
int executeCount = _fixedUpdateExecuteArray.Length;
|
|
for (int i = 0; i < executeCount; i++)
|
|
{
|
|
_fixedUpdateExecuteArray[i]?.FixedUpdate();
|
|
}
|
|
}
|
|
|
|
internal static void UpdateGizmosExecuteList()
|
|
{
|
|
BuildGizmosExecuteList();
|
|
int executeCount = _gizmosUpdateExecuteArray.Length;
|
|
for (int i = 0; i < executeCount; i++)
|
|
{
|
|
_gizmosUpdateExecuteArray[i]?.DrawGizmos();
|
|
}
|
|
}
|
|
|
|
internal static void UpdateGUIExecuteList()
|
|
{
|
|
BuildGUIExecuteList();
|
|
int executeCount = _guiUpdateExecuteArray.Length;
|
|
for (int i = 0; i < executeCount; i++)
|
|
{
|
|
_guiUpdateExecuteArray[i]?.OnGUI();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|