Add simple usage unittest

This commit is contained in:
mmcomando 2018-09-07 14:04:32 +02:00
parent a984824ec5
commit 8285bde71d

View file

@ -1,36 +1,38 @@
module ecs.ecs;
import std.stdio; import std.stdio;
alias SytemFuncType = void function(ref SystemCallData data, void* componentsStart); alias SytemFuncType = void function(ref SystemCallData data, void* componentsStart);
struct HasComponentsStore { struct HasComponentsStore
{
ulong[4] bits; //256 components ulong[4] bits; //256 components
bool has(HasComponentsStore components) { bool has(HasComponentsStore components)
{
return true; return true;
} }
bool notIn(HasComponentsStore components) { bool notIn(HasComponentsStore components)
{
return true; return true;
} }
int length() { int length()
{
assert(0); assert(0);
} }
} }
// Informacje o kompnencie // Informacje o kompnencie
struct ComponentInfo { struct ComponentInfo
{
int size; int size;
int aligment; int aligment;
SerializeJSON funsSerJ; SerializeJSON funsSerJ;
SerializeBiN funcSerB; SerializeBiN funcSerB;
} }
struct System { struct System
{
HasComponentsStore requiredComponents; HasComponentsStore requiredComponents;
HasComponentsStore absenComponents; HasComponentsStore absenComponents;
HasComponentsStore maybeComponents; HasComponentsStore maybeComponents;
@ -39,13 +41,15 @@ struct System {
SytemFuncType func; SytemFuncType func;
} }
// Informacje o systemie dla konkretnego entitiesa // Informacje o systemie dla konkretnego entitiesa
struct SystemCallData { struct SystemCallData
{
System* system; System* system;
int[] componentsDt; int[] componentsDt;
} }
// Informacje o entitiesie danego typu // Informacje o entitiesie danego typu
struct EntityTypeData { struct EntityTypeData
{
HasComponentsStore components; HasComponentsStore components;
int[] deltas; int[] deltas;
int totalSize; int totalSize;
@ -53,21 +57,25 @@ struct EntityTypeData {
SystemCallData[] systems; SystemCallData[] systems;
} }
struct EntitiesBlock { struct EntitiesBlock
{
EntityTypeData* typeData; EntityTypeData* typeData;
Entity* freeEntitySlot; Entity* freeEntitySlot;
EntitiesBlock* nextBlock; EntitiesBlock* nextBlock;
} }
struct EntityID { struct EntityID
{
ulong id = ulong.max; ulong id = ulong.max;
static immutable notUsedValue = EntityID(ulong.max); static immutable notUsedValue = EntityID(ulong.max);
} }
// Dane konkretnego Entitiesa // Dane konkretnego Entitiesa
struct Entity { struct Entity
{
EntityID entityID = EntityID.notUsedValue; EntityID entityID = EntityID.notUsedValue;
union { union
{
string name; string name;
Entity* nextFreeSlot; Entity* nextFreeSlot;
} }
@ -78,12 +86,14 @@ struct Entity {
//ubyte[XX] thereIsComponentsMemory; //ubyte[XX] thereIsComponentsMemory;
} }
struct Template { struct Template
{
HasComponentsStore hasComp; HasComponentsStore hasComp;
Entity* entity; Entity* entity;
} }
struct Manager { struct Manager
{
EntityAllocator entityArrayAllcoator; EntityAllocator entityArrayAllcoator;
ComponentInfo[] components; ComponentInfo[] components;
@ -92,19 +102,24 @@ struct Manager {
HashMapTwoWays!(string, Entity*) nameMap; HashMapTwoWays!(string, Entity*) nameMap;
HashMapTwoWays!(EntityID, Entity*) idMap; HashMapTwoWays!(EntityID, Entity*) idMap;
EntitiesBlock* getEntitiesBlock(HasComponentsStore hasComponents) { EntitiesBlock* getEntitiesBlock(HasComponentsStore hasComponents)
{
EntitiesBlock* block = entitiesDatas.get(hasComponents, null); EntitiesBlock* block = entitiesDatas.get(hasComponents, null);
if (block is null) { if (block is null)
{
// If such component combination was never present, add it // If such component combination was never present, add it
block = addNewBlock(hasComponents, block); block = addNewBlock(hasComponents, block);
return block; return block;
} }
// Iterate over list of components until free slot is found or lists ends // Iterate over list of components until free slot is found or lists ends
do { do
if (block.freeEntitySlot !is null) { {
if (block.freeEntitySlot !is null)
{
return block; return block;
} }
if (block.nextBlock is null) { if (block.nextBlock is null)
{
block = addNewBlock(hasComponents); block = addNewBlock(hasComponents);
return block; return block;
} }
@ -114,11 +129,14 @@ struct Manager {
} }
EntitiesBlock* addNewBlock(HasComponentsStore hasComponents, EntitiesBlock* firstBlock) { EntitiesBlock* addNewBlock(HasComponentsStore hasComponents, EntitiesBlock* firstBlock)
{
// Get last block so order of blocks is preserved, and first blocks are filled first // Get last block so order of blocks is preserved, and first blocks are filled first
EntitiesBlock* lastBlock = firstBlock; EntitiesBlock* lastBlock = firstBlock;
if (lastBlock !is null) { if (lastBlock !is null)
while (lastBlock.nextBlock !is null) { {
while (lastBlock.nextBlock !is null)
{
lastBlock = lastBlock.nextBlock; lastBlock = lastBlock.nextBlock;
} }
} }
@ -126,32 +144,39 @@ struct Manager {
ubyte[] memory = new ubyte[](4096); ubyte[] memory = new ubyte[](4096);
EntitiesBlock* block = cast(EntitiesBlock*) memory.ptr; EntitiesBlock* block = cast(EntitiesBlock*) memory.ptr;
if (lastBlock is null) { if (lastBlock is null)
{
EntityTypeData* entityTypeData = newEntityTypeData(hasComponents); EntityTypeData* entityTypeData = newEntityTypeData(hasComponents);
block.typeData = entityTypeData; block.typeData = entityTypeData;
block.nextBlock = null; block.nextBlock = null;
entitiesDatas.add(hasComponents, block); entitiesDatas.add(hasComponents, block);
} else { }
else
{
lastBlock.nextBlock = block; lastBlock.nextBlock = block;
block.typeData = lastBlock.typeData; block.typeData = lastBlock.typeData;
block.nextBlock = null; block.nextBlock = null;
} }
} }
void alignNum(ref int num, int aligment) { void alignNum(ref int num, int aligment)
{
int reminder = num % aligment; int reminder = num % aligment;
if (reminder != 0) { if (reminder != 0)
{
num += aligment - reminder; num += aligment - reminder;
} }
} }
EntityTypeData* newEntityTypeData(HasComponentsStore hasComponents) { EntityTypeData* newEntityTypeData(HasComponentsStore hasComponents)
{
EntityTypeData* typeData = new EntityTypeData(); EntityTypeData* typeData = new EntityTypeData();
typeData.components = hasComponents; typeData.components = hasComponents;
ComponentInfo[] components = getComponentsInfo(hasComponents); ComponentInfo[] components = getComponentsInfo(hasComponents);
typeData.deltas.length = hasComponents.length; typeData.deltas.length = hasComponents.length;
foreach (i, comp; components) { foreach (i, comp; components)
{
typeData.deltas[i] = typeData.totalSize; typeData.deltas[i] = typeData.totalSize;
typeData.totalAligment.max(comp.aligment); typeData.totalAligment.max(comp.aligment);
typeData.totalSize += comp.size; typeData.totalSize += comp.size;
@ -159,9 +184,11 @@ struct Manager {
} }
alignNum(typeData.totalSize, typeData.totalAligment); alignNum(typeData.totalSize, typeData.totalAligment);
foreach (sys; systems) { foreach (sys; systems)
{
if (!typeData.hasComp.has(sys.requiredComponents) if (!typeData.hasComp.has(sys.requiredComponents)
|| !typeData.hasComp.notIn(sys.absenComponents)) { || !typeData.hasComp.notIn(sys.absenComponents))
{
continue; continue;
} }
entTypeData.systems ~= sys entTypeData.systems ~= sys
@ -170,7 +197,8 @@ struct Manager {
return typeData; return typeData;
} }
void addEntity(Template* templ) { void addEntity(Template* templ)
{
EntitiesBlock* block = getEntitiesBlock(templ.hasComp); EntitiesBlock* block = getEntitiesBlock(templ.hasComp);
Entity* newEntity = block.freeEntitySlot; Entity* newEntity = block.freeEntitySlot;
block.freeEntitySlot = newEntity.nextFreeSlot; block.freeEntitySlot = newEntity.nextFreeSlot;
@ -178,21 +206,25 @@ struct Manager {
memcpy(temp.entity, newEntity, block.typeData.totalSize); memcpy(temp.entity, newEntity, block.typeData.totalSize);
} }
void addSystem(Func)(int priority) { void addSystem(Func)(int priority)
{
HasComponentsStore requiredComponents; HasComponentsStore requiredComponents;
HasComponentsStore absenComponents; HasComponentsStore absenComponents;
HasComponentsStore maybeComponents; HasComponentsStore maybeComponents;
void systemCaller(ref SystemCallData data, void * componentsStart) { void systemCaller(ref SystemCallData data, void * componentsStart)
{
Func(cast(FUnc.par1Type)(componentsStart + data.componentsDt[0]), Func(cast(FUnc.par1Type)(componentsStart + data.componentsDt[0]),
cast(FUnc.par1Type)(componentsStart + data.componentsDt[1])...); cast(FUnc.par1Type)(componentsStart + data.componentsDt[1])...);
} }
System* system = new System(&systemCaller, entTypeData); System* system = new System(&systemCaller, entTypeData);
systems ~= system; systems ~= system;
foreach (ref entTypeData; entitiesDatas) { foreach (ref entTypeData; entitiesDatas)
{
if (!entTypeData.hasComp.has(requiredComponents) if (!entTypeData.hasComp.has(requiredComponents)
|| !entTypeData.hasComp.notIn(absenComponents)) { || !entTypeData.hasComp.notIn(absenComponents))
{
continue; continue;
} }
entTypeData.systems ~= system; entTypeData.systems ~= system;
@ -200,42 +232,104 @@ struct Manager {
} }
} }
void someSystem(CompA a, CompB b, CompC* c) { void someSystem(CompA a, CompB b, CompC* c)
{
} }
void main() { void main()
{
writeln("Edit source/app.d to start your project."); writeln("Edit source/app.d to start your project.");
} }
class System
{
void start()
{
class System{
void start(){
} }
void end(){ void end()
{
} }
void update(ref ObjRend a){ void update(ref ObjRend a)
{
} }
void useEvent(EventData evvv, ref ObjRend a){ void useEvent(EventData evvv, ref ObjRend a)
{
} }
} }
alias SerializeVector = ubyte[];
__ghsared EntityManager gEntityManager;
unittest
{
struct ComponentA
{
__gshared static int component_id;
int a;
ulong b;
static void serializeComponent(ref ComponentA comp, SerializeVector output)
{
}
static void deerializeComponent(ref ComponentA comp, ubyte[] data)
{
}
}
gEM.addComponet!ComponentA();
assert(ComponentA.component_id == 0);
ComponentData* ccc = &gEM.componnets[ComponentA.component_id];
assert(ccc.totalAligment == 8);
assert(ccc.totalSize == 8);
HasComponentsStore hasComponents;
hasComponents.addComponet(ComponentA.component_id);
EntityTempalte* tmpl = gEM.allocateTemplate(hasComponents);
ComponentA* comp = tmpl.getComponent!ComponentA(ComponentA.component_id);
comp.a = 111;
comp.b = 222;
gEM.addEntity(tmpl);
struct SystemAdd
{
void update(ref ComponentA a)
{
a.a+=1000;
b.b+=2000;
}
void handleEvent(EventData evvv, ref ComponentA a)
{
}
}
int priority=10;
gEM.registerSystem!(SystemAdd)(priority);
gEM.updateStepAll();
foreach(EntityID id; gEM.IterateByAllEntiteis){
assert(id.getComponent(ComponentA.component_id));
ComponentA* ccc=id.getComponent(ComponentA.component_id);
assert(ccc.a==1111);
assert(ccc.b==2222);
}
}