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 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)
{
//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)
{
@ -52,6 +56,9 @@ export struct EntityManager
}
}
/************************************************************************************************************************
*Deinitialize and destroy ECS. This function release whole memory.
*/
export static void destroy()
{
if (instance is null)
@ -65,16 +72,25 @@ export struct EntityManager
if (system.m_destroy)
(cast(void function(void*)) system.m_destroy)(system.m_system_pointer);
if(system.jobs)Mallocator.dispose(system.jobs);
if(system.m_read_only_components)Mallocator.dispose(system.m_read_only_components);
if(system.m_modified_components)Mallocator.dispose(system.m_modified_components);
if(system.m_components)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.jobs)
Mallocator.dispose(system.jobs);
if (system.m_read_only_components)
Mallocator.dispose(system.m_read_only_components);
if (system.m_modified_components)
Mallocator.dispose(system.m_modified_components);
if (system.m_components)
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)
@ -92,17 +108,20 @@ export struct EntityManager
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)
{
if(info.callers)Mallocator.dispose(info.callers);
if (info.callers)
Mallocator.dispose(info.callers);
}
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;
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;
@ -175,6 +195,7 @@ export struct EntityManager
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);
}
@ -237,7 +258,8 @@ export struct EntityManager
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);
@ -252,17 +274,20 @@ export struct EntityManager
/************************************************************************************************************************
*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)
threads_count = 1;
threads = Mallocator.makeArray!ThreadData(threads_count);
//foreach(ref thread;threads)thread = ThreadData().init;
m_page_size = page_size;
m_pages_in_block = block_pages_count;
id_manager.initialize();
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;
entity_block_alloc_mutex = Mallocator.make!Mutex;
@ -276,7 +301,8 @@ export struct EntityManager
id_manager.deinitialize();
event_manager.destroy();
if(threads)Mallocator.dispose(threads);
if (threads)
Mallocator.dispose(threads);
if (entity_block_alloc_mutex)
{
entity_block_alloc_mutex.destroy();
@ -378,22 +404,22 @@ export struct EntityManager
void setEventCallers(Sys)(ref System system)
{
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;
foreach (j, func; __traits(getOverloads, Sys, "handleEvent"))
{
alias Params = Parameters!(__traits(getOverloads,
Sys, "handleEvent")[j]);
alias Params = Parameters!(__traits(getOverloads, Sys, "handleEvent")[j]);
static if (Params.length == 2 && is(Params[0] == Entity*))
{
alias EventParamType = Params[1];
enum EventName = Unqual!(EventParamType).stringof;
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(
void*)&callEventHandler!(EventParamType);
callers[i].callback = cast(void*)&callEventHandler!(EventParamType);
callers[i].id = EventParamType.event_id;
i++;
}
@ -516,9 +542,11 @@ export struct EntityManager
foreach (member; __traits(allMembers, Sys.EntitiesData))
{
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;
}
@ -536,7 +564,8 @@ export struct EntityManager
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")
{
@ -614,8 +643,10 @@ export struct EntityManager
static assert(0, "EntitiesData can't have any function!");
else static if (member == "length")
{
static assert(isIntegral!(MemberType), "EntitiesData 'length' member must be integral type.");
static assert(MemberType.sizeof > 1, "EntitiesData 'length' member can't be byte or ubyte.");
static assert(isIntegral!(MemberType),
"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)))
static assert(0, "EntitiesData members should be arrays of elements!");
@ -664,7 +695,8 @@ export struct EntityManager
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"))
@ -674,24 +706,27 @@ export struct EntityManager
static foreach (iii, comp_info; components_info.req)
{
__traits(getMember, input_data, comp_info.name) =
(cast(ForeachType!(typeof(__traits(getMember,
Sys.EntitiesData, comp_info.name)))*)(cast(void*) block + info.deltas[ system.m_components[iii]]))[offset .. entities_count];
__traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
Sys.EntitiesData, comp_info.name)))*)(
cast(void*) block + info.deltas[system.m_components[iii]]))[offset
.. entities_count];
}
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) =
(cast(ForeachType!(typeof(__traits(getMember,
Sys.EntitiesData, comp_info.name)))*)(cast(void*) block + info.deltas[ system.m_optional_components[iii]]))[offset .. entities_count];
__traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
Sys.EntitiesData, comp_info.name)))*)(cast(
void*) block + info.deltas[system.m_optional_components[iii]]))[offset
.. entities_count];
}
}
}
bool checkOnUpdateParams()()
/*bool checkOnUpdateParams()()
{
bool ret = false;
foreach (func; __traits(getOverloads, Sys, "onUpdate"))
@ -703,9 +738,29 @@ export struct EntityManager
}
}
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)
{
@ -745,7 +800,9 @@ export struct EntityManager
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;
offset = 0;
@ -767,9 +824,12 @@ export struct EntityManager
static RetType callFunc(void* system_pointer)
{
Sys* s = cast(Sys*) system_pointer;
static if(is(RetTyp == void))mixin("s."~func_name~"()");
else return mixin("s."~func_name~"()");
static if (is(RetTyp == void))
mixin("s." ~ func_name ~ "()");
else
return mixin("s." ~ func_name ~ "()");
}
*member = cast(void*)&callFunc;
break;
}
@ -783,16 +843,22 @@ export struct EntityManager
{
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)
{
Sys* s = cast(Sys*) data.system.m_system_pointer;
Sys.EntitiesData input_data;
fillInputData(input_data, data.block.type_info, data.block, data.begin, data.end, data.system);
static if(is(RetTyp == void))mixin("s."~func_name~"(input_data)");
else return mixin("s."~func_name~"(input_data)");
fillInputData(input_data, data.block.type_info,
data.block, data.begin, data.end, data.system);
static if (is(RetTyp == void))
mixin("s." ~ func_name ~ "(input_data)");
else
return mixin("s." ~ func_name ~ "(input_data)");
}
*member = cast(void*)&callFunc;
break;
}
@ -815,7 +881,15 @@ export struct EntityManager
system.m_priority = priority;
//(cast(Sys*) system.m_system_pointer).__ecsInitialize();
//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);
@ -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.
*/
@ -991,7 +1087,7 @@ export struct EntityManager
{
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();
}
}
@ -1085,7 +1181,8 @@ export struct EntityManager
if (full_blocks_count * info.max_entities + entities_count + (
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) first_elem, 0);
tmp_datas.add(data);
@ -1098,8 +1195,9 @@ export struct EntityManager
entities_count += full_blocks_count * info.max_entities + (
first_block.entities_count - first_elem); // - first_elem;
uint last_elem = entities_per_job - entities_count; // + first_elem - 1;
CallData data = CallData(caller.system_id, sys, info,
first_block, cast(ushort)(full_blocks_count + 2),
CallData data = CallData(caller.system_id, sys,
info, sys.m_update_delegate, first_block,
cast(ushort)(full_blocks_count + 2),
cast(ushort) first_elem, cast(ushort) last_elem);
tmp_datas.add(data);
first_elem = last_elem;
@ -1111,7 +1209,8 @@ export struct EntityManager
else
{
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));
tmp_datas.add(data);
first_elem += last_elem;
@ -1123,7 +1222,7 @@ export struct EntityManager
}
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);
tmp_datas.add(data);
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_thread_id_func = cast(uint delegate() nothrow @nogc) get_id_callback;
@ -1149,6 +1249,23 @@ export struct EntityManager
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
{
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
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]
= components[comp].init_data;*/
}
@ -1199,7 +1317,8 @@ export struct EntityManager
foreach (comp; info.components)
{
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
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]
= components[comp].init_data;*/
}
@ -1287,7 +1407,7 @@ export struct EntityManager
alignNum(info.size, info.alignment);
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 mem_begin = EntitiesBlock.sizeof;
@ -1555,7 +1675,8 @@ export struct EntityManager
new_info = new_info.getNewInfoRemove(id);
}
if(new_info == info)return;
if (new_info == info)
return;
//EntityInfo* new_info = getEntityInfo(ids[0 .. j]);
@ -1674,7 +1795,8 @@ export struct EntityManager
new_info = new_info.getNewInfoAdd(id);
}
if(new_info == info)return;
if (new_info == info)
return;
//EntityInfo* new_info = getEntityInfo(ids[0 .. len]);
@ -1835,12 +1957,13 @@ export struct EntityManager
foreach (i, comp; info.components)
{
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)
{
components[comp].create_callback(
cast(void*) block + info.deltas[comp] + new_id * components[comp].size);
components[comp].create_callback(cast(
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
{
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()
@ -2268,8 +2391,9 @@ export struct EntityManager
foreach (caller; events[i].callers)
{
call_data.system_pointer = caller.system.m_system_pointer;
(cast(void function(ref EventCallData) nothrow @nogc) caller
.callback)(call_data);
(cast(void function(
ref EventCallData) nothrow @nogc) caller.callback)(
call_data);
}
}
event_pointer += events[i].size;
@ -2448,8 +2572,7 @@ export struct EntityManager
caller.dependencies = Mallocator.makeArray(exclusion[0 .. index]);
/*caller.dependencies = Mallocator.makeArray!(SystemCaller*)(index);
caller.dependencies[0..$] = exclusion[0 .. index];*/
caller.job_group.dependencies = Mallocator.makeArray!(
JobGroup*)(index);
caller.job_group.dependencies = Mallocator.makeArray!(JobGroup*)(index);
foreach (j, dep; caller.dependencies)
{
@ -2467,7 +2590,9 @@ export struct EntityManager
*/
struct ComponentInfo
{
export ~this() nothrow @nogc {}
export ~this() nothrow @nogc
{
}
///Component size
ushort size;
///Component data alignment
@ -2537,16 +2662,19 @@ export struct EntityManager
{
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)
{
//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);
}
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
.. components.length + 1];
@ -2558,14 +2686,16 @@ export struct EntityManager
{
ids[len++] = comp;
}
else if(id == comp)return &this;
else if (id == comp)
return &this;
else
{
ids[len++] = id;
ids[len++] = comp;
}
}
if(id > components[$ - 1])ids[len++] = id;
if (id > components[$ - 1])
ids[len++] = id;
assert(len == components.length + 1);
@ -2579,16 +2709,19 @@ export struct EntityManager
{
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)
{
//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);
}
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
.. components.length - 1];
@ -2601,7 +2734,8 @@ export struct EntityManager
ids[len++] = comp;
}
}
if(len == components.length)return &this;
if (len == components.length)
return &this;
assert(len == components.length - 1);
@ -2613,13 +2747,20 @@ export struct EntityManager
export ~this() @nogc nothrow
{
if(components)Mallocator.dispose(components);
if(deltas)Mallocator.dispose(deltas);
if(tmpl_deltas)Mallocator.dispose(tmpl_deltas);
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);
if (components)
Mallocator.dispose(components);
if (deltas)
Mallocator.dispose(deltas);
if (tmpl_deltas)
Mallocator.dispose(tmpl_deltas);
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
@ -2722,6 +2863,8 @@ export struct EntityManager
System* system;
///poiner to Entity type 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)
EntitiesBlock* first_block;
@ -2845,9 +2988,9 @@ export struct EntityManager
alias SytemFuncType = void function(ref EntityManager.CallData data) nothrow @nogc;
///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.
enum pages_in_block = 128;
int m_pages_in_block = 128;
IDManager id_manager;
BlockAllocator allocator;

View file

@ -120,10 +120,13 @@ package:
ushort[] m_read_only_components;
ushort[] m_modified_components;
EntityManager.SystemCaller* m_any_system_caller;
EventCaller[] m_event_callers;
//void function(ref EntityManager.CallData data) m_update;
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_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()
{
@ -660,8 +674,6 @@ extern(C) int main()
gEM.registerSystem!TestSystem2(0);
gEM.endRegister();
System* sys = EntityManager.instance.getSystem(TestSystem2.system_id);
//gEM.generateDependencies();
//assert(*(cast(EntityID*)(cast(void*)tmpl.info.first_block+24)) == EntityID(1,1));
@ -799,6 +811,12 @@ extern(C) int main()
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");
writeEntityComponents(gEM.getEntity(entity));