This commit is contained in:
Mergul 2019-08-14 11:02:15 +02:00
commit ed99807871
3 changed files with 214 additions and 84 deletions

View file

@ -69,7 +69,7 @@ export class EntityManager
if(system.m_components)Mallocator.instance.dispose(system.m_components);
if(system.m_excluded_components)Mallocator.instance.dispose(system.m_excluded_components);
if(system.m_optional_components)Mallocator.instance.dispose(system.m_optional_components);
if(system.name)Mallocator.instance.dispose(system.name);
if(system.m_name)Mallocator.instance.dispose(system.m_name);
if(system.m_event_callers)Mallocator.instance.dispose(system.m_event_callers);
if(system.m_system_pointer)Mallocator.instance.dispose(system.m_system_pointer);
@ -301,13 +301,13 @@ export class EntityManager
static assert(0, "System should gave \"EntitiesData\" struct for input components");
}
static if (hasMember!(Sys, "EventInput"))
static if (hasMember!(Sys, "handleEvent"))
{
static void callEventHandler(Type)(ref EventCallData data)
{
Sys.EventInput input;
//Sys.EventInput input;
Sys* data_system = cast(Sys*) data.system_pointer;
EntityInfo* info = data.block.type_info;
/*EntityInfo* info = data.block.type_info;
alias EventFields = Fields!(Sys.EventInput);
foreach (ref event_field; input.tupleof)
@ -331,7 +331,10 @@ export class EntityManager
"optional");
static if (is_optional)
{
event_field = null;
if(info.deltas[EventFieldType.component_id] != 0)event_field = cast(EventFieldType*)(cast(void*) data.block
+ info.deltas[EventFieldType.component_id]
+ data.id * EventFieldType.sizeof);
else event_field = null;
}
else
{
@ -341,24 +344,48 @@ export class EntityManager
}
}
}
data_system.handleEvent(input, *cast(Type*) data.event);
}//*/
Type* event = cast(Type*) data.event;
data_system.handleEvent(/*input, */gEM.getEntity(event.entity_id), *event);
}
static void setEventCallers(Sys)(ref System system)
void setEventCallers(Sys)(ref System system)
{
enum event_handlers_num = __traits(getOverloads, Sys, "handleEvent").length;
system.m_event_callers = Mallocator.instance.makeArray!(
System.EventCaller)(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 EventParamType = Parameters!(__traits(getOverloads,
Sys, "handleEvent")[j])[1];
system.m_event_callers[j].callback = cast(
void*)&callEventHandler!(EventParamType);
system.m_event_callers[j].id = EventParamType.event_id;
alias Params = Parameters!(__traits(getOverloads,
Sys, "handleEvent")[j]);
/*static if(Params.length == 2 && is(Params[0] == __traits(getMember, Sys, "EventInput")))
{
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~"\".");
callers[i].callback = cast(
void*)&callEventHandler!(EventParamType);
callers[i].id = EventParamType.event_id;
i++;
}*/
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~"\".");
callers[i].callback = cast(
void*)&callEventHandler!(EventParamType);
callers[i].id = EventParamType.event_id;
i++;
}
}
system.m_event_callers = Mallocator.instance.makeArray(callers[0..i]);
}
static if (__traits(hasMember, Sys, "handleEvent"))
@ -376,9 +403,9 @@ export class EntityManager
static struct ComponentsIndices
{
CompInfo[] readonly;
CompInfo[] mutable;
CompInfo[] excluded;
CompInfo[] optional;
CompInfo[] mutable;
CompInfo[] req;
string entites_array;
}
@ -737,8 +764,8 @@ export class EntityManager
}
else
{
system.name = Mallocator.instance.makeArray(Sys.stringof);
systems_map.add(system.name, cast(ushort) systems.length);
system.m_name = Mallocator.instance.makeArray(Sys.stringof);
systems_map.add(system.m_name, cast(ushort) systems.length);
system.m_id = cast(ushort)(systems.length);
@ -1043,7 +1070,7 @@ export class EntityManager
m_dispatch_jobs = func;
}
static void alignNum(ref ushort num, ushort alignment) nothrow @nogc
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));
}
@ -1060,6 +1087,45 @@ export class EntityManager
return 1;
}
/************************************************************************************************************************
*Allocate EntityTemplate with all components from entity witch it's data and returns pointer to it.
*
*Params:
*id = ID of entity from which should be created template
*fill_default = if true, components will be filled with default data, instead entity data will be taken
*/
export EntityTemplate* allocateTemplate(EntityID entity_id, bool fill_default = false)
{
Entity* entity = getEntity(entity_id);
EntitiesBlock* block = getMetaData(entity);
EntityInfo* info = block.type_info;
EntityTemplate* temp = Mallocator.instance.make!EntityTemplate;
temp.entity_data = Mallocator.instance.makeArray!ubyte(info.size);
temp.info = info;
if(fill_default)
{
//fill components with default data
foreach (comp; info.components)
{
temp.entity_data[info.tmpl_deltas[comp] .. info.tmpl_deltas[comp] + components[comp].size]
= components[comp].init_data;
}
}
else
{
ushort index = block.entityIndex(entity);
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);
}
}
return temp;
}
/************************************************************************************************************************
*Allocate EntityTemplate with specifed components and returns pointer to it.
*
@ -1446,10 +1512,7 @@ export class EntityManager
new_entity.id = entity.id;
new_entity.updateID();
static if (EntityID.sizeof == 8)
uint ind = cast(uint)((cast(void*) entity - block.dataBegin()) >> 3);
else
uint ind = cast(uint)((cast(void*) entity - block.dataBegin()) / EntityID.sizeof());
uint ind = block.entityIndex(entity);
if (info.remove_listeners)
{
@ -1623,10 +1686,7 @@ export class EntityManager
uint j = 0;
uint k = 0;
static if (EntityID.sizeof == 8)
uint ind = cast(uint)((cast(void*) entity - block.dataBegin()) >> 3);
else
uint ind = cast(uint)((cast(void*) entity - block.dataBegin()) / EntityID.sizeof());
uint ind = block.entityIndex(entity);
if (info.remove_listeners)
{
@ -1748,12 +1808,66 @@ export class EntityManager
}
/************************************************************************************************************************
*Add entity to system.
*Add copy of entity to system and returns pointer to it. Added copy has same data as copied entity. Returen pointer is
*valid only before one from commit(), begin() or end() will be called. To save entity to further use you should save ID
*instead of pointer.
*
*Params:
*tmpl = pointer entity template allocated by EntityManager.
*/
export ref Entity addEntity(EntityTemplate* tmpl)
export Entity* addEntityCopy(EntityID id)
{
Entity* entity = getEntity(id);
EntitiesBlock* block = getMetaData(entity);
EntityInfo* info = block.type_info;
ushort index = block.entityIndex(entity);
ushort new_index = 0;
EntitiesBlock* new_block;
do
{
new_block = findBlockWithFreeSpaceMT(info);
new_index = new_block.added_count.atomicOp!"+="(1);
}
while (new_block.entities_count + new_index > info.max_entities);
ushort new_id = cast(ushort)(new_block.entities_count + new_index - 1);
const void* data_begin = new_block.dataBegin();
const void* start = data_begin + EntityID.sizeof * new_id;
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);
if (components[comp].create_callback)
{
components[comp].create_callback(
cast(void*) block + info.deltas[comp] + new_id * components[comp].size);
}
}
if (new_index == 1)
threads[thread_id].blocks_to_update.add(new_block);
Entity* new_entity = cast(Entity*) start;
//add_mutex.lock_nothrow();
new_entity.id = id_manager.getNewID();
//add_mutex.unlock_nothrow();
new_entity.updateID();
return new_entity;
}
/************************************************************************************************************************
*Add entity to system. Returen pointer is valid only before one from commit(), begin() or end() will be called. To save entity to further
*use you should save ID instead of pointer.
*
*Params:
*tmpl = pointer entity template allocated by EntityManager.
*/
export Entity* addEntity(EntityTemplate* tmpl)
{
EntityInfo* info = tmpl.info;
@ -1793,7 +1907,7 @@ export class EntityManager
//add_mutex.unlock_nothrow();
entity.updateID();
return *entity;
return entity;
}
/************************************************************************************************************************
@ -1890,11 +2004,7 @@ export class EntityManager
EntityInfo* info = block.type_info;
if (info.remove_listeners)
{
void* data_begin = block.dataBegin();
static if (EntityID.sizeof == 8)
uint pos = cast(uint)((cast(void*) entity - data_begin) >> 3);
else
uint pos = cast(uint)((cast(void*) entity - data_begin) / EntityID.sizeof());
uint pos = block.entityIndex(entity);
callRemoveEntityListeners(info, block, pos, pos + 1);
}
@ -1907,16 +2017,11 @@ export class EntityManager
private void removeEntityNoID(Entity* entity, EntitiesBlock* block,
bool call_destructors = false) nothrow @nogc
{
//pos is Entity number in block
void* data_begin = block.dataBegin();
EntityInfo* info = block.type_info;
info.last_block.entities_count--;
static if (EntityID.sizeof == 8)
uint pos = cast(uint)((cast(void*) entity - data_begin) >> 3);
else
uint pos = cast(uint)((cast(void*) entity - data_begin) / EntityID.sizeof());
uint pos = block.entityIndex(entity);
if (call_destructors)
{
@ -2160,14 +2265,7 @@ export class EntityManager
EntityID entity_id = *cast(EntityID*) event_pointer;
Entity* entity = id_manager.getEntityPointer(entity_id);
call_data.block = getMetaData(entity);
static if (EntityID.sizeof == 8)
call_data.id = cast(ushort)(
(cast(void*) entity - call_data.block.dataBegin()) >> 3);
else
call_data.id = cast(ushort)(
(cast(void*) entity - call_data.block.dataBegin()) / EntityID
.sizeof);
call_data.id = call_data.block.entityIndex(entity);
foreach (caller; events[i].callers)
{
@ -2303,9 +2401,9 @@ export class EntityManager
caller.exclusion = null;
/*import std.stdio;
write("Exclusive systems for system ", caller.system.name, ": ");
write("Exclusive systems for system ", caller.system.m_name, ": ");
foreach (ex; exclusion[0 .. index])
write(ex.system.name, " ");
write(ex.system.m_name, " ");
writeln();*/
}
@ -2363,9 +2461,9 @@ export class EntityManager
caller.dependencies = null;
/*import std.stdio;
write("Dependencies for system ", caller.system.name, ": ");
write("Dependencies for system ", caller.system.m_name, ": ");
foreach (ex; caller.dependencies)
write(ex.system.name, " ");
write(ex.system.m_name, " ");
writeln();*/
}
}
@ -2567,7 +2665,7 @@ export class EntityManager
struct EntitiesBlock
{
///return distance (in bytes) from begin of block to data
export uint dataDelta() nothrow @nogc
export uint dataDelta() nothrow @nogc pure
{
ushort dif = EntitiesBlock.sizeof;
alignNum(dif, type_info.alignment);
@ -2575,12 +2673,20 @@ export class EntityManager
}
///return pointer to first element in block
export void* dataBegin() nothrow @nogc
export void* dataBegin() nothrow @nogc pure
{
ushort dif = EntitiesBlock.sizeof;
return cast(void*)&this + dif;
}
export ushort entityIndex(Entity* entity) nothrow @nogc pure
{
static if (EntityID.sizeof == 8)
return cast(ushort)((cast(void*) entity - dataBegin()) >> 3);
else
return cast(ushort)((cast(void*) entity - dataBegin()) / EntityID.sizeof());
}
///pointer to Entity type info
EntityInfo* type_info = null;
///number of entities in block

View file

@ -74,6 +74,14 @@ struct System
return m_id;
}
/************************************************************************************************************************
*Get system name.
*/
export const (char)[] name() nothrow @nogc
{
return cast(const (char)[])m_name;
}
struct EventCaller
{
ushort id;
@ -97,7 +105,7 @@ package:
int m_pass;
///system name
char[] name;
char[] m_name;
///required components
ushort[] m_components;