-removed 'InputStruct' version switch (now it's default behaviour)

-checking if System struct has valid update(EntitiesData) prototype
This commit is contained in:
Mergul 2018-10-01 13:17:31 +02:00
parent d5780a6252
commit 0e13fafefd
3 changed files with 172 additions and 363 deletions

View file

@ -66,27 +66,137 @@ class EntityManager
static assert(0, "System should have \"__gshared ushort system_id");
}
version (InputStruct)
static if (!(hasMember!(Sys, "EntitiesData")))
{
static if (!(hasMember!(Sys, "EntitiesData")))
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))
{
static assert(0, "System should gave \"EntitiesData\" struct for input components");
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
{
{
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++;";
}
}
}
static string genCompList()()
ret ~= "system.m_components = Mallocator.instance.makeArray!ushort(req);";
ret ~= "system.m_optional_components = Mallocator.instance.makeArray!ushort(opt);";
ret ~= "system.m_absen_components = Mallocator.instance.makeArray!ushort(absen);";
ret ~= "opt = 0;req = 0;absen = 0;";
static foreach (member; __traits(allMembers, Sys.EntitiesData))
{
string ret = "ushort comp;uint req;uint opt;uint absen;";
static foreach (member; __traits(allMembers, Sys.EntitiesData))
static if (is(typeof(__traits(getMember, Sys.EntitiesData,
member)) == Entity[]) || is(typeof(__traits(getMember,
Sys.EntitiesData, member)) == const(Entity)[]))
{
//ret ~= "const string entities_name = \"" ~ member ~ "\";";
}
else
{
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 ~ "\";";
ret ~= "{comp = components_map.get(Unqual!(ForeachType!(typeof(
Sys.EntitiesData." ~ member ~ ")))
.stringof, ushort.max);\n
if(comp == ushort.max)assert(0,\"Can't register system \\\""
~ Sys.stringof
~ "\\\" due to non existing component \" ~ ForeachType!(typeof(
Sys.EntitiesData."
~ member ~ "))
.stringof
~ \".\");";
bool has_att = false;
foreach (att; __traits(getAttributes,
__traits(getMember, Sys.EntitiesData, member)))
{
if (att == "optional")
{
ret ~= "system.m_optional_components[opt++] = comp;}";
has_att = true;
break;
}
else if (att == "absen")
{
ret ~= "system.m_absen_components[absen++] = comp;}";
has_att = true;
break;
}
}
if (!has_att)
{
ret ~= "system.m_components[req++] = comp;}";
}
}
}
}
return ret;
}
string genParamsChecking()()
{
string ret;
foreach (func; __traits(getOverloads, Sys, "update"))
{
if ((Parameters!(func)).length == 1)
ret ~= "\"" ~ (fullyQualifiedName!(Sys.EntitiesData)) ~ "\" == \"" ~ (
fullyQualifiedName!((Parameters!(func))[0])) ~ "\" || ";
}
ret ~= "false";
return ret;
}
static if (hasMember!(Sys, "update") && (mixin(genParamsChecking())))
{
static string genFillInputData()()
{
string ret;
ushort comp;
uint req = 0;
uint opt = 0;
uint absen = 0;
foreach (member; __traits(allMembers, Sys.EntitiesData))
{
if (is(typeof(__traits(getMember, Sys.EntitiesData,
member)) == Entity[]) || is(typeof(__traits(getMember,
Sys.EntitiesData, member)) == const(Entity)[]))
{
ret ~= "input_data." ~ member
~ " = (cast(Entity*) block.dataBegin())[0 .. block.entities_count];";
}
else
{
@ -97,325 +207,55 @@ class EntityManager
{
if (att == "optional")
{
ret ~= "opt++;";
has_att = true;
break;
}
else if (att == "absen")
{
ret ~= "absen++;";
has_att = true;
break;
}
}
if (!has_att)
ret ~= "req++;";
}
}
}
ret ~= "system.m_components = Mallocator.instance.makeArray!ushort(req);";
ret ~= "system.m_optional_components = Mallocator.instance.makeArray!ushort(opt);";
ret ~= "system.m_absen_components = Mallocator.instance.makeArray!ushort(absen);";
ret ~= "opt = 0;req = 0;absen = 0;";
static foreach (member; __traits(allMembers, Sys.EntitiesData))
{
static if (is(typeof(__traits(getMember, Sys.EntitiesData, member)) == Entity[])
|| is(typeof(__traits(getMember, Sys.EntitiesData, member)) == const(Entity)[]))
{
//ret ~= "const string entities_name = \"" ~ member ~ "\";";
}
else
{
{
ret ~= "{comp = components_map.get(Unqual!(ForeachType!(typeof(
Sys.EntitiesData."
~ member ~ ")))
.stringof, ushort.max);\n
if(comp == ushort.max)assert(0,\"Can't register system \\\"" ~ Sys.stringof
~ "\\\" due to non existing component \" ~ ForeachType!(typeof(
Sys.EntitiesData."
~ member ~ "))
.stringof
~ \".\");";
bool has_att = false;
foreach (att; __traits(getAttributes,
__traits(getMember, Sys.EntitiesData, member)))
{
if (att == "optional")
{
ret ~= "system.m_optional_components[opt++] = comp;}";
has_att = true;
break;
}
else if (att == "absen")
{
ret ~= "system.m_absen_components[absen++] = comp;}";
has_att = true;
break;
}
}
if (!has_att)
{
ret ~= "system.m_components[req++] = comp;}";
}
}
}
}
return ret;
}
}
else
{
static string genCompList()()
{
string ret = "ushort comp;uint req;uint opt;";
foreach (i; 1 .. (Parameters!(Sys.update)).length)
{
ret ~= "
static if(isPointer!(types[" ~ i.to!string
~ "]))opt++;
else static if(storages[" ~ i.to!string ~ "] == STC.ref_)req++;\n
else static assert(0,\"Can't register system \\\"" ~ Sys.stringof
~ "\\\". Unsupported parameter type \\\"\"~types["
~ i.to!string ~ "].stringof~\"\\\".\");";
}
ret ~= "system.m_components = Mallocator.instance.makeArray!ushort(req);";
ret ~= "system.m_optional_components = Mallocator.instance.makeArray!ushort(opt);";
ret ~= "opt = 0;req = 0;";
foreach (i; 1 .. (Parameters!(Sys.update)).length)
{
ret ~= "
static if(isPointer!(types[" ~ i.to!string ~ "]))
{
comp = components_map.get(PointerTarget!(types["
~ i.to!string ~ "]).stringof, ushort.max);\n
if(comp == ushort.max)assert(0,\"Can't register system \\\"" ~ Sys.stringof
~ "\\\" due to non existing component \\\"\"~types[" ~ i.to!string ~ "].stringof~\"\\\".\");
system.m_optional_components[opt++] = comp;
}
else static if(storages["
~ i.to!string ~ "] == STC.ref_)
{
comp = components_map.get(types[" ~ i.to!string ~ "].stringof, ushort.max);\n
if(comp == ushort.max)assert(0,\"Can't register system \\\""
~ Sys.stringof ~ "\\\" due to non existing component \\\"\"~types["
~ i.to!string ~ "].stringof~\"\\\".\");
system.m_components[req++] = comp;
}";
}
return ret;
}
}
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++;
}
}
}
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;
}
version (InputStruct)
{
static string genFillInputData()()
{
string ret;
ushort comp;
uint req = 0;
uint opt = 0;
uint absen = 0;
foreach (member; __traits(allMembers, Sys.EntitiesData))
{
if (is(typeof(__traits(getMember, Sys.EntitiesData, member)) == Entity[])
|| is(typeof(__traits(getMember, Sys.EntitiesData, member)) == const(Entity)[]))
{
ret ~= "input_data." ~ member
~ " = (cast(Entity*) block.dataBegin())[0 .. block.entities_count];";
}
else
{
{
bool has_att = false;
foreach (att; __traits(getAttributes,
__traits(getMember, Sys.EntitiesData, member)))
{
if (att == "optional")
{
ret ~= "if(data.system.m_optional_components["
~ opt.to!string ~ "] < info.deltas.length && info.deltas[ data.system.m_optional_components["
~ opt.to!string ~ "]] != 0)input_data." ~ member ~ " = (cast(ForeachType!(typeof(Sys.EntitiesData."
~ member ~ "))*)(cast(void*) block + info.deltas[ data.system.m_optional_components["
ret ~= "if(data.system.m_optional_components[" ~ opt.to!string
~ "] < info.deltas.length && info.deltas[ data.system.m_optional_components["
~ opt.to!string ~ "]] != 0)input_data." ~ member
~ " = (cast(ForeachType!(typeof(Sys.EntitiesData." ~ member
~ "))*)(cast(void*) block + info.deltas[ data.system.m_optional_components["
~ opt.to!string ~ "]]))[0 .. block.entities_count];
else input_data." ~ member ~ " = null;";
opt++;
has_att = true;
break;
}
else if (att == "absen")
{
absen++;
has_att = true;
break;
}
else input_data."
~ member ~ " = null;";
opt++;
has_att = true;
break;
}
if (!has_att)
else if (att == "absen")
{
ret ~= "input_data." ~ member ~ " = (cast(ForeachType!(typeof(Sys.EntitiesData."
~ member ~ "))*)(cast(void*) block + info.deltas[ data.system.m_components["
~ req.to!string ~ "]]))[0 .. block.entities_count];";
req++;
absen++;
has_att = true;
break;
}
}
}
}
return ret;
}
static void callUpdate(ref CallData data, void* entity)
{
static if (hasMember!(Sys, "update"))
{
Sys* s = cast(Sys*) data.system.m_system_pointer;
/*void*[] pointers = (cast(void**) alloca(data.system.m_components.length * (void*)
.sizeof))[0 .. data.system.m_components.length];
void*[] optional_pointers = (cast(void**) alloca(
data.system.m_optional_components.length * (void*).sizeof))[0
.. data.system.m_optional_components.length];*/
Sys.EntitiesData input_data;
EntitiesBlock* block = data.info.first_block;
while (block !is null)
{
EntityInfo* info = block.type_info;
/*Entity[] id_array = (cast(Entity*) block.dataBegin())[0
.. block.entities_count];*/
//mixin(genArrays());
mixin(genFillInputData());
s.update(input_data);
/*foreach (i; 0 .. block.entities_count)
if (!has_att)
{
mixin(genCall());
}*/
block = block.next_block;
}
}
}
}
else
{
static void callUpdate(ref CallData data, void* entity)
{
static if (hasMember!(Sys, "update"))
{
Sys* s = cast(Sys*) data.system.m_system_pointer;
void*[] pointers = (cast(void**) alloca(data.system.m_components.length * (void*)
.sizeof))[0 .. data.system.m_components.length];
void*[] optional_pointers = (cast(void**) alloca(
data.system.m_optional_components.length * (void*).sizeof))[0
.. data.system.m_optional_components.length];
EntitiesBlock* block = data.info.first_block;
while (block !is null)
{
EntityInfo* info = block.type_info;
Entity[] id_array = (cast(Entity*) block.dataBegin())[0
.. block.entities_count];
mixin(genArrays());
foreach (i; 0 .. block.entities_count)
{
mixin(genCall());
//data_pointer += EntityID.sizeof; //data.info.size;
/*foreach (ref pointer; pointers)
pointer += size;
foreach (ref pointer; optional_pointers)
if (pointer != null)
pointer += size;*/
ret ~= "input_data." ~ member ~ " = (cast(ForeachType!(typeof(Sys.EntitiesData." ~ member
~ "))*)(cast(void*) block + info.deltas[ data.system.m_components["
~ req.to!string ~ "]]))[0 .. block.entities_count];";
req++;
}
block = block.next_block;
}
}
}
return ret;
}
static void callUpdate(ref CallData data, void* entity)
{
Sys* s = cast(Sys*) data.system.m_system_pointer;
Sys.EntitiesData input_data;
EntitiesBlock* block = data.info.first_block;
while (block !is null)
{
EntityInfo* info = block.type_info;
mixin(genFillInputData());
s.update(input_data);
block = block.next_block;
}
}
system.m_update = &callUpdate;
@ -449,16 +289,7 @@ class EntityManager
system.m_system_pointer = cast(void*) Mallocator.instance.make!Sys;
system.m_priority = priority;
//system.m_components = Mallocator.instance.makeArray!uint(types.length - 1);
version (InputStruct)
{
mixin(genCompList());
}
else static if (hasMember!(Sys, "update"))
{
mixin(genCompList());
}
mixin(genCompList());
ushort sys_id = systems_map.get(Sys.stringof, ushort.max);
if (sys_id < systems.length)
@ -487,9 +318,12 @@ class EntityManager
Sys.system_id = cast(ushort)(systems.length - 1);
foreach (info; &entities_infos.byValue)
if (system.m_update !is null)
{
addEntityCaller(*info, cast(uint) systems.length - 1);
foreach (info; &entities_infos.byValue)
{
addEntityCaller(*info, cast(uint) systems.length - 1);
}
}
}