Added section ordering for systems runtime

This commit is contained in:
Booklordofthedings 2024-11-19 16:27:52 +01:00
parent 34b929c4e7
commit 6cd249dc5b
4 changed files with 117 additions and 8 deletions

View file

@ -11,6 +11,8 @@ class PagedSparseSet
private List<Entity> _packed = new .() ~ delete _; private List<Entity> _packed = new .() ~ delete _;
private UList _packedEntities ~ delete _; private UList _packedEntities ~ delete _;
private function void(void* data) _deallocationFunction = null;
public this(int_cosize size) public this(int_cosize size)
{ {
_packedEntities = new .(size); _packedEntities = new .(size);
@ -29,12 +31,15 @@ class PagedSparseSet
_sparse[e.Index/PageSize][e.Index % PageSize] = (.)_packed.Count-1; _sparse[e.Index/PageSize][e.Index % PageSize] = (.)_packed.Count-1;
} }
public bool Remove(Entity e) public bool Remove(Entity e, bool cleanup = false)
{ {
EnsurePage(e.Index/PageSize); EnsurePage(e.Index/PageSize);
if(_sparse[e.Index/PageSize] == null) if(_sparse[e.Index/PageSize] == null)
return false; return false;
if(_deallocationFunction != null && !cleanup)
_deallocationFunction(_packedEntities[(.)(_sparse[e.Index/PageSize][e.Index % PageSize].Index)]);
let toRm = _packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index]; let toRm = _packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index];
let b = _packed.Back; let b = _packed.Back;
_packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index] = b; _packed[_sparse[e.Index/PageSize][e.Index % PageSize].Index] = b;

View file

@ -38,6 +38,9 @@ class ComponentManager
return (.)(Components.Count-1); return (.)(Components.Count-1);
} }
///Sets a function that should be called, when an object gets removed
public void SetDeallocationFunction(Component c, function void(void*) func) => Components[c].[Friend]_deallocationFunction = func;
[Inline] [Inline]
public void* GetData(Entity e, Component c) => Components[c].[Unchecked]Get(e); public void* GetData(Entity e, Component c) => Components[c].[Unchecked]Get(e);
@ -52,7 +55,7 @@ class ComponentManager
public void AddToEntity(Entity e, Component c, void* data) => Components[c].Add(e, data); public void AddToEntity(Entity e, Component c, void* data) => Components[c].Add(e, data);
///Remove a component from the given entity ///Remove a component from the given entity
public bool RemoveFromEntity(Entity e, Component c) => Components[c].Remove(e); public bool RemoveFromEntity(Entity e, Component c) => Components[c].Remove(e, true);
///Remove a component from the given entity and return it ///Remove a component from the given entity and return it
public Result<void*> GetAndRemoveFromEntity(Entity e, Component c) public Result<void*> GetAndRemoveFromEntity(Entity e, Component c)

View file

@ -7,6 +7,11 @@ class SystemsManager : IEnumerable<(String key, System value)>
{ {
private ECS _owner; private ECS _owner;
private Dictionary<String, System> _registeredSystems = new .() ~ delete _; private Dictionary<String, System> _registeredSystems = new .() ~ delete _;
private Dictionary<String, (function void(ECS), float, SystemSection)> _registeredLooseSystems = new .() ~ DeleteDictionaryAndKeys!(_);
private bool _dirty = false;
private List<System> _sortedSystems = new .() ~ delete _;
private List<(function void(ECS), float, SystemSection)> _sortedLooseSystems = new .() ~ delete _;
public this(ECS ecs) public this(ECS ecs)
{ {
@ -16,34 +21,103 @@ class SystemsManager : IEnumerable<(String key, System value)>
///Registers a system and returns false if its already contained ///Registers a system and returns false if its already contained
public bool RegisterSystem(System sys, StringView id) public bool RegisterSystem(System sys, StringView id)
{ {
if (_registeredSystems.ContainsKeyAlt<StringView>(id)) if (_registeredSystems.ContainsKeyAlt<StringView>(id) || _registeredLooseSystems.ContainsKeyAlt<StringView>(id))
return false; return false;
_dirty = true;
_registeredSystems.Add(new .(id), sys); _registeredSystems.Add(new .(id), sys);
sys.RegisterSystem(_owner); sys.RegisterSystem(_owner);
return true; 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<StringView>(id) || _registeredLooseSystems.ContainsKeyAlt<StringView>(id))
return false;
_dirty = true;
_registeredLooseSystems.Add(new .(id), (func, runtimeDelay, section));
return true;
}
///Deregister a single system ///Deregister a single system
public Result<System> DeregisterSystem(StringView id) public Result<System> DeregisterSystem(StringView id)
{ {
if (!_registeredSystems.ContainsKeyAlt<StringView>(id)) _dirty = true;
if (!(_registeredSystems.ContainsKeyAlt<StringView>(id) || _registeredLooseSystems.ContainsKeyAlt<StringView>(id)))
return .Err; return .Err;
return .Ok(_registeredSystems.GetAndRemoveAlt<StringView>(id).Value.value); if (_registeredSystems.ContainsKeyAlt<StringView>(id))
return .Ok(_registeredSystems.GetAndRemoveAlt<StringView>(id).Value.value);
else
{
_registeredLooseSystems.Remove(scope .(id));
return .Ok(null);
}
} }
///Remove all systems from use and return the amount of systems cleared ///Remove all systems from use and return the amount of systems cleared
public int ClearAllSystems() public int ClearAllSystems()
{ {
_dirty = true;
var c = _registeredSystems.Count; var c = _registeredSystems.Count;
_registeredSystems.Clear(); _registeredSystems.Clear();
return c; return c;
} }
///Runs all systems once ///Runs all systems once
public void RunAllSystems(ECS ecs) public void RunAllSystems(ECS ecs, float delta = 0)
{ {
for (var i in _registeredSystems) if (_dirty)
i.value.RunSystem(ecs); {
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 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 ///Run a single system
@ -67,4 +141,29 @@ class SystemsManager : IEnumerable<(String key, System value)>
public int Count => _registeredSystems.Count; public int Count => _registeredSystems.Count;
public Dictionary<String, System>.Enumerator GetEnumerator() => _registeredSystems.GetEnumerator(); public Dictionary<String, System>.Enumerator GetEnumerator() => _registeredSystems.GetEnumerator();
public Dictionary<String, (function void(ECS), float, SystemSection)>.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;
});
}
} }

View file

@ -1,4 +1,5 @@
namespace Theater_ECS; namespace Theater_ECS;
using Theater_ECS.Internal;
using Theater_ECS.Internal.Containers; using Theater_ECS.Internal.Containers;
using System; using System;
@ -8,6 +9,7 @@ abstract class System
{ {
public bool Paused = false; //Wether or not this service should be run public bool Paused = false; //Wether or not this service should be run
public float RuntimeDelay = 0; //How many seconds should we wait after running this system public float RuntimeDelay = 0; //How many seconds should we wait after running this system
public SystemSection Section = .TECS_Update;
private List<Component> _Components = new .(10) ~ delete _; private List<Component> _Components = new .(10) ~ delete _;