-some usefull functions for IDManager

-added EntityManager.removeEntity(EntityID)
-EntitiesBlock now has ID usefull for updating first_free_block in EntityInfo
This commit is contained in:
Mergul 2018-09-12 17:38:41 +02:00
parent ae53e13d42
commit d3222eefbb
4 changed files with 109 additions and 25 deletions

View file

@ -30,6 +30,19 @@ struct IDManager
m_ids_array[entity.id.id].entity = &entity; m_ids_array[entity.id.id].entity = &entity;
} }
Entity* getEntityPointer(EntityID id)
{
Data* data = &m_ids_array[id.id];
if(data.counter != id.counter)return null;
else return data.entity;
}
bool isExist(EntityID id)
{
Data* data = &m_ids_array[id.id];
return data.counter == id.counter;
}
struct Data struct Data
{ {
uint counter = 0; uint counter = 0;
@ -61,5 +74,7 @@ unittest
assert(id1 == EntityID(1,2)); assert(id1 == EntityID(1,2));
assert(id2 == EntityID(0,2)); assert(id2 == EntityID(0,2));
assert(id3 == EntityID(2,1)); assert(id3 == EntityID(2,1));
assert(manager.isExist(id3));
assert(!manager.isExist(EntityID(0,1)));
} }

View file

@ -54,7 +54,7 @@ class EntityManager
string ret; string ret;
foreach (i, param; Parameters!(Sys.update)) foreach (i, param; Parameters!(Sys.update))
{ {
ret ~= "system.components[" ~ i.to!string ret ~= "system.m_components[" ~ i.to!string
~ "] = components_map.get(types[" ~ i.to!string ~ "].stringof);\n"; ~ "] = components_map.get(types[" ~ i.to!string ~ "].stringof);\n";
} }
return ret; return ret;
@ -66,7 +66,7 @@ class EntityManager
{ {
static if (hasMember!(Sys, "update")) static if (hasMember!(Sys, "update"))
{ {
Sys* s = cast(Sys*) data.system.system_pointer; Sys* s = cast(Sys*) data.system.m_system_pointer;
EntitiesBlock* block = data.info.first_block; EntitiesBlock* block = data.info.first_block;
while (block !is null) while (block !is null)
@ -83,7 +83,7 @@ class EntityManager
} }
} }
system.update = &callUpdate; system.m_update = &callUpdate;
} }
static if (hasMember!(Sys, "onEnable")) static if (hasMember!(Sys, "onEnable"))
@ -110,9 +110,9 @@ class EntityManager
system.m_disable = &callDisable; system.m_disable = &callDisable;
} }
system.system_pointer = cast(void*) Mallocator.instance.make!Sys; system.m_system_pointer = cast(void*) Mallocator.instance.make!Sys;
system.components = Mallocator.instance.makeArray!uint(types.length); system.m_components = Mallocator.instance.makeArray!uint(types.length);
mixin(genCompList()); mixin(genCompList());
systems.add(system); systems.add(system);
@ -142,7 +142,7 @@ class EntityManager
foreach (data; info.callers) foreach (data; info.callers)
{ {
if (data.system.enabled) if (data.system.enabled)
(cast(SytemFuncType) data.system.update)(data, null); //caller(call_data,null); (cast(SytemFuncType) data.system.m_update)(data, null); //caller(call_data,null);
} }
} }
} }
@ -176,7 +176,7 @@ class EntityManager
foreach (ref system; systems) foreach (ref system; systems)
{ {
if (system.update is null) if (system.m_update is null)
continue; continue;
addEntityCaller(*info, system); addEntityCaller(*info, system);
} }
@ -193,9 +193,9 @@ class EntityManager
void addEntityCaller(ref EntityInfo entity, ref System system) void addEntityCaller(ref EntityInfo entity, ref System system)
{ {
CallData call_data = CallData(&system, &entity, null); CallData call_data = CallData(&system, &entity, null);
ushort[] deltas = (cast(ushort*) alloca(system.components.length * ushort.sizeof))[0 ushort[] deltas = (cast(ushort*) alloca(system.m_components.length * ushort.sizeof))[0
.. system.components.length]; .. system.m_components.length];
foreach (i, id; system.components) foreach (i, id; system.m_components)
{ {
deltas[i] = ushort.max; deltas[i] = ushort.max;
foreach (i2, id2; entity.components) foreach (i2, id2; entity.components)
@ -214,7 +214,7 @@ class EntityManager
} }
if (deltas) if (deltas)
{ {
call_data.deltas = Mallocator.instance.makeArray(deltas); //Mallocator.instance.makeArray!ushort(system.components.length); call_data.deltas = Mallocator.instance.makeArray(deltas); //Mallocator.instance.makeArray!ushort(system.m_components.length);
entity.callers.add(call_data); entity.callers.add(call_data);
} }
} }
@ -225,7 +225,7 @@ class EntityManager
Mallocator.instance.dispose(template_); Mallocator.instance.dispose(template_);
} }
void addEntity(EntityTemplate* tmpl) ref Entity addEntity(EntityTemplate* tmpl)
{ {
EntitiesBlock* previous_block; EntitiesBlock* previous_block;
EntitiesBlock* block = tmpl.info.first_with_free_space; //tmpl.info.first_block; EntitiesBlock* block = tmpl.info.first_with_free_space; //tmpl.info.first_block;
@ -241,10 +241,12 @@ class EntityManager
if (previous_block is null) if (previous_block is null)
{ {
tmpl.info.first_block = block; tmpl.info.first_block = block;
block.id = 0;
} }
else else
{ {
previous_block.next_block = block; previous_block.next_block = block;
block.id = previous_block.id + 1;
} }
tmpl.info.first_with_free_space = block; tmpl.info.first_with_free_space = block;
break; // new block certainly has free space break; // new block certainly has free space
@ -267,6 +269,37 @@ class EntityManager
entity.id = id_manager.getNewID(); entity.id = id_manager.getNewID();
entity.updateID(); entity.updateID();
block.entities_count++; block.entities_count++;
return *entity;
}
void removeEntity(EntityID id)
{
Entity* entity = id_manager.getEntityPointer(id);
if(entity is null)return;
EntitiesBlock* block = getMetaData(entity);
id_manager.releaseID(id);
void* data_begin = block.dataBegin();
uint pos = cast(int)(cast(void*)entity - data_begin) / block.type_data.size;
block.entities_count--;
if(block.type_data.first_with_free_space.id > block.id)block.type_data.first_with_free_space = block;
if(pos == block.entities_count)return;
void* src = data_begin + block.entities_count * block.type_data.size;
void* dst = data_begin + pos * block.type_data.size;
memcpy(dst,src,block.type_data.size);
entity = cast(Entity*) dst;
entity.updateID();
}
EntitiesBlock* getMetaData(void* pointer)
{
return cast(EntitiesBlock*)(cast(size_t) pointer & (~cast(size_t)(page_size - 1)));
} }
struct ComponentInfo struct ComponentInfo
@ -304,6 +337,7 @@ class EntityManager
EntityInfo* type_data; EntityInfo* type_data;
uint entities_count; uint entities_count;
uint id;
EntitiesBlock* next_block; EntitiesBlock* next_block;
///there is a loooot of data (4kB, pure magic) ///there is a loooot of data (4kB, pure magic)
} }
@ -317,7 +351,9 @@ class EntityManager
alias SytemFuncType = void function(ref EntityManager.CallData data, void* entity); alias SytemFuncType = void function(ref EntityManager.CallData data, void* entity);
///Single page size. Must be power of two.
enum page_size = 4096; enum page_size = 4096;
///Number of pages in block.
enum pages_in_block = 128; enum pages_in_block = 128;
IDManager id_manager; IDManager id_manager;

View file

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

View file

@ -135,7 +135,33 @@ int main()
time = MonoTime.currTime; time = MonoTime.currTime;
foreach(i; 0..1_000_000)gEM.addEntity(tmpl); //foreach(i; 0..1_000_000)gEM.addEntity(tmpl);
//foreach(i; 0..1_000_000)gEM.removeEntity(gEM.addEntity(tmpl).id);
EntityID[1000] idss;
foreach(i; 0..1_000)
{
foreach(j; 0..1_000)idss[j] = gEM.addEntity(tmpl).id;
foreach(j; 0..1_000)gEM.removeEntity(idss[j]);
}
uint blocks = 0;
foreach(info; &gEM.entities_infos.byValue)
{
EntityManager.EntitiesBlock* block = info.first_block;
while(block !is null)
{
block = block.next_block;
blocks++;
}
}
writeln("Entities blocks: ",blocks);
/*Entity entity = gEM.addEntity(tmpl);
gEM.removeEntity(entity.id);
gEM.addEntity(tmpl);*/
dur = (MonoTime.currTime - time).total!"usecs"; dur = (MonoTime.currTime - time).total!"usecs";
writeln("Entities adding: ",dur," usecs"); writeln("Entities adding: ",dur," usecs");