-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:
parent
ae53e13d42
commit
d3222eefbb
4 changed files with 109 additions and 25 deletions
|
|
@ -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)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue