-added EmptySystem supprort (called once per frame, sholud be once per jobs)

-EntitiesData can contain "thread_id" which is filled with ID of current thread
This commit is contained in:
Mergul 2020-03-06 13:52:21 +01:00
parent 5399b584dd
commit d6b53425dd
3 changed files with 237 additions and 156 deletions

View file

@ -164,6 +164,11 @@ export struct EntityManager
foreach (ref system; systems)
{
if (system.m_empty == true)
{
addSystemCaller(system.id);
continue;
}
if (system.m_update is null)
{
if (system.m_add_entity || system.m_remove_entity || system.m_change_entity)
@ -357,46 +362,8 @@ export struct EntityManager
{
static void callEventHandler(Type)(ref EventCallData data)
{
//Sys.EventInput input;
Sys* data_system = cast(Sys*) data.system_pointer;
/*EntityInfo* info = data.block.type_info;
alias EventFields = Fields!(Sys.EventInput);
foreach (ref event_field; input.tupleof)
{
alias EventFieldType = Unqual!(typeof(*event_field));
enum bool is_entity = is(EventFieldType == ecs.entity.Entity);
static if (is_entity)
{
event_field = cast(Entity*) data.block.dataBegin() + data.id;
continue;
}
else
{
enum long index_in_entities_data = getIndexOfTypeInEntitiesData!(Sys.EntitiesData,
EventFieldType);
static assert(index_in_entities_data != -1,
"Component present in EventInput has to be present in EntitiesData!"); // Type present in EventInput has to be present in EntitiesData
enum bool is_optional = hasUDA!(Sys.EntitiesData.tupleof[index_in_entities_data],
"optional");
static if (is_optional)
{
if(info.deltas[EventFieldType.component_id] != 0)event_field = cast(EventFieldType*)(cast(void*) data.block
+ info.deltas[EventFieldType.component_id]
+ data.id * EventFieldType.sizeof);
else event_field = null;
}
else
{
event_field = cast(EventFieldType*)(cast(void*) data.block
+ info.deltas[EventFieldType.component_id]
+ data.id * EventFieldType.sizeof);
}
}
}//*/
Type* event = cast(Type*) data.event;
data_system.handleEvent(gEM.getEntity(event.entity_id), *event);
}
@ -542,8 +509,8 @@ export struct EntityManager
foreach (member; __traits(allMembers, Sys.EntitiesData))
{
alias MemberType = typeof(__traits(getMember, Sys.EntitiesData, member));
if (member == "length" || member == "thread_id" || is(MemberType == Entity[])
|| is(MemberType == const(Entity)[]))
if (member == "length" || member == "thread_id"
|| is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
{
if (is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
components_info.entites_array = member;
@ -711,10 +678,10 @@ export struct EntityManager
input_data.length = cast(typeof(input_data.length))(entities_count - offset);
}
static if (hasMember!(Sys.EntitiesData, "thread_id"))
/*static if (hasMember!(Sys.EntitiesData, "thread_id"))
{
input_data.thread_id = cast(typeof(input_data.thread_id))threadID();
}
}//*/
static foreach (iii, comp_info; components_info.req)
{
@ -773,6 +740,8 @@ export struct EntityManager
//enum HasOnUpdate = (hasMember!(Sys, "onUpdate") && checkOnUpdateParams());
static if (OnUpdateOverloadNum != -1)
{
static if (components_info.req.length != 0 || components_info.optional.length != 0)
{
static void callUpdate(ref CallData data)
{
@ -808,10 +777,17 @@ export struct EntityManager
else
entities_count = block.entities_count;
assert(entities_count <= block.entities_count && offset <= block.entities_count);
assert(entities_count <= block.entities_count
&& offset <= block.entities_count);
fillInputData(input_data, info, block, offset, entities_count, system);
static if (hasMember!(Sys.EntitiesData, "thread_id"))
{
input_data.thread_id = cast(typeof(input_data.thread_id)) data
.thread_id;
}
//s.onUpdate(input_data);
(cast(typeof(&__traits(getOverloads, s,
"onUpdate")[OnUpdateOverloadNum])) data.update_delegate)(input_data);
@ -821,6 +797,31 @@ export struct EntityManager
blocks--;
}
}
}
else
{
static void callUpdate(ref CallData data)
{
Sys* s = cast(Sys*) data.system.m_system_pointer;
Sys.EntitiesData input_data;
/*static if (hasMember!(Sys.EntitiesData, "length"))
{
input_data.length = 0;
}//*/
static if (hasMember!(Sys.EntitiesData, "thread_id"))
{
input_data.thread_id = cast(typeof(input_data.thread_id)) data.thread_id;
}
(cast(typeof(&__traits(getOverloads, s,
"onUpdate")[OnUpdateOverloadNum])) data.update_delegate)(input_data);
}
system.m_empty = true;
}
system.m_update = &callUpdate;
}
@ -1097,9 +1098,16 @@ export struct EntityManager
System* sys = &systems[caller.system_id];
if (sys.enabled && sys.execute)
{
if (sys.m_empty)
{
CallData data = CallData(caller.system_id, sys, null, sys.m_update_delegate);
data.update();
}
else
foreach (info; caller.infos)
{
CallData data = CallData(caller.system_id, sys, info, sys.m_update_delegate);
CallData data = CallData(caller.system_id, sys, info,
sys.m_update_delegate);
data.update();
}
}
@ -1130,6 +1138,26 @@ export struct EntityManager
System* sys = &systems[caller.system_id];
if (sys.enabled && sys.execute)
{
uint job_id = 0;
void nextJob()
{
CallData[] callers = m_call_data_allocator.getCallData(
cast(uint) tmp_datas.length);
//callers[0 .. $] = tmp_datas[0 .. $];
memcpy(callers.ptr, &tmp_datas[0], CallData.sizeof * tmp_datas.length);
tmp_datas.clear();
sys.jobs[job_id].callers = callers;
job_id++;
}
if (sys.m_empty)
{
tmp_datas.add(CallData(caller.system_id, sys, null, sys.m_update_delegate));
nextJob();
caller.job_group.jobs = sys.jobs[0 .. 1];
(cast(void delegate(JobGroup) nothrow @nogc) m_dispatch_jobs)(caller.job_group);
continue;
}
uint entities_count = 0;
foreach (info; caller.infos)
{
@ -1155,20 +1183,8 @@ export struct EntityManager
entities_per_job = entities_count / jobs_count + 1;
}
uint job_id = 0;
entities_count = 0;
void nextJob()
{
CallData[] callers = m_call_data_allocator.getCallData(
cast(uint) tmp_datas.length);
//callers[0 .. $] = tmp_datas[0 .. $];
memcpy(callers.ptr, &tmp_datas[0], CallData.sizeof * tmp_datas.length);
tmp_datas.clear();
sys.jobs[job_id].callers = callers;
job_id++;
}
foreach (info; caller.infos)
{
uint blocks_count = info.nonEmptyBlocksCount();
@ -1596,6 +1612,41 @@ export struct EntityManager
entity.systems[system_id] = true;
}
export void addSystemCaller(uint system_id) nothrow @nogc
{
System* system = &systems[system_id];
uint index = 0;
for (; index < passes[system.m_pass].system_callers.length; index++)
{
if (passes[system.m_pass].system_callers[index].system_id == system_id)
return;
}
bool added = false;
foreach (i, caller; passes[system.m_pass].system_callers)
{
if (systems[caller.system_id].priority > system.priority)
{
SystemCaller* sys_caller = Mallocator.make!SystemCaller;
sys_caller.system_id = system.id;
sys_caller.job_group.caller = sys_caller;
system.m_any_system_caller = sys_caller;
passes[system.m_pass].system_callers.add(sys_caller, i);
added = true;
break;
}
}
if (!added)
{
SystemCaller* sys_caller = Mallocator.make!SystemCaller;
sys_caller.system_id = system.id;
sys_caller.job_group.caller = sys_caller;
system.m_any_system_caller = sys_caller;
passes[system.m_pass].system_callers.add(sys_caller);
}
}
export void addSystemCaller(ref EntityInfo info, uint system_id) nothrow @nogc
{
System* system = &systems[system_id];
@ -2402,7 +2453,10 @@ export struct EntityManager
foreach (caller; events[i].callers)
{
if(call_data.block.type_info.systems[caller.system.m_id] == false)continue;
if (
call_data.block.type_info.systems[caller.system.m_id]
== false)
continue;
call_data.system_pointer = caller.system.m_system_pointer;
(cast(void function(
ref EventCallData) nothrow @nogc) caller.callback)(
@ -2887,6 +2941,8 @@ export struct EntityManager
ushort begin;
///index of last element in last block
ushort end;
///current thread index
uint thread_id;
}
struct ListenerCallData
@ -2906,6 +2962,7 @@ export struct EntityManager
//EntityManager.instance.getThreadID();
foreach (ref caller; callers)
{
caller.thread_id = EntityManager.instance.threadID();
caller.update();
}
}

View file

@ -94,6 +94,8 @@ package:
bool m_execute = true;
///system id
ushort m_id;
///is system empty? Empty systems don't update entities, and is called once per update
bool m_empty = false;
///should system update and catch events?
bool m_enabled = false;

View file

@ -29,7 +29,6 @@ version(WebAssembly)
struct Time
{
static long getUSecTime()
{
time_t time;
@ -42,12 +41,15 @@ version(WebAssembly)
}
}
extern(C) void _start() {}
extern (C) void _start()
{
}
}
else version (Windows)
{
import core.stdc.stdio : printf;
import core.sys.windows.windows;
struct Time
{
static long getUSecTime()
@ -63,6 +65,7 @@ else version(Posix)
{
import core.stdc.stdio : printf;
import core.sys.posix.time;
struct Time
{
static long getUSecTime()
@ -409,6 +412,21 @@ struct Sys3
}
}
struct EmptySystem
{
mixin ECS.System;
struct EntitiesData
{
uint thread_id;
}
void onUpdate(EntitiesData data)
{
printf("EmptySystem.onUpdate() - this should be called once per update\n");
}
}
import std.meta;
struct TestSystem2
@ -556,7 +574,9 @@ extern(C) int main()
printf("TestComp3(%u, %u)", cast(uint) test_comp3.gg, cast(uint) test_comp3.bg); //write(*test_comp3);
TestComp4* test_comp4 = entity.getComponent!TestComp4;
if (test_comp4)
printf("TestComp4(%u, %u, %u, %u, %u, %u)",test_comp4.gg,test_comp4.bg,cast(uint)test_comp4.a,cast(uint)test_comp4.b,cast(uint)test_comp4.c,cast(uint)test_comp4.g);//write(*test_comp4);
printf("TestComp4(%u, %u, %u, %u, %u, %u)", test_comp4.gg, test_comp4.bg,
cast(uint) test_comp4.a, cast(uint) test_comp4.b,
cast(uint) test_comp4.c, cast(uint) test_comp4.g); //write(*test_comp4);
printf("\n");
//writeln();
////writeln((cast(uint*) pp)[0 .. 14], " ", pp);
@ -597,6 +617,7 @@ extern(C) int main()
gEM.registerSystem!Sys1(10);
gEM.registerSystem!Sys2(-100);
gEM.registerSystem!Sys3(-2);
gEM.registerSystem!EmptySystem(2);
//gEM.registerSystem!TestSystemWithHighPriority(100);
//gEM.registerSystem!TestSystem2(0);
gEM.endRegister();
@ -711,7 +732,8 @@ extern(C) int main()
foreach (i; 0 .. 1_000_000)
{
EntityManager.instance.addComponents(entities[i], TestComp5());
if((i & 0x00FFFF) == 0)gEM.commit();
if ((i & 0x00FFFF) == 0)
gEM.commit();
}
gEM.commit();