Web assembly #6

Merged
Mergul merged 38 commits from WebAssembly into master 2020-04-14 17:44:27 +02:00
3 changed files with 335 additions and 171 deletions
Showing only changes of commit 87e9a31d7f - Show all commits

View file

@ -33,12 +33,16 @@ alias SerializeVector = ecs.vector.Vector!ubyte;
*/ */
export struct EntityManager export struct EntityManager
{ {
export static void initialize(uint threads_count) /************************************************************************************************************************
*Initialize ECS.
*/
export static void initialize(uint threads_count, uint page_size = 32768,
uint block_pages_count = 128)
{ {
if (instance is null) if (instance is null)
{ {
//instance = Mallocator.make!EntityManager(threads_count); //instance = Mallocator.make!EntityManager(threads_count);
instance = Mallocator.make!EntityManager(threads_count); instance = Mallocator.make!EntityManager(threads_count, page_size, block_pages_count);
with (instance) with (instance)
{ {
@ -52,6 +56,9 @@ export struct EntityManager
} }
} }
/************************************************************************************************************************
*Deinitialize and destroy ECS. This function release whole memory.
*/
export static void destroy() export static void destroy()
{ {
if (instance is null) if (instance is null)
@ -65,16 +72,25 @@ export struct EntityManager
if (system.m_destroy) if (system.m_destroy)
(cast(void function(void*)) system.m_destroy)(system.m_system_pointer); (cast(void function(void*)) system.m_destroy)(system.m_system_pointer);
if(system.jobs)Mallocator.dispose(system.jobs); if (system.jobs)
if(system.m_read_only_components)Mallocator.dispose(system.m_read_only_components); Mallocator.dispose(system.jobs);
if(system.m_modified_components)Mallocator.dispose(system.m_modified_components); if (system.m_read_only_components)
if(system.m_components)Mallocator.dispose(system.m_components); Mallocator.dispose(system.m_read_only_components);
if(system.m_excluded_components)Mallocator.dispose(system.m_excluded_components); if (system.m_modified_components)
if(system.m_optional_components)Mallocator.dispose(system.m_optional_components); Mallocator.dispose(system.m_modified_components);
if(system.m_name)Mallocator.dispose(system.m_name); if (system.m_components)
if(system.m_event_callers)Mallocator.dispose(system.m_event_callers); Mallocator.dispose(system.m_components);
if (system.m_excluded_components)
Mallocator.dispose(system.m_excluded_components);
if (system.m_optional_components)
Mallocator.dispose(system.m_optional_components);
if (system.m_name)
Mallocator.dispose(system.m_name);
if (system.m_event_callers)
Mallocator.dispose(system.m_event_callers);
if(system.m_system_pointer)Mallocator.dispose(system.m_system_pointer); if (system.m_system_pointer)
Mallocator.dispose(system.m_system_pointer);
} }
foreach (EntityInfo* info; &entities_infos.byValue) foreach (EntityInfo* info; &entities_infos.byValue)
@ -92,17 +108,20 @@ export struct EntityManager
foreach (ComponentInfo info; components) foreach (ComponentInfo info; components)
{ {
if(info.init_data)Mallocator.dispose(info.init_data); if (info.init_data)
Mallocator.dispose(info.init_data);
} }
foreach (EventInfo info; events) foreach (EventInfo info; events)
{ {
if(info.callers)Mallocator.dispose(info.callers); if (info.callers)
Mallocator.dispose(info.callers);
} }
foreach (name; &components_map.byKey) foreach (name; &components_map.byKey)
{ {
if(name)Mallocator.dispose(name); if (name)
Mallocator.dispose(name);
} }
} }
@ -165,6 +184,7 @@ export struct EntityManager
SystemCaller* sys_caller = Mallocator.make!SystemCaller; SystemCaller* sys_caller = Mallocator.make!SystemCaller;
sys_caller.system_id = system.id; sys_caller.system_id = system.id;
sys_caller.job_group.caller = sys_caller; sys_caller.job_group.caller = sys_caller;
system.m_any_system_caller = sys_caller;
passes[system.m_pass].system_callers.add(sys_caller, i); passes[system.m_pass].system_callers.add(sys_caller, i);
added = true; added = true;
break; break;
@ -175,6 +195,7 @@ export struct EntityManager
SystemCaller* sys_caller = Mallocator.make!SystemCaller; SystemCaller* sys_caller = Mallocator.make!SystemCaller;
sys_caller.system_id = system.id; sys_caller.system_id = system.id;
sys_caller.job_group.caller = sys_caller; sys_caller.job_group.caller = sys_caller;
system.m_any_system_caller = sys_caller;
passes[system.m_pass].system_callers.add(sys_caller); passes[system.m_pass].system_callers.add(sys_caller);
} }
@ -237,7 +258,8 @@ export struct EntityManager
foreach (ref event; events) foreach (ref event; events)
{ {
qsort(event.callers.ptr, event.callers.length, EventCaller.sizeof, &comapreEventCaller); qsort(event.callers.ptr, event.callers.length,
EventCaller.sizeof, &comapreEventCaller);
} }
//qsort(event_callers.ptr, event_callers.length, EventInfo.sizeof, &compareUShorts); //qsort(event_callers.ptr, event_callers.length, EventInfo.sizeof, &compareUShorts);
@ -252,17 +274,20 @@ export struct EntityManager
/************************************************************************************************************************ /************************************************************************************************************************
*Default constructor. *Default constructor.
*/ */
export this(uint threads_count) nothrow @nogc export this(uint threads_count, uint page_size, uint block_pages_count) nothrow @nogc
{ {
if (threads_count == 0) if (threads_count == 0)
threads_count = 1; threads_count = 1;
threads = Mallocator.makeArray!ThreadData(threads_count); threads = Mallocator.makeArray!ThreadData(threads_count);
//foreach(ref thread;threads)thread = ThreadData().init; //foreach(ref thread;threads)thread = ThreadData().init;
m_page_size = page_size;
m_pages_in_block = block_pages_count;
id_manager.initialize(); id_manager.initialize();
event_manager.initialize(&this); event_manager.initialize(&this);
allocator = BlockAllocator(page_size, pages_in_block); allocator = BlockAllocator(m_page_size, m_pages_in_block);
//add_mutex = Mallocator.make!Mutex; //add_mutex = Mallocator.make!Mutex;
entity_block_alloc_mutex = Mallocator.make!Mutex; entity_block_alloc_mutex = Mallocator.make!Mutex;
@ -276,7 +301,8 @@ export struct EntityManager
id_manager.deinitialize(); id_manager.deinitialize();
event_manager.destroy(); event_manager.destroy();
if(threads)Mallocator.dispose(threads); if (threads)
Mallocator.dispose(threads);
if (entity_block_alloc_mutex) if (entity_block_alloc_mutex)
{ {
entity_block_alloc_mutex.destroy(); entity_block_alloc_mutex.destroy();
@ -378,22 +404,22 @@ export struct EntityManager
void setEventCallers(Sys)(ref System system) void setEventCallers(Sys)(ref System system)
{ {
enum event_handlers_num = __traits(getOverloads, Sys, "handleEvent").length; enum event_handlers_num = __traits(getOverloads, Sys, "handleEvent").length;
System.EventCaller[] callers = (cast(System.EventCaller*)alloca(event_handlers_num * System.EventCaller.sizeof))[0..event_handlers_num]; System.EventCaller[] callers = (cast(System.EventCaller*) alloca(
event_handlers_num * System.EventCaller.sizeof))[0 .. event_handlers_num];
int i = 0; int i = 0;
foreach (j, func; __traits(getOverloads, Sys, "handleEvent")) foreach (j, func; __traits(getOverloads, Sys, "handleEvent"))
{ {
alias Params = Parameters!(__traits(getOverloads, alias Params = Parameters!(__traits(getOverloads, Sys, "handleEvent")[j]);
Sys, "handleEvent")[j]);
static if (Params.length == 2 && is(Params[0] == Entity*)) static if (Params.length == 2 && is(Params[0] == Entity*))
{ {
alias EventParamType = Params[1]; alias EventParamType = Params[1];
enum EventName = Unqual!(EventParamType).stringof; enum EventName = Unqual!(EventParamType).stringof;
ushort evt = events_map.get(cast(char[]) EventName, ushort.max); ushort evt = events_map.get(cast(char[]) EventName, ushort.max);
assert(evt != ushort.max, "Can't register system \""~Sys.stringof~"\" due to non existing event \""~EventName~"\"."); assert(evt != ushort.max, "Can't register system \"" ~ Sys.stringof
~ "\" due to non existing event \"" ~ EventName ~ "\".");
callers[i].callback = cast( callers[i].callback = cast(void*)&callEventHandler!(EventParamType);
void*)&callEventHandler!(EventParamType);
callers[i].id = EventParamType.event_id; callers[i].id = EventParamType.event_id;
i++; i++;
} }
@ -516,9 +542,11 @@ export struct EntityManager
foreach (member; __traits(allMembers, Sys.EntitiesData)) foreach (member; __traits(allMembers, Sys.EntitiesData))
{ {
alias MemberType = typeof(__traits(getMember, Sys.EntitiesData, member)); alias MemberType = typeof(__traits(getMember, Sys.EntitiesData, member));
if (member == "length" || is(MemberType == Entity[]) || is(MemberType == const(Entity)[])) if (member == "length" || is(MemberType == Entity[])
|| is(MemberType == const(Entity)[]))
{ {
if(is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))components_info.entites_array = member; if (is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
components_info.entites_array = member;
continue; continue;
} }
@ -536,7 +564,8 @@ export struct EntityManager
is_read_only = true; is_read_only = true;
} }
foreach (att; __traits(getAttributes, __traits(getMember, Sys.EntitiesData, member))) foreach (att; __traits(getAttributes, __traits(getMember,
Sys.EntitiesData, member)))
{ {
if (att == "optional") if (att == "optional")
{ {
@ -614,8 +643,10 @@ export struct EntityManager
static assert(0, "EntitiesData can't have any function!"); static assert(0, "EntitiesData can't have any function!");
else static if (member == "length") else static if (member == "length")
{ {
static assert(isIntegral!(MemberType), "EntitiesData 'length' member must be integral type."); static assert(isIntegral!(MemberType),
static assert(MemberType.sizeof > 1, "EntitiesData 'length' member can't be byte or ubyte."); "EntitiesData 'length' member must be integral type.");
static assert(MemberType.sizeof > 1,
"EntitiesData 'length' member can't be byte or ubyte.");
} }
else static if (!(isArray!(MemberType))) else static if (!(isArray!(MemberType)))
static assert(0, "EntitiesData members should be arrays of elements!"); static assert(0, "EntitiesData members should be arrays of elements!");
@ -664,7 +695,8 @@ export struct EntityManager
static if (components_info.entites_array) static if (components_info.entites_array)
{ {
__traits(getMember, input_data, components_info.entites_array) = (cast(Entity*) block.dataBegin())[offset .. entities_count]; __traits(getMember, input_data, components_info.entites_array) = (
cast(Entity*) block.dataBegin())[offset .. entities_count];
} }
static if (hasMember!(Sys.EntitiesData, "length")) static if (hasMember!(Sys.EntitiesData, "length"))
@ -674,24 +706,27 @@ export struct EntityManager
static foreach (iii, comp_info; components_info.req) static foreach (iii, comp_info; components_info.req)
{ {
__traits(getMember, input_data, comp_info.name) = __traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
(cast(ForeachType!(typeof(__traits(getMember, Sys.EntitiesData, comp_info.name)))*)(
Sys.EntitiesData, comp_info.name)))*)(cast(void*) block + info.deltas[ system.m_components[iii]]))[offset .. entities_count]; cast(void*) block + info.deltas[system.m_components[iii]]))[offset
.. entities_count];
} }
static foreach (iii, comp_info; components_info.optional) static foreach (iii, comp_info; components_info.optional)
{ {
if(system.m_optional_components[iii] < info.deltas.length && info.deltas[system.m_optional_components[iii]] != 0) if (system.m_optional_components[iii] < info.deltas.length
&& info.deltas[system.m_optional_components[iii]] != 0)
{ {
__traits(getMember, input_data, comp_info.name) = __traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
(cast(ForeachType!(typeof(__traits(getMember, Sys.EntitiesData, comp_info.name)))*)(cast(
Sys.EntitiesData, comp_info.name)))*)(cast(void*) block + info.deltas[ system.m_optional_components[iii]]))[offset .. entities_count]; void*) block + info.deltas[system.m_optional_components[iii]]))[offset
.. entities_count];
} }
} }
} }
bool checkOnUpdateParams()() /*bool checkOnUpdateParams()()
{ {
bool ret = false; bool ret = false;
foreach (func; __traits(getOverloads, Sys, "onUpdate")) foreach (func; __traits(getOverloads, Sys, "onUpdate"))
@ -703,9 +738,29 @@ export struct EntityManager
} }
} }
return ret; return ret;
}*/
int getOnUpdateOverload()()
{
int ret = -1;
foreach (i, func; __traits(getOverloads, Sys, "onUpdate"))
{
if ((Parameters!(func)).length == 1 && is(Parameters!(func)[0] == Sys.EntitiesData))
{
ret = i;
break;
}
}
return ret;
} }
static if (hasMember!(Sys, "onUpdate") && checkOnUpdateParams()) static if (hasMember!(Sys, "onUpdate"))
enum OnUpdateOverloadNum = getOnUpdateOverload();
else
enum OnUpdateOverloadNum = -1;
//enum HasOnUpdate = (hasMember!(Sys, "onUpdate") && checkOnUpdateParams());
static if (OnUpdateOverloadNum != -1)
{ {
static void callUpdate(ref CallData data) static void callUpdate(ref CallData data)
{ {
@ -745,7 +800,9 @@ export struct EntityManager
fillInputData(input_data, info, block, offset, entities_count, system); fillInputData(input_data, info, block, offset, entities_count, system);
s.onUpdate(input_data); //s.onUpdate(input_data);
(cast(typeof(&__traits(getOverloads, s,
"onUpdate")[OnUpdateOverloadNum])) data.update_delegate)(input_data);
block = block.next_block; block = block.next_block;
offset = 0; offset = 0;
@ -767,9 +824,12 @@ export struct EntityManager
static RetType callFunc(void* system_pointer) static RetType callFunc(void* system_pointer)
{ {
Sys* s = cast(Sys*) system_pointer; Sys* s = cast(Sys*) system_pointer;
static if(is(RetTyp == void))mixin("s."~func_name~"()"); static if (is(RetTyp == void))
else return mixin("s."~func_name~"()"); mixin("s." ~ func_name ~ "()");
else
return mixin("s." ~ func_name ~ "()");
} }
*member = cast(void*)&callFunc; *member = cast(void*)&callFunc;
break; break;
} }
@ -783,16 +843,22 @@ export struct EntityManager
{ {
foreach (func; __traits(getOverloads, Sys, func_name)) foreach (func; __traits(getOverloads, Sys, func_name))
{ {
static if ((Parameters!(func)).length == 1 && is(Parameters!(func)[0] == Sys.EntitiesData) && is(ReturnType!(func) == RetType)) static if ((Parameters!(func)).length == 1
&& is(Parameters!(func)[0] == Sys.EntitiesData)
&& is(ReturnType!(func) == RetType))
{ {
static RetType callFunc(ref ListenerCallData data) static RetType callFunc(ref ListenerCallData data)
{ {
Sys* s = cast(Sys*) data.system.m_system_pointer; Sys* s = cast(Sys*) data.system.m_system_pointer;
Sys.EntitiesData input_data; Sys.EntitiesData input_data;
fillInputData(input_data, data.block.type_info, data.block, data.begin, data.end, data.system); fillInputData(input_data, data.block.type_info,
static if(is(RetTyp == void))mixin("s."~func_name~"(input_data)"); data.block, data.begin, data.end, data.system);
else return mixin("s."~func_name~"(input_data)"); static if (is(RetTyp == void))
mixin("s." ~ func_name ~ "(input_data)");
else
return mixin("s." ~ func_name ~ "(input_data)");
} }
*member = cast(void*)&callFunc; *member = cast(void*)&callFunc;
break; break;
} }
@ -815,7 +881,15 @@ export struct EntityManager
system.m_priority = priority; system.m_priority = priority;
//(cast(Sys*) system.m_system_pointer).__ecsInitialize(); //(cast(Sys*) system.m_system_pointer).__ecsInitialize();
//system.jobs = (cast(Sys*) system.m_system_pointer)._ecs_jobs; //system.jobs = (cast(Sys*) system.m_system_pointer)._ecs_jobs;
system.jobs = Mallocator.makeArray!(Job)((cast(Sys*) system.m_system_pointer).__ecs_jobs_count); system.jobs = Mallocator.makeArray!(Job)((cast(Sys*) system.m_system_pointer)
.__ecs_jobs_count);
static if (OnUpdateOverloadNum != -1)
{
Sys* s = cast(Sys*) system.m_system_pointer;
system.m_update_delegate = cast(void delegate())&__traits(getOverloads,
s, "onUpdate")[OnUpdateOverloadNum];
}
genCompList(system, components_map); genCompList(system, components_map);
@ -967,6 +1041,28 @@ export struct EntityManager
} }
} }
export void callEntitiesFunction(Sys, T)(T func)
{
Sys* s;
static assert(isDelegate!func, "Function must be delegate.");
static assert(__traits(hasMember, Sys, "EntitiesData"),
"Can't call function with system which hasn't EntitesData structure.");
static assert(__traits(hasMember, Sys, "onUpdate"),
"Can't call function with system which hasn't onUpdate function callback.");
static assert(is(T == typeof(&s.onUpdate)), "Function must match system update function.");
static assert(__traits(hasMember, Sys, "system_id"), "Sys must be system type.");
System* system = getSystem(Sys.system_id);
assert(system != null,
"System must be registered in EntityManager before any funcion can be called.");
foreach (info; system.m_any_system_caller.infos)
{
CallData data = CallData(system.id, system, info, cast(void delegate()) func);
data.update();
}
}
/************************************************************************************************************************ /************************************************************************************************************************
*Same as "void update(int pass = 0)" but use pass name instead of id. *Same as "void update(int pass = 0)" but use pass name instead of id.
*/ */
@ -991,7 +1087,7 @@ export struct EntityManager
{ {
foreach (info; caller.infos) foreach (info; caller.infos)
{ {
CallData data = CallData(caller.system_id, sys, info); CallData data = CallData(caller.system_id, sys, info, sys.m_update_delegate);
data.update(); data.update();
} }
} }
@ -1085,7 +1181,8 @@ export struct EntityManager
if (full_blocks_count * info.max_entities + entities_count + ( if (full_blocks_count * info.max_entities + entities_count + (
first_block.entities_count - first_elem) >= entities_per_job) first_block.entities_count - first_elem) >= entities_per_job)
{ {
CallData data = CallData(caller.system_id, sys, info, first_block, CallData data = CallData(caller.system_id, sys,
info, sys.m_update_delegate, first_block,
cast(ushort)(full_blocks_count + 1), cast(ushort)(full_blocks_count + 1),
cast(ushort) first_elem, 0); cast(ushort) first_elem, 0);
tmp_datas.add(data); tmp_datas.add(data);
@ -1098,8 +1195,9 @@ export struct EntityManager
entities_count += full_blocks_count * info.max_entities + ( entities_count += full_blocks_count * info.max_entities + (
first_block.entities_count - first_elem); // - first_elem; first_block.entities_count - first_elem); // - first_elem;
uint last_elem = entities_per_job - entities_count; // + first_elem - 1; uint last_elem = entities_per_job - entities_count; // + first_elem - 1;
CallData data = CallData(caller.system_id, sys, info, CallData data = CallData(caller.system_id, sys,
first_block, cast(ushort)(full_blocks_count + 2), info, sys.m_update_delegate, first_block,
cast(ushort)(full_blocks_count + 2),
cast(ushort) first_elem, cast(ushort) last_elem); cast(ushort) first_elem, cast(ushort) last_elem);
tmp_datas.add(data); tmp_datas.add(data);
first_elem = last_elem; first_elem = last_elem;
@ -1111,7 +1209,8 @@ export struct EntityManager
else else
{ {
uint last_elem = entities_per_job - entities_count; uint last_elem = entities_per_job - entities_count;
CallData data = CallData(caller.system_id, sys, info, first_block, 1, CallData data = CallData(caller.system_id, sys,
info, sys.m_update_delegate, first_block, 1,
cast(ushort) first_elem, cast(ushort)(first_elem + last_elem)); cast(ushort) first_elem, cast(ushort)(first_elem + last_elem));
tmp_datas.add(data); tmp_datas.add(data);
first_elem += last_elem; first_elem += last_elem;
@ -1123,7 +1222,7 @@ export struct EntityManager
} }
else else
{ {
CallData data = CallData(caller.system_id, sys, info, CallData data = CallData(caller.system_id, sys, info, sys.m_update_delegate,
first_block, cast(ushort) blocks_count, cast(ushort) first_elem); first_block, cast(ushort) blocks_count, cast(ushort) first_elem);
tmp_datas.add(data); tmp_datas.add(data);
entities_count += (blocks_count - 1) * info.max_entities entities_count += (blocks_count - 1) * info.max_entities
@ -1138,7 +1237,8 @@ export struct EntityManager
} }
} }
export void setMultithreadingCallbacks(void delegate(JobGroup) dispatch_callback, uint delegate() get_id_callback) export void setMultithreadingCallbacks(void delegate(JobGroup) dispatch_callback,
uint delegate() get_id_callback)
{ {
m_dispatch_jobs = cast(void delegate(JobGroup jobs) nothrow @nogc) dispatch_callback; m_dispatch_jobs = cast(void delegate(JobGroup jobs) nothrow @nogc) dispatch_callback;
m_thread_id_func = cast(uint delegate() nothrow @nogc) get_id_callback; m_thread_id_func = cast(uint delegate() nothrow @nogc) get_id_callback;
@ -1149,6 +1249,23 @@ export struct EntityManager
m_dispatch_jobs = func; m_dispatch_jobs = func;
}*/ }*/
/************************************************************************************************************************
*Return size of single page (block). Every entity data block has size of page.
*/
uint pageSize()
{
return m_page_size;
}
/************************************************************************************************************************
*Return number of pages in single block allocation. Library allocate defined number of pages at once and assign it's
*for entities.
*/
uint pagesInBlock()
{
return m_pages_in_block;
}
static void alignNum(ref ushort num, ushort alignment) nothrow @nogc pure static void alignNum(ref ushort num, ushort alignment) nothrow @nogc pure
{ {
num = cast(ushort)((num + alignment - 1) & (-cast(int) alignment)); //num += alignment - (num & (alignment - 1)); num = cast(ushort)((num + alignment - 1) & (-cast(int) alignment)); //num += alignment - (num & (alignment - 1));
@ -1188,7 +1305,8 @@ export struct EntityManager
//fill components with default data //fill components with default data
foreach (comp; info.components) foreach (comp; info.components)
{ {
memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp], components[comp].init_data.ptr, components[comp].size); memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp],
components[comp].init_data.ptr, components[comp].size);
/*temp.entity_data[info.tmpl_deltas[comp] .. info.tmpl_deltas[comp] + components[comp].size] /*temp.entity_data[info.tmpl_deltas[comp] .. info.tmpl_deltas[comp] + components[comp].size]
= components[comp].init_data;*/ = components[comp].init_data;*/
} }
@ -1199,7 +1317,8 @@ export struct EntityManager
foreach (comp; info.components) foreach (comp; info.components)
{ {
memcpy(cast(void*) temp.entity_data + info.tmpl_deltas[comp], memcpy(cast(void*) temp.entity_data + info.tmpl_deltas[comp],
cast(void*) block + info.deltas[comp] + components[comp].size * index, components[comp].size); cast(void*) block + info.deltas[comp] + components[comp].size * index,
components[comp].size);
} }
} }
@ -1244,7 +1363,8 @@ export struct EntityManager
//fill components with default data //fill components with default data
foreach (comp; info.components) foreach (comp; info.components)
{ {
memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp], components[comp].init_data.ptr, components[comp].size); memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp],
components[comp].init_data.ptr, components[comp].size);
/*temp.entity_data[info.tmpl_deltas[comp] .. info.tmpl_deltas[comp] + components[comp].size] /*temp.entity_data[info.tmpl_deltas[comp] .. info.tmpl_deltas[comp] + components[comp].size]
= components[comp].init_data;*/ = components[comp].init_data;*/
} }
@ -1287,7 +1407,7 @@ export struct EntityManager
alignNum(info.size, info.alignment); alignNum(info.size, info.alignment);
uint block_memory = cast(uint)( uint block_memory = cast(uint)(
page_size - EntitiesBlock.sizeof - (info.size - components_size)); m_page_size - EntitiesBlock.sizeof - (info.size - components_size));
//uint entity_comps_size = EntityID.sizeof; //uint entity_comps_size = EntityID.sizeof;
uint mem_begin = EntitiesBlock.sizeof; uint mem_begin = EntitiesBlock.sizeof;
@ -1555,7 +1675,8 @@ export struct EntityManager
new_info = new_info.getNewInfoRemove(id); new_info = new_info.getNewInfoRemove(id);
} }
if(new_info == info)return; if (new_info == info)
return;
//EntityInfo* new_info = getEntityInfo(ids[0 .. j]); //EntityInfo* new_info = getEntityInfo(ids[0 .. j]);
@ -1674,7 +1795,8 @@ export struct EntityManager
new_info = new_info.getNewInfoAdd(id); new_info = new_info.getNewInfoAdd(id);
} }
if(new_info == info)return; if (new_info == info)
return;
//EntityInfo* new_info = getEntityInfo(ids[0 .. len]); //EntityInfo* new_info = getEntityInfo(ids[0 .. len]);
@ -1835,12 +1957,13 @@ export struct EntityManager
foreach (i, comp; info.components) foreach (i, comp; info.components)
{ {
memcpy(cast(void*) new_block + info.deltas[comp] + components[comp].size * new_id, memcpy(cast(void*) new_block + info.deltas[comp] + components[comp].size * new_id,
cast(void*) block + info.deltas[comp] + components[comp].size * index, components[comp].size); cast(void*) block + info.deltas[comp] + components[comp].size * index,
components[comp].size);
if (components[comp].create_callback) if (components[comp].create_callback)
{ {
components[comp].create_callback( components[comp].create_callback(cast(
cast(void*) block + info.deltas[comp] + new_id * components[comp].size); void*) block + info.deltas[comp] + new_id * components[comp].size);
} }
} }
@ -2072,7 +2195,7 @@ export struct EntityManager
*/ */
export EntitiesBlock* getMetaData(const void* pointer) nothrow @nogc export EntitiesBlock* getMetaData(const void* pointer) nothrow @nogc
{ {
return cast(EntitiesBlock*)(cast(size_t) pointer & (~cast(size_t)(page_size - 1))); return cast(EntitiesBlock*)(cast(size_t) pointer & (~cast(size_t)(m_page_size - 1)));
} }
private void changeEntities() private void changeEntities()
@ -2268,8 +2391,9 @@ export struct EntityManager
foreach (caller; events[i].callers) foreach (caller; events[i].callers)
{ {
call_data.system_pointer = caller.system.m_system_pointer; call_data.system_pointer = caller.system.m_system_pointer;
(cast(void function(ref EventCallData) nothrow @nogc) caller (cast(void function(
.callback)(call_data); ref EventCallData) nothrow @nogc) caller.callback)(
call_data);
} }
} }
event_pointer += events[i].size; event_pointer += events[i].size;
@ -2448,8 +2572,7 @@ export struct EntityManager
caller.dependencies = Mallocator.makeArray(exclusion[0 .. index]); caller.dependencies = Mallocator.makeArray(exclusion[0 .. index]);
/*caller.dependencies = Mallocator.makeArray!(SystemCaller*)(index); /*caller.dependencies = Mallocator.makeArray!(SystemCaller*)(index);
caller.dependencies[0..$] = exclusion[0 .. index];*/ caller.dependencies[0..$] = exclusion[0 .. index];*/
caller.job_group.dependencies = Mallocator.makeArray!( caller.job_group.dependencies = Mallocator.makeArray!(JobGroup*)(index);
JobGroup*)(index);
foreach (j, dep; caller.dependencies) foreach (j, dep; caller.dependencies)
{ {
@ -2467,7 +2590,9 @@ export struct EntityManager
*/ */
struct ComponentInfo struct ComponentInfo
{ {
export ~this() nothrow @nogc {} export ~this() nothrow @nogc
{
}
///Component size ///Component size
ushort size; ushort size;
///Component data alignment ///Component data alignment
@ -2537,16 +2662,19 @@ export struct EntityManager
{ {
if (comp_add_info.length < id) if (comp_add_info.length < id)
{ {
EntityInfo*[] new_infos = Mallocator.makeArray!(EntityInfo*)(instance.components.length); EntityInfo*[] new_infos = Mallocator.makeArray!(EntityInfo*)(
instance.components.length);
if (comp_add_info !is null) if (comp_add_info !is null)
{ {
//new_infos[0 .. comp_add_info.length] = comp_add_info[0 .. $]; //new_infos[0 .. comp_add_info.length] = comp_add_info[0 .. $];
memcpy(new_infos.ptr, comp_add_info.ptr, (EntityInfo*).sizeof * comp_add_info.length); memcpy(new_infos.ptr, comp_add_info.ptr, (EntityInfo*)
.sizeof * comp_add_info.length);
Mallocator.dispose(comp_add_info); Mallocator.dispose(comp_add_info);
} }
comp_add_info = new_infos; comp_add_info = new_infos;
} }
if(comp_add_info[id])return comp_add_info[id]; if (comp_add_info[id])
return comp_add_info[id];
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (components.length + 1)))[0 ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (components.length + 1)))[0
.. components.length + 1]; .. components.length + 1];
@ -2558,14 +2686,16 @@ export struct EntityManager
{ {
ids[len++] = comp; ids[len++] = comp;
} }
else if(id == comp)return &this; else if (id == comp)
return &this;
else else
{ {
ids[len++] = id; ids[len++] = id;
ids[len++] = comp; ids[len++] = comp;
} }
} }
if(id > components[$ - 1])ids[len++] = id; if (id > components[$ - 1])
ids[len++] = id;
assert(len == components.length + 1); assert(len == components.length + 1);
@ -2579,16 +2709,19 @@ export struct EntityManager
{ {
if (comp_rem_info.length < id) if (comp_rem_info.length < id)
{ {
EntityInfo*[] new_infos = Mallocator.makeArray!(EntityInfo*)(instance.components.length); EntityInfo*[] new_infos = Mallocator.makeArray!(EntityInfo*)(
instance.components.length);
if (comp_rem_info !is null) if (comp_rem_info !is null)
{ {
//new_infos[0 .. comp_rem_info.length] = comp_rem_info[0 .. $]; //new_infos[0 .. comp_rem_info.length] = comp_rem_info[0 .. $];
memcpy(new_infos.ptr, comp_rem_info.ptr, (EntityInfo*).sizeof * comp_rem_info.length); memcpy(new_infos.ptr, comp_rem_info.ptr, (EntityInfo*)
.sizeof * comp_rem_info.length);
Mallocator.dispose(comp_rem_info); Mallocator.dispose(comp_rem_info);
} }
comp_rem_info = new_infos; comp_rem_info = new_infos;
} }
if(comp_rem_info[id])return comp_rem_info[id]; if (comp_rem_info[id])
return comp_rem_info[id];
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (components.length - 1)))[0 ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (components.length - 1)))[0
.. components.length - 1]; .. components.length - 1];
@ -2601,7 +2734,8 @@ export struct EntityManager
ids[len++] = comp; ids[len++] = comp;
} }
} }
if(len == components.length)return &this; if (len == components.length)
return &this;
assert(len == components.length - 1); assert(len == components.length - 1);
@ -2613,13 +2747,20 @@ export struct EntityManager
export ~this() @nogc nothrow export ~this() @nogc nothrow
{ {
if(components)Mallocator.dispose(components); if (components)
if(deltas)Mallocator.dispose(deltas); Mallocator.dispose(components);
if(tmpl_deltas)Mallocator.dispose(tmpl_deltas); if (deltas)
if(systems)Mallocator.dispose(systems); Mallocator.dispose(deltas);
if(add_listeners)Mallocator.dispose(add_listeners); if (tmpl_deltas)
if(remove_listeners)Mallocator.dispose(remove_listeners); Mallocator.dispose(tmpl_deltas);
if(change_listeners)Mallocator.dispose(change_listeners); if (systems)
Mallocator.dispose(systems);
if (add_listeners)
Mallocator.dispose(add_listeners);
if (remove_listeners)
Mallocator.dispose(remove_listeners);
if (change_listeners)
Mallocator.dispose(change_listeners);
} }
///entity components ///entity components
@ -2722,6 +2863,8 @@ export struct EntityManager
System* system; System* system;
///poiner to Entity type info ///poiner to Entity type info
EntityManager.EntityInfo* info; EntityManager.EntityInfo* info;
///delegate function to call (by default it's delegate to onUpdate call)
void delegate() update_delegate;
///pointer to first block into process (if 0 then first block will be used) ///pointer to first block into process (if 0 then first block will be used)
EntitiesBlock* first_block; EntitiesBlock* first_block;
@ -2845,9 +2988,9 @@ export struct EntityManager
alias SytemFuncType = void function(ref EntityManager.CallData data) nothrow @nogc; alias SytemFuncType = void function(ref EntityManager.CallData data) nothrow @nogc;
///Single page size. Must be power of two. ///Single page size. Must be power of two.
enum page_size = 32768; //4096; int m_page_size = 32768; //32768; //4096;
///Number of pages in block. ///Number of pages in block.
enum pages_in_block = 128; int m_pages_in_block = 128;
IDManager id_manager; IDManager id_manager;
BlockAllocator allocator; BlockAllocator allocator;

View file

@ -120,10 +120,13 @@ package:
ushort[] m_read_only_components; ushort[] m_read_only_components;
ushort[] m_modified_components; ushort[] m_modified_components;
EntityManager.SystemCaller* m_any_system_caller;
EventCaller[] m_event_callers; EventCaller[] m_event_callers;
//void function(ref EntityManager.CallData data) m_update; //void function(ref EntityManager.CallData data) m_update;
void* m_update; ///workaroud for DMD bug with upper line void* m_update; ///workaroud for DMD bug with upper line
void delegate() m_update_delegate;
//void function(void* system_pointer) m_enable; //void function(void* system_pointer) m_enable;
//void function(void* system_pointer) m_disable; //void function(void* system_pointer) m_disable;

View file

@ -501,6 +501,20 @@ struct TestSystem2
} }
struct ExternalUpdateCallTest
{
int print_count = 3;
void update(TestSystem2.EntitiesData data)
{
if(print_count > 0)
{
print_count--;
printf("ExternalUpdateCallTest %u %u\n", data.test[0].gg, cast(uint)data.length);
}
}
}
extern(C) int main() extern(C) int main()
{ {
@ -660,8 +674,6 @@ extern(C) int main()
gEM.registerSystem!TestSystem2(0); gEM.registerSystem!TestSystem2(0);
gEM.endRegister(); gEM.endRegister();
System* sys = EntityManager.instance.getSystem(TestSystem2.system_id);
//gEM.generateDependencies(); //gEM.generateDependencies();
//assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+24)) == EntityID(1,1)); //assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+24)) == EntityID(1,1));
@ -799,6 +811,12 @@ extern(C) int main()
gEM.commit(); gEM.commit();
System* sys = EntityManager.instance.getSystem(TestSystem2.system_id);
ExternalUpdateCallTest external_update_test;
EntityManager.instance.callEntitiesFunction!TestSystem2(&external_update_test.update);
printf("pre end\n"); printf("pre end\n");
writeEntityComponents(gEM.getEntity(entity)); writeEntityComponents(gEM.getEntity(entity));