-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
.dub
/.vscode
LOC
perf.data
perf.data.old
*.o
*.a
*.obj
*.exe
*.lib
*.so
*.def
*.lib
*.dll
*.exp
*
!source
!tests
!dub.json
!.gitignore

View file

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

View file

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

View file

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

View file

@ -4,15 +4,19 @@ import ecs.manager;
import ecs.block_allocator;
import ecs.entity;
import std.experimental.allocator;
import std.experimental.allocator.mallocator : AlignedMallocator, Mallocator;
import std.algorithm.comparison : max;
/*
struct Event
/*struct Event
{
uint type;
uint id;
}*/
mixin template EventManagerCode()
//mixin template EventManagerCode()
struct EventManager
{
//@disable this();
@ -22,7 +26,7 @@ mixin template EventManagerCode()
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 alignment = cast(ushort)(Ev.alignof);
@ -53,8 +57,6 @@ mixin template EventManagerCode()
aligned_index = index;
alignNum(aligned_index, alignment);
/*if(alignment > EntityID.sizeof + uint.sizeof)aligned_index = alignment;
else aligned_index = uint.sizeof * 4;*/
}
EventBlock* block = list.current_block;
@ -66,22 +68,101 @@ mixin template EventManagerCode()
*cast(EntityID*)&block.data[index + 2] = id;
*cast(Ev*)&block.data[aligned_index] = event;
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()
{
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;
process_events = tmp;
EventBlock* block = process_events.first_block;
/*if(block)
{
import std.stdio;
writeln(block.data);
}*/
while (block)
{
EventBlock* free = block;
@ -89,7 +170,30 @@ mixin template EventManagerCode()
allocator.freeBlock(free);
}
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.
@ -99,7 +203,7 @@ mixin template EventManagerCode()
struct EventBlock
{
union
/*union
{
struct
{
@ -108,17 +212,31 @@ mixin template EventManagerCode()
}
ubyte[events_block_size] data;
}
}*/
EventBlock* next;
ushort count = 0;
}
struct EventList
/*struct EventList
{
EventBlock* first_block;
EventBlock* current_block;
}*/
struct EventData
{
ushort data_offset;
ushort max_events;
EventBlock*[] blocks;
EventBlock*[] first_blocks;
//EventBlock*[] current_blocks;
}
EventList current_events;
EventList process_events;
/*EventList current_events;
EventList process_events;*/
uint current_index = 0;
EventData[] events;
BlockAllocator/*!(events_block_size, events_blocks_in_allocation)*/ allocator;
EntityManager manager;

View file

@ -57,12 +57,12 @@ class EntityManager
*/
void beginRegister()
{
assert(!register_state,"beginRegister() can't be called twice before endRegister();");
assert(!register_state, "beginRegister() can't be called twice before endRegister();");
register_state = true;
foreach(pass;passes)
foreach (pass; passes)
{
foreach(caller;pass.system_callers)
foreach (caller; pass.system_callers)
{
Mallocator.instance.dispose(caller);
}
@ -75,10 +75,10 @@ class EntityManager
*/
void endRegister()
{
assert(register_state,"beginRegister() should be called before endRegister();");
assert(register_state, "beginRegister() should be called before endRegister();");
register_state = false;
foreach(ref system;systems)
foreach (ref system; systems)
{
if (system.m_update is null)
continue;
@ -104,9 +104,44 @@ class EntityManager
passes[system.m_pass].system_callers.add(sys_caller);
}
foreach(info;&entities_infos.byValue)
foreach (info; &entities_infos.byValue)
{
addSystemCaller(*info,system.id);
addSystemCaller(*info, system.id);
}
}
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]++;
}
}
@ -119,10 +154,11 @@ class EntityManager
this(uint threads_count)
{
if (threads_count == 0)
threads_count = 0;
threads_count = 1;
threads = Mallocator.instance.makeArray!ThreadData(threads_count);
id_manager.initialize();
event_manager.initialize(this);
allocator = BlockAllocator(page_size, pages_in_block);
@ -144,7 +180,7 @@ class EntityManager
void registerSystem(Sys)(int priority, const(char)[] pass_name)
{
ushort pass = passes_map.get(pass_name, ushort.max);
assert(pass != ushort.max,"Update pass (Name "~pass_name~") doesn't exist.");
assert(pass != ushort.max, "Update pass (Name " ~ pass_name ~ ") doesn't exist.");
registerSystem!(Sys)(priority, pass);
}
@ -158,17 +194,18 @@ class EntityManager
*/
void registerSystem(Sys)(int priority, ushort pass = 0)
{
alias STC = ParameterStorageClass;
//alias STC = ParameterStorageClass;
assert(register_state,"asda");
assert(pass < passes.length,"Update pass (ID "~pass.to!string~") doesn't exist.");
assert(register_state,
"registerSystem must be called between beginRegister() and endRegister().");
assert(pass < passes.length, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist.");
System system;
system.m_pass = pass;
static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
{
static assert(0, "Add \"mixin ECS.System;\" in top of system structure;");//"System should have \"__gshared ushort system_id");
static assert(0, "Add \"mixin ECS.System;\" in top of system structure;"); //"System should have \"__gshared ushort system_id");
}
static if (!(hasMember!(Sys, "EntitiesData")))
@ -176,6 +213,126 @@ class EntityManager
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()()
{
@ -199,7 +356,7 @@ class EntityManager
uint req;
uint opt;
uint absent;
uint excluded;
uint read_only;
uint modified;
foreach (member; __traits(allMembers, Sys.EntitiesData))
@ -230,9 +387,9 @@ class EntityManager
attribs++;
//break;
}
else if (att == "absent")
else if (att == "excluded")
{
absent++;
excluded++;
attribs++;
//break;
}
@ -242,7 +399,7 @@ class EntityManager
}
}
assert(attribs <= 1,
"EntitiesData member can't have both \"@optional\" and \"@absent\".");
"EntitiesData member can't have both \"@optional\" and \"@excluded\".");
if (!attribs)
req++;
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)))
&& allSameType!(string, typeof(Sys.AbsentComponents))
&& isExpressions!(Sys.AbsentComponents))
else static if (__traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents)))
&& allSameType!(string, typeof(Sys.ExcludedComponents))
&& isExpressions!(Sys.ExcludedComponents))
{
absent += Sys.AbsentComponents.length;
excluded += Sys.ExcludedComponents.length;
}
}
@ -273,39 +430,39 @@ class EntityManager
if (opt > 0)
ret ~= "system.m_optional_components = Mallocator.instance.makeArray!ushort("
~ opt.to!string ~ ");";
if (absent > 0)
ret ~= "system.m_absent_components = Mallocator.instance.makeArray!ushort("
~ absent.to!string ~ ");";
if (excluded > 0)
ret ~= "system.m_excluded_components = Mallocator.instance.makeArray!ushort("
~ excluded.to!string ~ ");";
if (read_only > 0)
ret ~= "system.m_read_only_components = Mallocator.instance.makeArray!ushort("
~ read_only.to!string ~ ");";
if (modified > 0)
ret ~= "system.m_modified_components = Mallocator.instance.makeArray!ushort("
~ 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;
req = 0;
absent = 0;
excluded = 0;
read_only = 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.");
foreach (str; Fields!(Sys.AbsentComponents))
ret ~= "system.m_absent_components[" ~ (absent++)
//static assert(0,"Enum ExcludedComponents are not implemented yet.");
foreach (str; Fields!(Sys.ExcludedComponents))
ret ~= "system.m_excluded_components[" ~ (excluded++)
.to!string ~ "] = components_map.get(\""
~ str.stringof ~ "\", ushort.max);";
}
else static if (__traits(compiles, allSameType!(string, typeof(Sys.AbsentComponents)))
&& allSameType!(string, typeof(Sys.AbsentComponents))
&& isExpressions!(Sys.AbsentComponents))
else static if (__traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents)))
&& allSameType!(string, typeof(Sys.ExcludedComponents))
&& isExpressions!(Sys.ExcludedComponents))
{
foreach (str; Sys.AbsentComponents)
ret ~= "system.m_absent_components[" ~ (absent++)
foreach (str; Sys.ExcludedComponents)
ret ~= "system.m_excluded_components[" ~ (excluded++)
.to!string ~ "] = components_map.get(\"" ~ str ~ "\", ushort.max);";
}
}
@ -349,9 +506,9 @@ class EntityManager
has_att = true;
//break;
}
else if (att == "absent")
else if (att == "excluded")
{
ret ~= "system.m_absent_components[" ~ (absent++)
ret ~= "system.m_excluded_components[" ~ (excluded++)
.to!string ~ "] = comp;";
has_att = true;
//break;
@ -399,7 +556,7 @@ class EntityManager
ushort comp;
uint req = 0;
uint opt = 0;
uint absent = 0;
uint excluded = 0;
foreach (member; __traits(allMembers, Sys.EntitiesData))
{
if (is(typeof(__traits(getMember, Sys.EntitiesData,
@ -435,9 +592,9 @@ class EntityManager
has_att = true;
break;
}
else if (att == "absent")
else if (att == "excluded")
{
absent++;
excluded++;
has_att = true;
break;
}
@ -601,7 +758,7 @@ class EntityManager
static if (!(hasMember!(Comp, "component_id")) || !is(typeof(Comp.component_id) == ushort))
{
static assert(0, "Add \"mixin ECS.Component;\" in top of component structure;");//"Component should have \"__gshared ushort component_id");
static assert(0, "Add \"mixin ECS.Component;\" in top of component structure;"); //"Component should have \"__gshared ushort component_id");
}
static if (hasMember!(Comp, "onDestroy") && isFunction!(Comp.onDestroy)
@ -642,7 +799,7 @@ class EntityManager
static if (!(hasMember!(Ev, "event_id")) || !is(typeof(Ev.event_id) == ushort))
{
static assert(0, "Add \"mixin ECS.Event;\" in top of event structure;");//"Event should have \"__gshared ushort event_id");
static assert(0, "Add \"mixin ECS.Event;\" in top of event structure;"); //"Event should have \"__gshared ushort event_id");
}
static if (hasMember!(Ev, "onDestroy") && isFunction!(Ev.onDestroy)
@ -979,9 +1136,9 @@ class EntityManager
{
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)
{
@ -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()
{
updateEvents();
id_manager.optimize();
updateBlocks();
removeEntities();
changeEntities();
event_manager.clearEvents();
}
/************************************************************************************************************************
@ -1601,7 +1812,8 @@ class EntityManager
foreach (ref system; systems)
{
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();
//clearEvents();
//event_manager.clearEvents();
}
private void getThreadID()
@ -1630,6 +1842,11 @@ class EntityManager
thread_id = 0;
}
void sendEvent(Ev)(EntityID id, Ev event)
{
event_manager.sendEvent(id, event, thread_id);
}
/*private */
void generateDependencies()
{
@ -1795,10 +2012,25 @@ class EntityManager
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
{
ushort size;
ushort alignment;
EventCaller[] callers;
void function(void* pointer) destroy_callback;
}
@ -1951,12 +2183,13 @@ class EntityManager
{
~this()
{
if(dependencies)
if (dependencies)
{
Mallocator.instance.dispose(dependencies);
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;
@ -2011,8 +2244,8 @@ class EntityManager
IDManager id_manager;
BlockAllocator /*!(page_size, pages_in_block)*/ allocator;
//EventManager event_manager;
mixin EventManagerCode;
EventManager event_manager;
//mixin EventManagerCode;
//Vector!EntityID entities_to_remove;
//Vector!(EntitiesBlock*) blocks_to_update;

View file

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

View file

@ -10,23 +10,20 @@ import ecs.core;
import core.time;
import std.stdio;
int main()
struct TestEvent
{
struct TestEvent
{
mixin ECS.Event;//__gshared ushort event_id;
int a;
}
}
struct TestEvent2
{
struct TestEvent2
{
mixin ECS.Event;//__gshared ushort event_id;
float a;
}
}
static struct TestComp
{
static struct TestComp
{
mixin ECS.Component;//__gshared ushort component_id;
int a = 1;
ulong b = 2;
@ -40,10 +37,10 @@ int main()
{
}
}
}
static struct TestComp2
{
static struct TestComp2
{
mixin ECS.Component;//__gshared ushort component_id;
int b = 3;
int a = 4;
@ -57,10 +54,10 @@ int main()
{
}
}
}
static struct TestComp3
{
static struct TestComp3
{
mixin ECS.Component;//__gshared ushort component_id;
uint gg = 5; //good game
uint bg = 6; //bad game
@ -74,10 +71,10 @@ int main()
{
}
}
}
static struct TestComp4
{
static struct TestComp4
{
mixin ECS.Component;//__gshared ushort component_id;
uint gg = 7; //good game
uint bg = 8; //bad game
@ -95,10 +92,10 @@ int main()
{
}
}
}
struct TestSystem
{
struct TestSystem
{
mixin ECS.System!16;//__gshared ushort system_id;
void onCreate()
@ -133,7 +130,7 @@ int main()
TestComp[] test;
TestComp2[] test2;
@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)
@ -163,10 +160,10 @@ int main()
{
}
}
}
struct TestSystemWithHighPriority
{
struct TestSystemWithHighPriority
{
mixin ECS.System!16;//__gshared ushort system_id;
static struct EntitiesData
@ -188,30 +185,50 @@ int main()
{
}*/
}
}
import std.meta;
struct TestSystem2
{
struct TestSystem2
{
mixin ECS.System!16;//__gshared ushort system_id;
enum AbsentComponents0
/*enum ExcludedComponents0
{
TestComp,
TestComp4
}
alias AbsentComponents = AliasSeq!("TestComp", "TestComp4");
alias ExcludedComponents = AliasSeq!("TestComp", "TestComp4");
string AbsentComponents2;
string ExcludedComponents2;*/
static struct EntitiesData
{
short length;
const (Entity)[] entity;
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()
@ -233,12 +250,19 @@ import std.meta;
}
void update(ref EntitiesData data)
void update(EntitiesData data)
{
foreach(i;0..data.test.length)
{
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)
{
data.test[i].gg -= 1;
gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent());
//gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent());
}
}
@ -255,7 +279,10 @@ import std.meta;
{
}*/
}
}
int main()
{
void dispatch(EntityManager.JobGroup jobs)
{