Demos #10
5 changed files with 440 additions and 5 deletions
|
|
@ -92,4 +92,20 @@ static struct ECS
|
|||
{
|
||||
alias ExcludedComponents = T;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************
|
||||
Make list of readonly ependencies. This template get strings as arguments. Should be added inside System structure.
|
||||
*/
|
||||
mixin template ReadOnlyDependencies(T...)
|
||||
{
|
||||
alias ReadOnlyDependencies = T;
|
||||
}
|
||||
|
||||
/************************************************************************************************************************
|
||||
Make list of writable ependencies. This template get strings as arguments. Should be added inside System structure.
|
||||
*/
|
||||
mixin template WritableDependencies(T...)
|
||||
{
|
||||
alias WritableDependencies = T;
|
||||
}
|
||||
}
|
||||
|
|
@ -452,6 +452,8 @@ export struct EntityManager
|
|||
uint excluded = 1;
|
||||
uint optional = 1;
|
||||
uint req = 1;
|
||||
uint readonly_dep = 1;
|
||||
uint writable_dep = 1;
|
||||
}
|
||||
|
||||
static ComponentsCounts getComponentsCounts()()
|
||||
|
|
@ -532,7 +534,22 @@ export struct EntityManager
|
|||
{
|
||||
components_counts.excluded++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static if (__traits(hasMember, Sys, "ReadOnlyDependencies"))
|
||||
{
|
||||
foreach (str; Sys.ReadOnlyDependencies)
|
||||
{
|
||||
components_counts.readonly_dep++;
|
||||
}
|
||||
}
|
||||
|
||||
static if (__traits(hasMember, Sys, "WritableDependencies"))
|
||||
{
|
||||
foreach (str; Sys.WritableDependencies)
|
||||
{
|
||||
components_counts.writable_dep++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -568,6 +585,16 @@ export struct EntityManager
|
|||
return m_req[0 .. m_req_counter];
|
||||
}
|
||||
|
||||
CompInfo[] readonlyDeps()
|
||||
{
|
||||
return m_readonly_dep[0 .. m_readonly_dep_counter];
|
||||
}
|
||||
|
||||
CompInfo[] writableDeps()
|
||||
{
|
||||
return m_writable_dep[0 .. m_writable_dep_counter];
|
||||
}
|
||||
|
||||
void addReadonly(CompInfo info)
|
||||
{
|
||||
m_readonly[m_readonly_counter++] = info;
|
||||
|
|
@ -593,17 +620,31 @@ export struct EntityManager
|
|||
m_req[m_req_counter++] = info;
|
||||
}
|
||||
|
||||
void addReadonlyDep(CompInfo info)
|
||||
{
|
||||
m_readonly_dep[m_readonly_dep_counter++] = info;
|
||||
}
|
||||
|
||||
void addWritableDep(CompInfo info)
|
||||
{
|
||||
m_writable_dep[m_writable_dep_counter++] = info;
|
||||
}
|
||||
|
||||
CompInfo[counts.readonly] m_readonly;
|
||||
CompInfo[counts.mutable] m_mutable;
|
||||
CompInfo[counts.excluded] m_excluded;
|
||||
CompInfo[counts.optional] m_optional;
|
||||
CompInfo[counts.req] m_req;
|
||||
CompInfo[counts.readonly_dep] m_readonly_dep;
|
||||
CompInfo[counts.writable_dep] m_writable_dep;
|
||||
|
||||
uint m_readonly_counter;
|
||||
uint m_mutable_counter;
|
||||
uint m_excluded_counter;
|
||||
uint m_optional_counter;
|
||||
uint m_req_counter;
|
||||
uint m_readonly_dep_counter;
|
||||
uint m_writable_dep_counter;
|
||||
|
||||
string entites_array;
|
||||
}
|
||||
|
|
@ -616,6 +657,8 @@ export struct EntityManager
|
|||
size_t excluded = components_info.excluded.length;
|
||||
size_t read_only = components_info.readonly.length;
|
||||
size_t modified = components_info.mutable.length;
|
||||
size_t read_only_deps = components_info.readonlyDeps.length;
|
||||
size_t writable_deps = components_info.writableDeps.length;
|
||||
|
||||
if (req > 0)
|
||||
system.m_components = Mallocator.makeArray!ushort(req);
|
||||
|
|
@ -627,6 +670,10 @@ export struct EntityManager
|
|||
system.m_read_only_components = Mallocator.makeArray!ushort(read_only);
|
||||
if (modified > 0)
|
||||
system.m_modified_components = Mallocator.makeArray!ushort(modified);
|
||||
if (read_only_deps > 0)
|
||||
system.m_readonly_dependencies = Mallocator.makeArray!ushort(read_only_deps);
|
||||
if (writable_deps > 0)
|
||||
system.m_writable_dependencies = Mallocator.makeArray!ushort(writable_deps);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -714,6 +761,22 @@ export struct EntityManager
|
|||
}
|
||||
}
|
||||
|
||||
static if (__traits(hasMember, Sys, "ReadOnlyDependencies"))
|
||||
{
|
||||
foreach (str; Sys.ReadOnlyDependencies)
|
||||
{
|
||||
components_info.addReadonlyDep(CompInfo(str, str));
|
||||
}
|
||||
}
|
||||
|
||||
static if (__traits(hasMember, Sys, "WritableDependencies"))
|
||||
{
|
||||
foreach (str; Sys.WritableDependencies)
|
||||
{
|
||||
components_info.addWritableDep(CompInfo(str, str));
|
||||
}
|
||||
}
|
||||
|
||||
return components_info;
|
||||
}
|
||||
|
||||
|
|
@ -809,7 +872,6 @@ export struct EntityManager
|
|||
~ "\" due to non existing component \"" ~ comp_info.type ~ "\".");
|
||||
system.m_modified_components[iii] = comp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void fillInputData(ref Sys.EntitiesData input_data, EntityInfo* info,
|
||||
|
|
@ -1059,6 +1121,32 @@ export struct EntityManager
|
|||
|
||||
genCompList(system, components_map);
|
||||
|
||||
foreach (iii, comp_info; components_info.readonlyDeps)
|
||||
{
|
||||
ushort comp = external_dependencies_map.get(cast(const (char)[]) comp_info.type, ushort.max);
|
||||
version (D_BetterC)
|
||||
assert(comp != ushort.max,
|
||||
"Can't register system \"" ~ Sys.stringof
|
||||
~ "\" due to non existing dependency.");
|
||||
else
|
||||
assert(comp != ushort.max, "Can't register system \"" ~ Sys.stringof
|
||||
~ "\" due to non existing dependency \"" ~ comp_info.type ~ "\".");
|
||||
system.m_readonly_dependencies[iii] = comp;
|
||||
}
|
||||
|
||||
foreach (iii, comp_info; components_info.writableDeps)
|
||||
{
|
||||
ushort comp = external_dependencies_map.get(cast(char[]) comp_info.type, ushort.max);
|
||||
version (D_BetterC)
|
||||
assert(comp != ushort.max,
|
||||
"Can't register system \"" ~ Sys.stringof
|
||||
~ "\" due to non existing dependency.");
|
||||
else
|
||||
assert(comp != ushort.max, "Can't register system \"" ~ Sys.stringof
|
||||
~ "\" due to non existing dependency \"" ~ comp_info.type ~ "\".");
|
||||
system.m_writable_dependencies[iii] = comp;
|
||||
}
|
||||
|
||||
ushort sys_id = systems_map.get(cast(char[]) Sys.stringof, ushort.max);
|
||||
if (sys_id < systems.length)
|
||||
{
|
||||
|
|
@ -1118,6 +1206,11 @@ export struct EntityManager
|
|||
return cast(ushort)(passes.length - 1);
|
||||
}
|
||||
|
||||
export void registerDependency(const(char)[] name)
|
||||
{
|
||||
return external_dependencies_map.add(name, cast(ushort)external_dependencies_map.length);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************
|
||||
Register component into EntityManager.
|
||||
*/
|
||||
|
|
@ -2820,10 +2913,45 @@ export struct EntityManager
|
|||
foreach (caller; pass.system_callers)
|
||||
{
|
||||
index = 0;
|
||||
///gets systems which are excluding each other
|
||||
out_for: foreach (caller2; pass.system_callers)
|
||||
{
|
||||
if (caller is caller2)
|
||||
continue;
|
||||
|
||||
///check for external dependencies
|
||||
foreach (cmp; caller.system.m_readonly_dependencies)
|
||||
{
|
||||
foreach (cmp2; caller2.system.m_writable_dependencies)
|
||||
{
|
||||
if (cmp == cmp2)
|
||||
{
|
||||
exclusion[index++] = caller2;
|
||||
continue out_for;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (cmp; caller.system.m_writable_dependencies)
|
||||
{
|
||||
foreach (cmp2; caller2.system.m_readonly_dependencies)
|
||||
{
|
||||
if (cmp == cmp2)
|
||||
{
|
||||
exclusion[index++] = caller2;
|
||||
continue out_for;
|
||||
}
|
||||
}
|
||||
foreach (cmp2; caller2.system.m_writable_dependencies)
|
||||
{
|
||||
if (cmp == cmp2)
|
||||
{
|
||||
exclusion[index++] = caller2;
|
||||
continue out_for;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///check for component dependencies
|
||||
foreach (cmp; caller.system.m_read_only_components)
|
||||
{
|
||||
foreach (cmp2; caller2.system.m_modified_components)
|
||||
|
|
@ -2923,6 +3051,18 @@ export struct EntityManager
|
|||
}
|
||||
}
|
||||
|
||||
const (UpdatePass)* getPass(const (char)[] name)
|
||||
{
|
||||
ushort id = getPassID(name);
|
||||
if(id == ushort.max)return null;
|
||||
return passes[id];
|
||||
}
|
||||
|
||||
ushort getPassID(const (char)[] name)
|
||||
{
|
||||
return passes_map.get(name, ushort.max);
|
||||
}
|
||||
|
||||
/************************************************************************************************************************
|
||||
Component info;
|
||||
*/
|
||||
|
|
@ -3350,6 +3490,7 @@ export struct EntityManager
|
|||
HashMap!(char[], ushort) components_map;
|
||||
HashMap!(const(char)[], ushort) events_map;
|
||||
HashMap!(const(char)[], ushort) passes_map;
|
||||
HashMap!(const(char)[], ushort) external_dependencies_map;
|
||||
Vector!System systems;
|
||||
Vector!ComponentInfo components;
|
||||
Vector!EventInfo events;
|
||||
|
|
|
|||
|
|
@ -129,6 +129,9 @@ package:
|
|||
ushort[] m_read_only_components;
|
||||
ushort[] m_modified_components;
|
||||
|
||||
ushort[] m_readonly_dependencies;
|
||||
ushort[] m_writable_dependencies;
|
||||
|
||||
EntityManager.SystemCaller* m_any_system_caller;
|
||||
|
||||
EventCaller[] m_event_callers;
|
||||
|
|
|
|||
|
|
@ -62,11 +62,11 @@ public:
|
|||
used = 0;
|
||||
}
|
||||
|
||||
export bool empty() {
|
||||
export bool empty() const {
|
||||
return (used == 0);
|
||||
}
|
||||
|
||||
export size_t length() {
|
||||
export size_t length() const {
|
||||
return used;
|
||||
}
|
||||
|
||||
|
|
@ -197,9 +197,9 @@ public:
|
|||
assert(ok, "There is no such an element in vector");
|
||||
}
|
||||
|
||||
export ref T opIndex(size_t elemNum) {
|
||||
export ref T opIndex(size_t elemNum) const {
|
||||
//debug assert(elemNum < used, "Range violation [index]");
|
||||
return array.ptr[elemNum];
|
||||
return *cast(T*)&array.ptr[elemNum];
|
||||
}
|
||||
|
||||
export auto opSlice() {
|
||||
|
|
|
|||
275
tests/basic.d
275
tests/basic.d
|
|
@ -1221,3 +1221,278 @@ unittest
|
|||
|
||||
gEM.end();
|
||||
}
|
||||
|
||||
@("SystemDependencies")
|
||||
unittest
|
||||
{
|
||||
struct TestSystem
|
||||
{
|
||||
mixin ECS.System;
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
uint length;
|
||||
@readonly CInt[] int_;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData entities)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSystem2
|
||||
{
|
||||
mixin ECS.System;
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
uint length;
|
||||
CInt[] int_;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData entities)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSystem3
|
||||
{
|
||||
mixin ECS.System;
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
uint length;
|
||||
@readonly CInt[] int_;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData entities)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSystem4
|
||||
{
|
||||
mixin ECS.System;
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
uint length;
|
||||
CInt[] int_;
|
||||
CLong[] long_;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData entities)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSystem5
|
||||
{
|
||||
mixin ECS.System;
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
uint length;
|
||||
@readonly CLong[] int_;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData entities)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void func1(TestSystem.EntitiesData entities)
|
||||
{
|
||||
foreach(i;0 .. entities.length)
|
||||
{
|
||||
entities.int_[i] += entities.int_[i] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
void func2(TestSystem.EntitiesData entities)
|
||||
{
|
||||
foreach(i;0 .. entities.length)
|
||||
{
|
||||
entities.int_[i] += 8;
|
||||
}
|
||||
}
|
||||
|
||||
gEM.beginRegister();
|
||||
|
||||
gEM.registerSystem!TestSystem(0);
|
||||
gEM.registerSystem!TestSystem2(1);
|
||||
gEM.registerSystem!TestSystem3(2);
|
||||
gEM.registerSystem!TestSystem4(3);
|
||||
gEM.registerSystem!TestSystem5(4);
|
||||
|
||||
gEM.endRegister();
|
||||
|
||||
const (EntityManager.UpdatePass)* pass = gEM.getPass("update");
|
||||
assert(pass != null);
|
||||
assert(pass.system_callers.length == 5);
|
||||
assert(pass.system_callers[0].system_id == TestSystem.system_id);
|
||||
assert(pass.system_callers[1].system_id == TestSystem2.system_id);
|
||||
assert(pass.system_callers[2].system_id == TestSystem3.system_id);
|
||||
assert(pass.system_callers[3].system_id == TestSystem4.system_id);
|
||||
assert(pass.system_callers[4].system_id == TestSystem5.system_id);
|
||||
assert(pass.system_callers[0].dependencies.length == 0);
|
||||
assert(pass.system_callers[1].dependencies.length == 1);
|
||||
assert(pass.system_callers[2].dependencies.length == 1);
|
||||
assert(pass.system_callers[3].dependencies.length == 3);
|
||||
assert(pass.system_callers[4].dependencies.length == 1);
|
||||
assert(pass.system_callers[1].dependencies[0].system_id == TestSystem.system_id);
|
||||
assert(pass.system_callers[2].dependencies[0].system_id == TestSystem2.system_id);
|
||||
assert(pass.system_callers[3].dependencies[0].system_id == TestSystem.system_id);
|
||||
assert(pass.system_callers[3].dependencies[1].system_id == TestSystem2.system_id);
|
||||
assert(pass.system_callers[3].dependencies[2].system_id == TestSystem3.system_id);
|
||||
assert(pass.system_callers[4].dependencies[0].system_id == TestSystem4.system_id);
|
||||
}
|
||||
|
||||
@("ExternalSystemDependencies")
|
||||
unittest
|
||||
{
|
||||
enum TestDependency = "TestDepencency";
|
||||
|
||||
struct TestSystem
|
||||
{
|
||||
mixin ECS.System;
|
||||
|
||||
mixin ECS.ReadOnlyDependencies!(TestDependency);
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
uint length;
|
||||
@readonly CInt[] int_;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData entities)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSystem2
|
||||
{
|
||||
mixin ECS.System;
|
||||
|
||||
mixin ECS.WritableDependencies!(TestDependency);
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
uint length;
|
||||
@readonly CInt[] int_;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData entities)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSystem3
|
||||
{
|
||||
mixin ECS.System;
|
||||
|
||||
mixin ECS.ReadOnlyDependencies!(TestDependency);
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
uint thread_id;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData entities)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSystem4
|
||||
{
|
||||
mixin ECS.System;
|
||||
|
||||
mixin ECS.WritableDependencies!(TestDependency);
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
uint length;
|
||||
@readonly CInt[] int_;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData entities)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSystem5
|
||||
{
|
||||
mixin ECS.System;
|
||||
|
||||
mixin ECS.ReadOnlyDependencies!(TestDependency);
|
||||
|
||||
struct EntitiesData
|
||||
{
|
||||
uint length;
|
||||
@readonly CLong[] int_;
|
||||
}
|
||||
|
||||
void onUpdate(EntitiesData entities)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void func1(TestSystem.EntitiesData entities)
|
||||
{
|
||||
foreach(i;0 .. entities.length)
|
||||
{
|
||||
entities.int_[i] += entities.int_[i] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
void func2(TestSystem.EntitiesData entities)
|
||||
{
|
||||
foreach(i;0 .. entities.length)
|
||||
{
|
||||
entities.int_[i] += 8;
|
||||
}
|
||||
}
|
||||
|
||||
gEM.beginRegister();
|
||||
|
||||
gEM.registerDependency(TestDependency);
|
||||
|
||||
gEM.registerSystem!TestSystem(0);
|
||||
gEM.registerSystem!TestSystem2(1);
|
||||
gEM.registerSystem!TestSystem3(2);
|
||||
gEM.registerSystem!TestSystem4(3);
|
||||
gEM.registerSystem!TestSystem5(4);
|
||||
|
||||
gEM.endRegister();
|
||||
|
||||
const (EntityManager.UpdatePass)* pass = gEM.getPass("update");
|
||||
assert(pass != null);
|
||||
assert(pass.system_callers.length == 5);
|
||||
assert(pass.system_callers[0].system_id == TestSystem.system_id);
|
||||
assert(pass.system_callers[1].system_id == TestSystem2.system_id);
|
||||
assert(pass.system_callers[2].system_id == TestSystem3.system_id);
|
||||
assert(pass.system_callers[3].system_id == TestSystem4.system_id);
|
||||
assert(pass.system_callers[4].system_id == TestSystem5.system_id);
|
||||
assert(pass.system_callers[0].dependencies.length == 0);
|
||||
assert(pass.system_callers[1].dependencies.length == 1);
|
||||
assert(pass.system_callers[2].dependencies.length == 1);
|
||||
assert(pass.system_callers[3].dependencies.length == 3);
|
||||
assert(pass.system_callers[4].dependencies.length == 2);
|
||||
assert(pass.system_callers[1].dependencies[0].system_id == TestSystem.system_id);
|
||||
assert(pass.system_callers[2].dependencies[0].system_id == TestSystem2.system_id);
|
||||
assert(pass.system_callers[3].dependencies[0].system_id == TestSystem.system_id);
|
||||
assert(pass.system_callers[3].dependencies[1].system_id == TestSystem2.system_id);
|
||||
assert(pass.system_callers[3].dependencies[2].system_id == TestSystem3.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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue