-Assert if callEntitiesFunction is called for system which is not alive
-cleanup and formatting
This commit is contained in:
Mergul 2022-11-12 12:10:09 +01:00
parent 5f4ba90b3e
commit c2ba4c632a
2 changed files with 121 additions and 116 deletions

View file

@ -63,7 +63,7 @@
], ],
"dflags": [ "dflags": [
"-unittest", "-unittest",
"-cov" "-cov=ctfe"
] ]
}, },
{ {

View file

@ -69,11 +69,10 @@ export struct EntityManager
Initialize ECS. Initialize ECS.
*/ */
export static void initialize(uint threads_count = 1, uint page_size = 32768, export static void initialize(uint threads_count = 1, uint page_size = 32768,
uint block_pages_count = 128) uint block_pages_count = 128)
{ {
if (gEntityManager is null) if (gEntityManager is null)
{ {
//gEntityManager = Mallocator.make!EntityManager(threads_count);
gEntityManager = Mallocator.make!EntityManager(threads_count, page_size, block_pages_count); gEntityManager = Mallocator.make!EntityManager(threads_count, page_size, block_pages_count);
with (gEntityManager) with (gEntityManager)
@ -183,7 +182,7 @@ export struct EntityManager
if (system.m_update is null) if (system.m_update is null)
{ {
if (system.m_add_entity || system.m_remove_entity if (system.m_add_entity || system.m_remove_entity
|| system.m_change_entity || system.m_event_callers.length) || system.m_change_entity || system.m_event_callers.length)
{ {
foreach (info; &entities_infos.byValue) foreach (info; &entities_infos.byValue)
{ {
@ -281,7 +280,7 @@ export struct EntityManager
foreach (ref event; events) foreach (ref event; events)
{ {
qsort(event.callers.ptr, event.callers.length, qsort(event.callers.ptr, event.callers.length,
EventCaller.sizeof, &comapreEventCaller); EventCaller.sizeof, &comapreEventCaller);
} }
//qsort(event_callers.ptr, event_callers.length, EventInfo.sizeof, &compareUShorts); //qsort(event_callers.ptr, event_callers.length, EventInfo.sizeof, &compareUShorts);
@ -334,17 +333,19 @@ export struct EntityManager
allocator.freeMemory(); allocator.freeMemory();
} }
/************************************************************************************************************************ /************************************************************************************************************************
Unregister given system form EntityManager. Unregister given system form EntityManager.
*/ */
void unregisterSystem(Sys)() void unregisterSystem(Sys)()
{ {
assert(register_state, "unregisterSystem must be called between beginRegister() and endRegister()."); assert(register_state, "unregisterSystem must be called between beginRegister() and endRegister().");
ushort system_id = becsID!Sys; ushort system_id = becsID!Sys;
System* system = getSystem(system_id); System* system = getSystem(system_id);
assert(system, "System was not registered"); assert(system, "System was not registered");
assert(system.isAlive, "System already unregistered"); assert(system.isAlive, "System already unregistered");
system.destroy(); system.destroy();
*system = System.init; *system = System.init;
} }
@ -376,7 +377,7 @@ export struct EntityManager
//alias STC = ParameterStorageClass; //alias STC = ParameterStorageClass;
assert(register_state, assert(register_state,
"registerSystem must be called between beginRegister() and endRegister()."); "registerSystem must be called between beginRegister() and endRegister().");
version (D_BetterC) version (D_BetterC)
assert(pass < passes.length, "Update pass doesn't exist."); assert(pass < passes.length, "Update pass doesn't exist.");
else else
@ -426,7 +427,7 @@ export struct EntityManager
// enum EventName = fullyQualifiedName!(Unqual!(EventParamType));//.stringof; // enum EventName = fullyQualifiedName!(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, assert(evt != ushort.max,
"Can't register system \"" ~ SystemName "Can't register system \"" ~ SystemName
~ "\" due to non existing event \"" ~ EventName ~ "\"."); ~ "\" due to non existing event \"" ~ EventName ~ "\".");
callers[i].callback = cast(void*)&callEventHandler!(EventParamType); callers[i].callback = cast(void*)&callEventHandler!(EventParamType);
@ -469,14 +470,14 @@ export struct EntityManager
bool checkExcludedComponentsSomething(Sys)() bool checkExcludedComponentsSomething(Sys)()
{ {
return __traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents))) && allSameType!(string, return __traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents))) && allSameType!(string,
typeof(Sys.ExcludedComponents)) && isExpressions!(Sys.ExcludedComponents); typeof(Sys.ExcludedComponents)) && isExpressions!(Sys.ExcludedComponents);
} }
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" || member == "thread_id" || member == "job_id" if (member == "length" || member == "thread_id" || member == "job_id"
|| is(MemberType == Entity[]) || is(MemberType == const(Entity)[])) || is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
{ {
//continue; //continue;
} }
@ -659,7 +660,7 @@ export struct EntityManager
} }
static void allocateSystemComponents(ComponentsIndices!component_counts components_info)( static void allocateSystemComponents(ComponentsIndices!component_counts components_info)(
ref System system) ref System system)
{ {
size_t req = components_info.req.length; size_t req = components_info.req.length;
size_t opt = components_info.optional.length; size_t opt = components_info.optional.length;
@ -693,14 +694,14 @@ export struct EntityManager
bool checkExcludedComponentsSomething(Sys)() bool checkExcludedComponentsSomething(Sys)()
{ {
return __traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents))) && allSameType!(string, return __traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents))) && allSameType!(string,
typeof(Sys.ExcludedComponents)) && isExpressions!(Sys.ExcludedComponents); typeof(Sys.ExcludedComponents)) && isExpressions!(Sys.ExcludedComponents);
} }
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" || member == "thread_id" || member == "job_id" if (member == "length" || member == "thread_id" || member == "job_id"
|| is(MemberType == Entity[]) || is(MemberType == const(Entity)[])) || is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
{ {
if (is(MemberType == Entity[]) || is(MemberType == const(Entity)[])) if (is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
components_info.entites_array = member; components_info.entites_array = member;
@ -808,23 +809,23 @@ export struct EntityManager
else static if (member == "length") else static if (member == "length")
{ {
static assert(isIntegral!(MemberType), static assert(isIntegral!(MemberType),
"EntitiesData 'length' member must be integral type."); "EntitiesData 'length' member must be integral type.");
static assert(MemberType.sizeof > 1, static assert(MemberType.sizeof > 1,
"EntitiesData 'length' member can't be byte or ubyte."); "EntitiesData 'length' member can't be byte or ubyte.");
} }
else static if (member == "thread_id") else static if (member == "thread_id")
{ {
static assert(isIntegral!(MemberType), static assert(isIntegral!(MemberType),
"EntitiesData 'thread_id' member must be integral type."); "EntitiesData 'thread_id' member must be integral type.");
static assert(MemberType.sizeof > 1, static assert(MemberType.sizeof > 1,
"EntitiesData 'thread_id' member can't be byte or ubyte."); "EntitiesData 'thread_id' member can't be byte or ubyte.");
} }
else static if (member == "job_id") else static if (member == "job_id")
{ {
static assert(isIntegral!(MemberType), static assert(isIntegral!(MemberType),
"EntitiesData 'job_id' member must be integral type."); "EntitiesData 'job_id' member must be integral type.");
static assert(MemberType.sizeof > 1, static assert(MemberType.sizeof > 1,
"EntitiesData 'job_id' member can't be byte or ubyte."); "EntitiesData 'job_id' 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!");
@ -838,7 +839,7 @@ export struct EntityManager
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
version (D_BetterC) version (D_BetterC)
assert(comp != ushort.max, assert(comp != ushort.max,
"Can't register system \"" ~ SystemName "Can't register system \"" ~ SystemName
~ "\" due to non existing component."); ~ "\" due to non existing component.");
else else
assert(comp != ushort.max, "Can't register system \"" ~ SystemName assert(comp != ushort.max, "Can't register system \"" ~ SystemName
@ -850,7 +851,7 @@ export struct EntityManager
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
version (D_BetterC) version (D_BetterC)
assert(comp != ushort.max, assert(comp != ushort.max,
"Can't register system \"" ~ SystemName "Can't register system \"" ~ SystemName
~ "\" due to non existing component."); ~ "\" due to non existing component.");
else else
assert(comp != ushort.max, "Can't register system \"" ~ SystemName assert(comp != ushort.max, "Can't register system \"" ~ SystemName
@ -862,7 +863,7 @@ export struct EntityManager
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
version (D_BetterC) version (D_BetterC)
assert(comp != ushort.max, assert(comp != ushort.max,
"Can't register system \"" ~ SystemName "Can't register system \"" ~ SystemName
~ "\" due to non existing component."); ~ "\" due to non existing component.");
else else
assert(comp != ushort.max, "Can't register system \"" ~ SystemName assert(comp != ushort.max, "Can't register system \"" ~ SystemName
@ -874,7 +875,7 @@ export struct EntityManager
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
version (D_BetterC) version (D_BetterC)
assert(comp != ushort.max, assert(comp != ushort.max,
"Can't register system \"" ~ SystemName "Can't register system \"" ~ SystemName
~ "\" due to non existing component."); ~ "\" due to non existing component.");
else else
assert(comp != ushort.max, "Can't register system \"" ~ SystemName assert(comp != ushort.max, "Can't register system \"" ~ SystemName
@ -886,7 +887,7 @@ export struct EntityManager
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
version (D_BetterC) version (D_BetterC)
assert(comp != ushort.max, assert(comp != ushort.max,
"Can't register system \"" ~ SystemName "Can't register system \"" ~ SystemName
~ "\" due to non existing component."); ~ "\" due to non existing component.");
else else
assert(comp != ushort.max, "Can't register system \"" ~ SystemName assert(comp != ushort.max, "Can't register system \"" ~ SystemName
@ -896,14 +897,14 @@ export struct EntityManager
} }
static void fillInputData(ref Sys.EntitiesData input_data, EntityInfo* info, static void fillInputData(ref Sys.EntitiesData input_data, EntityInfo* info,
EntitiesBlock* block, uint offset, uint entities_count, System* system) EntitiesBlock* block, uint offset, uint entities_count, System* system)
{ {
//enum ComponentsIndices components_info = getComponentsInfo(); //enum ComponentsIndices components_info = getComponentsInfo();
static if (components_info.entites_array) static if (components_info.entites_array)
{ {
__traits(getMember, input_data, components_info.entites_array) = ( __traits(getMember, input_data, components_info.entites_array) = (
cast(Entity*) block.dataBegin())[offset .. entities_count]; cast(Entity*) block.dataBegin())[offset .. entities_count];
} }
static if (hasMember!(Sys.EntitiesData, "length")) static if (hasMember!(Sys.EntitiesData, "length"))
@ -923,8 +924,7 @@ export struct EntityManager
__traits(getMember, input_data, comp_info.name) = ( __traits(getMember, input_data, comp_info.name) = (
cast(typeof( cast(typeof(
(typeof(__traits(getMember, Sys.EntitiesData, comp_info.name))).init[0] (typeof(__traits(getMember, Sys.EntitiesData, comp_info.name))).init[0]
)*) )*)(cast(void*) block + info.deltas[system.m_components[iii]])
(cast(void*) block + info.deltas[system.m_components[iii]])
)[offset .. entities_count]; )[offset .. entities_count];
} }
@ -932,7 +932,7 @@ export struct EntityManager
.. components_info.m_optional_counter]) .. components_info.m_optional_counter])
{ {
if (system.m_optional_components[iii] < info.deltas.length if (system.m_optional_components[iii] < info.deltas.length
&& info.deltas[system.m_optional_components[iii]] != 0) && info.deltas[system.m_optional_components[iii]] != 0)
{ {
__traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember, __traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
Sys.EntitiesData, comp_info.name)))*)(cast( Sys.EntitiesData, comp_info.name)))*)(cast(
@ -1031,7 +1031,7 @@ export struct EntityManager
static if (hasMember!(Sys.EntitiesData, "thread_id")) static if (hasMember!(Sys.EntitiesData, "thread_id"))
{ {
input_data.thread_id = cast( input_data.thread_id = cast(
typeof(input_data.thread_id)) data.thread_id; typeof(input_data.thread_id)) data.thread_id;
} }
static if (hasMember!(Sys.EntitiesData, "job_id")) static if (hasMember!(Sys.EntitiesData, "job_id"))
@ -1042,7 +1042,7 @@ export struct EntityManager
//s.onUpdate(input_data); //s.onUpdate(input_data);
(cast(typeof(&__traits(getOverloads, s, (cast(typeof(&__traits(getOverloads, s,
"onUpdate")[OnUpdateOverloadNum])) data.update_delegate)( "onUpdate")[OnUpdateOverloadNum])) data.update_delegate)(
input_data); input_data);
} }
block = block.next_block; block = block.next_block;
offset = 0; offset = 0;
@ -1112,15 +1112,15 @@ export struct EntityManager
foreach (func; __traits(getOverloads, Sys, func_name)) foreach (func; __traits(getOverloads, Sys, func_name))
{ {
static if ((Parameters!(func)).length == 1 static if ((Parameters!(func)).length == 1
&& is(Parameters!(func)[0] == Sys.EntitiesData) && is(Parameters!(func)[0] == Sys.EntitiesData)
&& is(ReturnType!(func) == RetType)) && 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, fillInputData(input_data, data.block.type_info,
data.block, data.begin, data.end, data.system); data.block, data.begin, data.end, data.system);
static if (is(RetTyp == void)) static if (is(RetTyp == void))
mixin("s." ~ func_name ~ "(input_data)"); mixin("s." ~ func_name ~ "(input_data)");
else else
@ -1141,8 +1141,8 @@ export struct EntityManager
foreach (func; __traits(getOverloads, Sys, func_name)) foreach (func; __traits(getOverloads, Sys, func_name))
{ {
static if ((Parameters!(func)).length == 1 static if ((Parameters!(func)).length == 1
&& is(Parameters!(func)[0] == EntityInfo*) && is(Parameters!(func)[0] == EntityInfo*)
&& is(ReturnType!(func) == RetType)) && is(ReturnType!(func) == RetType))
{ {
static RetType callFunc(void* system_pointer, EntityInfo* info) static RetType callFunc(void* system_pointer, EntityInfo* info)
{ {
@ -1177,14 +1177,16 @@ 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;
static if(__traits(hasMember, Sys ,"__becs_jobs_count"))system.jobs = Mallocator.makeArray!(Job)(Sys.__becs_jobs_count); static if (__traits(hasMember, Sys, "__becs_jobs_count"))
else system.jobs = Mallocator.makeArray!(Job)(32); system.jobs = Mallocator.makeArray!(Job)(Sys.__becs_jobs_count);
else
system.jobs = Mallocator.makeArray!(Job)(32);
static if (OnUpdateOverloadNum != -1) static if (OnUpdateOverloadNum != -1)
{ {
Sys* s = cast(Sys*) system.m_system_pointer; Sys* s = cast(Sys*) system.m_system_pointer;
system.m_update_delegate = cast(void delegate())&__traits(getOverloads, system.m_update_delegate = cast(void delegate())&__traits(getOverloads,
s, "onUpdate")[OnUpdateOverloadNum]; s, "onUpdate")[OnUpdateOverloadNum];
} }
genCompList(system, components_map); genCompList(system, components_map);
@ -1192,10 +1194,10 @@ export struct EntityManager
foreach (iii, comp_info; components_info.readonlyDeps) foreach (iii, comp_info; components_info.readonlyDeps)
{ {
ushort comp = external_dependencies_map.get(cast(const(char)[]) comp_info.type, ushort comp = external_dependencies_map.get(cast(const(char)[]) comp_info.type,
ushort.max); ushort.max);
version (D_BetterC) version (D_BetterC)
assert(comp != ushort.max, assert(comp != ushort.max,
"Can't register system \"" ~ SystemName "Can't register system \"" ~ SystemName
~ "\" due to non existing dependency."); ~ "\" due to non existing dependency.");
else else
assert(comp != ushort.max, "Can't register system \"" ~ SystemName assert(comp != ushort.max, "Can't register system \"" ~ SystemName
@ -1208,7 +1210,7 @@ export struct EntityManager
ushort comp = external_dependencies_map.get(cast(char[]) comp_info.type, ushort.max); ushort comp = external_dependencies_map.get(cast(char[]) comp_info.type, ushort.max);
version (D_BetterC) version (D_BetterC)
assert(comp != ushort.max, assert(comp != ushort.max,
"Can't register system \"" ~ SystemName "Can't register system \"" ~ SystemName
~ "\" due to non existing dependency."); ~ "\" due to non existing dependency.");
else else
assert(comp != ushort.max, "Can't register system \"" ~ SystemName assert(comp != ushort.max, "Can't register system \"" ~ SystemName
@ -1300,8 +1302,8 @@ export struct EntityManager
// } // }
static if (hasMember!(Comp, "onDestroy") && isFunction!(Comp.onDestroy) static if (hasMember!(Comp, "onDestroy") && isFunction!(Comp.onDestroy)
&& is(ReturnType!(Comp.onDestroy) == void) && is(ReturnType!(Comp.onDestroy) == void)
&& Parameters!(Comp.onDestroy).length == 0) && Parameters!(Comp.onDestroy).length == 0)
{ {
static void callDestroy(void* pointer) nothrow @nogc static void callDestroy(void* pointer) nothrow @nogc
{ {
@ -1312,7 +1314,7 @@ export struct EntityManager
} }
static if (hasMember!(Comp, "onCreate") && isFunction!(Comp.onCreate) static if (hasMember!(Comp, "onCreate") && isFunction!(Comp.onCreate)
&& is(ReturnType!(Comp.onCreate) == void) && Parameters!(Comp.onCreate).length == 0) && is(ReturnType!(Comp.onCreate) == void) && Parameters!(Comp.onCreate).length == 0)
{ {
static void callCreate(void* pointer) nothrow @nogc static void callCreate(void* pointer) nothrow @nogc
{ {
@ -1358,7 +1360,7 @@ export struct EntityManager
// } // }
static if (hasMember!(Ev, "onDestroy") && isFunction!(Ev.onDestroy) static if (hasMember!(Ev, "onDestroy") && isFunction!(Ev.onDestroy)
&& is(ReturnType!(Ev.onDestroy) == void) && Parameters!(Ev.onDestroy).length == 0) && is(ReturnType!(Ev.onDestroy) == void) && Parameters!(Ev.onDestroy).length == 0)
{ {
static void callDestroy(void* pointer) static void callDestroy(void* pointer)
{ {
@ -1392,10 +1394,10 @@ export struct EntityManager
Sys* s; Sys* s;
static assert(isDelegate!func, "Function must be delegate."); static assert(isDelegate!func, "Function must be delegate.");
static assert(__traits(hasMember, Sys, "EntitiesData"), static assert(__traits(hasMember, Sys, "EntitiesData"),
"Can't call function with system which hasn't EntitesData structure."); "Can't call function with system which hasn't EntitesData structure.");
///TODO: make possibly to call function to group without system with onUpdate function ///TODO: make possibly to call function to group without system with onUpdate function
static assert(__traits(hasMember, Sys, "onUpdate"), static assert(__traits(hasMember, Sys, "onUpdate"),
"Can't call function with system which hasn't onUpdate function callback."); "Can't call function with system which hasn't onUpdate function callback.");
// static assert(is(SetFunctionAttributes!(T, functionLinkage!(s.onUpdate), // static assert(is(SetFunctionAttributes!(T, functionLinkage!(s.onUpdate),
// functionAttributes!(s.onUpdate)) == typeof(&s.onUpdate)), // functionAttributes!(s.onUpdate)) == typeof(&s.onUpdate)),
// "Function must match system update function."); FIXME: It's lead to crash on android build // "Function must match system update function."); FIXME: It's lead to crash on android build
@ -1403,7 +1405,9 @@ export struct EntityManager
System* system = getSystem(becsID!Sys); System* system = getSystem(becsID!Sys);
assert(system != null, assert(system != null,
"System must be registered in EntityManager before any funcion can be called."); "System must be registered in EntityManager before any funcion can be called.");
assert(system.isAlive(), "System must be alive (registered) in order to call entities function on its entities");
if (!system.m_any_system_caller) if (!system.m_any_system_caller)
return; return;
@ -1445,7 +1449,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); sys.m_update_delegate);
data.update(); data.update();
} }
} }
@ -1467,7 +1471,7 @@ export struct EntityManager
assert(!register_state); assert(!register_state);
assert(pass < passes.length); assert(pass < passes.length);
assert(m_dispatch_jobs, assert(m_dispatch_jobs,
"Can't update with multithreading without JobDispatch function. Please use setJobDispatchFunc()."); "Can't update with multithreading without JobDispatch function. Please use setJobDispatchFunc().");
Vector!CallData tmp_datas; Vector!CallData tmp_datas;
tmp_datas.reserve(8); tmp_datas.reserve(8);
@ -1480,7 +1484,7 @@ export struct EntityManager
void nextJob() void nextJob()
{ {
CallData[] callers = m_call_data_allocator.getCallData( CallData[] callers = m_call_data_allocator.getCallData(
cast(uint) tmp_datas.length); cast(uint) tmp_datas.length);
//callers[0 .. $] = tmp_datas[0 .. $]; //callers[0 .. $] = tmp_datas[0 .. $];
memcpy(callers.ptr, &tmp_datas[0], CallData.sizeof * tmp_datas.length); memcpy(callers.ptr, &tmp_datas[0], CallData.sizeof * tmp_datas.length);
tmp_datas.clear(); tmp_datas.clear();
@ -1535,7 +1539,7 @@ export struct EntityManager
//if this info will fill job //if this info will fill job
if ((blocks_count - 1) * info.max_entities + entities_count if ((blocks_count - 1) * info.max_entities + entities_count
+ info.last_block.entities_count - first_elem >= entities_per_job) + info.last_block.entities_count - first_elem >= entities_per_job)
{ {
int reamaining_entities = (entities_per_job - entities_count - ( int reamaining_entities = (entities_per_job - entities_count - (
first_block.entities_count - first_elem)); first_block.entities_count - first_elem));
@ -1556,9 +1560,9 @@ export struct EntityManager
assert(entities_per_job == full_blocks_count * info.max_entities + entities_count + ( assert(entities_per_job == full_blocks_count * info.max_entities + entities_count + (
first_block.entities_count - first_elem)); first_block.entities_count - first_elem));
CallData data = CallData(caller.system_id, sys, CallData data = CallData(caller.system_id, sys,
info, sys.m_update_delegate, first_block, 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);
first_elem = 0; first_elem = 0;
blocks_count -= full_blocks_count + 1; blocks_count -= full_blocks_count + 1;
@ -1567,14 +1571,14 @@ export struct EntityManager
else else
{ {
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;
assert(last_elem > 0); assert(last_elem > 0);
assert(last_elem <= block.entities_count); assert(last_elem <= block.entities_count);
CallData data = CallData(caller.system_id, sys, CallData data = CallData(caller.system_id, sys,
info, sys.m_update_delegate, first_block, info, sys.m_update_delegate, first_block,
cast(ushort)(full_blocks_count + 2), 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;
blocks_count -= full_blocks_count + 1; blocks_count -= full_blocks_count + 1;
@ -1591,8 +1595,8 @@ export struct EntityManager
uint last_elem = entities_per_job - entities_count; uint last_elem = entities_per_job - entities_count;
assert(last_elem > 0); assert(last_elem > 0);
CallData data = CallData(caller.system_id, sys, CallData data = CallData(caller.system_id, sys,
info, sys.m_update_delegate, first_block, 1, 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;
assert(first_elem <= first_block.entities_count); assert(first_elem <= first_block.entities_count);
@ -1612,7 +1616,7 @@ export struct EntityManager
{ {
//take whole info blocks //take whole info blocks
CallData data = CallData(caller.system_id, sys, info, sys.m_update_delegate, 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
+ info.last_block.entities_count - first_elem; + info.last_block.entities_count - first_elem;
@ -1627,7 +1631,7 @@ export struct EntityManager
} }
export void setMultithreadingCallbacks(void delegate(JobGroup) dispatch_callback, export void setMultithreadingCallbacks(void delegate(JobGroup) dispatch_callback,
uint delegate() get_id_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;
@ -1692,7 +1696,7 @@ export struct EntityManager
if (components[comp].size == 0) if (components[comp].size == 0)
continue; continue;
memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp], memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp],
components[comp].init_data.ptr, components[comp].size); components[comp].init_data.ptr, components[comp].size);
} }
} }
else else
@ -1703,8 +1707,8 @@ export struct EntityManager
if (components[comp].size == 0) if (components[comp].size == 0)
continue; continue;
memcpy(cast(void*) temp.entity_data.ptr + info.tmpl_deltas[comp], memcpy(cast(void*) temp.entity_data.ptr + info.tmpl_deltas[comp],
cast(void*) block + info.deltas[comp] + components[comp].size * index, cast(void*) block + info.deltas[comp] + components[comp].size * index,
components[comp].size); components[comp].size);
} }
} }
@ -1753,7 +1757,7 @@ export struct EntityManager
if (components[comp].size == 0) if (components[comp].size == 0)
continue; continue;
memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp], memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp],
components[comp].init_data.ptr, components[comp].size); components[comp].init_data.ptr, components[comp].size);
} }
return temp; return temp;
@ -1769,18 +1773,18 @@ export struct EntityManager
remove_components_ids = array of components to remove from base template remove_components_ids = array of components to remove from base template
*/ */
export EntityTemplate* allocateTemplate(EntityTemplate* base_tmpl, export EntityTemplate* allocateTemplate(EntityTemplate* base_tmpl,
ushort[] components_ids, ushort[] remove_components_ids = null) ushort[] components_ids, ushort[] remove_components_ids = null)
{ {
size_t len = base_tmpl.info.components.length + components_ids.length; size_t len = base_tmpl.info.components.length + components_ids.length;
ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * len))[0 .. len]; ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * len))[0 .. len];
memcpy(ids.ptr, base_tmpl.info.components.ptr, memcpy(ids.ptr, base_tmpl.info.components.ptr,
ushort.sizeof * base_tmpl.info.components.length); ushort.sizeof * base_tmpl.info.components.length);
memcpy(ids.ptr + base_tmpl.info.components.length, components_ids.ptr, memcpy(ids.ptr + base_tmpl.info.components.length, components_ids.ptr,
ushort.sizeof * components_ids.length); ushort.sizeof * components_ids.length);
qsort(ids.ptr, ids.length, ushort.sizeof, &compareUShorts); qsort(ids.ptr, ids.length, ushort.sizeof, &compareUShorts);
qsort(remove_components_ids.ptr, remove_components_ids.length, qsort(remove_components_ids.ptr, remove_components_ids.length,
ushort.sizeof, &compareUShorts); ushort.sizeof, &compareUShorts);
{ {
uint k = 0; uint k = 0;
uint j = 1; uint j = 1;
@ -1820,20 +1824,20 @@ export struct EntityManager
foreach (comp; info.components) foreach (comp; info.components)
{ {
if (comp < base_tmpl.info.tmpl_deltas.length if (comp < base_tmpl.info.tmpl_deltas.length
&& base_tmpl.info.tmpl_deltas[comp] != ushort.max) //copy data from base component && base_tmpl.info.tmpl_deltas[comp] != ushort.max) //copy data from base component
{ {
if (components[comp].size == 0) if (components[comp].size == 0)
continue; continue;
memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp], memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp],
base_tmpl.entity_data.ptr + base_tmpl.info.tmpl_deltas[comp], base_tmpl.entity_data.ptr + base_tmpl.info.tmpl_deltas[comp],
components[comp].size); components[comp].size);
} }
else //fill with default data else //fill with default data
{ {
if (components[comp].size == 0) if (components[comp].size == 0)
continue; continue;
memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp], memcpy(temp.entity_data.ptr + info.tmpl_deltas[comp],
components[comp].init_data.ptr, components[comp].size); components[comp].init_data.ptr, components[comp].size);
} }
} }
@ -1887,7 +1891,7 @@ export struct EntityManager
alignNum(info.size, info.alignment); alignNum(info.size, info.alignment);
uint block_memory = cast(uint)( uint block_memory = cast(uint)(
m_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;
@ -1915,15 +1919,14 @@ export struct EntityManager
if (system.m_update is null) if (system.m_update is null)
{ {
if (system.m_add_entity || system.m_remove_entity if (system.m_add_entity || system.m_remove_entity
|| system.m_change_entity || system.m_event_callers.length) || system.m_change_entity || system.m_event_callers.length)
connectListenerToEntityInfo(*info, cast(uint) i); connectListenerToEntityInfo(*info, cast(uint) i);
continue; continue;
} }
addSystemCaller(*info, cast(uint) i); addSystemCaller(*info, cast(uint) i);
} }
info.comp_add_info = Mallocator.makeArray!(EntityInfo*)(gEntityManager.components.length); info.comp_add_info = Mallocator.makeArray!(EntityInfo*)(info.deltas.length);
//info.comp_rem_info = Mallocator.makeArray!(EntityInfo*)(gEntityManager.components.length);
info.comp_rem_info = Mallocator.makeArray!(EntityInfo*)(info.deltas.length); info.comp_rem_info = Mallocator.makeArray!(EntityInfo*)(info.deltas.length);
foreach (comp; info.components) foreach (comp; info.components)
@ -2082,7 +2085,9 @@ export struct EntityManager
} }
///call Custom Entity Filter test if function exists ///call Custom Entity Filter test if function exists
if(system.m_filter_entity && !(cast(bool function(void* system_pointer, EntityInfo* info) @nogc nothrow)system.m_filter_entity)(system, &entity))return; if (system.m_filter_entity && !(cast(bool function(void* system_pointer, EntityInfo* info) @nogc nothrow) system
.m_filter_entity)(system, &entity))
return;
entity.systems[system_id] = true; entity.systems[system_id] = true;
} }
@ -2127,7 +2132,8 @@ export struct EntityManager
System* system = &systems[system_id]; System* system = &systems[system_id];
connectListenerToEntityInfo(info, system_id); connectListenerToEntityInfo(info, system_id);
if(!info.systems[system_id])return; if (!info.systems[system_id])
return;
uint index = 0; uint index = 0;
for (; index < passes[system.m_pass].system_callers.length; index++) for (; index < passes[system.m_pass].system_callers.length; index++)
@ -2236,7 +2242,7 @@ export struct EntityManager
if (comp_size == 0) if (comp_size == 0)
continue; continue;
memcpy(cast(void*) new_block + new_info.deltas[comp] + new_block.entities_count * comp_size, memcpy(cast(void*) new_block + new_info.deltas[comp] + new_block.entities_count * comp_size,
cast(void*) block + info.deltas[comp] + ind * comp_size, comp_size); cast(void*) block + info.deltas[comp] + ind * comp_size, comp_size);
} }
new_block.entities_count++; new_block.entities_count++;
@ -2250,7 +2256,7 @@ export struct EntityManager
if (!info.systems[listener]) if (!info.systems[listener])
{ {
callAddEntityListener(&systems[listener], new_info, new_block, callAddEntityListener(&systems[listener], new_info, new_block,
new_block.entities_count - 1, new_block.entities_count); new_block.entities_count - 1, new_block.entities_count);
} }
} }
} }
@ -2262,7 +2268,7 @@ export struct EntityManager
if (info.systems[listener]) if (info.systems[listener])
{ {
callChangeEntityListener(&systems[listener], new_info, new_block, callChangeEntityListener(&systems[listener], new_info, new_block,
new_block.entities_count - 1, new_block.entities_count, del_ids); new_block.entities_count - 1, new_block.entities_count, del_ids);
} }
} }
} }
@ -2413,7 +2419,7 @@ export struct EntityManager
if (!info.systems[listener]) if (!info.systems[listener])
{ {
callAddEntityListener(&systems[listener], new_info, new_block, callAddEntityListener(&systems[listener], new_info, new_block,
new_block.entities_count - 1, new_block.entities_count); new_block.entities_count - 1, new_block.entities_count);
} }
} }
} }
@ -2425,7 +2431,7 @@ export struct EntityManager
if (info.systems[listener]) if (info.systems[listener])
{ {
callChangeEntityListener(&systems[listener], new_info, new_block, callChangeEntityListener(&systems[listener], new_info, new_block,
new_block.entities_count - 1, new_block.entities_count, new_ids); new_block.entities_count - 1, new_block.entities_count, new_ids);
} }
} }
} }
@ -2468,7 +2474,7 @@ export struct EntityManager
{ {
if (components[ref_.component_id].size != 0) if (components[ref_.component_id].size != 0)
data.changeEntitiesList.add( data.changeEntitiesList.add(
(cast(ubyte*) ref_.ptr)[0 .. components[ref_.component_id].size]); (cast(ubyte*) ref_.ptr)[0 .. components[ref_.component_id].size]);
} }
} }
@ -2518,12 +2524,12 @@ export struct EntityManager
ushort size = components[comp].size; ushort size = components[comp].size;
if (size != 0) if (size != 0)
memcpy(cast(void*) new_block + info.deltas[comp] + new_id * size, memcpy(cast(void*) new_block + info.deltas[comp] + new_id * size,
cast(void*) block + info.deltas[comp] + size * index, size); cast(void*) block + info.deltas[comp] + size * index, size);
if (components[comp].create_callback) if (components[comp].create_callback)
{ {
components[comp].create_callback( components[comp].create_callback(
cast(void*) new_block + info.deltas[comp] + new_id * size); cast(void*) new_block + info.deltas[comp] + new_id * size);
} }
} }
@ -2580,7 +2586,7 @@ export struct EntityManager
uint size = components[comp].size; uint size = components[comp].size;
if (size != 0) if (size != 0)
memcpy(cast(void*) block + info.deltas[comp] + size * id, memcpy(cast(void*) block + info.deltas[comp] + size * id,
tmpl.entity_data.ptr + info.tmpl_deltas[comp], size); tmpl.entity_data.ptr + info.tmpl_deltas[comp], size);
} }
foreach (comp; replacement) foreach (comp; replacement)
@ -2602,7 +2608,7 @@ export struct EntityManager
if (components[comp].create_callback) if (components[comp].create_callback)
{ {
components[comp].create_callback( components[comp].create_callback(
cast(void*) block + info.deltas[comp] + id * components[comp].size); cast(void*) block + info.deltas[comp] + id * components[comp].size);
} }
} }
@ -2737,7 +2743,7 @@ export struct EntityManager
} }
private void removeEntityNoID(Entity* entity, EntitiesBlock* block, private void removeEntityNoID(Entity* entity, EntitiesBlock* block,
bool call_destructors = false) nothrow @nogc bool call_destructors = false) nothrow @nogc
{ {
EntityInfo* info = block.type_info; EntityInfo* info = block.type_info;
@ -2869,7 +2875,7 @@ export struct EntityManager
} }
private static void callAddEntityListener(System* system, EntityInfo* info, private static void callAddEntityListener(System* system, EntityInfo* info,
EntitiesBlock* block, int begin, int end) @nogc nothrow EntitiesBlock* block, int begin, int end) @nogc nothrow
{ {
ListenerCallData data; ListenerCallData data;
data.system = system; data.system = system;
@ -2880,7 +2886,7 @@ export struct EntityManager
} }
private void callRemoveEntityListeners(EntityInfo* info, EntitiesBlock* block, int begin, private void callRemoveEntityListeners(EntityInfo* info, EntitiesBlock* block, int begin,
int end) @nogc nothrow int end) @nogc nothrow
{ {
foreach (listener; info.remove_listeners) foreach (listener; info.remove_listeners)
{ {
@ -2890,7 +2896,7 @@ export struct EntityManager
} }
private static void callRemoveEntityListener(System* system, private static void callRemoveEntityListener(System* system,
EntityInfo* info, EntitiesBlock* block, int begin, int end) @nogc nothrow EntityInfo* info, EntitiesBlock* block, int begin, int end) @nogc nothrow
{ {
ListenerCallData data; ListenerCallData data;
data.system = system; data.system = system;
@ -2901,7 +2907,7 @@ export struct EntityManager
} }
private void callChangeEntityListener(System* system, EntityInfo* info, private void callChangeEntityListener(System* system, EntityInfo* info,
EntitiesBlock* block, int begin, int end, ushort[] ch_ids) @nogc nothrow EntitiesBlock* block, int begin, int end, ushort[] ch_ids) @nogc nothrow
{ {
int i = 0; int i = 0;
int j = 0; int j = 0;
@ -3055,7 +3061,7 @@ export struct EntityManager
foreach (caller; events[i].callers) foreach (caller; events[i].callers)
{ {
if (call_data.block.type_info.systems[caller.system.m_id] == false if (call_data.block.type_info.systems[caller.system.m_id] == false
|| !caller.system.enabled || !caller.system.willExecute) || !caller.system.enabled || !caller.system.willExecute)
continue; continue;
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(ref EventCallData) nothrow @nogc) caller
@ -3122,7 +3128,7 @@ export struct EntityManager
continue; continue;
if (system.enabled && system.m_begin) if (system.enabled && system.m_begin)
system.m_execute = (cast(bool function(void*)) system.m_begin)( system.m_execute = (cast(bool function(void*)) system.m_begin)(
system.m_system_pointer); system.m_system_pointer);
} }
} }
@ -3135,9 +3141,8 @@ export struct EntityManager
foreach (ref system; systems) foreach (ref system; systems)
{ {
if (system.isAlive() == false) if (system.isAlive() == false)
{
continue; continue;
}
if (system.enabled && system.m_end) if (system.enabled && system.m_end)
(cast(void function(void*)) system.m_end)(system.m_system_pointer); (cast(void function(void*)) system.m_end)(system.m_system_pointer);
} }
@ -3276,7 +3281,7 @@ export struct EntityManager
} }
qsort(pass.system_callers.array.ptr, pass.system_callers.length, qsort(pass.system_callers.array.ptr, pass.system_callers.length,
(SystemCaller*).sizeof, &compareSystems); (SystemCaller*).sizeof, &compareSystems);
foreach (i, caller; pass.system_callers) foreach (i, caller; pass.system_callers)
caller.job_group.id = cast(uint) i; caller.job_group.id = cast(uint) i;
@ -3403,7 +3408,7 @@ export struct EntityManager
if (comp_add_info.length <= id) if (comp_add_info.length <= id)
{ {
EntityInfo*[] new_infos = Mallocator.makeArray!(EntityInfo*)( EntityInfo*[] new_infos = Mallocator.makeArray!(EntityInfo*)(
gEntityManager.components.length); gEntityManager.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 .. $];
@ -3491,7 +3496,8 @@ export struct EntityManager
export bool hasComponent(ushort component_id) export bool hasComponent(ushort component_id)
{ {
if(component_id >= deltas.length || !deltas[component_id])return false; if (component_id >= deltas.length || !deltas[component_id])
return false;
return true; return true;
} }
@ -3643,7 +3649,6 @@ export struct EntityManager
export void execute() nothrow @nogc export void execute() nothrow @nogc
{ {
//gEntityManager.getThreadID();
foreach (ref caller; callers) foreach (ref caller; callers)
{ {
caller.thread_id = gEntityManager.threadID(); caller.thread_id = gEntityManager.threadID();