Demos #10
6 changed files with 137 additions and 20 deletions
|
|
@ -62,6 +62,7 @@ private:
|
||||||
{
|
{
|
||||||
next_block = cast(void*) Mallocator.alignAlloc(
|
next_block = cast(void*) Mallocator.alignAlloc(
|
||||||
block_size * blocks_in_allocation, block_size);
|
block_size * blocks_in_allocation, block_size);
|
||||||
|
if(next_block is null)assert(0);
|
||||||
|
|
||||||
if(pointers is null)pointers = Mallocator.make!BlockPointers;
|
if(pointers is null)pointers = Mallocator.make!BlockPointers;
|
||||||
if(pointers.numberof >= 32)
|
if(pointers.numberof >= 32)
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,11 @@ static struct ECS
|
||||||
mixin template Component()
|
mixin template Component()
|
||||||
{
|
{
|
||||||
__gshared ushort component_id = ushort.max;
|
__gshared ushort component_id = ushort.max;
|
||||||
|
|
||||||
|
ComponentRef ref_() @nogc nothrow
|
||||||
|
{
|
||||||
|
return ComponentRef(&this,component_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
|
|
|
||||||
|
|
@ -114,3 +114,14 @@ export struct EntityTemplate
|
||||||
return cast(T*)(entity_data.ptr + info.tmpl_deltas[T.component_id]);
|
return cast(T*)(entity_data.ptr + info.tmpl_deltas[T.component_id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
ComponentRef contain component ID and pointer to it. It used to add component data to entity.
|
||||||
|
*/
|
||||||
|
export struct ComponentRef
|
||||||
|
{
|
||||||
|
///pointer to component
|
||||||
|
void* ptr;
|
||||||
|
///component index
|
||||||
|
ushort component_id;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,9 @@ package struct EventManager
|
||||||
if(block is null)
|
if(block is null)
|
||||||
{
|
{
|
||||||
event_block_alloc_mutex.lock();
|
event_block_alloc_mutex.lock();
|
||||||
scope (exit)
|
block = cast(EventBlock*) allocator.getBlock();
|
||||||
event_block_alloc_mutex.unlock();
|
event_block_alloc_mutex.unlock();
|
||||||
|
|
||||||
block = cast(EventBlock*) allocator.getBlock();
|
|
||||||
*block = EventBlock();
|
*block = EventBlock();
|
||||||
data.first_blocks[block_id] = block;
|
data.first_blocks[block_id] = block;
|
||||||
data.blocks[block_id] = block;
|
data.blocks[block_id] = block;
|
||||||
|
|
@ -52,10 +51,9 @@ package struct EventManager
|
||||||
if(block.count >= data.max_events)
|
if(block.count >= data.max_events)
|
||||||
{
|
{
|
||||||
event_block_alloc_mutex.lock();
|
event_block_alloc_mutex.lock();
|
||||||
scope (exit)
|
EventBlock* new_block = cast(EventBlock*) allocator.getBlock();
|
||||||
event_block_alloc_mutex.unlock();
|
event_block_alloc_mutex.unlock();
|
||||||
|
|
||||||
EventBlock* new_block = cast(EventBlock*) allocator.getBlock();
|
|
||||||
*new_block = EventBlock();
|
*new_block = EventBlock();
|
||||||
block.next = new_block;
|
block.next = new_block;
|
||||||
block = new_block;
|
block = new_block;
|
||||||
|
|
|
||||||
|
|
@ -2356,12 +2356,7 @@ export struct EntityManager
|
||||||
void addComponents(Components...)(const EntityID entity_id, Components comps) nothrow @nogc
|
void addComponents(Components...)(const EntityID entity_id, Components comps) nothrow @nogc
|
||||||
{
|
{
|
||||||
const uint num = Components.length;
|
const uint num = Components.length;
|
||||||
//Entity* entity = id_manager.getEntityPointer(entity_id);
|
/*ushort[num] new_ids;
|
||||||
//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;
|
|
||||||
|
|
||||||
static foreach (i, comp; Components)
|
static foreach (i, comp; Components)
|
||||||
{
|
{
|
||||||
|
|
@ -2376,9 +2371,39 @@ export struct EntityManager
|
||||||
static foreach (i, comp; comps)
|
static foreach (i, comp; comps)
|
||||||
{
|
{
|
||||||
data.changeEntitiesList.add((cast(ubyte*)&comp)[0 .. comp.sizeof]);
|
data.changeEntitiesList.add((cast(ubyte*)&comp)[0 .. comp.sizeof]);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
//__addComponents(entity_id, new_ids, pointers);
|
//__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.
|
tmpl = pointer entity template allocated by EntityManager.
|
||||||
*/
|
*/
|
||||||
export Entity* addEntity(EntityTemplate* tmpl)
|
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;
|
EntityInfo* info = tmpl.info;
|
||||||
|
|
||||||
|
|
@ -2472,17 +2549,34 @@ export struct EntityManager
|
||||||
void* data_begin = block.dataBegin();
|
void* data_begin = block.dataBegin();
|
||||||
void* start = data_begin + EntityID.sizeof * id;
|
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)
|
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)
|
if (components[comp].create_callback)
|
||||||
{
|
{
|
||||||
components[comp].create_callback(
|
components[comp].create_callback(
|
||||||
cast(void*) block + info.deltas[comp] + id * components[comp].size);
|
cast(void*) block + info.deltas[comp] + id * components[comp].size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 1)
|
if (index == 1)
|
||||||
|
|
@ -2916,12 +3010,12 @@ export struct EntityManager
|
||||||
swapData();
|
swapData();
|
||||||
|
|
||||||
has_work = false;
|
has_work = false;
|
||||||
|
has_work |= updateEvents();
|
||||||
|
|
||||||
id_manager.optimize();
|
id_manager.optimize();
|
||||||
has_work |= updateBlocks();
|
has_work |= updateBlocks();
|
||||||
has_work |= changeEntities();
|
has_work |= changeEntities();
|
||||||
has_work |= removeEntities();
|
has_work |= removeEntities();
|
||||||
|
|
||||||
has_work |= updateEvents();
|
|
||||||
}
|
}
|
||||||
event_manager.clearEvents();
|
event_manager.clearEvents();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,14 @@ unittest
|
||||||
assert(entity2.getComponent!CFloat);
|
assert(entity2.getComponent!CFloat);
|
||||||
assert(*entity2.getComponent!CInt == 2);
|
assert(*entity2.getComponent!CInt == 2);
|
||||||
assert(*entity2.getComponent!CFloat == 2.0);
|
assert(*entity2.getComponent!CFloat == 2.0);
|
||||||
|
|
||||||
|
CInt cint = CInt(10);
|
||||||
|
CLong clong;
|
||||||
|
Entity* entity3 = gEM.addEntity(tmpl_, [cint.ref_, clong.ref_].staticArray);
|
||||||
|
assert(entity3.getComponent!CInt);
|
||||||
|
assert(entity3.getComponent!CFloat);
|
||||||
|
assert(*entity3.getComponent!CInt == 10);
|
||||||
|
assert(*entity3.getComponent!CFloat == 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//allocate templates
|
//allocate templates
|
||||||
|
|
@ -1142,7 +1150,7 @@ unittest
|
||||||
|
|
||||||
entity = gEM.getEntity(id);
|
entity = gEM.getEntity(id);
|
||||||
assert(*entity.getComponent!CLong == 66);
|
assert(*entity.getComponent!CLong == 66);
|
||||||
assert(*entity.getComponent!CInt == 36);
|
assert(*entity.getComponent!CInt == 2);//36);
|
||||||
|
|
||||||
//test for multiple event blocks
|
//test for multiple event blocks
|
||||||
long result = *entity.getComponent!CLong;
|
long result = *entity.getComponent!CLong;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue