-PageSize and PagesInBlock values can be adjust in runtime (at initialization time)
-added support for calling custon delegate function for all entities supported by selected system
This commit is contained in:
parent
1f78f2506c
commit
87e9a31d7f
3 changed files with 335 additions and 171 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue