-changes in gitignore

-changed "absent" to "excluded" everywhere
-added Events support:
 *systems are scanned by handleEvent() function
 *generate system callers for events
 *event sending have (untested) multithreaded support
 *EventInput structure in System has input components for event
This commit is contained in:
Mergul 2018-11-02 15:39:46 +01:00
parent 16a5696840
commit 3bc5ff2423
8 changed files with 689 additions and 310 deletions

22
.gitignore vendored
View file

@ -1,17 +1,5 @@
dub.userprefs *
dub.selections.json !source
.dub !tests
/.vscode !dub.json
LOC !.gitignore
perf.data
perf.data.old
*.o
*.a
*.obj
*.exe
*.lib
*.so
*.def
*.lib
*.dll
*.exp

View file

@ -10,6 +10,9 @@
"dflags-posix-ldc": [ "dflags-posix-ldc": [
"-defaultlib=phobos2-ldc,druntime-ldc" "-defaultlib=phobos2-ldc,druntime-ldc"
], ],
"dflagss": [
"-betterC"
],
"configurations" : [ "configurations" : [
{ {
"name" : "library", "name" : "library",

View file

@ -2,7 +2,7 @@ module ecs.attributes;
///Used to mark optional components for system. ///Used to mark optional components for system.
enum optional = "optional"; enum optional = "optional";
///Used to mark absent components for system. Enum 'AbsentComponents' should be used instead of it. ///Used to mark components excluded from update for system. Enum 'ExcludedComponents' should be used instead of it.
enum absent = "absent"; enum excluded = "excluded";
///Used to mark readonly components for system. "const" can be used insted. ///Used to mark readonly components for system. "const" can be used insted.
enum readonly = "readonly"; enum readonly = "readonly";

View file

@ -1,6 +1,7 @@
module ecs.core; module ecs.core;
public import ecs.manager; public import ecs.manager;
public import ecs.entity;
static struct ECS static struct ECS
{ {
@ -25,5 +26,6 @@ static struct ECS
mixin template Event() mixin template Event()
{ {
__gshared ushort event_id; __gshared ushort event_id;
EntityID entity_id;
} }
} }

View file

@ -4,15 +4,19 @@ import ecs.manager;
import ecs.block_allocator; import ecs.block_allocator;
import ecs.entity; import ecs.entity;
import std.experimental.allocator;
import std.experimental.allocator.mallocator : AlignedMallocator, Mallocator;
import std.algorithm.comparison : max; import std.algorithm.comparison : max;
/*
struct Event /*struct Event
{ {
uint type; uint id;
}*/ }*/
mixin template EventManagerCode() //mixin template EventManagerCode()
struct EventManager
{ {
//@disable this(); //@disable this();
@ -22,7 +26,7 @@ mixin template EventManagerCode()
manager = m; manager = m;
}*/ }*/
void sendSelfEvent(Ev)(EntityID id, Ev event) /*void sendSelfEvent(Ev)(EntityID id, Ev event)
{ {
ushort size = cast(ushort)(Ev.sizeof); // + EntityID.sizeof + ushort.sizeof); ushort size = cast(ushort)(Ev.sizeof); // + EntityID.sizeof + ushort.sizeof);
ushort alignment = cast(ushort)(Ev.alignof); ushort alignment = cast(ushort)(Ev.alignof);
@ -53,8 +57,6 @@ mixin template EventManagerCode()
aligned_index = index; aligned_index = index;
alignNum(aligned_index, alignment); alignNum(aligned_index, alignment);
/*if(alignment > EntityID.sizeof + uint.sizeof)aligned_index = alignment;
else aligned_index = uint.sizeof * 4;*/
} }
EventBlock* block = list.current_block; EventBlock* block = list.current_block;
@ -66,22 +68,101 @@ mixin template EventManagerCode()
*cast(EntityID*)&block.data[index + 2] = id; *cast(EntityID*)&block.data[index + 2] = id;
*cast(Ev*)&block.data[aligned_index] = event; *cast(Ev*)&block.data[aligned_index] = event;
block.index = cast(ushort)(aligned_index + Ev.sizeof); block.index = cast(ushort)(aligned_index + Ev.sizeof);
}*/
void initialize(EntityManager m)
{
allocator = BlockAllocator(events_block_size, events_blocks_in_allocation);
manager = m;
}
void sendEvent(Ev)(EntityID id, Ev event, uint thread_id = 0)
{
uint block_id = current_index+thread_id;
EventData* data = &events[Ev.event_id];
EventBlock* block = data.blocks[block_id];
EntityManager.EventInfo* info = &gEM.events[Ev.event_id];
event.entity_id = id;
if(block is null)
{
block = cast(EventBlock*) allocator.getBlock();
*block = EventBlock();
data.first_blocks[block_id] = block;
data.blocks[block_id] = block;
}
if(block.count >= data.max_events)
{
EventBlock* new_block = cast(EventBlock*) allocator.getBlock();
*new_block = EventBlock();
block.next = new_block;
block = new_block;
data.blocks[block_id] = block;
}
/*void* start = cast(void*)block + data.data_offset + block.count * info.size;
Ev* event_ptr = cast(Ev*)start;
*event_ptr = event;*/
Ev* event_array = cast(Ev*)(cast(void*)block + data.data_offset);
event_array[block.count] = event;
block.count++;
}
void swapCurrent()
{
uint threads_count = cast(uint)manager.threads.length;
if(current_index == 0)current_index = threads_count;
else current_index = 0;
foreach(ref event;events)
{
foreach(ref first_block; event.first_blocks[current_index .. current_index + threads_count])
{
EventBlock* block = first_block;
while(block)
{
EventBlock* to_dispose = block;
block = block.next;
allocator.freeBlock(to_dispose);
}
first_block = null;
}
foreach(ref block; event.blocks[current_index .. current_index + threads_count])
{
block = null;
}
}
} }
void clearEvents() void clearEvents()
{ {
EventList tmp = current_events; uint threads_count = cast(uint)manager.threads.length;
foreach(ref event;events)
{
foreach(ref first_block; event.first_blocks)
{
EventBlock* block = first_block;
while(block)
{
EventBlock* to_dispose = block;
block = block.next;
allocator.freeBlock(to_dispose);
}
first_block = null;
}
foreach(ref block; event.blocks)
{
block = null;
}
}
/*EventList tmp = current_events;
current_events = process_events; current_events = process_events;
process_events = tmp; process_events = tmp;
EventBlock* block = process_events.first_block; EventBlock* block = process_events.first_block;
/*if(block)
{
import std.stdio;
writeln(block.data);
}*/
while (block) while (block)
{ {
EventBlock* free = block; EventBlock* free = block;
@ -89,7 +170,30 @@ mixin template EventManagerCode()
allocator.freeBlock(free); allocator.freeBlock(free);
} }
process_events.first_block = null; process_events.first_block = null;
process_events.current_block = null; process_events.current_block = null;*/
}
void allocateData(uint threads_count)
{
if(events)
{
foreach(ref event;events)
{
Mallocator.instance.dispose(event.blocks);
Mallocator.instance.dispose(event.first_blocks);
}
Mallocator.instance.dispose(events);
}
events = Mallocator.instance.makeArray!EventData(gEM.events.length);
foreach(i,ref event;events)
{
event.blocks = Mallocator.instance.makeArray!(EventBlock*)(threads_count*2);
event.first_blocks = Mallocator.instance.makeArray!(EventBlock*)(threads_count*2);
event.data_offset = EventBlock.sizeof;//gEM.events[i].
gEM.alignNum(event.data_offset, gEM.events[i].alignment);
event.max_events = cast(ushort)((events_block_size - event.data_offset) / gEM.events[i].size);
}
} }
///Single page size. Must be power of two. ///Single page size. Must be power of two.
@ -99,7 +203,7 @@ mixin template EventManagerCode()
struct EventBlock struct EventBlock
{ {
union /*union
{ {
struct struct
{ {
@ -108,17 +212,31 @@ mixin template EventManagerCode()
} }
ubyte[events_block_size] data; ubyte[events_block_size] data;
} }*/
EventBlock* next;
ushort count = 0;
} }
struct EventList /*struct EventList
{ {
EventBlock* first_block; EventBlock* first_block;
EventBlock* current_block; EventBlock* current_block;
}*/
struct EventData
{
ushort data_offset;
ushort max_events;
EventBlock*[] blocks;
EventBlock*[] first_blocks;
//EventBlock*[] current_blocks;
} }
EventList current_events; /*EventList current_events;
EventList process_events; EventList process_events;*/
uint current_index = 0;
EventData[] events;
BlockAllocator/*!(events_block_size, events_blocks_in_allocation)*/ allocator; BlockAllocator/*!(events_block_size, events_blocks_in_allocation)*/ allocator;
EntityManager manager; EntityManager manager;

View file

@ -110,6 +110,41 @@ class EntityManager
} }
} }
event_manager.allocateData(cast(uint) threads.length);
foreach(ref info;events)
{
Mallocator.instance.dispose(info.callers);
}
ushort[] event_callers = (cast(ushort*)alloca(ushort.sizeof * events.length))[0..events.length];
foreach(ref caller; event_callers)caller = 0;
foreach(ref system;systems)
{
foreach(caller;system.m_event_callers)
{
event_callers[caller.id]++;
}
}
foreach(i,ref info; events)
{
info.callers = Mallocator.instance.makeArray!(EventCaller)(event_callers[i]);
}
foreach(ref caller; event_callers)caller = 0;
foreach(ref system;systems)
{
foreach(caller;system.m_event_callers)
{
events[caller.id].callers[event_callers[caller.id]].callback = caller.callback;
events[caller.id].callers[event_callers[caller.id]].system = &system;
event_callers[caller.id]++;
}
}
generateDependencies(); generateDependencies();
} }
@ -119,10 +154,11 @@ class EntityManager
this(uint threads_count) this(uint threads_count)
{ {
if (threads_count == 0) if (threads_count == 0)
threads_count = 0; threads_count = 1;
threads = Mallocator.instance.makeArray!ThreadData(threads_count); threads = Mallocator.instance.makeArray!ThreadData(threads_count);
id_manager.initialize(); id_manager.initialize();
event_manager.initialize(this);
allocator = BlockAllocator(page_size, pages_in_block); allocator = BlockAllocator(page_size, pages_in_block);
@ -158,9 +194,10 @@ class EntityManager
*/ */
void registerSystem(Sys)(int priority, ushort pass = 0) void registerSystem(Sys)(int priority, ushort pass = 0)
{ {
alias STC = ParameterStorageClass; //alias STC = ParameterStorageClass;
assert(register_state,"asda"); assert(register_state,
"registerSystem must be called between beginRegister() and endRegister().");
assert(pass < passes.length, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist."); assert(pass < passes.length, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist.");
System system; System system;
@ -176,6 +213,126 @@ class EntityManager
static assert(0, "System should gave \"EntitiesData\" struct for input components"); static assert(0, "System should gave \"EntitiesData\" struct for input components");
} }
//dfmt off
static if(hasMember!(Sys,"EventInput"))
{
static string genEventCompList()()
{
string ret = "Sys.EventInput input;\n";
string type;
//bool has = true;
foreach (member; __traits(allMembers, Sys.EventInput))
{
if(mixin("fullyQualifiedName!(ConstOf!(PointerTarget!(typeof(Sys.EventInput."~member~")))) == \"const(ecs.entity.Entity)\""))
{
ret ~= "input." ~ member ~ " = cast(Entity*) data.block.dataBegin() + data.id;\n";
continue;
}
bool has = false;
bool optional = false;
foreach(member2; __traits(allMembers, Sys.EntitiesData))
{
static if(mixin("isBasicType!(typeof(Sys.EntitiesData."~member2~"))")){}
else static if(mixin("fullyQualifiedName!(ConstOf!(PointerTarget!(typeof(Sys.EventInput."~member~")))) == fullyQualifiedName!(ConstOf!(ForeachType!(typeof(Sys.EntitiesData."~member2~"))))"))
{
has = true;
if(mixin("hasUDA!(Sys.EntitiesData."~member2~",\"optional\")"))optional = true;
break;
}
}
if(!has)assert(0);
if(optional)ret ~= "input." ~ member ~ " = null;\n";
else ret ~= "input." ~ member ~ " = cast(typeof(Sys.EventInput." ~ member
~ "))(cast(void*) data.block + info.deltas[typeof(Sys.EventInput."
~ member ~ ").component_id] + data.id * typeof(Sys.EventInput." ~ member
~ ").sizeof);\n";
}
return ret;
}
//pragma(msg,genEventCompList());
//pragma(msg,genEventCompList());
static string checkHandler()(string member)
{
string ret;
ret ~= "(Parameters!(Sys."~member~")).length == 2 && ";
ret ~= "((is(Parameters!(Sys."~member~")[0] == Sys.EventInput) && hasStaticMember!(Parameters!(Sys."~member~")[1],\"event_id\")) ||";
ret ~= " (is(Parameters!(Sys."~member~")[1] == Sys.EventInput) && hasStaticMember!(Parameters!(Sys."~member~")[0],\"event_id\")))";
return ret;
}
/*static struct Handler
{
ushort id;
void* callback;
}*/
static string catchEventHanlders()()
{
int event_handlers = 0;
string ret;
string event_param;
static if(__traits(hasMember, Sys, "handleEvent"))
{
foreach(func; __traits(getOverloads, Sys, "handleEvent"))
{
event_handlers++;//pragma(msg,"kupa");
}
//ret ~= "Handler[] handlers = (cast(Handler*)alloca("~event_handlers.to!string~" * (Handler).sizeof))[0 .. "~event_handlers.to!string~"];\n";
ret ~= "system.m_event_callers = Mallocator.instance.makeArray!(System.EventCaller)("~event_handlers.to!string~");";
event_handlers = 0;
foreach(j,func; __traits(getOverloads, Sys, "handleEvent"))
{
event_param = "Parameters!(__traits(getOverloads, Sys, \"handleEvent\")["~j.to!string~"])[1]";
ret ~= "static void callHandler"~event_handlers.to!string~"(ref EventCallData data)\n{\n";
ret ~= "Sys* s = cast(Sys*) data.system_pointer;
EntityInfo* info = data.block.type_info;";
ret ~= genEventCompList();
ret ~= "s.handleEvent(input, *cast("~event_param~"*)data.event);";
ret ~= "}\n";
ret ~= "system.m_event_callers["~event_handlers.to!string~"].callback = cast(void*)&callHandler"~event_handlers.to!string~";";
ret ~= "system.m_event_callers["~event_handlers.to!string~"].id = "~event_param~".event_id;";
event_handlers++;
}
/*ret ~= "ushort max_id = 0;";
ret ~= "foreach(handler;handlers)
{
if(handler.id > max_id)max_id = handler.id;
}";
ret ~= "system.m_event_callback = Mallocator.instance.makeArray!(System.EventHandler)(max_id);";
ret ~= "foreach(handler;handlers)
{
system.m_event_callback[handler.id] = handler.callback;
}";*/
}
/*static if(__traits(hasMember, Sys, "handleEvent"))//foreach(member; __traits(allMembers,Sys))
{
//static foreach()
static if (member == "handleEvent" && mixin("isFunction!(Sys."~member~")"))
{
static if(mixin(checkHandler(member)))
{
event_handlers++;
}
}
}*/
return ret;
}
//pragma(msg,catchEventHanlders());
mixin(catchEventHanlders());
}
//dfmt on
static string genCompList()() static string genCompList()()
{ {
@ -199,7 +356,7 @@ class EntityManager
uint req; uint req;
uint opt; uint opt;
uint absent; uint excluded;
uint read_only; uint read_only;
uint modified; uint modified;
foreach (member; __traits(allMembers, Sys.EntitiesData)) foreach (member; __traits(allMembers, Sys.EntitiesData))
@ -230,9 +387,9 @@ class EntityManager
attribs++; attribs++;
//break; //break;
} }
else if (att == "absent") else if (att == "excluded")
{ {
absent++; excluded++;
attribs++; attribs++;
//break; //break;
} }
@ -242,7 +399,7 @@ class EntityManager
} }
} }
assert(attribs <= 1, assert(attribs <= 1,
"EntitiesData member can't have both \"@optional\" and \"@absent\"."); "EntitiesData member can't have both \"@optional\" and \"@excluded\".");
if (!attribs) if (!attribs)
req++; req++;
if (is_read_only) if (is_read_only)
@ -253,17 +410,17 @@ class EntityManager
} }
} }
static if (__traits(hasMember, Sys, "AbsentComponents")) static if (__traits(hasMember, Sys, "ExcludedComponents"))
{ {
static if (is(Sys.AbsentComponents == enum)) static if (is(Sys.ExcludedComponents == enum))
{ {
absent += (Fields!(Sys.AbsentComponents)).length; //static assert(0,"Enum AbsentComponents are not implemented yet."); excluded += (Fields!(Sys.ExcludedComponents)).length; //static assert(0,"Enum ExcludedComponents are not implemented yet.");
} }
else static if (__traits(compiles, allSameType!(string, typeof(Sys.AbsentComponents))) else static if (__traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents)))
&& allSameType!(string, typeof(Sys.AbsentComponents)) && allSameType!(string, typeof(Sys.ExcludedComponents))
&& isExpressions!(Sys.AbsentComponents)) && isExpressions!(Sys.ExcludedComponents))
{ {
absent += Sys.AbsentComponents.length; excluded += Sys.ExcludedComponents.length;
} }
} }
@ -273,39 +430,39 @@ class EntityManager
if (opt > 0) if (opt > 0)
ret ~= "system.m_optional_components = Mallocator.instance.makeArray!ushort(" ret ~= "system.m_optional_components = Mallocator.instance.makeArray!ushort("
~ opt.to!string ~ ");"; ~ opt.to!string ~ ");";
if (absent > 0) if (excluded > 0)
ret ~= "system.m_absent_components = Mallocator.instance.makeArray!ushort(" ret ~= "system.m_excluded_components = Mallocator.instance.makeArray!ushort("
~ absent.to!string ~ ");"; ~ excluded.to!string ~ ");";
if (read_only > 0) if (read_only > 0)
ret ~= "system.m_read_only_components = Mallocator.instance.makeArray!ushort(" ret ~= "system.m_read_only_components = Mallocator.instance.makeArray!ushort("
~ read_only.to!string ~ ");"; ~ read_only.to!string ~ ");";
if (modified > 0) if (modified > 0)
ret ~= "system.m_modified_components = Mallocator.instance.makeArray!ushort(" ret ~= "system.m_modified_components = Mallocator.instance.makeArray!ushort("
~ modified.to!string ~ ");"; ~ modified.to!string ~ ");";
ret ~= "ushort comp;"; //uint opt = 0;uint req = 0;uint absent = 0;"; ret ~= "ushort comp;"; //uint opt = 0;uint req = 0;uint excluded = 0;";
opt = 0; opt = 0;
req = 0; req = 0;
absent = 0; excluded = 0;
read_only = 0; read_only = 0;
modified = 0; modified = 0;
static if (__traits(hasMember, Sys, "AbsentComponents")) static if (__traits(hasMember, Sys, "ExcludedComponents"))
{ {
static if (is(Sys.AbsentComponents == enum)) static if (is(Sys.ExcludedComponents == enum))
{ {
//static assert(0,"Enum AbsentComponents are not implemented yet."); //static assert(0,"Enum ExcludedComponents are not implemented yet.");
foreach (str; Fields!(Sys.AbsentComponents)) foreach (str; Fields!(Sys.ExcludedComponents))
ret ~= "system.m_absent_components[" ~ (absent++) ret ~= "system.m_excluded_components[" ~ (excluded++)
.to!string ~ "] = components_map.get(\"" .to!string ~ "] = components_map.get(\""
~ str.stringof ~ "\", ushort.max);"; ~ str.stringof ~ "\", ushort.max);";
} }
else static if (__traits(compiles, allSameType!(string, typeof(Sys.AbsentComponents))) else static if (__traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents)))
&& allSameType!(string, typeof(Sys.AbsentComponents)) && allSameType!(string, typeof(Sys.ExcludedComponents))
&& isExpressions!(Sys.AbsentComponents)) && isExpressions!(Sys.ExcludedComponents))
{ {
foreach (str; Sys.AbsentComponents) foreach (str; Sys.ExcludedComponents)
ret ~= "system.m_absent_components[" ~ (absent++) ret ~= "system.m_excluded_components[" ~ (excluded++)
.to!string ~ "] = components_map.get(\"" ~ str ~ "\", ushort.max);"; .to!string ~ "] = components_map.get(\"" ~ str ~ "\", ushort.max);";
} }
} }
@ -349,9 +506,9 @@ class EntityManager
has_att = true; has_att = true;
//break; //break;
} }
else if (att == "absent") else if (att == "excluded")
{ {
ret ~= "system.m_absent_components[" ~ (absent++) ret ~= "system.m_excluded_components[" ~ (excluded++)
.to!string ~ "] = comp;"; .to!string ~ "] = comp;";
has_att = true; has_att = true;
//break; //break;
@ -399,7 +556,7 @@ class EntityManager
ushort comp; ushort comp;
uint req = 0; uint req = 0;
uint opt = 0; uint opt = 0;
uint absent = 0; uint excluded = 0;
foreach (member; __traits(allMembers, Sys.EntitiesData)) foreach (member; __traits(allMembers, Sys.EntitiesData))
{ {
if (is(typeof(__traits(getMember, Sys.EntitiesData, if (is(typeof(__traits(getMember, Sys.EntitiesData,
@ -435,9 +592,9 @@ class EntityManager
has_att = true; has_att = true;
break; break;
} }
else if (att == "absent") else if (att == "excluded")
{ {
absent++; excluded++;
has_att = true; has_att = true;
break; break;
} }
@ -979,9 +1136,9 @@ class EntityManager
{ {
System* system = &systems[system_id]; System* system = &systems[system_id];
if (system.m_absent_components) if (system.m_excluded_components)
{ {
foreach (id; system.m_absent_components) foreach (id; system.m_excluded_components)
{ {
foreach (id2; entity.components) foreach (id2; entity.components)
{ {
@ -1581,12 +1738,66 @@ class EntityManager
} }
} }
void updateEvents()
{
bool empty = true;
//uint index = event_manager.
while(1)
{
event_manager.swapCurrent();
//event_manager.clearEvents();
uint current_index;
if(event_manager.current_index == 0)current_index = cast(uint)threads.length;
else current_index = 0;
foreach(i,event;event_manager.events)
{
foreach(first_block;event.first_blocks[current_index .. current_index + threads.length])
{
EventManager.EventBlock* block = first_block;
if(block)empty = false;
while(block)
{
EventCallData call_data;
void* event_pointer = cast(void*)block + event.data_offset;
call_data.event = event_pointer;
foreach(j;0..block.count)
{
//void* event_pointer = cast(void*)block + event.data_offset;
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);
foreach(caller; events[i].callers)
{
call_data.system_pointer = caller.system.m_system_pointer;
(cast(void function(ref EventCallData))caller.callback)(call_data);
}
event_pointer += events[i].size;
}
block = block.next;
}
}
}
if(empty)break;
empty = true;
//event_manager.clearEvents();
}
//event_manager.swapCurrent();
}
export void commit() export void commit()
{ {
updateEvents();
id_manager.optimize(); id_manager.optimize();
updateBlocks(); updateBlocks();
removeEntities(); removeEntities();
changeEntities(); changeEntities();
event_manager.clearEvents();
} }
/************************************************************************************************************************ /************************************************************************************************************************
@ -1601,7 +1812,8 @@ class EntityManager
foreach (ref system; systems) foreach (ref system; systems)
{ {
if (system.enabled && system.m_begin) if (system.enabled && system.m_begin)
system.m_execute = (cast(bool function(void*)) system.m_begin)(system.m_system_pointer); system.m_execute = (cast(bool function(void*)) system.m_begin)(
system.m_system_pointer);
} }
} }
@ -1619,7 +1831,7 @@ class EntityManager
commit(); commit();
//clearEvents(); //event_manager.clearEvents();
} }
private void getThreadID() private void getThreadID()
@ -1630,6 +1842,11 @@ class EntityManager
thread_id = 0; thread_id = 0;
} }
void sendEvent(Ev)(EntityID id, Ev event)
{
event_manager.sendEvent(id, event, thread_id);
}
/*private */ /*private */
void generateDependencies() void generateDependencies()
{ {
@ -1795,10 +2012,25 @@ class EntityManager
void function(void* pointer) destroy_callback; void function(void* pointer) destroy_callback;
} }
struct EventCaller
{
System* system;
void* callback;
}
struct EventCallData
{
EntitiesBlock* block;
void* system_pointer;
void* event;
ushort id;
}
struct EventInfo struct EventInfo
{ {
ushort size; ushort size;
ushort alignment; ushort alignment;
EventCaller[] callers;
void function(void* pointer) destroy_callback; void function(void* pointer) destroy_callback;
} }
@ -1956,7 +2188,8 @@ class EntityManager
Mallocator.instance.dispose(dependencies); Mallocator.instance.dispose(dependencies);
Mallocator.instance.dispose(exclusion); Mallocator.instance.dispose(exclusion);
} }
if(job_group.dependencies)Mallocator.instance.dispose(job_group.dependencies); if (job_group.dependencies)
Mallocator.instance.dispose(job_group.dependencies);
} }
uint system_id; uint system_id;
@ -2011,8 +2244,8 @@ class EntityManager
IDManager id_manager; IDManager id_manager;
BlockAllocator /*!(page_size, pages_in_block)*/ allocator; BlockAllocator /*!(page_size, pages_in_block)*/ allocator;
//EventManager event_manager; EventManager event_manager;
mixin EventManagerCode; //mixin EventManagerCode;
//Vector!EntityID entities_to_remove; //Vector!EntityID entities_to_remove;
//Vector!(EntitiesBlock*) blocks_to_update; //Vector!(EntitiesBlock*) blocks_to_update;

View file

@ -61,6 +61,12 @@ struct System
return m_id; return m_id;
} }
struct EventCaller
{
ushort id;
void* callback;
}
package: package:
///should system be executed in current update? ///should system be executed in current update?
@ -82,8 +88,8 @@ package:
///required components ///required components
ushort[] m_components; ushort[] m_components;
///absent components ///excluded components
ushort[] m_absent_components; ushort[] m_excluded_components;
///optional components ///optional components
ushort[] m_optional_components; ushort[] m_optional_components;
@ -93,6 +99,8 @@ package:
ushort[] m_read_only_components; ushort[] m_read_only_components;
ushort[] m_modified_components; ushort[] m_modified_components;
EventCaller[] m_event_callers;
//void function(ref EntityManager.CallData data) m_update; //void function(ref EntityManager.CallData data) m_update;
void* m_update; ///workaroud for DMD bug with upper line void* m_update; ///workaroud for DMD bug with upper line

View file

@ -10,9 +10,6 @@ import ecs.core;
import core.time; import core.time;
import std.stdio; import std.stdio;
int main()
{
struct TestEvent struct TestEvent
{ {
mixin ECS.Event;//__gshared ushort event_id; mixin ECS.Event;//__gshared ushort event_id;
@ -133,7 +130,7 @@ int main()
TestComp[] test; TestComp[] test;
TestComp2[] test2; TestComp2[] test2;
@readonly @optional const(TestComp3)[] test3; @readonly @optional const(TestComp3)[] test3;
//@absent TestComp4[] test4; //@excluded TestComp4[] test4;
} }
void update(ref Entity entity, ref TestComp test, ref TestComp2 test2)//, TestComp3* test3) //ref TestComp comp) void update(ref Entity entity, ref TestComp test, ref TestComp2 test2)//, TestComp3* test3) //ref TestComp comp)
@ -196,22 +193,42 @@ import std.meta;
{ {
mixin ECS.System!16;//__gshared ushort system_id; mixin ECS.System!16;//__gshared ushort system_id;
enum AbsentComponents0 /*enum ExcludedComponents0
{ {
TestComp, TestComp,
TestComp4 TestComp4
} }
alias AbsentComponents = AliasSeq!("TestComp", "TestComp4"); alias ExcludedComponents = AliasSeq!("TestComp", "TestComp4");
string AbsentComponents2; string ExcludedComponents2;*/
static struct EntitiesData static struct EntitiesData
{ {
short length; short length;
const (Entity)[] entity; const (Entity)[] entity;
TestComp3[] test; TestComp3[] test;
//@absent TestComp[] testt; //@excluded TestComp[] testt;
}
static struct EventInput
{
Entity* entity;
TestComp3* test;
//TestComp* tt;
}
void handleEvent(EventInput input, ref TestEvent event)
{
input.test.bg = event.a;
TestEvent2 event2;
event2.a = event.a + 8;
gEM.sendEvent(input.entity.id, event2);
}
void handleEvent(EventInput input, ref TestEvent2 event)
{
input.test.gg = cast(uint)event.a;
} }
void onEnable() void onEnable()
@ -233,12 +250,19 @@ import std.meta;
} }
void update(ref EntitiesData data) void update(EntitiesData data)
{ {
foreach(i;0..data.test.length) foreach(i;0..data.test.length)
{ {
data.test[i].gg += 14; data.test[i].gg += 14;
gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent()); TestEvent event;
event.a = data.test[i].gg + 4;
gEM.sendEvent(data.entity[i].id, event);//*/
/*TestEvent2 event2;
event2.a = data.test[i].gg + 8;
gEM.sendEvent(data.entity[i].id, event2);//*/
//gEM.sendEvent!(TestEvent)(data.entity[i].id, event);
//gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent());
} }
} }
@ -247,7 +271,7 @@ import std.meta;
foreach(i;0..data.test.length) foreach(i;0..data.test.length)
{ {
data.test[i].gg -= 1; data.test[i].gg -= 1;
gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent()); //gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent());
} }
} }
@ -257,6 +281,9 @@ import std.meta;
}*/ }*/
} }
int main()
{
void dispatch(EntityManager.JobGroup jobs) void dispatch(EntityManager.JobGroup jobs)
{ {
foreach(job;jobs.jobs) foreach(job;jobs.jobs)