Template allocation update and some tests
-test runner support before/after everty test callback funcion -added some basic tests for template allocation -added function to allocate new template from different template and list of addition and removed components
This commit is contained in:
parent
8f5f2f3baf
commit
998240f7be
3 changed files with 243 additions and 3 deletions
|
|
@ -1374,8 +1374,6 @@ export struct EntityManager
|
||||||
{
|
{
|
||||||
memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp],
|
memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp],
|
||||||
components[comp].init_data.ptr, components[comp].size);
|
components[comp].init_data.ptr, components[comp].size);
|
||||||
/*temp.entity_data[info.tmpl_deltas[comp] .. info.tmpl_deltas[comp] + components[comp].size]
|
|
||||||
= components[comp].init_data;*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1383,7 +1381,7 @@ export struct EntityManager
|
||||||
ushort index = block.entityIndex(entity);
|
ushort index = block.entityIndex(entity);
|
||||||
foreach (comp; info.components)
|
foreach (comp; info.components)
|
||||||
{
|
{
|
||||||
memcpy(cast(void*) temp.entity_data + info.tmpl_deltas[comp],
|
memcpy(cast(void*) temp.entity_data.ptr + info.tmpl_deltas[comp],
|
||||||
cast(void*) block + info.deltas[comp] + components[comp].size * index,
|
cast(void*) block + info.deltas[comp] + components[comp].size * index,
|
||||||
components[comp].size);
|
components[comp].size);
|
||||||
}
|
}
|
||||||
|
|
@ -1440,6 +1438,74 @@ export struct EntityManager
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
*Allocate EntityTemplate with specifed components and returns pointer to it.
|
||||||
|
*
|
||||||
|
*Params:
|
||||||
|
*components_ids = array of components allocated with template
|
||||||
|
*/
|
||||||
|
export EntityTemplate* allocateTemplate(EntityTemplate* base_tmpl, ushort[] components_ids, ushort[] remove_components_ids = null)
|
||||||
|
{
|
||||||
|
size_t len = base_tmpl.info.components.length + components_ids.length;
|
||||||
|
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * len))[0
|
||||||
|
.. len];
|
||||||
|
memcpy(ids.ptr, base_tmpl.info.components.ptr, ushort.sizeof * base_tmpl.info.components.length);
|
||||||
|
memcpy(ids.ptr + base_tmpl.info.components.length, components_ids.ptr, ushort.sizeof * components_ids.length);
|
||||||
|
|
||||||
|
qsort(ids.ptr, ids.length, ushort.sizeof, &compareUShorts);
|
||||||
|
qsort(remove_components_ids.ptr, remove_components_ids.length, ushort.sizeof, &compareUShorts);
|
||||||
|
{
|
||||||
|
uint k = 0;
|
||||||
|
uint j = 1;
|
||||||
|
foreach (i; 1 .. ids.length)
|
||||||
|
{
|
||||||
|
assert(ids[i] != ushort.max);
|
||||||
|
if(k < remove_components_ids.length)
|
||||||
|
{
|
||||||
|
while(k < remove_components_ids.length && remove_components_ids[k] < ids[i])
|
||||||
|
{
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
if(k < remove_components_ids.length)
|
||||||
|
{
|
||||||
|
if(remove_components_ids[k] == ids[i])continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ids[i] != ids[j - 1])
|
||||||
|
{
|
||||||
|
ids[j] = ids[i];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
debug assert(0, "Duplicated components in template!!!");
|
||||||
|
}
|
||||||
|
ids = ids[0 .. j];
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityInfo* info = getEntityInfo(ids);
|
||||||
|
|
||||||
|
EntityTemplate* temp = Mallocator.make!EntityTemplate;
|
||||||
|
temp.entity_data = Mallocator.makeArray!ubyte(info.size);
|
||||||
|
temp.info = info;
|
||||||
|
|
||||||
|
//fill components with default data and copy from base template
|
||||||
|
foreach (comp; info.components)
|
||||||
|
{
|
||||||
|
if(comp < base_tmpl.info.deltas.length && base_tmpl.info.deltas[comp] != ushort.max) //copy data from base component
|
||||||
|
{
|
||||||
|
memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp],
|
||||||
|
base_tmpl.entity_data.ptr + base_tmpl.info.tmpl_deltas[comp], components[comp].size);
|
||||||
|
}
|
||||||
|
else //fill with default data
|
||||||
|
{
|
||||||
|
memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp],
|
||||||
|
components[comp].init_data.ptr, components[comp].size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
*Returns entity type info.
|
*Returns entity type info.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
172
tests/basic.d
172
tests/basic.d
|
|
@ -1,2 +1,174 @@
|
||||||
module tests.basic;
|
module tests.basic;
|
||||||
|
|
||||||
|
import ecs.manager;
|
||||||
|
import ecs.core;
|
||||||
|
|
||||||
|
struct CInt
|
||||||
|
{
|
||||||
|
mixin ECS.Component;
|
||||||
|
|
||||||
|
alias value this;
|
||||||
|
|
||||||
|
int value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CFloat
|
||||||
|
{
|
||||||
|
mixin ECS.Component;
|
||||||
|
|
||||||
|
alias value this;
|
||||||
|
|
||||||
|
float value = 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CDouble
|
||||||
|
{
|
||||||
|
mixin ECS.Component;
|
||||||
|
|
||||||
|
alias value this;
|
||||||
|
|
||||||
|
double value = 3.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CLong
|
||||||
|
{
|
||||||
|
mixin ECS.Component;
|
||||||
|
|
||||||
|
alias value this;
|
||||||
|
|
||||||
|
long value = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CShort
|
||||||
|
{
|
||||||
|
mixin ECS.Component;
|
||||||
|
|
||||||
|
alias value this;
|
||||||
|
|
||||||
|
short value = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
void beforeEveryTest()
|
||||||
|
{
|
||||||
|
gEM.initialize(1);
|
||||||
|
|
||||||
|
gEM.registerComponent!CInt;
|
||||||
|
gEM.registerComponent!CFloat;
|
||||||
|
gEM.registerComponent!CDouble;
|
||||||
|
gEM.registerComponent!CLong;
|
||||||
|
gEM.registerComponent!CShort;
|
||||||
|
}
|
||||||
|
|
||||||
|
void afterEveryTest()
|
||||||
|
{
|
||||||
|
gEM.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@("AddEntity")
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
ushort[2] ids = [CInt.component_id, CFloat.component_id];
|
||||||
|
EntityTemplate* tmpl_ = gEM.allocateTemplate(ids);
|
||||||
|
assert(tmpl_.info.components.length == 2);
|
||||||
|
assert(tmpl_.getComponent!CInt);
|
||||||
|
assert(tmpl_.getComponent!CFloat);
|
||||||
|
assert(*tmpl_.getComponent!CInt == 1);
|
||||||
|
assert(*tmpl_.getComponent!CFloat == 2.0);
|
||||||
|
|
||||||
|
Entity* entity = gEM.addEntity(tmpl_);
|
||||||
|
assert(entity.getComponent!CInt);
|
||||||
|
assert(entity.getComponent!CFloat);
|
||||||
|
assert(*entity.getComponent!CInt == 1);
|
||||||
|
assert(*entity.getComponent!CFloat == 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//allocate templates
|
||||||
|
@("AllocateTemplates")
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
//basic template allocation
|
||||||
|
ushort[2] ids = [CInt.component_id, CFloat.component_id];
|
||||||
|
EntityTemplate* tmpl_ = gEM.allocateTemplate(ids);
|
||||||
|
assert(tmpl_.info.components.length == 2);
|
||||||
|
assert(tmpl_.getComponent!CInt);
|
||||||
|
assert(tmpl_.getComponent!CFloat);
|
||||||
|
assert(*tmpl_.getComponent!CInt == 1);
|
||||||
|
assert(*tmpl_.getComponent!CFloat == 2.0);
|
||||||
|
*tmpl_.getComponent!CInt = 4;
|
||||||
|
*tmpl_.getComponent!CFloat = 5.0;
|
||||||
|
|
||||||
|
//allocate template from template with additional component
|
||||||
|
ushort[1] ids2 = [CDouble.component_id];
|
||||||
|
EntityTemplate* tmpl_2 = gEM.allocateTemplate(tmpl_, ids2);
|
||||||
|
assert(tmpl_2.info.components.length == 3);
|
||||||
|
assert(tmpl_2.getComponent!CInt);
|
||||||
|
assert(tmpl_2.getComponent!CFloat);
|
||||||
|
assert(tmpl_2.getComponent!CDouble);
|
||||||
|
assert(*tmpl_2.getComponent!CInt == 4);
|
||||||
|
assert(*tmpl_2.getComponent!CFloat == 5.0);
|
||||||
|
assert(*tmpl_2.getComponent!CDouble == 3.0);
|
||||||
|
|
||||||
|
Entity* entity = gEM.addEntity(tmpl_);
|
||||||
|
gEM.addComponents(entity.id, CDouble(8.0));
|
||||||
|
|
||||||
|
//apply entity changes
|
||||||
|
gEM.commit();
|
||||||
|
|
||||||
|
//allocate template as entity copy
|
||||||
|
EntityTemplate* tmpl_3 = gEM.allocateTemplate(entity.id);
|
||||||
|
assert(tmpl_3.info.components.length == 3);
|
||||||
|
assert(tmpl_3.getComponent!CInt);
|
||||||
|
assert(tmpl_3.getComponent!CFloat);
|
||||||
|
assert(tmpl_3.getComponent!CDouble);
|
||||||
|
assert(*tmpl_3.getComponent!CInt == 4);
|
||||||
|
assert(*tmpl_3.getComponent!CFloat == 5.0);
|
||||||
|
assert(*tmpl_3.getComponent!CDouble == 8.0);
|
||||||
|
|
||||||
|
//allocate template with entity data but default values
|
||||||
|
EntityTemplate* tmpl_4 = gEM.allocateTemplate(entity.id, true);
|
||||||
|
assert(tmpl_4.info.components.length == 3);
|
||||||
|
assert(tmpl_4.getComponent!CInt);
|
||||||
|
assert(tmpl_4.getComponent!CFloat);
|
||||||
|
assert(tmpl_4.getComponent!CDouble);
|
||||||
|
assert(*tmpl_4.getComponent!CInt == 1);
|
||||||
|
assert(*tmpl_4.getComponent!CFloat == 2.0);
|
||||||
|
assert(*tmpl_4.getComponent!CDouble == 3.0);
|
||||||
|
|
||||||
|
//allocate template from template with two additional component
|
||||||
|
ushort[2] ids3 = [CDouble.component_id, CLong.component_id];
|
||||||
|
EntityTemplate* tmpl_5 = gEM.allocateTemplate(tmpl_, ids3);
|
||||||
|
assert(tmpl_5.info.components.length == 4);
|
||||||
|
assert(tmpl_5.getComponent!CInt);
|
||||||
|
assert(tmpl_5.getComponent!CFloat);
|
||||||
|
assert(tmpl_5.getComponent!CDouble);
|
||||||
|
assert(tmpl_5.getComponent!CLong);
|
||||||
|
assert(*tmpl_5.getComponent!CInt == 4);
|
||||||
|
assert(*tmpl_5.getComponent!CFloat == 5.0);
|
||||||
|
assert(*tmpl_5.getComponent!CDouble == 3.0);
|
||||||
|
assert(*tmpl_5.getComponent!CLong == 10);
|
||||||
|
|
||||||
|
//allocate template from template without one component
|
||||||
|
ushort[1] rem_ids = [CFloat.component_id];
|
||||||
|
EntityTemplate* tmpl_6 = gEM.allocateTemplate(tmpl_, null, rem_ids);
|
||||||
|
assert(tmpl_6.info.components.length == 1);
|
||||||
|
assert(tmpl_6.getComponent!CInt);
|
||||||
|
assert(*tmpl_6.getComponent!CInt == 4);
|
||||||
|
|
||||||
|
//allocate template from template without one component and two additional
|
||||||
|
EntityTemplate* tmpl_7 = gEM.allocateTemplate(tmpl_, ids3, rem_ids);
|
||||||
|
assert(tmpl_7.info.components.length == 3);
|
||||||
|
assert(tmpl_7.getComponent!CInt);
|
||||||
|
assert(tmpl_7.getComponent!CDouble);
|
||||||
|
assert(tmpl_7.getComponent!CLong);
|
||||||
|
assert(*tmpl_7.getComponent!CInt == 4);
|
||||||
|
assert(*tmpl_7.getComponent!CDouble == 3.0);
|
||||||
|
assert(*tmpl_7.getComponent!CLong == 10);
|
||||||
|
|
||||||
|
gEM.freeTemplate(tmpl_);
|
||||||
|
gEM.freeTemplate(tmpl_2);
|
||||||
|
gEM.freeTemplate(tmpl_3);
|
||||||
|
gEM.freeTemplate(tmpl_4);
|
||||||
|
gEM.freeTemplate(tmpl_5);
|
||||||
|
gEM.freeTemplate(tmpl_6);
|
||||||
|
gEM.freeTemplate(tmpl_7);
|
||||||
|
}
|
||||||
|
|
@ -130,6 +130,7 @@ struct TestRunner(Args...)
|
||||||
{
|
{
|
||||||
TestSuite* suite = &suites[i];
|
TestSuite* suite = &suites[i];
|
||||||
suite.name = module_.stringof;
|
suite.name = module_.stringof;
|
||||||
|
static if(__traits(hasMember, module_, "beforeEveryTest"))module_.beforeEveryTest();
|
||||||
foreach (index, unittest_; __traits(getUnitTests, module_))
|
foreach (index, unittest_; __traits(getUnitTests, module_))
|
||||||
{
|
{
|
||||||
enum attributes = __traits(getAttributes, unittest_);
|
enum attributes = __traits(getAttributes, unittest_);
|
||||||
|
|
@ -161,6 +162,7 @@ struct TestRunner(Args...)
|
||||||
}
|
}
|
||||||
passed += suite.passed;
|
passed += suite.passed;
|
||||||
failed += suite.failed;
|
failed += suite.failed;
|
||||||
|
static if(__traits(hasMember, module_, "afterEveryTest"))module_.afterEveryTest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue