namespace Theater_ECS.Internal.Managers; using System; using System.Collections; class SystemsManager : IEnumerable<(String key, System value)> { private ECS _owner; private Dictionary _registeredSystems = new .() ~ delete _; private Dictionary _registeredLooseSystems = new .() ~ DeleteDictionaryAndKeys!(_); private bool _dirty = false; private List _sortedSystems = new .() ~ delete _; private List<(function void(ECS), float, SystemSection)> _sortedLooseSystems = new .() ~ delete _; public this(ECS ecs) { _owner = ecs; } ///Registers a system and returns false if its already contained public bool RegisterSystem(System sys, StringView id) { if (_registeredSystems.ContainsKeyAlt(id) || _registeredLooseSystems.ContainsKeyAlt(id)) return false; _dirty = true; _registeredSystems.Add(new .(id), sys); sys.RegisterSystem(_owner); return true; } ///Register a system without an actual system object public bool RegisterLooseSystem(StringView id, function void(ECS) func, float runtimeDelay = 0, SystemSection section = .TECS_Update) { if (_registeredSystems.ContainsKeyAlt(id) || _registeredLooseSystems.ContainsKeyAlt(id)) return false; _dirty = true; _registeredLooseSystems.Add(new .(id), (func, runtimeDelay, section)); return true; } ///Deregister a single system public Result DeregisterSystem(StringView id) { _dirty = true; if (!(_registeredSystems.ContainsKeyAlt(id) || _registeredLooseSystems.ContainsKeyAlt(id))) return .Err; if (_registeredSystems.ContainsKeyAlt(id)) return .Ok(_registeredSystems.GetAndRemoveAlt(id).Value.value); else { _registeredLooseSystems.Remove(scope .(id)); return .Ok(null); } } ///Remove all systems from use and return the amount of systems cleared public int ClearAllSystems() { _dirty = true; var c = _registeredSystems.Count; _registeredSystems.Clear(); return c; } ///Runs all systems once public void RunAllSystems(ECS ecs, float delta = 0) { if (_dirty) { SortSystemPriorites(); _dirty = false; } int counter = 0; int counterLoose = 0; for (uint8 section <= 255) { if (_sortedSystems.Count > counter) while (_sortedSystems[counter].Section == (.)section) { _sortedSystems[counter].RunSystem(ecs); counter++; } if (_sortedLooseSystems.Count > counterLoose) while (_sortedLooseSystems[counterLoose].2 == (.)section) { _sortedLooseSystems[counterLoose].0(ecs); counter++; } } } ///Run all systems that fall inbetween two Sections public void RunSystemsBetween(ECS ecs, SystemSection sectionStart, SystemSection sectionEnd, float delta = 0) { if (_dirty) { SortSystemPriorites(); _dirty = false; } int counter = 0; int counterLoose = 0; for (uint8 section = (.)sectionStart; section <= (uint8)sectionEnd; section++) { if (_sortedSystems.Count > counter) while (_sortedSystems[counter].Section == (.)section) { _sortedSystems[counter].RunSystem(ecs); counter++; } if (_sortedLooseSystems.Count > counterLoose) while (_sortedLooseSystems[counterLoose].2 == (.)section) { _sortedLooseSystems[counterLoose].0(ecs); counter++; } } } ///Run all systems with a specific section public void RunSystemsBySection(ECS ecs, SystemSection section, float delta = 0) { if (_dirty) { SortSystemPriorites(); _dirty = false; } int counter = 0; int counterLoose = 0; if (_sortedSystems.Count > counter) while (_sortedSystems[counter].Section == (.)section) { _sortedSystems[counter].RunSystem(ecs); counter++; } if (_sortedLooseSystems.Count > counterLoose) while (_sortedLooseSystems[counterLoose].2 == (.)section) { _sortedLooseSystems[counterLoose].0(ecs); counter++; } } ///Run a single system public Result RunSystem(StringView id, ECS ecs) { if (!_registeredSystems.ContainsKeyAlt(id)) return .Err; _registeredSystems[scope .(id)].RunSystem(ecs); return .Ok; } ///Runs a function over all systems public void EnumerateSystems(delegate void(System) func) { for (var i in _registeredSystems) func.Invoke(i.value); } public int Count => _registeredSystems.Count; public Dictionary.Enumerator GetEnumerator() => _registeredSystems.GetEnumerator(); public Dictionary.Enumerator GetLooseEnumerator() => _registeredLooseSystems.GetEnumerator(); private void SortSystemPriorites() { _sortedSystems.Clear(); _sortedLooseSystems.Clear(); for (var i in _registeredSystems) _sortedSystems.Add(i.value); _sortedSystems.Sort(scope (a, b) => { return a.Section - b.Section; }); for (var i in _registeredLooseSystems) _sortedLooseSystems.Add(i.value); _sortedLooseSystems.Sort(scope (a, b) => { return a.2 - b.2; }); } }