Basic update, multithreading emplate support, fixed

-Added possibility to add entity form template + components to replace template data
-basic tests for new functionality
-small performance improvement for events
-added ComponentRef structure which contain data pointer and component ID
-now events are called before entities removing
This commit is contained in:
Mergul 2020-05-24 21:57:48 +02:00
parent 3d98b0ee5e
commit 15cd57dbcb
6 changed files with 137 additions and 20 deletions

View file

@ -2356,12 +2356,7 @@ export struct EntityManager
void addComponents(Components...)(const EntityID entity_id, Components comps) nothrow @nogc
{
const uint num = Components.length;
//Entity* entity = id_manager.getEntityPointer(entity_id);
//EntitiesBlock* block = getMetaData(entity);
//EntityInfo* info = block.type_info;
/*ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0
.. info.components.length + num];*/
ushort[num] new_ids;
/*ushort[num] new_ids;
static foreach (i, comp; Components)
{
@ -2376,9 +2371,39 @@ export struct EntityManager
static foreach (i, comp; comps)
{
data.changeEntitiesList.add((cast(ubyte*)&comp)[0 .. comp.sizeof]);
}
}*/
//__addComponents(entity_id, new_ids, pointers);
ComponentRef[num] _comps;
static foreach(i, comp; comps)
{
_comps[i] = comp.ref_;
}
addComponents(entity_id, _comps);
}
export void addComponents(const EntityID entity_id, ComponentRef[] comps) nothrow @nogc
{
uint num = cast(uint)comps.length;
ThreadData* data = &threads[threadID];
data.changeEntitiesList.add(cast(ubyte) 1u);
data.changeEntitiesList.add((cast(ubyte*)&entity_id)[0 .. EntityID.sizeof]);
data.changeEntitiesList.add((cast(ubyte*)&num)[0 .. uint.sizeof]);
foreach(ref_; comps)
{
data.changeEntitiesList.add((cast(ubyte*)&ref_.component_id)[0 .. ushort.sizeof]);
}
foreach(ref_; comps)
{
data.changeEntitiesList.add((cast(ubyte*)ref_.ptr)[0 .. components[ref_.component_id].size]);
}
/*data.changeEntitiesList.add(cast(ubyte[]) new_ids);
static foreach (i, comp; comps)
{
data.changeEntitiesList.add((cast(ubyte*)&comp)[0 .. comp.sizeof]);
}*/
}
/************************************************************************************************************************
@ -2455,6 +2480,58 @@ export struct EntityManager
tmpl = pointer entity template allocated by EntityManager.
*/
export Entity* addEntity(EntityTemplate* tmpl)
{
/*EntityInfo* info = tmpl.info;
ushort index = 0;
EntitiesBlock* block;
do
{
block = findBlockWithFreeSpaceMT(info);
index = block.added_count.atomicOp!"+="(1);
}
while (block.entities_count + index > info.max_entities);
uint id = (block.entities_count + index - 1); //block.added_count);
void* data_begin = block.dataBegin();
void* start = data_begin + EntityID.sizeof * id;
foreach (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);
if (components[comp].create_callback)
{
components[comp].create_callback(
cast(void*) block + info.deltas[comp] + id * components[comp].size);
}
}
if (index == 1)
threads[threadID].blockToUpdate.add(block);
Entity* entity = cast(Entity*) start;
//add_mutex.lock_nothrow();
entity.id = id_manager.getNewID();
//add_mutex.unlock_nothrow();
id_manager.update(*entity); //entity.updateID();
return entity;*/
return addEntity(tmpl, null);
}
/************************************************************************************************************************
Add entity to system. Returen pointer is valid only before one from commit(), begin() or end() will be called. To save entity to further
use you should save ID instead of pointer.
Params:
tmpl = pointer entity template allocated by EntityManager.
replacement = list of components references to used. Memory form list replace data from template inside new entity. Should be used only for data which vary between most entities (like 3D position etc.)
*/
export Entity* addEntity(EntityTemplate* tmpl, ComponentRef[] replacement)
{
EntityInfo* info = tmpl.info;
@ -2472,17 +2549,34 @@ export struct EntityManager
void* data_begin = block.dataBegin();
void* start = data_begin + EntityID.sizeof * id;
foreach (comp; info.components)
{
uint size = components[comp].size;
memcpy(cast(void*) block + info.deltas[comp] + size * id,
tmpl.entity_data.ptr + info.tmpl_deltas[comp], size);
}
foreach(comp; replacement)
{
if(comp.component_id < info.deltas.length)
{
ushort delta = info.deltas[comp.component_id];
if(delta != ushort.max)
{
uint size = components[comp.component_id].size;
memcpy(cast(void*) block + delta + size * id,
comp.ptr, size);
}
}
}
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);
if (components[comp].create_callback)
{
components[comp].create_callback(
cast(void*) block + info.deltas[comp] + id * components[comp].size);
}
}
if (index == 1)
@ -2916,12 +3010,12 @@ export struct EntityManager
swapData();
has_work = false;
has_work |= updateEvents();
id_manager.optimize();
has_work |= updateBlocks();
has_work |= changeEntities();
has_work |= removeEntities();
has_work |= updateEvents();
}
event_manager.clearEvents();
}