-added filterEntity callback (used to filter EntityInfos for system, better control than simply @optional)
-removed some redundant code (two times same code) -added some common functions
This commit is contained in:
parent
13c82acad4
commit
3c1c67efd0
4 changed files with 155 additions and 25 deletions
|
|
@ -128,6 +128,15 @@ export struct EntityTemplate
|
||||||
if(T.component_id >= info.tmpl_deltas.length || info.tmpl_deltas[T.component_id] == ushort.max)return null;
|
if(T.component_id >= info.tmpl_deltas.length || info.tmpl_deltas[T.component_id] == ushort.max)return null;
|
||||||
return cast(T*)(entity_data.ptr + info.tmpl_deltas[T.component_id]);
|
return cast(T*)(entity_data.ptr + info.tmpl_deltas[T.component_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************************************************
|
||||||
|
Get specified component. If component doesn't exist function return null. Returned pointer is valid during EntityTemplate lifetime.
|
||||||
|
*/
|
||||||
|
void* getComponent(ushort component_id) const nothrow @nogc
|
||||||
|
{
|
||||||
|
if(component_id >= info.tmpl_deltas.length || info.tmpl_deltas[component_id] == ushort.max)return null;
|
||||||
|
return cast(void*)(entity_data.ptr + info.tmpl_deltas[component_id]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
|
|
|
||||||
|
|
@ -1110,6 +1110,32 @@ export struct EntityManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void catchEntityFilterFunction(string func_name, RetType = void)(void** member)
|
||||||
|
{
|
||||||
|
static if (hasMember!(Sys, func_name))
|
||||||
|
{
|
||||||
|
foreach (func; __traits(getOverloads, Sys, func_name))
|
||||||
|
{
|
||||||
|
static if ((Parameters!(func)).length == 1
|
||||||
|
&& is(Parameters!(func)[0] == EntityInfo*)
|
||||||
|
&& is(ReturnType!(func) == RetType))
|
||||||
|
{
|
||||||
|
static RetType callFunc(void* system_pointer, EntityInfo* info)
|
||||||
|
{
|
||||||
|
Sys* s = cast(Sys*) system_pointer;
|
||||||
|
static if (is(RetTyp == void))
|
||||||
|
mixin("s." ~ func_name ~ "(info)");
|
||||||
|
else
|
||||||
|
return mixin("s." ~ func_name ~ "(info)");
|
||||||
|
}
|
||||||
|
|
||||||
|
*member = cast(void*)&callFunc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
catchFunction!("onEnable")(&system.m_enable);
|
catchFunction!("onEnable")(&system.m_enable);
|
||||||
catchFunction!("onDisable")(&system.m_disable);
|
catchFunction!("onDisable")(&system.m_disable);
|
||||||
catchFunction!("onCreate")(&system.m_create);
|
catchFunction!("onCreate")(&system.m_create);
|
||||||
|
|
@ -1121,6 +1147,8 @@ export struct EntityManager
|
||||||
catchEntityFunction!("onRemoveEntity")(&system.m_remove_entity);
|
catchEntityFunction!("onRemoveEntity")(&system.m_remove_entity);
|
||||||
catchEntityFunction!("onChangeEntity")(&system.m_change_entity);
|
catchEntityFunction!("onChangeEntity")(&system.m_change_entity);
|
||||||
|
|
||||||
|
catchEntityFilterFunction!("filterEntity", bool)(&system.m_filter_entity);
|
||||||
|
|
||||||
system.m_system_pointer = cast(void*) Mallocator.make!Sys;
|
system.m_system_pointer = cast(void*) Mallocator.make!Sys;
|
||||||
system.m_priority = priority;
|
system.m_priority = priority;
|
||||||
//(cast(Sys*) system.m_system_pointer).__ecsInitialize();
|
//(cast(Sys*) system.m_system_pointer).__ecsInitialize();
|
||||||
|
|
@ -2035,6 +2063,9 @@ export struct EntityManager
|
||||||
is_:
|
is_:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///call Custom Entity Filter test if function exists
|
||||||
|
if(system.m_filter_entity && !(cast(bool function(void* system_pointer, EntityInfo* info) @nogc nothrow)system.m_filter_entity)(system, &entity))return;
|
||||||
|
|
||||||
entity.systems[system_id] = true;
|
entity.systems[system_id] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2077,30 +2108,8 @@ export struct EntityManager
|
||||||
{
|
{
|
||||||
System* system = &systems[system_id];
|
System* system = &systems[system_id];
|
||||||
|
|
||||||
if (system.m_excluded_components)
|
connectListenerToEntityInfo(info, system_id);
|
||||||
{
|
if(!info.systems[system_id])return;
|
||||||
foreach (id; system.m_excluded_components)
|
|
||||||
{
|
|
||||||
foreach (id2; info.components)
|
|
||||||
{
|
|
||||||
if (id == id2)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (id; system.m_components)
|
|
||||||
{
|
|
||||||
foreach (i2, id2; info.components)
|
|
||||||
{
|
|
||||||
if (id2 == id)
|
|
||||||
goto is_;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
is_:
|
|
||||||
}
|
|
||||||
|
|
||||||
info.systems[system_id] = true;
|
|
||||||
|
|
||||||
uint index = 0;
|
uint index = 0;
|
||||||
for (; index < passes[system.m_pass].system_callers.length; index++)
|
for (; index < passes[system.m_pass].system_callers.length; index++)
|
||||||
|
|
@ -3483,6 +3492,12 @@ export struct EntityManager
|
||||||
return new_info;
|
return new_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export bool hasComponent(ushort component_id)
|
||||||
|
{
|
||||||
|
if(component_id >= deltas.length || !deltas[component_id])return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
export ~this() @nogc nothrow
|
export ~this() @nogc nothrow
|
||||||
{
|
{
|
||||||
if (components)
|
if (components)
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,8 @@ package:
|
||||||
void* m_remove_entity;
|
void* m_remove_entity;
|
||||||
void* m_change_entity;
|
void* m_change_entity;
|
||||||
|
|
||||||
|
void* m_filter_entity;
|
||||||
|
|
||||||
//void function(ref EntityManager.CallData data) m_initialize;
|
//void function(ref EntityManager.CallData data) m_initialize;
|
||||||
//void function(ref EntityManager.CallData data) m_deinitilize;
|
//void function(ref EntityManager.CallData data) m_deinitilize;
|
||||||
void* m_initialize;
|
void* m_initialize;
|
||||||
|
|
|
||||||
104
tests/basic.d
104
tests/basic.d
|
|
@ -139,6 +139,7 @@ void afterEveryTest()
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
EntityTemplate* tmpl_ = gEM.allocateTemplate([CInt.component_id, CFloat.component_id, CFlag.component_id].staticArray);
|
EntityTemplate* tmpl_ = gEM.allocateTemplate([CInt.component_id, CFloat.component_id, CFlag.component_id].staticArray);
|
||||||
|
scope(exit)gEM.freeTemplate(tmpl_);
|
||||||
Entity* entity = gEM.addEntity(tmpl_);
|
Entity* entity = gEM.addEntity(tmpl_);
|
||||||
EntityMeta meta = entity.getMeta();
|
EntityMeta meta = entity.getMeta();
|
||||||
assert(meta.hasComponent(CInt.component_id));
|
assert(meta.hasComponent(CInt.component_id));
|
||||||
|
|
@ -1616,3 +1617,106 @@ unittest
|
||||||
assert(pass.system_callers[4].dependencies[0].system_id == TestSystem2.system_id);
|
assert(pass.system_callers[4].dependencies[0].system_id == TestSystem2.system_id);
|
||||||
assert(pass.system_callers[4].dependencies[1].system_id == TestSystem4.system_id);
|
assert(pass.system_callers[4].dependencies[1].system_id == TestSystem4.system_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@("CustomFilter")
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
struct TestSystem
|
||||||
|
{
|
||||||
|
mixin ECS.System;
|
||||||
|
|
||||||
|
struct EntitiesData
|
||||||
|
{
|
||||||
|
uint length;
|
||||||
|
@optional CInt[] int_;
|
||||||
|
@optional CLong[] long_;
|
||||||
|
@optional CFloat[] float_;
|
||||||
|
@optional CDouble[] double_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool filterEntity(EntityManager.EntityInfo* info)
|
||||||
|
{
|
||||||
|
if(!info.hasComponent(CInt.component_id))return false;
|
||||||
|
int one_from = 0;
|
||||||
|
if(info.hasComponent(CLong.component_id))one_from++;
|
||||||
|
if(info.hasComponent(CFloat.component_id))one_from++;
|
||||||
|
if(info.hasComponent(CDouble.component_id))one_from++;
|
||||||
|
if(one_from == 1)return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onUpdate(EntitiesData entities)
|
||||||
|
{
|
||||||
|
updates++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint updates = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestSystem2
|
||||||
|
{
|
||||||
|
mixin ECS.System;
|
||||||
|
|
||||||
|
struct EntitiesData
|
||||||
|
{
|
||||||
|
uint length;
|
||||||
|
@optional CInt[] int_;
|
||||||
|
@optional CLong[] long_;
|
||||||
|
@optional CFloat[] float_;
|
||||||
|
@optional CDouble[] double_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool filterEntity(EntityManager.EntityInfo* info)
|
||||||
|
{
|
||||||
|
if(info.hasComponent(CInt.component_id) && info.hasComponent(CFloat.component_id) && !info.hasComponent(CLong.component_id) && !info.hasComponent(CDouble.component_id))return true;
|
||||||
|
if(info.hasComponent(CLong.component_id) && info.hasComponent(CDouble.component_id) && !info.hasComponent(CInt.component_id) && !info.hasComponent(CFloat.component_id))return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onUpdate(EntitiesData entities)
|
||||||
|
{
|
||||||
|
updates++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint updates = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gEM.beginRegister();
|
||||||
|
|
||||||
|
gEM.registerSystem!TestSystem(0);
|
||||||
|
gEM.registerSystem!TestSystem2(1);
|
||||||
|
|
||||||
|
gEM.endRegister();
|
||||||
|
|
||||||
|
|
||||||
|
EntityTemplate* tmpl_ = gEM.allocateTemplate([CInt.component_id, CLong.component_id, CFloat.component_id, CDouble.component_id].staticArray);
|
||||||
|
scope(exit)gEM.freeTemplate(tmpl_);
|
||||||
|
EntityTemplate* tmpl_2 = gEM.allocateTemplate([CInt.component_id, CFloat.component_id].staticArray);
|
||||||
|
scope(exit)gEM.freeTemplate(tmpl_2);
|
||||||
|
EntityTemplate* tmpl_3 = gEM.allocateTemplate([CLong.component_id, CDouble.component_id].staticArray);
|
||||||
|
scope(exit)gEM.freeTemplate(tmpl_3);
|
||||||
|
EntityTemplate* tmpl_4 = gEM.allocateTemplate([CInt.component_id, CLong.component_id, CDouble.component_id].staticArray);
|
||||||
|
scope(exit)gEM.freeTemplate(tmpl_4);
|
||||||
|
EntityTemplate* tmpl_5 = gEM.allocateTemplate([CInt.component_id, CDouble.component_id].staticArray);
|
||||||
|
scope(exit)gEM.freeTemplate(tmpl_5);
|
||||||
|
EntityTemplate* tmpl_6 = gEM.allocateTemplate([CDouble.component_id].staticArray);
|
||||||
|
scope(exit)gEM.freeTemplate(tmpl_6);
|
||||||
|
|
||||||
|
gEM.addEntity(tmpl_);
|
||||||
|
gEM.addEntity(tmpl_2);
|
||||||
|
gEM.addEntity(tmpl_3);
|
||||||
|
gEM.addEntity(tmpl_4);
|
||||||
|
gEM.addEntity(tmpl_5);
|
||||||
|
gEM.addEntity(tmpl_6);
|
||||||
|
|
||||||
|
TestSystem* test_system = gEM.getSystem!TestSystem;
|
||||||
|
TestSystem2* test_system2 = gEM.getSystem!TestSystem2;
|
||||||
|
|
||||||
|
gEM.begin();
|
||||||
|
gEM.update();
|
||||||
|
gEM.end();
|
||||||
|
|
||||||
|
assert(test_system.updates == 2);
|
||||||
|
assert(test_system2.updates == 2);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue