diff --git a/c-api/meson.build b/c-api/meson.build
new file mode 100644
index 0000000..5e1e2cf
--- /dev/null
+++ b/c-api/meson.build
@@ -0,0 +1,7 @@
+src += files(
+ 'manager.d'
+)
+
+c_src = files(
+ 'test.c'
+)
\ No newline at end of file
diff --git a/demos/compile_wasm.py b/demos/compile_wasm.py
index 06d31ac..336221a 100644
--- a/demos/compile_wasm.py
+++ b/demos/compile_wasm.py
@@ -75,7 +75,7 @@ for arg in sys.argv[1:]:
elif(arg == '-opt'):
shared_flags += '-O3 '
ldc_flags += '-release -enable-inlining '
- emc_flags += '--llvm-lto 3 -s SIMD=1 '
+ emc_flags += '--llvm-lto 3 '
elif(arg == '-quiet'):
emc_flags += "-Wl,--no-check-features "
elif(arg == '--clean'):
diff --git a/meson.build b/meson.build
index 0aff444..5b72d64 100644
--- a/meson.build
+++ b/meson.build
@@ -5,11 +5,13 @@ betterC_opt = get_option('betterC')
BuildDemos_opt = get_option('BuildDemos')
BuildTests_opt = get_option('BuildTests')
LTO_otp = get_option('LTO')
+C_API_opt = get_option('C-API')
summary('betterC enabled', betterC_opt)
summary('build demos', BuildDemos_opt)
summary('build tests', BuildTests_opt)
summary('LTO enabled', LTO_otp)
+summary('C-API enabled', C_API_opt)
meson_minimum_version = '>=0.57.1'
assert(meson.version().version_compare(meson_minimum_version), 'Newer verson of meson required, current version: @0@, required: @1@'.format(meson.version(), meson_minimum_version))
@@ -18,7 +20,14 @@ assert(meson.version().version_compare(meson_minimum_version), 'Newer verson of
src = files()
subdir('source')
-inc = include_directories('source/')
+inc = [include_directories('source/')]
+
+#C API files
+if C_API_opt
+ c_src = files()
+ subdir('c-api')
+ inc += include_directories('c-api/')
+endif
# Arguments
args = []
diff --git a/meson_options.txt b/meson_options.txt
index 335f32b..30f9c3d 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -2,3 +2,4 @@ option('betterC', type: 'boolean', value: false)
option('BuildDemos', type: 'boolean', value: false)
option('BuildTests', type: 'boolean', value: false)
option('LTO', type: 'boolean', value: false)
+option('C-API', type: 'boolean', value: false)
diff --git a/source/bubel/ecs/manager.d b/source/bubel/ecs/manager.d
index e3ad7bc..6cba7e8 100644
--- a/source/bubel/ecs/manager.d
+++ b/source/bubel/ecs/manager.d
@@ -371,6 +371,8 @@ export struct EntityManager
System system;
system.m_pass = pass;
+ alias SystemData = SystemEntityData!Sys;
+
// static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort))
// {
// static assert(0, "Add \"mixin ECS.System;\" in top of system structure;");
@@ -426,221 +428,9 @@ export struct EntityManager
}
}
- static struct CompInfo
- {
- string name;
- string type;
- }
+ alias components_info = SystemData.components_info;
- static struct ComponentsCounts
- {
- //one more than should be to prevent null arrays (zero length arrays)
- uint readonly = 1;
- uint mutable = 1;
- uint excluded = 1;
- uint optional = 1;
- uint req = 1;
- uint readonly_dep = 1;
- uint writable_dep = 1;
- }
-
- static ComponentsCounts getComponentsCounts()
- {
- ComponentsCounts components_counts;
-
- bool checkExcludedComponentsSomething(Sys)()
- {
- return __traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents))) && allSameType!(string,
- typeof(Sys.ExcludedComponents)) && isExpressions!(Sys.ExcludedComponents);
- }
-
- foreach (member; __traits(allMembers, Sys.EntitiesData))
- {
- alias MemberType = typeof(__traits(getMember, Sys.EntitiesData, member));
- if (member == "length" || member == "thread_id" || member == "job_id"
- || is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
- {
- //continue;
- }
- else
- {
- string name;
- static if (isArray!MemberType)
- { // Workaround. This code is never called with: not an array type, but compiler prints an error
- // name = fullyQualifiedName!(Unqual!(ForeachType!MemberType));//.stringof;
- name = fullName!(Unqual!(ForeachType!MemberType));
- }
-
- bool is_optional;
- bool is_read_only;
-
- if (is(CopyConstness!(ForeachType!(MemberType), int) == const(int)))
- {
- is_read_only = true;
- }
-
- foreach (att; __traits(getAttributes, __traits(getMember,
- Sys.EntitiesData, member)))
- {
- if (att == "optional")
- {
- is_optional = true;
- }
- if (att == "readonly")
- {
- is_read_only = true;
- }
- }
- if (is_read_only)
- {
- components_counts.readonly++;
- }
- else
- {
- components_counts.mutable++;
- }
- if (is_optional)
- {
- components_counts.optional++;
- }
- else
- {
- components_counts.req++;
- }
- }
- }
-
- static if (__traits(hasMember, Sys, "ExcludedComponents"))
- {
- static if (is(Sys.ExcludedComponents == enum))
- {
- foreach (str; __traits(allMembers, Sys.ExcludedComponents))
- {
- components_counts.excluded++;
- }
- }
- else //static if (checkExcludedComponentsSomething!Sys)
- {
- foreach (str; Sys.ExcludedComponents)
- {
- 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++;
- }
- }
-
- return components_counts;
- }
-
- enum ComponentsCounts component_counts = getComponentsCounts();
-
- static struct ComponentsIndices(ComponentsCounts counts)
- {
- CompInfo[] readonly()
- {
- return m_readonly[0 .. m_readonly_counter];
- }
-
- CompInfo[] mutable()
- {
- return m_mutable[0 .. m_mutable_counter];
- }
-
- CompInfo[] excluded()
- {
- return m_excluded[0 .. m_excluded_counter];
- }
-
- CompInfo[] optional()
- {
- return m_optional[0 .. m_optional_counter];
- }
-
- CompInfo[] req()
- {
- 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;
- }
-
- void addMutable(CompInfo info)
- {
- m_mutable[m_mutable_counter++] = info;
- }
-
- void addExcluded(CompInfo info)
- {
- m_excluded[m_excluded_counter++] = info;
- }
-
- void addOptional(CompInfo info)
- {
- m_optional[m_optional_counter++] = info;
- }
-
- void addReq(CompInfo info)
- {
- 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;
- }
-
- static void allocateSystemComponents(ComponentsIndices!component_counts components_info)(
+ static void allocateSystemComponents/*(ComponentsIndices!component_counts components_info)*/(
ref System system)
{
size_t req = components_info.req.length;
@@ -665,119 +455,8 @@ export struct EntityManager
system.m_readonly_dependencies = Mallocator.makeArray!ushort(read_only_deps);
if (writable_deps > 0)
system.m_writable_dependencies = Mallocator.makeArray!ushort(writable_deps);
-
}
- static ComponentsIndices!component_counts getComponentsInfo()
- {
- ComponentsIndices!component_counts components_info;
-
- bool checkExcludedComponentsSomething(Sys)()
- {
- return __traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents))) && allSameType!(string,
- typeof(Sys.ExcludedComponents)) && isExpressions!(Sys.ExcludedComponents);
- }
-
- foreach (member; __traits(allMembers, Sys.EntitiesData))
- {
- alias MemberType = typeof(__traits(getMember, Sys.EntitiesData, member));
- if (member == "length" || member == "thread_id" || member == "job_id"
- || is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
- {
- if (is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
- components_info.entites_array = member;
- //continue;
- }
- else
- {
- string name;
- static if (isArray!MemberType)
- { // Workaround. This code is never called with: not an array type, but compiler prints an error
- // name = fullyQualifiedName!(Unqual!(ForeachType!MemberType));
- name = fullName!(Unqual!(ForeachType!MemberType));
- //name = Unqual!(ForeachType!MemberType).stringof;
- }
-
- bool is_optional;
- bool is_read_only;
-
- if (is(CopyConstness!(ForeachType!(MemberType), int) == const(int)))
- {
- is_read_only = true;
- }
-
- foreach (att; __traits(getAttributes, __traits(getMember,
- Sys.EntitiesData, member)))
- {
- if (att == "optional")
- {
- is_optional = true;
- }
- if (att == "readonly")
- {
- is_read_only = true;
- }
- }
- if (is_read_only)
- {
- components_info.addReadonly(CompInfo(member, name));
- }
- else
- {
- components_info.addMutable(CompInfo(member, name));
- }
- if (is_optional)
- {
- components_info.addOptional(CompInfo(member, name));
- }
- else
- {
- components_info.addReq(CompInfo(member, name));
- }
- }
- }
-
- static if (__traits(hasMember, Sys, "ExcludedComponents"))
- {
- static if (is(Sys.ExcludedComponents == enum))
- {
- foreach (str; __traits(allMembers, Sys.ExcludedComponents))
- {
- components_info.addExcluded(CompInfo(str, str));
- }
- }
- else //static if (checkExcludedComponentsSomething!Sys)
- {
- foreach (str; Sys.ExcludedComponents)
- {
- components_info.addExcluded(CompInfo(str.stringof, fullName!str));
- // components_info.addExcluded(CompInfo(str.stringof, str.stringof));
- }
-
- }
- }
-
- 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;
- }
-
- enum ComponentsIndices!component_counts components_info = getComponentsInfo();
-
static void genCompList(ref System system, ref HashMap!(char[], ushort) components_map)
{
@@ -813,7 +492,7 @@ export struct EntityManager
}
//enum ComponentsIndices components_info = getComponentsInfo();
- allocateSystemComponents!(components_info)(system);
+ allocateSystemComponents(system);
foreach (iii, comp_info; components_info.req)
{
@@ -877,50 +556,34 @@ export struct EntityManager
}
}
- static void fillInputData(ref Sys.EntitiesData input_data, EntityInfo* info,
+ struct InputData
+ {
+ uint length;
+ uint thread_id;
+ uint job_id;
+ //this struct containt multiple data pointers in linear memory (e.g. data_pointer+1 may be valid)
+ void* data_pointer;
+ }
+
+ static void fillInputData_dyn(ref InputData input_data, EntityInfo* info,
EntitiesBlock* block, uint offset, uint entities_count, System* system)
{
- //enum ComponentsIndices components_info = getComponentsInfo();
-
- static if (components_info.entites_array)
+ input_data.length = entities_count;
+ // input_data.thread_id = 0;
+ foreach(size_t i, ushort component; system.m_components)
{
- __traits(getMember, input_data, components_info.entites_array) = (
- cast(Entity*) block.dataBegin())[offset .. entities_count];
+ *(&input_data.data_pointer + i) = cast(void*) block + info.deltas[component] + offset * gEntityManager.components[component].size;
}
- static if (hasMember!(Sys.EntitiesData, "length"))
+ foreach(size_t i, ushort component; system.m_optional_components)
{
- input_data.length = cast(typeof(input_data.length))(entities_count - offset);
+ if(component < info.deltas.length && info.deltas[component] != 0)*(&input_data.data_pointer + i + system.m_components.length) = cast(void*) block + info.deltas[component] + offset * gEntityManager.components[component].size;
}
+ }
- /*static if (hasMember!(Sys.EntitiesData, "thread_id"))
- {
- input_data.thread_id = cast(typeof(input_data.thread_id))threadID();
- }//*/
-
- ///FIXME: should be "components_info.req()" but it's not compile with GCC
- static foreach (iii, comp_info; components_info.m_req[0
- .. components_info.m_req_counter])
- {
- __traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
- Sys.EntitiesData, comp_info.name)))*)(
- cast(void*) block + info.deltas[system.m_components[iii]]))[offset
- .. entities_count];
- }
-
- static foreach (iii, comp_info; components_info.m_optional[0
- .. components_info.m_optional_counter])
- {
- if (system.m_optional_components[iii] < info.deltas.length
- && info.deltas[system.m_optional_components[iii]] != 0)
- {
- __traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
- Sys.EntitiesData, comp_info.name)))*)(cast(
- void*) block + info.deltas[system.m_optional_components[iii]]))[offset
- .. entities_count];
-
- }
- }
+ static void fillEntitiesData(ref Sys.EntitiesData entities_data, ref InputData input_data)
+ {
+
}
/*bool checkOnUpdateParams()
@@ -964,9 +627,9 @@ export struct EntityManager
static if (OnUpdateOverloadNum != -1)
{
- static if (!IsEmpty)
- {
- static void callUpdate(ref CallData data)
+ //static if (!IsEmpty)
+ //{
+ /*static void callUpdate(ref CallData data)
{
Sys* s = cast(Sys*) data.system.m_system_pointer;
@@ -1019,29 +682,46 @@ export struct EntityManager
input_data.job_id = cast(typeof(input_data.job_id)) data.job_id;
}
- //s.onUpdate(input_data);
- (cast(typeof(&__traits(getOverloads, s,
- "onUpdate")[OnUpdateOverloadNum])) data.update_delegate)(
- input_data);
+ if(data.context) (*cast(void delegate(Sys.EntitiesData)*)data.context)(input_data);
+ else s.onUpdate(input_data);
}
block = block.next_block;
offset = 0;
blocks--;
}
- }
- }
- else
- {
- static void callUpdate(ref CallData data)
+ }*/
+
+ static void callUpdate(SystemCallData* data)
{
- Sys* s = cast(Sys*) data.system.m_system_pointer;
+ Sys* s = cast(Sys*) data.system_pointer;
Sys.EntitiesData input_data;
+ // EntityInfo* info = data.block.type_info; //block.type_info;
+ //System* system = data.system;
- /*static if (hasMember!(Sys.EntitiesData, "length"))
+ static if (!IsEmpty)SystemData.fillInputData(input_data, data.info, data.block, data.begin, data.count);//, system);
+
+ static if (hasMember!(Sys.EntitiesData, "thread_id"))
{
- input_data.length = 0;
- }//*/
+ input_data.thread_id = cast(
+ typeof(input_data.thread_id)) data.thread_id;
+ }
+
+ static if (hasMember!(Sys.EntitiesData, "job_id"))
+ {
+ input_data.job_id = cast(typeof(input_data.job_id)) data.job_id;
+ }
+
+ s.onUpdate(input_data);
+ }
+ /*}
+ else
+ {*/
+ /*static void callUpdate(SystemCallData data)
+ {
+ Sys* s = cast(Sys*) data.system_pointer;
+
+ Sys.EntitiesData input_data;
static if (hasMember!(Sys.EntitiesData, "thread_id"))
{
@@ -1053,10 +733,27 @@ export struct EntityManager
input_data.job_id = cast(typeof(input_data.job_id)) data.job_id;
}
- (cast(typeof(&__traits(getOverloads, s,
- "onUpdate")[OnUpdateOverloadNum])) data.update_delegate)(input_data);
- }
- }
+ s.onUpdate(input_data);
+ }*/
+ /*static void callUpdate(ref CallData data)
+ {
+ Sys* s = cast(Sys*) data.system.m_system_pointer;
+
+ Sys.EntitiesData input_data;
+
+ static if (hasMember!(Sys.EntitiesData, "thread_id"))
+ {
+ input_data.thread_id = cast(typeof(input_data.thread_id)) data.thread_id;
+ }
+
+ static if (hasMember!(Sys.EntitiesData, "job_id"))
+ {
+ input_data.job_id = cast(typeof(input_data.job_id)) data.job_id;
+ }
+
+ s.onUpdate(input_data);
+ }*/
+ // }
system.m_update = &callUpdate;
}
@@ -1099,8 +796,8 @@ export struct EntityManager
{
Sys* s = cast(Sys*) data.system.m_system_pointer;
Sys.EntitiesData input_data;
- fillInputData(input_data, data.block.type_info,
- data.block, data.begin, data.end, data.system);
+ SystemData.fillInputData(input_data, data.block.type_info,
+ data.block, data.begin, data.end);//, data.system);
static if (is(RetTyp == void))
mixin("s." ~ func_name ~ "(input_data)");
else
@@ -1160,12 +857,12 @@ export struct EntityManager
static if(__traits(hasMember, Sys ,"__becs_jobs_count"))system.jobs = Mallocator.makeArray!(Job)(Sys.__becs_jobs_count);
else system.jobs = Mallocator.makeArray!(Job)(32);
- static if (OnUpdateOverloadNum != -1)
+ /*static if (OnUpdateOverloadNum != -1)
{
Sys* s = cast(Sys*) system.m_system_pointer;
system.m_update_delegate = cast(void delegate())&__traits(getOverloads,
s, "onUpdate")[OnUpdateOverloadNum];
- }
+ }*/
genCompList(system, components_map);
@@ -1229,6 +926,41 @@ export struct EntityManager
becsID!Sys = system.id;
}
+ export ushort registerSystem(const (char)[] name, System system)
+ {
+ ushort sys_id = systems_map.get(cast(char[]) name, ushort.max);
+ if (sys_id < systems.length)
+ {
+ system.m_name = systems[sys_id].m_name;
+ systems[sys_id].m_name = null;
+ systems[sys_id].destroy();
+
+ if (system.m_create)
+ (cast(void function(void*)) system.m_create)(system.m_system_pointer);
+
+ system.enable();
+
+ system.m_id = sys_id;
+ systems[sys_id] = system;
+ }
+ else
+ {
+ system.m_name = Mallocator.makeArray(cast(char[]) name);
+
+ systems_map.add(system.m_name, cast(ushort) systems.length);
+
+ system.m_id = cast(ushort)(systems.length);
+
+ systems.add(system);
+
+ if (system.m_create)
+ (cast(void function(void*)) system.m_create)(system.m_system_pointer);
+
+ systems[$ - 1].enable();
+ }
+ return system.m_id;
+ }
+
/************************************************************************************************************************
Return system ECS api by id
*/
@@ -1312,7 +1044,7 @@ export struct EntityManager
info.init_data = Mallocator.makeArray!ubyte(Comp.sizeof);
*cast(Comp*) info.init_data.ptr = Comp.init; // = Comp();
- ushort comp_id = components_map.get(cast(char[]) ComponentName, ushort.max);
+ /*ushort comp_id = components_map.get(cast(char[]) ComponentName, ushort.max);
if (comp_id < components.length)
{
becsID!Comp = comp_id;
@@ -1326,7 +1058,29 @@ export struct EntityManager
becsID!Comp = cast(ushort)(components.length - 1);
char[] name = Mallocator.makeArray(cast(char[]) ComponentName);
components_map.add(name, cast(ushort)(components.length - 1));
+ }*/
+ becsID!Comp = registerComponent(ComponentName, info);
+ }
+
+ ushort registerComponent(const (char)[] name, ComponentInfo info)
+ {
+ ushort comp_id = components_map.get(cast(char[]) name, ushort.max);
+ if (comp_id < components.length)
+ {
+ // becsID!Comp = comp_id;
+ if (components[comp_id].init_data)
+ Mallocator.dispose(components[comp_id].init_data);
+ components[comp_id] = info;
}
+ else
+ {
+ components.add(info);
+ // becsID!Comp = cast(ushort)(components.length - 1);
+ comp_id = cast(ushort)(components.length - 1);
+ char[] name_copy = Mallocator.makeArray(cast(char[]) name);
+ components_map.add(name_copy, cast(ushort)(components.length - 1));
+ }
+ return comp_id;
}
void registerEvent(Ev)()
@@ -1388,9 +1142,46 @@ export struct EntityManager
if (!system.m_any_system_caller)
return;
+ /* struct Delegate
+ {
+ void* context;
+ void* func;
+ }*/
+
+ /*static void fillInputData_dyn(ref Sys.EntitiesData input_data, EntityInfo* info,
+ EntitiesBlock* block, uint offset, uint entities_count)
+ {
+ System* system = gEntityManager.getSystem(becsID!Sys);
+ input_data.length = cast(typeof(input_data.length))entities_count;
+ // input_data.thread_id = 0;
+ foreach(size_t i, ushort component; system.m_components)
+ {
+ *(&block.data_pointer + i) = cast(void*) block + info.deltas[component] + offset * gEntityManager.components[component].size;
+ }
+
+ foreach(size_t i, ushort component; system.m_optional_components)
+ {
+ if(component < info.deltas.length && info.deltas[component] != 0)*(&input_data.data_pointer + i + system.m_components.length) = cast(void*) block + info.deltas[component] + offset * gEntityManager.components[component].size;
+ }
+ }*/
+
+ static void callUpdate(SystemCallData* data)
+ {
+ //Sys* s = cast(Sys*) data.system_pointer;
+ Sys.EntitiesData input_data;
+ EntityInfo* info = data.info;
+
+ alias SystemData = SystemEntityData!Sys;
+ SystemData.fillInputData(input_data, info, data.block, data.begin, data.count);
+ //fillInputData(input_data, info, data.block, data.begin, data.end - data.begin);
+ //fillInputData_dyn(input_data, info, data.block, data.begin, data.end - data.begin);
+
+ (*cast(void delegate(Sys.EntitiesData)*)data.context)(input_data);
+ }
+
foreach (info; system.m_any_system_caller.infos)
{
- CallData data = CallData(system.id, system, info, cast(void delegate()) func);
+ CallData data = CallData(system.id, system, info, cast(void*)&func, cast(void*)&callUpdate);
data.update();
}
}
@@ -1419,14 +1210,14 @@ export struct EntityManager
{
if (sys.m_empty)
{
- CallData data = CallData(caller.system_id, sys, null, sys.m_update_delegate);
+ CallData data = CallData(caller.system_id, sys, null, null, sys.m_update);
data.update();
}
else
foreach (info; caller.infos)
{
CallData data = CallData(caller.system_id, sys, info,
- sys.m_update_delegate);
+ null, sys.m_update);
data.update();
}
}
@@ -1472,7 +1263,7 @@ export struct EntityManager
if (sys.m_empty)
{
- tmp_datas.add(CallData(caller.system_id, sys, null, sys.m_update_delegate));
+ tmp_datas.add(CallData(caller.system_id, sys, null, null, sys.m_update));
nextJob();
caller.job_group.jobs = sys.jobs[0 .. 1];
(cast(void delegate(JobGroup) nothrow @nogc) m_dispatch_jobs)(caller.job_group);
@@ -1537,7 +1328,7 @@ export struct EntityManager
assert(entities_per_job == full_blocks_count * info.max_entities + entities_count + (
first_block.entities_count - first_elem));
CallData data = CallData(caller.system_id, sys,
- info, sys.m_update_delegate, first_block,
+ info, null, sys.m_update, first_block,
cast(ushort)(full_blocks_count + 1),
cast(ushort) first_elem, 0);
tmp_datas.add(data);
@@ -1553,7 +1344,7 @@ export struct EntityManager
assert(last_elem > 0);
assert(last_elem <= block.entities_count);
CallData data = CallData(caller.system_id, sys,
- info, sys.m_update_delegate, first_block,
+ info, null, sys.m_update, first_block,
cast(ushort)(full_blocks_count + 2),
cast(ushort) first_elem, cast(ushort) last_elem);
tmp_datas.add(data);
@@ -1572,7 +1363,7 @@ export struct EntityManager
uint last_elem = entities_per_job - entities_count;
assert(last_elem > 0);
CallData data = CallData(caller.system_id, sys,
- info, sys.m_update_delegate, first_block, 1,
+ info, null, sys.m_update, first_block, 1,
cast(ushort) first_elem, cast(ushort)(first_elem + last_elem));
tmp_datas.add(data);
first_elem += last_elem;
@@ -1592,7 +1383,7 @@ export struct EntityManager
else
{
//take whole info blocks
- CallData data = CallData(caller.system_id, sys, info, sys.m_update_delegate,
+ CallData data = CallData(caller.system_id, sys, info, null, sys.m_update,
first_block, cast(ushort) blocks_count, cast(ushort) first_elem);
tmp_datas.add(data);
entities_count += (blocks_count - 1) * info.max_entities
@@ -3331,9 +3122,9 @@ export struct EntityManager
*/
struct ComponentInfo
{
- export ~this() nothrow @nogc
+ /*export ~this() nothrow @nogc
{
- }
+ }*/
///Component size
ushort size;
///Component data alignment
@@ -3604,7 +3395,65 @@ export struct EntityManager
{
export void update() nothrow @nogc
{
- (cast(SytemFuncType) system.m_update)(this);
+ //(cast(SytemFuncType) system.m_update)(this);
+ if(!system.m_empty)
+ {
+ // Sys* s = cast(Sys*) system.m_system_pointer;
+
+ //Sys.EntitiesData input_data;
+ // EntityInfo* info = info; //block.type_info;
+ // System* system = system;
+
+ EntitiesBlock* block;
+ if (first_block)
+ block = first_block;
+ else
+ block = info.first_block;
+
+ uint offset = begin;
+ uint last_entity;
+ uint blocks;
+ if (blocks_count)
+ blocks = blocks_count;
+ else
+ blocks = uint.max;
+
+ SystemCallData call_data = SystemCallData(0, thread_id, job_id, system.m_system_pointer, context, info);
+
+ while (block !is null && blocks > 0)
+ {
+ if (blocks == 1)
+ {
+ if (end)
+ last_entity = end;
+ else
+ last_entity = block.entities_count;
+ }
+ else
+ last_entity = block.entities_count;
+
+ if (last_entity > 0)
+ {
+ call_data.block = block;
+ call_data.begin = offset;
+ call_data.count = last_entity - offset;
+
+ assert(last_entity <= block.entities_count
+ && offset < block.entities_count);
+ assert(last_entity > offset);
+
+ (cast(void function(SystemCallData*) @nogc nothrow) update_func)(&call_data);
+ }
+ block = block.next_block;
+ offset = 0;
+ blocks--;
+ }
+ }
+ else
+ {
+ SystemCallData call_data = SystemCallData(0, thread_id, job_id, system.m_system_pointer, context, info);
+ (cast(void function(SystemCallData*) @nogc nothrow) update_func)(&call_data);
+ }
}
///system ID. Used to update system pointer after system reload.
@@ -3614,12 +3463,14 @@ export struct EntityManager
///poiner to Entity type info
EntityManager.EntityInfo* info;
///delegate function to call (by default it's delegate to onUpdate call)
- void delegate() update_delegate;
+ void* context;
+ void* update_func;
+ //void delegate() update_delegate;
///pointer to first block into process (if 0 then first block will be used)
EntitiesBlock* first_block;
///number of blocks to update (if 0 then update all)
- ushort blocks;
+ ushort blocks_count;
///index of first element in first block
ushort begin;
///index of last element in last block
@@ -3630,6 +3481,24 @@ export struct EntityManager
uint job_id;
}
+ /************************************************************************************************************************
+ Structure with data used to call single System call.
+
+ first_block, begin, end, blocks parameters are used
+ to call partial info update
+ */
+ struct SystemCallData
+ {
+ uint count;
+ uint thread_id;
+ uint job_id;
+ void* system_pointer;
+ void* context;
+ EntityInfo* info;
+ EntitiesBlock* block;
+ uint begin;
+ }
+
struct ListenerCallData
{
System* system;
@@ -3853,3 +3722,425 @@ export struct EntityManager
}
}
+
+/*static void fillInputData(Sys)(ref Sys.EntitiesData input_data, EntityManager.EntityInfo* info,
+ EntityManager.EntitiesBlock* block, uint offset, uint entities_count)//, System* system)
+{
+ //enum ComponentsIndices components_info = getComponentsInfo();
+
+ static if (components_info.entites_array)
+ {
+ __traits(getMember, input_data, components_info.entites_array) = (
+ cast(Entity*) block.dataBegin())[offset .. entities_count];
+ }
+
+ static if (hasMember!(Sys.EntitiesData, "length"))
+ {
+ input_data.length = cast(typeof(input_data.length))(entities_count - offset);
+ }
+
+ // static if (hasMember!(Sys.EntitiesData, "thread_id"))
+ // {
+ // input_data.thread_id = cast(typeof(input_data.thread_id))threadID();
+ // }
+
+ ///FIXME: should be "components_info.req()" but it's not compile with GCC
+ static foreach(comp; __traits(Stru))
+ static foreach (iii, comp_info; components_info.m_req[0
+ .. components_info.m_req_counter])
+ {
+ __traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
+ Sys.EntitiesData, comp_info.name)))*)(
+ cast(void*) block + info.deltas[becsID!(typeof(__traits(getMember, Sys.EntitiesData, comp_info.name)))]))[offset
+ .. entities_count];
+ }
+
+ static foreach (iii, comp_info; components_info.m_optional[0
+ .. components_info.m_optional_counter])
+ {
+ ushort system_id = becsID!(typeof(__traits(getMember, Sys.EntitiesData, comp_info.name)));
+ if (system_id < info.deltas.length
+ && info.deltas[system_id] != 0)
+ {
+ __traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
+ Sys.EntitiesData, comp_info.name)))*)(cast(
+ void*) block + info.deltas[system_id]))[offset
+ .. entities_count];
+
+ }
+ }
+}*/
+
+struct SystemEntityData(Sys)
+{
+ static struct CompInfo
+ {
+ string name;
+ string type;
+ }
+
+ static struct ComponentsCounts
+ {
+ //one more than should be to prevent null arrays (zero length arrays)
+ uint readonly = 1;
+ uint mutable = 1;
+ uint excluded = 1;
+ uint optional = 1;
+ uint req = 1;
+ uint readonly_dep = 1;
+ uint writable_dep = 1;
+ }
+
+ static ComponentsCounts getComponentsCounts()
+ {
+ ComponentsCounts components_counts;
+
+ bool checkExcludedComponentsSomething(Sys)()
+ {
+ return __traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents))) && allSameType!(string,
+ typeof(Sys.ExcludedComponents)) && isExpressions!(Sys.ExcludedComponents);
+ }
+
+ foreach (member; __traits(allMembers, Sys.EntitiesData))
+ {
+ alias MemberType = typeof(__traits(getMember, Sys.EntitiesData, member));
+ if (member == "length" || member == "thread_id" || member == "job_id"
+ || is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
+ {
+ //continue;
+ }
+ else
+ {
+ string name;
+ static if (isArray!MemberType)
+ { // Workaround. This code is never called with: not an array type, but compiler prints an error
+ // name = fullyQualifiedName!(Unqual!(ForeachType!MemberType));//.stringof;
+ name = fullName!(Unqual!(ForeachType!MemberType));
+ }
+
+ bool is_optional;
+ bool is_read_only;
+
+ if (is(CopyConstness!(ForeachType!(MemberType), int) == const(int)))
+ {
+ is_read_only = true;
+ }
+
+ foreach (att; __traits(getAttributes, __traits(getMember,
+ Sys.EntitiesData, member)))
+ {
+ if (att == "optional")
+ {
+ is_optional = true;
+ }
+ if (att == "readonly")
+ {
+ is_read_only = true;
+ }
+ }
+ if (is_read_only)
+ {
+ components_counts.readonly++;
+ }
+ else
+ {
+ components_counts.mutable++;
+ }
+ if (is_optional)
+ {
+ components_counts.optional++;
+ }
+ else
+ {
+ components_counts.req++;
+ }
+ }
+ }
+
+ static if (__traits(hasMember, Sys, "ExcludedComponents"))
+ {
+ static if (is(Sys.ExcludedComponents == enum))
+ {
+ foreach (str; __traits(allMembers, Sys.ExcludedComponents))
+ {
+ components_counts.excluded++;
+ }
+ }
+ else //static if (checkExcludedComponentsSomething!Sys)
+ {
+ foreach (str; Sys.ExcludedComponents)
+ {
+ 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++;
+ }
+ }
+
+ return components_counts;
+ }
+
+ enum ComponentsCounts component_counts = getComponentsCounts();
+
+ static struct ComponentsIndices(ComponentsCounts counts)
+ {
+ CompInfo[] readonly()
+ {
+ return m_readonly[0 .. m_readonly_counter];
+ }
+
+ CompInfo[] mutable()
+ {
+ return m_mutable[0 .. m_mutable_counter];
+ }
+
+ CompInfo[] excluded()
+ {
+ return m_excluded[0 .. m_excluded_counter];
+ }
+
+ CompInfo[] optional()
+ {
+ return m_optional[0 .. m_optional_counter];
+ }
+
+ CompInfo[] req()
+ {
+ 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;
+ }
+
+ void addMutable(CompInfo info)
+ {
+ m_mutable[m_mutable_counter++] = info;
+ }
+
+ void addExcluded(CompInfo info)
+ {
+ m_excluded[m_excluded_counter++] = info;
+ }
+
+ void addOptional(CompInfo info)
+ {
+ m_optional[m_optional_counter++] = info;
+ }
+
+ void addReq(CompInfo info)
+ {
+ 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;
+ }
+
+ enum ComponentsIndices!component_counts components_info = getComponentsInfo();
+
+ static ComponentsIndices!component_counts getComponentsInfo()
+ {
+ ComponentsIndices!component_counts components_info;
+
+ bool checkExcludedComponentsSomething(Sys)()
+ {
+ return __traits(compiles, allSameType!(string, typeof(Sys.ExcludedComponents))) && allSameType!(string,
+ typeof(Sys.ExcludedComponents)) && isExpressions!(Sys.ExcludedComponents);
+ }
+
+ foreach (member; __traits(allMembers, Sys.EntitiesData))
+ {
+ alias MemberType = typeof(__traits(getMember, Sys.EntitiesData, member));
+ if (member == "length" || member == "thread_id" || member == "job_id"
+ || is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
+ {
+ if (is(MemberType == Entity[]) || is(MemberType == const(Entity)[]))
+ components_info.entites_array = member;
+ //continue;
+ }
+ else
+ {
+ string name;
+ static if (isArray!MemberType)
+ { // Workaround. This code is never called with: not an array type, but compiler prints an error
+ // name = fullyQualifiedName!(Unqual!(ForeachType!MemberType));
+ name = fullName!(Unqual!(ForeachType!MemberType));
+ //name = Unqual!(ForeachType!MemberType).stringof;
+ }
+
+ bool is_optional;
+ bool is_read_only;
+
+ if (is(CopyConstness!(ForeachType!(MemberType), int) == const(int)))
+ {
+ is_read_only = true;
+ }
+
+ foreach (att; __traits(getAttributes, __traits(getMember,
+ Sys.EntitiesData, member)))
+ {
+ if (att == "optional")
+ {
+ is_optional = true;
+ }
+ if (att == "readonly")
+ {
+ is_read_only = true;
+ }
+ }
+ if (is_read_only)
+ {
+ components_info.addReadonly(CompInfo(member, name));
+ }
+ else
+ {
+ components_info.addMutable(CompInfo(member, name));
+ }
+ if (is_optional)
+ {
+ components_info.addOptional(CompInfo(member, name));
+ }
+ else
+ {
+ components_info.addReq(CompInfo(member, name));
+ }
+ }
+ }
+
+ static if (__traits(hasMember, Sys, "ExcludedComponents"))
+ {
+ static if (is(Sys.ExcludedComponents == enum))
+ {
+ foreach (str; __traits(allMembers, Sys.ExcludedComponents))
+ {
+ components_info.addExcluded(CompInfo(str, str));
+ }
+ }
+ else //static if (checkExcludedComponentsSomething!Sys)
+ {
+ foreach (str; Sys.ExcludedComponents)
+ {
+ components_info.addExcluded(CompInfo(str.stringof, fullName!str));
+ // components_info.addExcluded(CompInfo(str.stringof, str.stringof));
+ }
+
+ }
+ }
+
+ 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;
+ }
+
+ static void fillInputData(ref Sys.EntitiesData input_data, EntityManager.EntityInfo* info,
+ EntityManager.EntitiesBlock* block, uint offset, uint entities_count)//, System* system)
+ {
+ //enum ComponentsIndices components_info = getComponentsInfo();
+ uint last_entity = entities_count + offset;
+
+ static if (components_info.entites_array)
+ {
+ __traits(getMember, input_data, components_info.entites_array) = (
+ cast(Entity*) block.dataBegin())[offset .. last_entity];
+ }
+
+ static if (hasMember!(Sys.EntitiesData, "length"))
+ {
+ input_data.length = cast(typeof(input_data.length))(entities_count);
+ }
+
+ // static if (hasMember!(Sys.EntitiesData, "thread_id"))
+ // {
+ // input_data.thread_id = cast(typeof(input_data.thread_id))threadID();
+ // }
+
+ ///FIXME: should be "components_info.req()" but it's not compile with GCC
+ static foreach (iii, comp_info; components_info.m_req[0
+ .. components_info.m_req_counter])
+ {
+ __traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
+ Sys.EntitiesData, comp_info.name)))*)(
+ cast(void*) block + info.deltas[becsID!(ForeachType!(typeof(__traits(getMember, Sys.EntitiesData, comp_info.name))))]))[offset
+ .. last_entity];
+ }
+
+ static foreach (iii, comp_info; components_info.m_optional[0
+ .. components_info.m_optional_counter])
+ {
+ if (becsID!(ForeachType!(typeof(__traits(getMember, Sys.EntitiesData, comp_info.name)))) < info.deltas.length
+ && info.deltas[becsID!(ForeachType!(typeof(__traits(getMember, Sys.EntitiesData, comp_info.name))))] != 0)
+ {
+ __traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
+ Sys.EntitiesData, comp_info.name)))*)(cast(
+ void*) block + info.deltas[becsID!(ForeachType!(typeof(__traits(getMember, Sys.EntitiesData, comp_info.name))))]))[offset
+ .. last_entity];
+
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/bubel/ecs/system.d b/source/bubel/ecs/system.d
index e571e8b..256841d 100644
--- a/source/bubel/ecs/system.d
+++ b/source/bubel/ecs/system.d
@@ -89,7 +89,7 @@ struct System
return cast(const(char)[]) m_name;
}
-package:
+//package:
void destroy()
{
@@ -170,7 +170,7 @@ package:
//void function(ref EntityManager.CallData data) m_update;
void* m_update; ///workaroud for DMD bug with upper line
- void delegate() m_update_delegate;
+ //void delegate() m_update_delegate;
//void function(void* system_pointer) m_enable;
//void function(void* system_pointer) m_disable;
@@ -198,6 +198,6 @@ package:
//void function(ref EntityManager.CallData data) m_initialize;
//void function(ref EntityManager.CallData data) m_deinitilize;
- void* m_initialize;
- void* m_deinitilize;
+ // void* m_initialize;
+ // void* m_deinitilize;
}