-add systemCaller to entity only if their components matches

-System onEnable() and onDisable() callbacks
This commit is contained in:
Mergul 2018-09-12 14:28:32 +02:00
parent 22fdd2f4e4
commit ae53e13d42
4 changed files with 152 additions and 78 deletions

View file

@ -7,6 +7,7 @@ import std.algorithm : max;
import std.conv : to;
import core.stdc.string;
import core.stdc.stdlib;
import ecs.system;
import ecs.entity;
@ -34,6 +35,8 @@ class EntityManager
{
alias types = Parameters!(Sys.update);
System system;
static string genCall()()
{
string ret = "s.update(";
@ -57,6 +60,8 @@ class EntityManager
return ret;
}
static if (hasMember!(Sys, "update"))
{
static void callUpdate(ref CallData data, void* entity)
{
static if (hasMember!(Sys, "update"))
@ -78,25 +83,44 @@ class EntityManager
}
}
System system;
static if (hasMember!(Sys, "update"))
{
system.update = &callUpdate;
}
static if (hasMember!(Sys, "onEnable"))
{
static void callEnable(void* system_pointer)
{
Sys* s = cast(Sys*) system_pointer;
s.onEnable();
}
system.m_enable = &callEnable;
}
static if (hasMember!(Sys, "onDisable"))
{
static void callDisable(void* system_pointer)
{
Sys* s = cast(Sys*) system_pointer;
s.onDisable();
}
system.m_disable = &callDisable;
}
system.system_pointer = cast(void*) Mallocator.instance.make!Sys;
system.components = Mallocator.instance.makeArray!uint(types.length);
mixin(genCompList());
if (systems is null)
systems.add(system);
systems[$ - 1].enable();
foreach (info; &entities_infos.byValue)
{
systems = Mallocator.instance.makeArray!System(1);
systems[0] = system;
}
else
{
Mallocator.instance.expandArray(systems, 1);
systems[$ - 1] = system;
addEntityCaller(*info, systems[$ - 1]);
}
}
@ -107,17 +131,7 @@ class EntityManager
info.size = size;
info.aligment = Comp.alignof; //8;
if (components is null)
{
components = Mallocator.instance.makeArray!ComponentInfo(1);
components[0] = info;
}
else
{
Mallocator.instance.expandArray(components, 1);
components[$ - 1] = info;
}
components.add(info);
components_map.add(Comp.stringof, cast(uint)(components.length - 1));
}
@ -127,7 +141,8 @@ class EntityManager
{
foreach (data; info.callers)
{
data.system.update(data, null); //caller(call_data,null);
if (data.system.enabled)
(cast(SytemFuncType) data.system.update)(data, null); //caller(call_data,null);
}
}
}
@ -163,20 +178,7 @@ class EntityManager
{
if (system.update is null)
continue;
CallData call_data = CallData(&system, info, null);
call_data.deltas = Mallocator.instance.makeArray!ushort(system.components.length);
foreach (i, id; system.components)
{
foreach (i2, id2; info.components)
{
if (id2 == id)
{
call_data.deltas[i] = info.deltas[i2];
break;
}
}
}
info.callers.add(call_data);
addEntityCaller(*info, system);
}
entities_infos.add(info.components, info);
@ -188,6 +190,35 @@ class EntityManager
return temp;
}
void addEntityCaller(ref EntityInfo entity, ref System system)
{
CallData call_data = CallData(&system, &entity, null);
ushort[] deltas = (cast(ushort*) alloca(system.components.length * ushort.sizeof))[0
.. system.components.length];
foreach (i, id; system.components)
{
deltas[i] = ushort.max;
foreach (i2, id2; entity.components)
{
if (id2 == id)
{
deltas[i] = entity.deltas[i2];
break;
}
}
if (deltas[i] == ushort.max)
{
deltas = null;
break;
}
}
if (deltas)
{
call_data.deltas = Mallocator.instance.makeArray(deltas); //Mallocator.instance.makeArray!ushort(system.components.length);
entity.callers.add(call_data);
}
}
void freeTemplate(EntityTemplate* template_)
{
Mallocator.instance.dispose(template_.entity_data);
@ -204,7 +235,8 @@ class EntityManager
{
if (block is null)
{
block = cast(EntitiesBlock*) AlignedMallocator.instance.alignedAllocate(page_size, page_size);
block = cast(EntitiesBlock*) AlignedMallocator.instance.alignedAllocate(page_size,
page_size);
*block = EntitiesBlock(tmpl.info);
if (previous_block is null)
{
@ -237,13 +269,6 @@ class EntityManager
block.entities_count++;
}
struct CallData
{
System* system;
EntityInfo* info;
ushort[] deltas;
}
struct ComponentInfo
{
ushort size;
@ -283,17 +308,24 @@ class EntityManager
///there is a loooot of data (4kB, pure magic)
}
enum page_size = 4096;
enum pages_in_block = 128;
struct CallData
{
System* system;
EntityManager.EntityInfo* info;
ushort[] deltas;
}
alias SytemFuncType = void function(ref EntityManager.CallData data, void* entity);
enum page_size = 4096;
enum pages_in_block = 128;
IDManager id_manager;
HashMap!(ushort[], EntityInfo*) entities_infos;
HashMap!(string, uint) components_map;
System[] systems;
ComponentInfo[] components;
Vector!System systems;
Vector!ComponentInfo components;
__gshared EntityManager instance;
}

7
source/ecs/package.d Normal file
View file

@ -0,0 +1,7 @@
module ecs;
public import ecs.manager;
public import ecs.entity;
public import ecs.system;
import ecs.id_manager;
import ecs.events;

View file

@ -6,7 +6,7 @@ import ecs.manager;
struct System
{
///should system update and catch events?
bool enabled = true;
bool m_enabled = false;
///system priority
int prority;
///pointer to system implementation
@ -14,5 +14,26 @@ struct System
uint[] components;
void function(ref EntityManager.CallData data, void* entity) update;
bool enabled()
{
return m_enabled;
}
void enable()
{
if(!m_enabled && m_enable)m_enable(system_pointer);
m_enabled = true;
}
void disable()
{
if(m_enabled && m_disable)m_disable(system_pointer);
m_enabled = false;
}
//void function(ref EntityManager.CallData data, void* entity) update;
void* update; ///workaroud for DMD bug with upper line
void function(void* system_pointer) m_enable;
void function(void* system_pointer) m_disable;
}

View file

@ -77,6 +77,18 @@ int main()
struct TestSystem2
{
void onEnable()
{
import std.stdio;
writeln("TestSystem2 enabled");
}
void onDisable()
{
import std.stdio;
writeln("TestSystem2 disabled");
}
void initialize(ref TestComp comp)
{
@ -102,15 +114,15 @@ int main()
gEM.registerComponent!TestComp;
ulong dur = (MonoTime.currTime - time).total!"usecs";
writeln("Components register time: ",dur," usecs");
writeln("Components register: ",dur," usecs");
time = MonoTime.currTime;
gEM.registerSystem!TestSystem(0);
gEM.registerSystem!TestSystem2(0);
//gEM.registerSystem!TestSystem2(0);
dur = (MonoTime.currTime - time).total!"usecs";
writeln("System register time: ",dur," usecs");
writeln("Systems register: ",dur," usecs");
time = MonoTime.currTime;
@ -119,7 +131,7 @@ int main()
*cast(EntityID*)tmpl.entity_data.ptr = EntityID(1,1);
dur = (MonoTime.currTime - time).total!"usecs";
writeln("Template allocating time: ",dur," usecs");
writeln("Template allocating: ",dur," usecs");
time = MonoTime.currTime;
@ -128,6 +140,8 @@ int main()
dur = (MonoTime.currTime - time).total!"usecs";
writeln("Entities adding: ",dur," usecs");
gEM.registerSystem!TestSystem2(0);
//assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+24)) == EntityID(1,1));
//assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+48)) == EntityID(1,1));
@ -136,10 +150,10 @@ int main()
gEM.update();
dur = (MonoTime.currTime - time).total!"usecs";
writeln("Update time: ",dur," usecs");
writeln("Update: ",dur," usecs");
import std.stdio;
writeln((cast(uint*)tmpl.info.first_block)[0..48]);
//import std.stdio;
//writeln((cast(uint*)tmpl.info.first_block)[0..48]);
gEM.freeTemplate(tmpl);
return 0;
}