-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:
parent
16a5696840
commit
3bc5ff2423
8 changed files with 689 additions and 310 deletions
22
.gitignore
vendored
22
.gitignore
vendored
|
|
@ -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
|
||||
3
dub.json
3
dub.json
|
|
@ -10,6 +10,9 @@
|
|||
"dflags-posix-ldc": [
|
||||
"-defaultlib=phobos2-ldc,druntime-ldc"
|
||||
],
|
||||
"dflagss": [
|
||||
"-betterC"
|
||||
],
|
||||
"configurations" : [
|
||||
{
|
||||
"name" : "library",
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,13 +75,13 @@ 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;
|
||||
continue;
|
||||
|
||||
bool added = false;
|
||||
foreach (i, caller; passes[system.m_pass].system_callers)
|
||||
|
|
@ -103,10 +103,45 @@ class EntityManager
|
|||
sys_caller.job_group.caller = sys_caller;
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
453
tests/tests.d
453
tests/tests.d
|
|
@ -10,253 +10,280 @@ import ecs.core;
|
|||
import core.time;
|
||||
import std.stdio;
|
||||
|
||||
int main()
|
||||
struct TestEvent
|
||||
{
|
||||
mixin ECS.Event;//__gshared ushort event_id;
|
||||
int a;
|
||||
}
|
||||
|
||||
struct TestEvent
|
||||
struct TestEvent2
|
||||
{
|
||||
mixin ECS.Event;//__gshared ushort event_id;
|
||||
float a;
|
||||
}
|
||||
|
||||
static struct TestComp
|
||||
{
|
||||
mixin ECS.Component;//__gshared ushort component_id;
|
||||
int a = 1;
|
||||
ulong b = 2;
|
||||
|
||||
static void serializeComponent(SerializeVector output)
|
||||
{
|
||||
mixin ECS.Event;//__gshared ushort event_id;
|
||||
int a;
|
||||
|
||||
}
|
||||
|
||||
struct TestEvent2
|
||||
static void deserializeComponent(ubyte[] data)
|
||||
{
|
||||
mixin ECS.Event;//__gshared ushort event_id;
|
||||
float a;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static struct TestComp2
|
||||
{
|
||||
mixin ECS.Component;//__gshared ushort component_id;
|
||||
int b = 3;
|
||||
int a = 4;
|
||||
|
||||
static void serializeComponent(ref TestComp comp, SerializeVector output)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static struct TestComp
|
||||
static void deserializeComponent(ref TestComp comp, ubyte[] data)
|
||||
{
|
||||
mixin ECS.Component;//__gshared ushort component_id;
|
||||
int a = 1;
|
||||
ulong b = 2;
|
||||
|
||||
static void serializeComponent(SerializeVector output)
|
||||
}
|
||||
}
|
||||
|
||||
static struct TestComp3
|
||||
{
|
||||
mixin ECS.Component;//__gshared ushort component_id;
|
||||
uint gg = 5; //good game
|
||||
uint bg = 6; //bad game
|
||||
|
||||
void serializeComponent(SerializeVector output)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void deserializeComponent(ubyte[] data)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static struct TestComp4
|
||||
{
|
||||
mixin ECS.Component;//__gshared ushort component_id;
|
||||
uint gg = 7; //good game
|
||||
uint bg = 8; //bad game
|
||||
ulong a = 9;
|
||||
ulong b = 10;
|
||||
ulong c = 11;
|
||||
ulong g = 12;
|
||||
|
||||
static void serializeComponent(ref TestComp comp, SerializeVector output)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void deserializeComponent(ref TestComp comp, ubyte[] data)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSystem
|
||||
{
|
||||
mixin ECS.System!16;//__gshared ushort system_id;
|
||||
|
||||
void onCreate()
|
||||
{
|
||||
writeln("On Test System create.");
|
||||
}
|
||||
|
||||
void onDestroy()
|
||||
{
|
||||
writeln("On Test System destroy.");
|
||||
}
|
||||
|
||||
bool onBegin()
|
||||
{
|
||||
//writeln("On Test System begin.");
|
||||
return true;
|
||||
}
|
||||
|
||||
void onEnd()
|
||||
{
|
||||
//writeln("On Test System end.");
|
||||
}
|
||||
|
||||
void initialize(ref Entity entity, ref TestComp comp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static struct EntitiesData
|
||||
{
|
||||
size_t length;
|
||||
TestComp[] test;
|
||||
TestComp2[] test2;
|
||||
@readonly @optional const(TestComp3)[] test3;
|
||||
//@excluded TestComp4[] test4;
|
||||
}
|
||||
|
||||
void update(ref Entity entity, ref TestComp test, ref TestComp2 test2)//, TestComp3* test3) //ref TestComp comp)
|
||||
{
|
||||
assert(cast(size_t)&test % TestComp.alignof == 0);
|
||||
assert(cast(size_t)&test2 % TestComp2.alignof == 0);
|
||||
import std.stdio;
|
||||
|
||||
test.a += 1000;
|
||||
test.b += 2000;
|
||||
test2.b += 2;
|
||||
test2.a = 8;
|
||||
}
|
||||
|
||||
void update(EntitiesData data)
|
||||
{
|
||||
foreach(i;0..data.length)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void deserializeComponent(ubyte[] data)
|
||||
{
|
||||
|
||||
data.test[i].a += 1000;
|
||||
data.test[i].b += 2000;
|
||||
data.test2[i].b += 2;
|
||||
data.test2[i].a = 8;
|
||||
}
|
||||
}
|
||||
|
||||
static struct TestComp2
|
||||
void handleEvent(TestEvent event, ref TestComp test, ref TestComp2 test2, TestComp3* test3)
|
||||
{
|
||||
mixin ECS.Component;//__gshared ushort component_id;
|
||||
int b = 3;
|
||||
int a = 4;
|
||||
|
||||
static void serializeComponent(ref TestComp comp, SerializeVector output)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
struct TestSystemWithHighPriority
|
||||
{
|
||||
mixin ECS.System!16;//__gshared ushort system_id;
|
||||
|
||||
static void deserializeComponent(ref TestComp comp, ubyte[] data)
|
||||
{
|
||||
|
||||
}
|
||||
static struct EntitiesData
|
||||
{
|
||||
TestComp[] test;
|
||||
}
|
||||
|
||||
static struct TestComp3
|
||||
void initialize(ref Entity entity, ref TestComp comp)
|
||||
{
|
||||
mixin ECS.Component;//__gshared ushort component_id;
|
||||
uint gg = 5; //good game
|
||||
uint bg = 6; //bad game
|
||||
|
||||
void serializeComponent(SerializeVector output)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void deserializeComponent(ubyte[] data)
|
||||
{
|
||||
|
||||
}
|
||||
int o = 1;
|
||||
}
|
||||
|
||||
static struct TestComp4
|
||||
void update(EntitiesData data)
|
||||
{
|
||||
mixin ECS.Component;//__gshared ushort component_id;
|
||||
uint gg = 7; //good game
|
||||
uint bg = 8; //bad game
|
||||
ulong a = 9;
|
||||
ulong b = 10;
|
||||
ulong c = 11;
|
||||
ulong g = 12;
|
||||
|
||||
static void serializeComponent(ref TestComp comp, SerializeVector output)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void deserializeComponent(ref TestComp comp, ubyte[] data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct TestSystem
|
||||
/*void handleEvent(Event event, ref TestComp comp)
|
||||
{
|
||||
mixin ECS.System!16;//__gshared ushort system_id;
|
||||
|
||||
void onCreate()
|
||||
{
|
||||
writeln("On Test System create.");
|
||||
}
|
||||
|
||||
void onDestroy()
|
||||
{
|
||||
writeln("On Test System destroy.");
|
||||
}
|
||||
|
||||
bool onBegin()
|
||||
{
|
||||
//writeln("On Test System begin.");
|
||||
return true;
|
||||
}
|
||||
|
||||
void onEnd()
|
||||
{
|
||||
//writeln("On Test System end.");
|
||||
}
|
||||
|
||||
void initialize(ref Entity entity, ref TestComp comp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static struct EntitiesData
|
||||
{
|
||||
size_t length;
|
||||
TestComp[] test;
|
||||
TestComp2[] test2;
|
||||
@readonly @optional const(TestComp3)[] test3;
|
||||
//@absent TestComp4[] test4;
|
||||
}
|
||||
|
||||
void update(ref Entity entity, ref TestComp test, ref TestComp2 test2)//, TestComp3* test3) //ref TestComp comp)
|
||||
{
|
||||
assert(cast(size_t)&test % TestComp.alignof == 0);
|
||||
assert(cast(size_t)&test2 % TestComp2.alignof == 0);
|
||||
import std.stdio;
|
||||
|
||||
test.a += 1000;
|
||||
test.b += 2000;
|
||||
test2.b += 2;
|
||||
test2.a = 8;
|
||||
}
|
||||
|
||||
void update(EntitiesData data)
|
||||
{
|
||||
foreach(i;0..data.length)
|
||||
{
|
||||
data.test[i].a += 1000;
|
||||
data.test[i].b += 2000;
|
||||
data.test2[i].b += 2;
|
||||
data.test2[i].a = 8;
|
||||
}
|
||||
}
|
||||
|
||||
void handleEvent(TestEvent event, ref TestComp test, ref TestComp2 test2, TestComp3* test3)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSystemWithHighPriority
|
||||
{
|
||||
mixin ECS.System!16;//__gshared ushort system_id;
|
||||
|
||||
static struct EntitiesData
|
||||
{
|
||||
TestComp[] test;
|
||||
}
|
||||
|
||||
void initialize(ref Entity entity, ref TestComp comp)
|
||||
{
|
||||
int o = 1;
|
||||
}
|
||||
|
||||
void update(EntitiesData data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*void handleEvent(Event event, ref TestComp comp)
|
||||
{
|
||||
|
||||
}*/
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
import std.meta;
|
||||
|
||||
struct TestSystem2
|
||||
struct TestSystem2
|
||||
{
|
||||
mixin ECS.System!16;//__gshared ushort system_id;
|
||||
|
||||
/*enum ExcludedComponents0
|
||||
{
|
||||
mixin ECS.System!16;//__gshared ushort system_id;
|
||||
|
||||
enum AbsentComponents0
|
||||
{
|
||||
TestComp,
|
||||
TestComp4
|
||||
}
|
||||
|
||||
alias AbsentComponents = AliasSeq!("TestComp", "TestComp4");
|
||||
|
||||
string AbsentComponents2;
|
||||
|
||||
static struct EntitiesData
|
||||
{
|
||||
short length;
|
||||
const (Entity)[] entity;
|
||||
TestComp3[] test;
|
||||
//@absent TestComp[] testt;
|
||||
}
|
||||
|
||||
void onEnable()
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
writeln("TestSystem2 enabled");
|
||||
}
|
||||
|
||||
void onDisable()
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
writeln("TestSystem2 disabled");
|
||||
}
|
||||
|
||||
void initialize(ref Entity entity, ref TestComp comp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void update(ref EntitiesData data)
|
||||
{
|
||||
foreach(i;0..data.test.length)
|
||||
{
|
||||
data.test[i].gg += 14;
|
||||
gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void lateUpdate(ref EntitiesData data)
|
||||
{
|
||||
foreach(i;0..data.test.length)
|
||||
{
|
||||
data.test[i].gg -= 1;
|
||||
gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent());
|
||||
}
|
||||
}
|
||||
|
||||
/*void handleEvent(Event event, ref TestComp comp)
|
||||
{
|
||||
|
||||
}*/
|
||||
TestComp,
|
||||
TestComp4
|
||||
}
|
||||
|
||||
alias ExcludedComponents = AliasSeq!("TestComp", "TestComp4");
|
||||
|
||||
string ExcludedComponents2;*/
|
||||
|
||||
static struct EntitiesData
|
||||
{
|
||||
short length;
|
||||
const (Entity)[] entity;
|
||||
TestComp3[] test;
|
||||
//@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()
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
writeln("TestSystem2 enabled");
|
||||
}
|
||||
|
||||
void onDisable()
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
writeln("TestSystem2 disabled");
|
||||
}
|
||||
|
||||
void initialize(ref Entity entity, ref TestComp comp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void update(EntitiesData data)
|
||||
{
|
||||
foreach(i;0..data.test.length)
|
||||
{
|
||||
data.test[i].gg += 14;
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
void lateUpdate(ref EntitiesData data)
|
||||
{
|
||||
foreach(i;0..data.test.length)
|
||||
{
|
||||
data.test[i].gg -= 1;
|
||||
//gEM.sendSelfEvent!(TestEvent)(data.entity[i].id, TestEvent());
|
||||
}
|
||||
}
|
||||
|
||||
/*void handleEvent(Event event, ref TestComp comp)
|
||||
{
|
||||
|
||||
}*/
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
void dispatch(EntityManager.JobGroup jobs)
|
||||
{
|
||||
foreach(job;jobs.jobs)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue