-LinearLayout implemntation:
*Entity.getComponent works *adding/removing objects work *update work
This commit is contained in:
parent
535071ebb9
commit
cb9bac5dde
5 changed files with 411 additions and 120 deletions
3
dub.json
3
dub.json
|
|
@ -10,6 +10,9 @@
|
||||||
"versions": [
|
"versions": [
|
||||||
"LinearLayout"
|
"LinearLayout"
|
||||||
],
|
],
|
||||||
|
"dflags-posix-ldc": [
|
||||||
|
"-defaultlib=phobos2-ldc,druntime-ldc"
|
||||||
|
],
|
||||||
"configurations" : [
|
"configurations" : [
|
||||||
{
|
{
|
||||||
"name" : "library",
|
"name" : "library",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import std.experimental.allocator.mallocator : AlignedMallocator, Mallocator;
|
||||||
|
|
||||||
struct BlockAllocator(uint block_size, uint blocks_in_allocation)
|
struct BlockAllocator(uint block_size, uint blocks_in_allocation)
|
||||||
{
|
{
|
||||||
void* next_block;
|
void* next_block = null;
|
||||||
|
|
||||||
void* getBlock()
|
void* getBlock()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,22 @@ struct Entity
|
||||||
T* getComponent(T)()
|
T* getComponent(T)()
|
||||||
{
|
{
|
||||||
EntityManager.EntitiesBlock* block = gEM.getMetaData(&this);
|
EntityManager.EntitiesBlock* block = gEM.getMetaData(&this);
|
||||||
EntityManager.EntityInfo* info = block.type_data;
|
EntityManager.EntityInfo* info = block.type_info;
|
||||||
if(T.component_id >= info.deltas.length || info.deltas[T.component_id] == 0)return null;
|
if (T.component_id >= info.deltas.length || info.deltas[T.component_id] == 0)
|
||||||
|
return null;
|
||||||
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
static if (EntityID.sizeof == 8)
|
||||||
|
uint ind = cast(uint)((cast(void*)&this - block.dataBegin()) >> 3);
|
||||||
|
else
|
||||||
|
uint ind = cast(uint)((cast(void*)&this - block.dataBegin()) / EntityID.sizeof());
|
||||||
|
return cast(T*)(cast(void*)block + info.deltas[T.component_id] + ind * T.sizeof);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return cast(T*)(cast(void*)&this + info.deltas[T.component_id]);
|
return cast(T*)(cast(void*)&this + info.deltas[T.component_id]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export struct EntityTemplate
|
export struct EntityTemplate
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,24 @@ class EntityManager
|
||||||
alias storages = ParameterStorageClassTuple!(Sys.update);
|
alias storages = ParameterStorageClassTuple!(Sys.update);
|
||||||
static string genCall()()
|
static string genCall()()
|
||||||
{
|
{
|
||||||
string ret = "s.update(*cast(Entity*)data_pointer,";
|
string ret;
|
||||||
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
uint i = 0;
|
||||||
|
uint opt = 0;
|
||||||
|
static foreach (param; (Parameters!(Sys.update))[1 .. $])
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if (isPointer!param)
|
||||||
|
{
|
||||||
|
ret ~= "if(opt_ptr" ~ opt.to!string ~ " !is null)opt_ptr"
|
||||||
|
~ opt.to!string ~ " = &opt_array" ~ opt.to!string ~ "[i];";
|
||||||
|
opt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/*foreach (i; 1 .. (Parameters!(Sys.update)).length)
|
/*foreach (i; 1 .. (Parameters!(Sys.update)).length)
|
||||||
{
|
{
|
||||||
ret ~= "*cast(types[" ~ i.to!string ~ "]*)(pointers[" ~ (i - 1)
|
ret ~= "*cast(types[" ~ i.to!string ~ "]*)(pointers[" ~ (i - 1)
|
||||||
|
|
@ -81,6 +98,25 @@ class EntityManager
|
||||||
uint i = 0;
|
uint i = 0;
|
||||||
uint req = 0;
|
uint req = 0;
|
||||||
uint opt = 0;
|
uint opt = 0;
|
||||||
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
ret ~= "s.update(id_array[i],";
|
||||||
|
static foreach (param; (Parameters!(Sys.update))[1 .. $])
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if (isPointer!param)
|
||||||
|
{
|
||||||
|
ret ~= "opt_ptr" ~ (opt++).to!string ~ ",";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret ~= "array" ~ (req++).to!string ~ "[i],";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret ~= "s.update(*cast(Entity*)data_pointer,";
|
||||||
static foreach (param; (Parameters!(Sys.update))[1 .. $])
|
static foreach (param; (Parameters!(Sys.update))[1 .. $])
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -95,10 +131,38 @@ class EntityManager
|
||||||
.to!string ~ "]),";
|
.to!string ~ "]),";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret ~= ");";
|
ret ~= ");";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static string genArrays()()
|
||||||
|
{
|
||||||
|
string ret;
|
||||||
|
|
||||||
|
uint i = 0;
|
||||||
|
uint req = 0;
|
||||||
|
uint opt = 0;
|
||||||
|
static foreach (param; (Parameters!(Sys.update))[1 .. $])
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if (isPointer!param)
|
||||||
|
{
|
||||||
|
ret ~= "PointerTarget!(types[" ~ i.to!string
|
||||||
|
~ "])[] opt_array" ~ opt.to!string ~ ";";
|
||||||
|
ret ~= "types[" ~ i.to!string ~ "] opt_ptr" ~ opt.to!string ~ ";";
|
||||||
|
opt++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret ~= "types[" ~ i.to!string ~ "][] array" ~ req.to!string ~ " = (cast(types[" ~ i.to!string ~ "]*)(cast(void*)block + info.deltas[types[" ~ i.to!string ~ "].component_id]))[0..block.entities_count];";
|
||||||
|
req++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static string genCompList()()
|
static string genCompList()()
|
||||||
{
|
{
|
||||||
string ret = "ushort comp;uint req;uint opt;";
|
string ret = "ushort comp;uint req;uint opt;";
|
||||||
|
|
@ -154,7 +218,39 @@ class EntityManager
|
||||||
EntitiesBlock* block = data.info.first_block;
|
EntitiesBlock* block = data.info.first_block;
|
||||||
while (block !is null)
|
while (block !is null)
|
||||||
{
|
{
|
||||||
uint size = block.type_data.size;
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
//uint size = block.type_info.size;
|
||||||
|
/*void* data_pointer = block.dataBegin();
|
||||||
|
foreach (i, ref pointer; pointers)
|
||||||
|
{
|
||||||
|
pointer = cast(void*) block + data.deltas[i];
|
||||||
|
}
|
||||||
|
foreach (i, ref pointer; optional_pointers)
|
||||||
|
{
|
||||||
|
uint ind = cast(uint)(i + pointers.length);
|
||||||
|
if (data.deltas[ind] != uint.max)
|
||||||
|
pointer = cast(void*) block + data.deltas[ind];
|
||||||
|
else
|
||||||
|
pointer = null;
|
||||||
|
}*/
|
||||||
|
EntityInfo* info = block.type_info;
|
||||||
|
Entity[] id_array = (cast(Entity*)block.dataBegin())[0..block.entities_count];
|
||||||
|
mixin(genArrays());
|
||||||
|
foreach (i; 0 .. block.entities_count)
|
||||||
|
{
|
||||||
|
mixin(genCall());
|
||||||
|
//data_pointer += EntityID.sizeof; //data.info.size;
|
||||||
|
/*foreach (ref pointer; pointers)
|
||||||
|
pointer += size;
|
||||||
|
foreach (ref pointer; optional_pointers)
|
||||||
|
if (pointer != null)
|
||||||
|
pointer += size;*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint size = block.type_info.size;
|
||||||
void* data_pointer = block.dataBegin();
|
void* data_pointer = block.dataBegin();
|
||||||
foreach (i, ref pointer; pointers)
|
foreach (i, ref pointer; pointers)
|
||||||
{
|
{
|
||||||
|
|
@ -178,6 +274,7 @@ class EntityManager
|
||||||
if (pointer != null)
|
if (pointer != null)
|
||||||
pointer += size;
|
pointer += size;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
block = block.next_block;
|
block = block.next_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -393,11 +490,22 @@ class EntityManager
|
||||||
temp.info = info;
|
temp.info = info;
|
||||||
|
|
||||||
//fill components with default data
|
//fill components with default data
|
||||||
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
foreach (comp; info.components)
|
||||||
|
{
|
||||||
|
temp.entity_data[info.tmpl_deltas[comp] .. info.tmpl_deltas[comp] + components[comp].size]
|
||||||
|
= components[comp].init_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
foreach (comp; info.components)
|
foreach (comp; info.components)
|
||||||
{
|
{
|
||||||
temp.entity_data[info.deltas[comp] .. info.deltas[comp] + components[comp].size]
|
temp.entity_data[info.deltas[comp] .. info.deltas[comp] + components[comp].size]
|
||||||
= components[comp].init_data;
|
= components[comp].init_data;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
@ -412,6 +520,23 @@ class EntityManager
|
||||||
info.components = Mallocator.instance.makeArray(ids);
|
info.components = Mallocator.instance.makeArray(ids);
|
||||||
info.deltas = Mallocator.instance.makeArray!ushort(ids[$ - 1] + 1);
|
info.deltas = Mallocator.instance.makeArray!ushort(ids[$ - 1] + 1);
|
||||||
|
|
||||||
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
info.tmpl_deltas = Mallocator.instance.makeArray!ushort(ids[$ - 1] + 1);
|
||||||
|
uint block_memory = page_size - EntitiesBlock.sizeof;
|
||||||
|
uint entity_comps_size = EntityID.sizeof;
|
||||||
|
uint mem_begin = EntitiesBlock.sizeof;
|
||||||
|
|
||||||
|
foreach (id; ids)
|
||||||
|
{
|
||||||
|
entity_comps_size += components[id].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint entites_in_block = block_memory / entity_comps_size;
|
||||||
|
info.max_entities = cast(ushort) entites_in_block;
|
||||||
|
uint current_delta = cast(uint)(mem_begin + entites_in_block * EntityID.sizeof);
|
||||||
|
}
|
||||||
|
|
||||||
info.size = EntityID.sizeof;
|
info.size = EntityID.sizeof;
|
||||||
info.alignment = EntityID.alignof;
|
info.alignment = EntityID.alignof;
|
||||||
|
|
||||||
|
|
@ -419,11 +544,29 @@ class EntityManager
|
||||||
{
|
{
|
||||||
info.alignment = max(info.alignment, components[id].alignment);
|
info.alignment = max(info.alignment, components[id].alignment);
|
||||||
alignNum(info.size, components[id].alignment);
|
alignNum(info.size, components[id].alignment);
|
||||||
|
|
||||||
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
info.tmpl_deltas[id] = info.size;
|
||||||
|
|
||||||
|
info.deltas[id] = cast(ushort) current_delta;
|
||||||
|
current_delta += entites_in_block * components[id].size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
info.deltas[id] = info.size;
|
info.deltas[id] = info.size;
|
||||||
|
}
|
||||||
|
|
||||||
info.size += components[id].size;
|
info.size += components[id].size;
|
||||||
}
|
}
|
||||||
alignNum(info.size, info.alignment);
|
alignNum(info.size, info.alignment);
|
||||||
|
|
||||||
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
info.max_entities = (page_size - EntitiesBlock.sizeof) / info.size;
|
||||||
|
|
||||||
foreach (uint i, ref system; systems)
|
foreach (uint i, ref system; systems)
|
||||||
{
|
{
|
||||||
if (system.m_update is null)
|
if (system.m_update is null)
|
||||||
|
|
@ -497,7 +640,6 @@ class EntityManager
|
||||||
delta_id++;
|
delta_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
call_data.deltas = Mallocator.instance.makeArray(deltas); //Mallocator.instance.makeArray!ushort(system.m_components.length);
|
call_data.deltas = Mallocator.instance.makeArray(deltas); //Mallocator.instance.makeArray!ushort(system.m_components.length);
|
||||||
|
|
||||||
uint index = 0;
|
uint index = 0;
|
||||||
|
|
@ -527,9 +669,10 @@ class EntityManager
|
||||||
private void __removeComponents(EntityID entity_id, ushort[] del_ids)
|
private void __removeComponents(EntityID entity_id, ushort[] del_ids)
|
||||||
{
|
{
|
||||||
Entity* entity = id_manager.getEntityPointer(entity_id);
|
Entity* entity = id_manager.getEntityPointer(entity_id);
|
||||||
if(!entity)return;
|
if (!entity)
|
||||||
|
return;
|
||||||
EntitiesBlock* block = getMetaData(entity);
|
EntitiesBlock* block = getMetaData(entity);
|
||||||
EntityInfo* info = block.type_data;
|
EntityInfo* info = block.type_info;
|
||||||
|
|
||||||
qsort(del_ids.ptr, del_ids.length, ushort.sizeof, &compareUShorts);
|
qsort(del_ids.ptr, del_ids.length, ushort.sizeof, &compareUShorts);
|
||||||
|
|
||||||
|
|
@ -598,9 +741,10 @@ class EntityManager
|
||||||
{
|
{
|
||||||
uint num = cast(uint) new_ids.length;
|
uint num = cast(uint) new_ids.length;
|
||||||
Entity* entity = id_manager.getEntityPointer(entity_id);
|
Entity* entity = id_manager.getEntityPointer(entity_id);
|
||||||
if(!entity)return;
|
if (!entity)
|
||||||
|
return;
|
||||||
EntitiesBlock* block = getMetaData(entity);
|
EntitiesBlock* block = getMetaData(entity);
|
||||||
EntityInfo* info = block.type_data;
|
EntityInfo* info = block.type_info;
|
||||||
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0
|
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0
|
||||||
.. info.components.length + num];
|
.. info.components.length + num];
|
||||||
/*ushort[num] new_ids;
|
/*ushort[num] new_ids;
|
||||||
|
|
@ -717,7 +861,7 @@ class EntityManager
|
||||||
const uint num = Components.length;
|
const uint num = Components.length;
|
||||||
Entity* entity = id_manager.getEntityPointer(entity_id);
|
Entity* entity = id_manager.getEntityPointer(entity_id);
|
||||||
EntitiesBlock* block = getMetaData(entity);
|
EntitiesBlock* block = getMetaData(entity);
|
||||||
EntityInfo* info = block.type_data;
|
EntityInfo* info = block.type_info;
|
||||||
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0
|
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0
|
||||||
.. info.components.length + num];
|
.. info.components.length + num];
|
||||||
ushort[num] new_ids;
|
ushort[num] new_ids;
|
||||||
|
|
@ -755,10 +899,25 @@ class EntityManager
|
||||||
export ref Entity addEntity(EntityTemplate* tmpl)
|
export ref Entity addEntity(EntityTemplate* tmpl)
|
||||||
{
|
{
|
||||||
EntitiesBlock* block = findBlockWithFreeSpace(tmpl.info);
|
EntitiesBlock* block = findBlockWithFreeSpace(tmpl.info);
|
||||||
|
uint id = (block.entities_count + block.added_count);
|
||||||
|
EntityInfo* info = tmpl.info;
|
||||||
|
|
||||||
void* start = block.dataBegin() + (block.entities_count + block.added_count)
|
version (LinearLayout)
|
||||||
* tmpl.info.size;
|
{
|
||||||
memcpy(start, tmpl.entity_data.ptr, tmpl.info.size);
|
void* data_begin = block.dataBegin();
|
||||||
|
void* start = data_begin + EntityID.sizeof * id;
|
||||||
|
//memcpy(data_begin + EntityID.sizeof * id, tmpl.entity_data.ptr, EntityID.sizeof);
|
||||||
|
foreach (i, comp; info.components)
|
||||||
|
{
|
||||||
|
memcpy(cast(void*) block + info.deltas[comp] + components[comp].size * id,
|
||||||
|
tmpl.entity_data.ptr + info.tmpl_deltas[comp], components[comp].size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
void* start = block.dataBegin() + id * info.size;
|
||||||
|
memcpy(start, tmpl.entity_data.ptr, info.size);
|
||||||
|
}
|
||||||
|
|
||||||
if (!block.added_count)
|
if (!block.added_count)
|
||||||
blocks_to_update.add(block);
|
blocks_to_update.add(block);
|
||||||
|
|
@ -791,14 +950,15 @@ class EntityManager
|
||||||
{
|
{
|
||||||
previous_block.next_block = block;
|
previous_block.next_block = block;
|
||||||
block.prev_block = previous_block;
|
block.prev_block = previous_block;
|
||||||
block.id = previous_block.id + 1;
|
block.id = cast(ushort)(previous_block.id + 1);
|
||||||
}
|
}
|
||||||
info.first_with_free_space = block;
|
info.first_with_free_space = block;
|
||||||
break; // new block certainly has free space
|
break; // new block certainly has free space
|
||||||
}
|
}
|
||||||
// check if there is enought space
|
// check if there is enought space
|
||||||
if (block.dataDelta() + (
|
/*if (block.dataDelta() + (
|
||||||
block.entities_count + block.added_count + 1) * info.size > page_size)
|
block.entities_count + block.added_count + 1) * info.size > page_size)*/
|
||||||
|
if (block.entities_count + block.added_count >= block.type_info.max_entities)
|
||||||
{
|
{
|
||||||
previous_block = block;
|
previous_block = block;
|
||||||
block = block.next_block;
|
block = block.next_block;
|
||||||
|
|
@ -834,41 +994,66 @@ class EntityManager
|
||||||
{
|
{
|
||||||
//pos is Entity number in block
|
//pos is Entity number in block
|
||||||
void* data_begin = block.dataBegin();
|
void* data_begin = block.dataBegin();
|
||||||
uint pos = cast(int)(cast(void*) entity - data_begin) / block.type_data.size;
|
EntityInfo* info = block.type_info;
|
||||||
|
|
||||||
block.entities_count--;
|
block.entities_count--;
|
||||||
|
|
||||||
//set "first_with_free_space" if should it be
|
//set "first_with_free_space" if should it be
|
||||||
if (block.type_data.first_with_free_space.id > block.id)
|
if (info.first_with_free_space.id > block.id)
|
||||||
block.type_data.first_with_free_space = block;
|
info.first_with_free_space = block;
|
||||||
|
|
||||||
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
static if (EntityID.sizeof == 8)
|
||||||
|
uint pos = cast(uint)((cast(void*) entity - data_begin) >> 3);
|
||||||
|
else
|
||||||
|
uint pos = cast(uint)((cast(void*) entity - data_begin) / EntityID.sizeof());
|
||||||
|
|
||||||
if (call_destructors)
|
if (call_destructors)
|
||||||
{
|
{
|
||||||
void* data = data_begin + pos * block.type_data.size;
|
//void* data = data_begin + pos * info.size;
|
||||||
foreach (comp; block.type_data.components)
|
foreach (comp; info.components)
|
||||||
{
|
{
|
||||||
if (components[comp].destroy_callback)
|
if (components[comp].destroy_callback)
|
||||||
{
|
{
|
||||||
components[comp].destroy_callback(data + block.type_data.deltas[comp]);
|
//components[comp].destroy_callback(data + info.deltas[comp]);
|
||||||
|
components[comp].destroy_callback(cast(
|
||||||
|
void*) block + info.deltas[comp] + pos * components[comp].size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint pos = cast(int)(cast(void*) entity - data_begin) / info.size;
|
||||||
|
if (call_destructors)
|
||||||
|
{
|
||||||
|
void* data = data_begin + pos * info.size;
|
||||||
|
foreach (comp; info.components)
|
||||||
|
{
|
||||||
|
if (components[comp].destroy_callback)
|
||||||
|
{
|
||||||
|
components[comp].destroy_callback(data + info.deltas[comp]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block.entities_count == 0)
|
if (block.entities_count == 0)
|
||||||
{
|
{
|
||||||
if (block.type_data.first_block is block)
|
if (info.first_block is block)
|
||||||
{
|
{
|
||||||
block.type_data.first_block = block.next_block;
|
info.first_block = block.next_block;
|
||||||
}
|
}
|
||||||
if (block.type_data.first_with_free_space is block)
|
if (info.first_with_free_space is block)
|
||||||
{
|
{
|
||||||
block.type_data.first_with_free_space = block.next_block;//block.type_data.first_block;
|
info.first_with_free_space = block.next_block; //info.first_block;
|
||||||
}
|
}
|
||||||
if (block.prev_block)
|
if (block.prev_block)
|
||||||
{
|
{
|
||||||
block.prev_block.next_block = block.next_block;
|
block.prev_block.next_block = block.next_block;
|
||||||
}
|
}
|
||||||
if(block.next_block)
|
if (block.next_block)
|
||||||
{
|
{
|
||||||
block.next_block.prev_block = block.prev_block;
|
block.next_block.prev_block = block.prev_block;
|
||||||
}
|
}
|
||||||
|
|
@ -879,14 +1064,27 @@ class EntityManager
|
||||||
if (pos == block.entities_count)
|
if (pos == block.entities_count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
foreach (comp; info.components)
|
||||||
|
{
|
||||||
|
void* ptr = cast(void*) block + info.deltas[comp];
|
||||||
|
uint size = components[comp].size;
|
||||||
|
memcpy(ptr + pos * size, ptr + block.entities_count * size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.id = *cast(EntityID*)(data_begin + block.entities_count * EntityID.sizeof);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
//copy memory of last entity to position of removed entity
|
//copy memory of last entity to position of removed entity
|
||||||
void* src = data_begin + block.entities_count * block.type_data.size;
|
void* src = data_begin + block.entities_count * info.size;
|
||||||
void* dst = data_begin + pos * block.type_data.size;
|
void* dst = data_begin + pos * info.size;
|
||||||
|
|
||||||
memcpy(dst, src, block.type_data.size);
|
|
||||||
|
|
||||||
|
memcpy(dst, src, info.size);
|
||||||
|
}
|
||||||
//update pointer for moved entity ID
|
//update pointer for moved entity ID
|
||||||
entity = cast(Entity*) dst;
|
//entity = cast(Entity*) dst;
|
||||||
entity.updateID();
|
entity.updateID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -981,7 +1179,7 @@ class EntityManager
|
||||||
removeEntities();
|
removeEntities();
|
||||||
changeEntites();
|
changeEntites();
|
||||||
|
|
||||||
clearEvents();
|
//clearEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ComponentInfo
|
struct ComponentInfo
|
||||||
|
|
@ -1006,12 +1204,27 @@ class EntityManager
|
||||||
{
|
{
|
||||||
///entity components
|
///entity components
|
||||||
ushort[] components;
|
ushort[] components;
|
||||||
|
|
||||||
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
///deltas in memory for components in EntitiesBlock
|
||||||
|
ushort[] deltas;
|
||||||
|
///deltas in memory for components in EntityTemplate
|
||||||
|
ushort[] tmpl_deltas;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
///deltas in memory for components
|
///deltas in memory for components
|
||||||
ushort[] deltas;
|
ushort[] deltas;
|
||||||
|
}
|
||||||
|
|
||||||
///alignment of whole entity
|
///alignment of whole entity
|
||||||
ushort alignment;
|
ushort alignment; //unused in linear-layout
|
||||||
///size of entity (with alignment respect)
|
///size of entity (with alignment respect)
|
||||||
ushort size;
|
ushort size;
|
||||||
|
///max number of entities in block
|
||||||
|
ushort max_entities;
|
||||||
|
|
||||||
///pointer to first block/page
|
///pointer to first block/page
|
||||||
EntitiesBlock* first_block;
|
EntitiesBlock* first_block;
|
||||||
///a hint for allocations
|
///a hint for allocations
|
||||||
|
|
@ -1029,7 +1242,7 @@ class EntityManager
|
||||||
uint dataDelta()
|
uint dataDelta()
|
||||||
{
|
{
|
||||||
ushort dif = EntitiesBlock.sizeof;
|
ushort dif = EntitiesBlock.sizeof;
|
||||||
alignNum(dif, type_data.alignment);
|
alignNum(dif, type_info.alignment);
|
||||||
return dif;
|
return dif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1037,23 +1250,29 @@ class EntityManager
|
||||||
export void* dataBegin()
|
export void* dataBegin()
|
||||||
{
|
{
|
||||||
ushort dif = EntitiesBlock.sizeof;
|
ushort dif = EntitiesBlock.sizeof;
|
||||||
alignNum(dif, type_data.alignment);
|
version (LinearLayout)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
alignNum(dif, type_info.alignment);
|
||||||
return cast(void*)&this + dif;
|
return cast(void*)&this + dif;
|
||||||
}
|
}
|
||||||
|
|
||||||
///pointer to Entity type info
|
///pointer to Entity type info
|
||||||
EntityInfo* type_data = null;
|
EntityInfo* type_info = null;
|
||||||
///number of entities in block
|
///number of entities in block
|
||||||
ushort entities_count = 0;
|
ushort entities_count = 0;
|
||||||
///number of new entities in block
|
///number of new entities in block
|
||||||
ushort added_count = 0;
|
ushort added_count = 0;
|
||||||
///block id
|
///block id
|
||||||
uint id = 0;
|
ushort id = 0;
|
||||||
|
///maximum number of entities in block
|
||||||
|
//ushort max_entities = 0;
|
||||||
///pointer to next block/page
|
///pointer to next block/page
|
||||||
EntitiesBlock* next_block = null;
|
EntitiesBlock* next_block = null;
|
||||||
///pointer to next block/page
|
///pointer to next block/page
|
||||||
EntitiesBlock* prev_block = null;
|
EntitiesBlock* prev_block = null;
|
||||||
//there is a loooot of data (4kB, pure magic)
|
//there is a loooot of data (some kB of memory, pure magic)
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
|
|
@ -1068,7 +1287,7 @@ class EntityManager
|
||||||
///poiner to Entity type info
|
///poiner to Entity type info
|
||||||
EntityManager.EntityInfo* info;
|
EntityManager.EntityInfo* info;
|
||||||
///deltas for components
|
///deltas for components
|
||||||
ushort[] deltas;
|
ushort[] deltas; //unused in linear-layout
|
||||||
}
|
}
|
||||||
|
|
||||||
alias SytemFuncType = void function(ref EntityManager.CallData data, void* entity);
|
alias SytemFuncType = void function(ref EntityManager.CallData data, void* entity);
|
||||||
|
|
@ -1078,7 +1297,7 @@ class EntityManager
|
||||||
//alias event_manager this;
|
//alias event_manager this;
|
||||||
|
|
||||||
///Single page size. Must be power of two.
|
///Single page size. Must be power of two.
|
||||||
enum page_size = 4096;
|
enum page_size = 32768; //4096;
|
||||||
///Number of pages in block.
|
///Number of pages in block.
|
||||||
enum pages_in_block = 128;
|
enum pages_in_block = 128;
|
||||||
|
|
||||||
|
|
|
||||||
143
tests/tests.d
143
tests/tests.d
|
|
@ -23,11 +23,11 @@ int main()
|
||||||
float a;
|
float a;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestComp
|
static struct TestComp
|
||||||
{
|
{
|
||||||
__gshared ushort component_id;
|
__gshared ushort component_id;
|
||||||
int a;
|
int a = 1;
|
||||||
ulong b;
|
ulong b = 2;
|
||||||
|
|
||||||
static void serializeComponent(SerializeVector output)
|
static void serializeComponent(SerializeVector output)
|
||||||
{
|
{
|
||||||
|
|
@ -40,11 +40,11 @@ int main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestComp2
|
static struct TestComp2
|
||||||
{
|
{
|
||||||
__gshared ushort component_id;
|
__gshared ushort component_id;
|
||||||
int b;
|
int b = 3;
|
||||||
int a;
|
int a = 4;
|
||||||
|
|
||||||
static void serializeComponent(ref TestComp comp, SerializeVector output)
|
static void serializeComponent(ref TestComp comp, SerializeVector output)
|
||||||
{
|
{
|
||||||
|
|
@ -57,11 +57,11 @@ int main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestComp3
|
static struct TestComp3
|
||||||
{
|
{
|
||||||
__gshared ushort component_id;
|
__gshared ushort component_id;
|
||||||
uint gg; //good game
|
uint gg = 5; //good game
|
||||||
uint bg; //bad game
|
uint bg = 6; //bad game
|
||||||
|
|
||||||
void serializeComponent(SerializeVector output)
|
void serializeComponent(SerializeVector output)
|
||||||
{
|
{
|
||||||
|
|
@ -74,11 +74,15 @@ int main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestComp4
|
static struct TestComp4
|
||||||
{
|
{
|
||||||
__gshared ushort component_id;
|
__gshared ushort component_id;
|
||||||
uint gg; //good game
|
uint gg = 7; //good game
|
||||||
uint bg; //bad game
|
uint bg = 8; //bad game
|
||||||
|
ulong a;
|
||||||
|
ulong b;
|
||||||
|
ulong c;
|
||||||
|
ulong g;
|
||||||
|
|
||||||
static void serializeComponent(ref TestComp comp, SerializeVector output)
|
static void serializeComponent(ref TestComp comp, SerializeVector output)
|
||||||
{
|
{
|
||||||
|
|
@ -107,12 +111,12 @@ int main()
|
||||||
|
|
||||||
void onBegin()
|
void onBegin()
|
||||||
{
|
{
|
||||||
writeln("On Test System begin.");
|
//writeln("On Test System begin.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void onEnd()
|
void onEnd()
|
||||||
{
|
{
|
||||||
writeln("On Test System end.");
|
//writeln("On Test System end.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize(ref Entity entity, ref TestComp comp)
|
void initialize(ref Entity entity, ref TestComp comp)
|
||||||
|
|
@ -127,7 +131,7 @@ int main()
|
||||||
@("optional") TestComp3* test3;
|
@("optional") TestComp3* test3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(ref Entity entity, ref TestComp test, ref TestComp2 test2, TestComp3* test3) //ref TestComp comp)
|
void update(ref Entity entity, ref TestComp test, ref TestComp2 test2)//, TestComp3* test3) //ref TestComp comp)
|
||||||
{
|
{
|
||||||
assert(cast(size_t)&test % TestComp.alignof == 0);
|
assert(cast(size_t)&test % TestComp.alignof == 0);
|
||||||
assert(cast(size_t)&test2 % TestComp2.alignof == 0);
|
assert(cast(size_t)&test2 % TestComp2.alignof == 0);
|
||||||
|
|
@ -141,8 +145,12 @@ int main()
|
||||||
test2.a = 8;
|
test2.a = 8;
|
||||||
//writeln("Jakis tekst! ",test2.b);
|
//writeln("Jakis tekst! ",test2.b);
|
||||||
//writeln("Low priority tekst! ");
|
//writeln("Low priority tekst! ");
|
||||||
if (test3)
|
/*if (test3)
|
||||||
|
{
|
||||||
test3.gg = 200;
|
test3.gg = 200;
|
||||||
|
test3.bg += 1;
|
||||||
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleEvent(TestEvent event, ref TestComp test, ref TestComp2 test2, TestComp3* test3)
|
void handleEvent(TestEvent event, ref TestComp test, ref TestComp2 test2, TestComp3* test3)
|
||||||
|
|
@ -209,6 +217,21 @@ int main()
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeEntityComponents(Entity* entity)
|
||||||
|
{
|
||||||
|
write(entity.id);
|
||||||
|
TestComp* test_comp = entity.getComponent!TestComp;
|
||||||
|
if(test_comp)write(*test_comp);
|
||||||
|
TestComp2* test_comp2 = entity.getComponent!TestComp2;
|
||||||
|
if(test_comp2)write(*test_comp2);
|
||||||
|
TestComp3* test_comp3 = entity.getComponent!TestComp3;
|
||||||
|
if(test_comp3)write(*test_comp3);
|
||||||
|
TestComp4* test_comp4 = entity.getComponent!TestComp4;
|
||||||
|
if(test_comp4)write(*test_comp4);
|
||||||
|
writeln();
|
||||||
|
//writeln((cast(uint*) pp)[0 .. 14], " ", pp);
|
||||||
|
}
|
||||||
|
|
||||||
EntityManager.initialize();
|
EntityManager.initialize();
|
||||||
assert(gEM !is null);
|
assert(gEM !is null);
|
||||||
|
|
||||||
|
|
@ -237,14 +260,24 @@ int main()
|
||||||
|
|
||||||
time = MonoTime.currTime;
|
time = MonoTime.currTime;
|
||||||
|
|
||||||
ushort[2] ids = [TestComp2.component_id, TestComp.component_id];
|
ushort[3] ids = [TestComp2.component_id, TestComp.component_id, TestComp4.component_id];
|
||||||
EntityTemplate* tmpl = gEM.allocateTemplate(ids);
|
EntityTemplate* tmpl = gEM.allocateTemplate(ids);
|
||||||
|
|
||||||
|
ushort[3] ids2 = [TestComp3.component_id, TestComp.component_id, TestComp4.component_id];
|
||||||
|
EntityTemplate* tmpl2 = gEM.allocateTemplate(ids2);
|
||||||
//writeln(tmpl.info.components[]);
|
//writeln(tmpl.info.components[]);
|
||||||
*cast(EntityID*) tmpl.entity_data.ptr = EntityID(1, 1);
|
//*cast(EntityID*) tmpl.entity_data.ptr = EntityID(1, 1);
|
||||||
|
|
||||||
dur = (MonoTime.currTime - time).total!"usecs";
|
dur = (MonoTime.currTime - time).total!"usecs";
|
||||||
writeln("Template allocating: ", dur, " usecs");
|
writeln("Template allocating: ", dur, " usecs");
|
||||||
|
|
||||||
|
Entity entity;
|
||||||
|
|
||||||
|
{
|
||||||
|
entity = gEM.addEntity(tmpl);
|
||||||
|
writeEntityComponents(gEM.getEntity(entity.id));
|
||||||
|
}
|
||||||
|
|
||||||
time = MonoTime.currTime;
|
time = MonoTime.currTime;
|
||||||
|
|
||||||
//foreach(i; 0..1_000_000)gEM.addEntity(tmpl);
|
//foreach(i; 0..1_000_000)gEM.addEntity(tmpl);
|
||||||
|
|
@ -253,13 +286,18 @@ int main()
|
||||||
|
|
||||||
EntityID[1000] idss;
|
EntityID[1000] idss;
|
||||||
|
|
||||||
foreach (i; 0 .. 1_000)
|
/*foreach (i; 0 .. 1_000)
|
||||||
{
|
{
|
||||||
|
gEM.begin();
|
||||||
foreach (j; 0 .. 1_000)
|
foreach (j; 0 .. 1_000)
|
||||||
idss[j] = gEM.addEntity(tmpl).id;
|
idss[j] = gEM.addEntity(tmpl).id;
|
||||||
foreach (j; 0 .. 1_000)
|
foreach (j; 0 .. 1_000)
|
||||||
gEM.removeEntity(idss[j]);
|
gEM.removeEntity(idss[j]);
|
||||||
}
|
gEM.end();
|
||||||
|
}*/
|
||||||
|
|
||||||
|
dur = (MonoTime.currTime - time).total!"usecs";
|
||||||
|
writeln("Entities adding: ", dur, " usecs");
|
||||||
|
|
||||||
uint blocks = 0;
|
uint blocks = 0;
|
||||||
foreach (info; &gEM.entities_infos.byValue)
|
foreach (info; &gEM.entities_infos.byValue)
|
||||||
|
|
@ -273,13 +311,6 @@ int main()
|
||||||
}
|
}
|
||||||
writeln("Entities blocks: ", blocks);
|
writeln("Entities blocks: ", blocks);
|
||||||
|
|
||||||
/*Entity entity = gEM.addEntity(tmpl);
|
|
||||||
gEM.removeEntity(entity.id);
|
|
||||||
gEM.addEntity(tmpl);*/
|
|
||||||
|
|
||||||
dur = (MonoTime.currTime - time).total!"usecs";
|
|
||||||
writeln("Entities adding: ", dur, " usecs");
|
|
||||||
|
|
||||||
//foreach(j; 0..1_000)gEM.addEntity(tmpl);
|
//foreach(j; 0..1_000)gEM.addEntity(tmpl);
|
||||||
|
|
||||||
gEM.registerSystem!TestSystem2(0);
|
gEM.registerSystem!TestSystem2(0);
|
||||||
|
|
@ -287,43 +318,69 @@ int main()
|
||||||
//assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+24)) == EntityID(1,1));
|
//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));
|
//assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+48)) == EntityID(1,1));
|
||||||
|
|
||||||
|
foreach (i; 0 .. 500_000)
|
||||||
|
{
|
||||||
|
gEM.addEntity(tmpl);
|
||||||
|
gEM.addEntity(tmpl2);
|
||||||
|
}
|
||||||
|
|
||||||
time = MonoTime.currTime;
|
time = MonoTime.currTime;
|
||||||
|
|
||||||
//gEM.update();
|
|
||||||
|
|
||||||
dur = (MonoTime.currTime - time).total!"usecs";
|
|
||||||
writeln("Update: ", dur, " usecs");
|
|
||||||
|
|
||||||
Entity entity = gEM.addEntity(tmpl);
|
|
||||||
|
|
||||||
gEM.begin();
|
gEM.begin();
|
||||||
gEM.update();
|
gEM.update();
|
||||||
gEM.end();
|
gEM.end();
|
||||||
|
|
||||||
Entity* pp = gEM.getEntity(entity.id);
|
dur = (MonoTime.currTime - time).total!"usecs";
|
||||||
writeln((cast(uint*) pp)[0 .. 14], " ", pp);
|
writeln("Update: ", dur, " usecs");
|
||||||
|
|
||||||
|
time = MonoTime.currTime;
|
||||||
|
|
||||||
|
gEM.begin();
|
||||||
|
gEM.update();
|
||||||
|
gEM.end();
|
||||||
|
|
||||||
|
dur = (MonoTime.currTime - time).total!"usecs";
|
||||||
|
writeln("Update: ", dur, " usecs");
|
||||||
|
|
||||||
|
time = MonoTime.currTime;
|
||||||
|
|
||||||
|
gEM.begin();
|
||||||
|
gEM.update();
|
||||||
|
gEM.end();
|
||||||
|
|
||||||
|
dur = (MonoTime.currTime - time).total!"usecs";
|
||||||
|
writeln("Update: ", dur, " usecs");
|
||||||
|
|
||||||
|
writeEntityComponents(gEM.getEntity(entity.id));
|
||||||
|
|
||||||
|
entity = gEM.addEntity(tmpl);
|
||||||
|
|
||||||
|
gEM.begin();
|
||||||
|
gEM.update();
|
||||||
|
gEM.end();
|
||||||
|
|
||||||
|
//Entity* pp;// = gEM.getEntity(entity.id);
|
||||||
|
//writeln((cast(uint*) pp)[0 .. 14], " ", pp);
|
||||||
|
writeEntityComponents(gEM.getEntity(entity.id));
|
||||||
|
|
||||||
gEM.addEntity(tmpl);
|
gEM.addEntity(tmpl);
|
||||||
|
|
||||||
|
gEM.addComponents(entity.id, TestComp4());
|
||||||
gEM.addComponents(entity.id, TestComp3());
|
gEM.addComponents(entity.id, TestComp3());
|
||||||
|
|
||||||
gEM.begin();
|
gEM.begin();
|
||||||
gEM.update();
|
gEM.update();
|
||||||
gEM.end();
|
gEM.end();
|
||||||
|
|
||||||
pp = gEM.getEntity(entity.id);
|
writeEntityComponents(gEM.getEntity(entity.id));
|
||||||
|
|
||||||
writeln((cast(uint*) pp)[0 .. 14], " ", pp);
|
gEM.removeComponents!(TestComp)(entity.id);
|
||||||
|
|
||||||
//gEM.removeComponents!(TestComp)(entity.id);
|
|
||||||
|
|
||||||
gEM.begin();
|
gEM.begin();
|
||||||
gEM.update();
|
gEM.update();
|
||||||
gEM.end();
|
gEM.end();
|
||||||
|
|
||||||
pp = gEM.getEntity(entity.id);
|
writeEntityComponents(gEM.getEntity(entity.id));
|
||||||
|
|
||||||
writeln((cast(uint*) pp)[0 .. 14], " ", pp);
|
|
||||||
|
|
||||||
//import std.stdio;
|
//import std.stdio;
|
||||||
//writeln((cast(uint*)tmpl.info.first_block)[0..48]);
|
//writeln((cast(uint*)tmpl.info.first_block)[0..48]);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue