-added absen components list to system

-added ECS uda attributes
-added InputStruct version switch (gets update() input as structure of arrays)
-initial (WIP) EntitiesData update() input structure compile time parsing
This commit is contained in:
Mergul 2018-09-29 23:10:31 +02:00
parent 8468335b50
commit ed589bbd71
5 changed files with 238 additions and 79 deletions

View file

@ -10,6 +10,9 @@
"dflags-posix-ldc": [
"-defaultlib=phobos2-ldc,druntime-ldc"
],
"versions": [
"InputStruct"
],
"configurations" : [
{
"name" : "library",

4
source/ecs/attributes.d Normal file
View file

@ -0,0 +1,4 @@
module ecs.attributes;
enum optional = "optional";
enum absen = "absen";

View file

@ -61,92 +61,120 @@ class EntityManager
System system;
static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
version (InputStruct)
{
static assert(0, "System should have \"__gshared ushort system_id");
}
static if (hasMember!(Sys, "update"))
{
alias types = Parameters!(Sys.update);
alias storages = ParameterStorageClassTuple!(Sys.update);
static string genCall()()
static if (!(hasMember!(Sys, "EntitiesData")))
{
string ret;
static assert(0, "System should gave \"EntitiesData\" struct for input components");
}
static string genCompList()()
{
string ret = "ushort comp;uint req;uint opt;uint absen;";
static foreach (member; __traits(allMembers, Sys.EntitiesData))
{
uint i = 0;
uint opt = 0;
static foreach (param; (Parameters!(Sys.update))[1 .. $])
static if (isFunction!(__traits(getMember, Sys.EntitiesData, member)))
static assert(0, "EntitiesData can't have any function!");
else static if (isArray!(typeof(__traits(getMember,
Sys.EntitiesData, member))))
static assert(0, "EntitiesData members should be arrays of elements!");
else static if (is(typeof(__traits(getMember,
Sys.EntitiesData, member)) == Entity[]))
{
ret ~= "const string entities_name = \"" ~ member ~ "\";";
}
else
{
i++;
if (isPointer!param)
{
ret ~= "if(opt_array" ~ opt.to!string ~ " !is null)opt_ptr"
~ opt.to!string ~ " = &opt_array" ~ opt.to!string ~ "[i];";
opt++;
bool has_att = false;
foreach (att; __traits(getAttributes,
__traits(getMember, Sys.EntitiesData, member)))
{
if (att == "optional")
{
ret ~= "opt++;";
has_att = true;
break;
}
else if (att == "absen")
{
ret ~= "absen++;";
has_att = true;
break;
}
}
if (!has_att)
ret ~= "req++;";
}
}
}
/*foreach (i; 1 .. (Parameters!(Sys.update)).length)
ret ~= "system.m_components = Mallocator.instance.makeArray!ushort(req);";
ret ~= "system.m_optional_components = Mallocator.instance.makeArray!ushort(opt);";
ret ~= "opt = 0;req = 0;absen = 0;";
static foreach (member; __traits(allMembers, Sys.EntitiesData))
{
ret ~= "*cast(types[" ~ i.to!string ~ "]*)(pointers[" ~ (i - 1)
.to!string ~ "]),";
}*/
uint i = 0;
uint req = 0;
uint opt = 0;
ret ~= "s.update(id_array[i],";
static foreach (param; (Parameters!(Sys.update))[1 .. $])
{
i++;
if (isPointer!param)
static if (isFunction!(__traits(getMember, Sys.EntitiesData, member)))
static assert(0, "EntitiesData can't have any function!");
else static if (isArray!(typeof(__traits(getMember,
Sys.EntitiesData, member))))
static assert(0, "EntitiesData members should be arrays of elements!");
else static if (is(typeof(__traits(getMember,
Sys.EntitiesData, member)) == Entity[]))
{
ret ~= "opt_ptr" ~ (opt++).to!string ~ ",";
//ret ~= "const string entities_name = \"" ~ member ~ "\";";
}
else
{
ret ~= "array" ~ (req++).to!string ~ "[i],";
}
}
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 ~ " = null;";
ret ~= "if(info.deltas[types[" ~ i.to!string ~ "].component_id] != 0)opt_array"
~ opt.to!string ~ "
= (cast(types[" ~ i.to!string ~ "])(cast(void*)block + info.deltas[types["
~ i.to!string ~ "].component_id]))[0..block.entities_count];";
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++;
{
bool has_att = false;
foreach (att; __traits(getAttributes,
__traits(getMember, Sys.EntitiesData, member)))
{
if (att == "optional")
{
ret ~= "{comp = components_map.get(\"" ~ (typeof(__traits(getMember,
Sys.EntitiesData, member)))
.stringof ~ "\", ushort.max);\n
if(comp == ushort.max)assert(0,\"Can't register system \\\"" ~ Sys.stringof
~ "\\\" due to non existing component " ~ typeof(__traits(getMember,
Sys.EntitiesData, member)).stringof ~ ".\");
system.m_optional_components[opt++] = comp;}";
has_att = true;
break;
}
else if (att == "absen")
{
ret ~= "{comp = components_map.get(\"" ~ (typeof(__traits(getMember,
Sys.EntitiesData, member)))
.stringof ~ "\", ushort.max);\n
if(comp == ushort.max)assert(0,\"Can't register system \\\"" ~ Sys.stringof
~ "\\\" due to non existing component " ~ typeof(__traits(getMember,
Sys.EntitiesData, member)).stringof
~ ".\");system.m_absen_components[absen++] = comp;}";
has_att = true;
break;
}
}
if (!has_att)
{
ret ~= "{comp = components_map.get(\"" ~ (typeof(__traits(getMember,
Sys.EntitiesData, member)))
.stringof ~ "\", ushort.max);\n
if(comp == ushort.max)assert(0,\"Can't register system \\\"" ~ Sys.stringof
~ "\\\" due to non existing component " ~ typeof(__traits(getMember,
Sys.EntitiesData, member)).stringof ~ ".\");
system.m_components[req++] = comp;}";
}
}
}
}
return ret;
}
}
else
{
static string genCompList()()
{
string ret = "ushort comp;uint req;uint opt;";
@ -186,6 +214,92 @@ class EntityManager
}
return ret;
}
}
static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
{
static assert(0, "System should have \"__gshared ushort system_id");
}
static if (hasMember!(Sys, "update"))
{
alias types = Parameters!(Sys.update);
alias storages = ParameterStorageClassTuple!(Sys.update);
static string genCall()()
{
string ret;
{
uint i = 0;
uint opt = 0;
static foreach (param; (Parameters!(Sys.update))[1 .. $])
{
i++;
if (isPointer!param)
{
ret ~= "if(opt_array" ~ opt.to!string ~ " !is null)opt_ptr"
~ opt.to!string ~ " = &opt_array" ~ opt.to!string ~ "[i];";
opt++;
}
}
}
/*foreach (i; 1 .. (Parameters!(Sys.update)).length)
{
ret ~= "*cast(types[" ~ i.to!string ~ "]*)(pointers[" ~ (i - 1)
.to!string ~ "]),";
}*/
uint i = 0;
uint req = 0;
uint opt = 0;
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],";
}
}
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 ~ " = null;";
ret ~= "if(info.deltas[types[" ~ i.to!string ~ "].component_id] != 0)opt_array" ~ opt.to!string
~ "
= (cast(types[" ~ i.to!string ~ "])(cast(void*)block + info.deltas[types["
~ i.to!string ~ "].component_id]))[0..block.entities_count];";
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 void callUpdate(ref CallData data, void* entity)
{
@ -255,7 +369,12 @@ class EntityManager
system.m_priority = priority;
//system.m_components = Mallocator.instance.makeArray!uint(types.length - 1);
static if (hasMember!(Sys, "update"))
version (InputStruct)
{
mixin(genCompList());
}
else static if (hasMember!(Sys, "update"))
{
mixin(genCompList());
}
@ -452,7 +571,6 @@ class EntityManager
= components[comp].init_data;
}
return temp;
}
@ -505,7 +623,6 @@ class EntityManager
current_delta += entites_in_block * components[id].size;
}
foreach (uint i, ref system; systems)
{
if (system.m_update is null)
@ -644,7 +761,7 @@ class EntityManager
EntitiesBlock* new_block = findBlockWithFreeSpace(new_info);
void* start = new_block.dataBegin() + new_block.entities_count * EntityID.sizeof;
Entity* new_entity = cast(Entity*) start;
new_entity.id = entity.id;
new_entity.updateID();
@ -759,7 +876,7 @@ class EntityManager
//removeEntityNoID(entity, block);
void* start = new_block.dataBegin() + new_block.entities_count * EntityID.sizeof;
Entity* new_entity = cast(Entity*) start;
new_entity.id = entity.id;
new_entity.updateID();
@ -797,7 +914,6 @@ class EntityManager
}
}
new_block.entities_count++;
removeEntityNoID(entity, block);
}
@ -857,7 +973,6 @@ class EntityManager
tmpl.entity_data.ptr + info.tmpl_deltas[comp], components[comp].size);
}
if (!block.added_count)
blocks_to_update.add(block);
@ -960,7 +1075,6 @@ class EntityManager
}
}
if (block.entities_count == 0)
{
if (info.first_block is block)

View file

@ -39,6 +39,7 @@ package:
void* m_system_pointer;
ushort[] m_components;
ushort[] m_absen_components;
ushort[] m_optional_components;
//void function(ref EntityManager.CallData data, void* entity) update;

View file

@ -4,6 +4,7 @@ import ecs.entity;
import ecs.events;
import ecs.manager;
import ecs.system;
import ecs.attributes;
import core.time;
import std.stdio;
@ -124,11 +125,12 @@ int main()
}
struct InputData
static struct EntitiesData
{
TestComp* test;
TestComp2* test2;
@("optional") TestComp3* test3;
@optional TestComp3* test3;
@absen TestComp4* test4;
}
void update(ref Entity entity, ref TestComp test, ref TestComp2 test2)//, TestComp3* test3) //ref TestComp comp)
@ -153,6 +155,11 @@ int main()
}
void update(ref EntitiesData data)
{
}
void handleEvent(TestEvent event, ref TestComp test, ref TestComp2 test2, TestComp3* test3)
{
@ -163,6 +170,11 @@ int main()
{
__gshared ushort system_id;
static struct EntitiesData
{
TestComp* test;
}
void initialize(ref Entity entity, ref TestComp comp)
{
@ -175,6 +187,13 @@ int main()
//writeln("High priority tekst! ");
}
void update(ref EntitiesData data) //ref TestComp comp)
{
assert(cast(size_t)&data.test % TestComp.alignof == 0);
//writeln("High priority tekst! ");
}
/*void handleEvent(Event event, ref TestComp comp)
{
@ -185,6 +204,17 @@ int main()
{
__gshared ushort system_id;
static struct EntitiesData
{
Entity* entity;
TestComp3* test;
/*void a()
{
}*/
}
void onEnable()
{
import std.stdio;
@ -211,6 +241,13 @@ int main()
gEM.sendSelfEvent!(TestEvent)(entity.id, TestEvent());
}
void update(ref EntitiesData data) //ref TestComp comp)
{
//writeln("TestSystem2 update");
data.test.gg += 14;
gEM.sendSelfEvent!(TestEvent)(data.entity.id, TestEvent());
}
/*void handleEvent(Event event, ref TestComp comp)
{