-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
|
!source
|
||||||
.dub
|
!tests
|
||||||
/.vscode
|
!dub.json
|
||||||
LOC
|
!.gitignore
|
||||||
perf.data
|
|
||||||
perf.data.old
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.obj
|
|
||||||
*.exe
|
|
||||||
*.lib
|
|
||||||
*.so
|
|
||||||
*.def
|
|
||||||
*.lib
|
|
||||||
*.dll
|
|
||||||
*.exp
|
|
||||||
3
dub.json
3
dub.json
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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";
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -57,12 +57,12 @@ class EntityManager
|
||||||
*/
|
*/
|
||||||
void beginRegister()
|
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;
|
register_state = true;
|
||||||
|
|
||||||
foreach(pass;passes)
|
foreach (pass; passes)
|
||||||
{
|
{
|
||||||
foreach(caller;pass.system_callers)
|
foreach (caller; pass.system_callers)
|
||||||
{
|
{
|
||||||
Mallocator.instance.dispose(caller);
|
Mallocator.instance.dispose(caller);
|
||||||
}
|
}
|
||||||
|
|
@ -75,10 +75,10 @@ class EntityManager
|
||||||
*/
|
*/
|
||||||
void endRegister()
|
void endRegister()
|
||||||
{
|
{
|
||||||
assert(register_state,"beginRegister() should be called before endRegister();");
|
assert(register_state, "beginRegister() should be called before endRegister();");
|
||||||
register_state = false;
|
register_state = false;
|
||||||
|
|
||||||
foreach(ref system;systems)
|
foreach (ref system; systems)
|
||||||
{
|
{
|
||||||
if (system.m_update is null)
|
if (system.m_update is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -104,9 +104,44 @@ class EntityManager
|
||||||
passes[system.m_pass].system_callers.add(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)
|
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);
|
||||||
|
|
||||||
|
|
@ -144,7 +180,7 @@ class EntityManager
|
||||||
void registerSystem(Sys)(int priority, const(char)[] pass_name)
|
void registerSystem(Sys)(int priority, const(char)[] pass_name)
|
||||||
{
|
{
|
||||||
ushort pass = passes_map.get(pass_name, ushort.max);
|
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);
|
registerSystem!(Sys)(priority, pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,17 +194,18 @@ 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,
|
||||||
assert(pass < passes.length,"Update pass (ID "~pass.to!string~") doesn't exist.");
|
"registerSystem must be called between beginRegister() and endRegister().");
|
||||||
|
assert(pass < passes.length, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist.");
|
||||||
|
|
||||||
System system;
|
System system;
|
||||||
system.m_pass = pass;
|
system.m_pass = pass;
|
||||||
|
|
||||||
static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
|
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")))
|
static if (!(hasMember!(Sys, "EntitiesData")))
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
@ -601,7 +758,7 @@ class EntityManager
|
||||||
|
|
||||||
static if (!(hasMember!(Comp, "component_id")) || !is(typeof(Comp.component_id) == ushort))
|
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)
|
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 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)
|
static if (hasMember!(Ev, "onDestroy") && isFunction!(Ev.onDestroy)
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1951,12 +2183,13 @@ class EntityManager
|
||||||
{
|
{
|
||||||
~this()
|
~this()
|
||||||
{
|
{
|
||||||
if(dependencies)
|
if (dependencies)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
101
tests/tests.d
101
tests/tests.d
|
|
@ -10,23 +10,20 @@ 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;
|
||||||
int a;
|
int a;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestEvent2
|
struct TestEvent2
|
||||||
{
|
{
|
||||||
mixin ECS.Event;//__gshared ushort event_id;
|
mixin ECS.Event;//__gshared ushort event_id;
|
||||||
float a;
|
float a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct TestComp
|
static struct TestComp
|
||||||
{
|
{
|
||||||
mixin ECS.Component;//__gshared ushort component_id;
|
mixin ECS.Component;//__gshared ushort component_id;
|
||||||
int a = 1;
|
int a = 1;
|
||||||
ulong b = 2;
|
ulong b = 2;
|
||||||
|
|
@ -40,10 +37,10 @@ int main()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct TestComp2
|
static struct TestComp2
|
||||||
{
|
{
|
||||||
mixin ECS.Component;//__gshared ushort component_id;
|
mixin ECS.Component;//__gshared ushort component_id;
|
||||||
int b = 3;
|
int b = 3;
|
||||||
int a = 4;
|
int a = 4;
|
||||||
|
|
@ -57,10 +54,10 @@ int main()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct TestComp3
|
static struct TestComp3
|
||||||
{
|
{
|
||||||
mixin ECS.Component;//__gshared ushort component_id;
|
mixin ECS.Component;//__gshared ushort component_id;
|
||||||
uint gg = 5; //good game
|
uint gg = 5; //good game
|
||||||
uint bg = 6; //bad 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;
|
mixin ECS.Component;//__gshared ushort component_id;
|
||||||
uint gg = 7; //good game
|
uint gg = 7; //good game
|
||||||
uint bg = 8; //bad game
|
uint bg = 8; //bad game
|
||||||
|
|
@ -95,10 +92,10 @@ int main()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestSystem
|
struct TestSystem
|
||||||
{
|
{
|
||||||
mixin ECS.System!16;//__gshared ushort system_id;
|
mixin ECS.System!16;//__gshared ushort system_id;
|
||||||
|
|
||||||
void onCreate()
|
void onCreate()
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -163,10 +160,10 @@ int main()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestSystemWithHighPriority
|
struct TestSystemWithHighPriority
|
||||||
{
|
{
|
||||||
mixin ECS.System!16;//__gshared ushort system_id;
|
mixin ECS.System!16;//__gshared ushort system_id;
|
||||||
|
|
||||||
static struct EntitiesData
|
static struct EntitiesData
|
||||||
|
|
@ -188,30 +185,50 @@ int main()
|
||||||
{
|
{
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
import std.meta;
|
import std.meta;
|
||||||
|
|
||||||
struct TestSystem2
|
struct TestSystem2
|
||||||
{
|
{
|
||||||
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,7 +279,10 @@ import std.meta;
|
||||||
{
|
{
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
void dispatch(EntityManager.JobGroup jobs)
|
void dispatch(EntityManager.JobGroup jobs)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue