diff --git a/compile_wasm.py b/compile_wasm.py index 7214801..3bd1afd 100644 --- a/compile_wasm.py +++ b/compile_wasm.py @@ -13,7 +13,7 @@ def compile(sources, output): if file_extension == '.d' and filename != 'package': files.append(os.path.join(r, file)) - ldc_cmd = 'ldc2 ' + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-emscripten -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' ' + ldc_cmd = 'ldc2 ' + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-unknown-wasm -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' ' for path in sources: ldc_cmd += '-I' + path + ' ' @@ -33,7 +33,7 @@ def compile(sources, output): shared_flags = '' clean = 0 emc_flags = '' -ldc_flags = '' +ldc_flags = '--d-version=ECSEmscripten ' import_paths = ['source','tests'] build_tests = 0 diff --git a/demos/compile_wasm.py b/demos/compile_wasm.py index b178260..06d31ac 100644 --- a/demos/compile_wasm.py +++ b/demos/compile_wasm.py @@ -1,6 +1,7 @@ import os import ntpath import sys +import imp def compile(sources, output): files = [] @@ -13,7 +14,7 @@ def compile(sources, output): if file_extension == '.d' and filename != 'package': files.append(os.path.join(r, file)) - ldc_cmd = compiler + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-emscripten -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' ' + ldc_cmd = compiler + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-unknown-wasm -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' ' for path in sources: ldc_cmd += '-I' + path + ' ' @@ -40,7 +41,7 @@ only_bc = 0 multi = 0 sources = ['tests', 'source'] emc_flags = '-s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS="[\'png\']" ' -ldc_flags = '--d-version=SDL_209 --d-version=BindSDL_Static --d-version=BindSDL_Image --d-version=MM_USE_POSIX_THREADS ' +ldc_flags = '--d-version=ECSEmscripten --d-version=SDL_209 --d-version=BindSDL_Static --d-version=BindSDL_Image --d-version=MM_USE_POSIX_THREADS ' import_paths = ['external/sources', 'external/imports', 'external/wasm_imports', '../source', 'utils/source', 'simple/source'] for arg in sys.argv[1:]: @@ -120,9 +121,8 @@ emcc_cmd += 'demo.bc ' os.system("mkdir build") -# emscripten = imp.load_source('', os.path.expanduser("~") + '/.emscripten') -# pack_cmd = emscripten.EMSCRIPTEN_ROOT + '/tools/file_packager.py build/assets.data --preload assets --js-output=build/assets.js' -pack_cmd = os.path.expandvars('$EMSDK/upstream/emscripten') + '/tools/file_packager.py build/assets.data --preload assets --js-output=build/assets.js' +emscripten = imp.load_source('', os.path.expanduser("~") + '/.emscripten') +pack_cmd = emscripten.EMSCRIPTEN_ROOT + '/tools/file_packager.py build/assets.data --preload assets --js-output=build/assets.js' print('Packafing files: ' + pack_cmd) os.system(pack_cmd) diff --git a/meson.build b/meson.build index 141cb25..3f261f8 100644 --- a/meson.build +++ b/meson.build @@ -58,7 +58,7 @@ threads_dep = dependency('threads') d_versions = [] deps = [] if host_machine.cpu_family() == 'wasm32' - + d_versions += 'ECSEmscripten' else # meson incorectly adds "-s USE_PTHREADS=1" to ldc2 invocation whe pthreads is added as dependency # add it for non wasm builds diff --git a/source/bubel/ecs/atomic.d b/source/bubel/ecs/atomic.d index d8995ae..40f0aa9 100644 --- a/source/bubel/ecs/atomic.d +++ b/source/bubel/ecs/atomic.d @@ -9,5 +9,124 @@ License: BSD 3-clause, see LICENSE file in project root folder. */ module bubel.ecs.atomic; -public import core.atomic; +version (Emscripten) version = ECSEmscripten; +version (ECSEmscripten) +{ + import std.traits; + + enum MemoryOrder + { + acq, + acq_rel, + raw, + rel, + seq + } + + extern (C) ubyte emscripten_atomic_cas_u8(void* addr, ubyte oldVal, ubyte newVal) @nogc nothrow pure; + extern (C) ushort emscripten_atomic_cas_u16(void* addr, ushort oldVal, ushort newVal) @nogc nothrow pure; + extern (C) uint emscripten_atomic_cas_u32(void* addr, uint oldVal, uint newVal) @nogc nothrow pure; + + extern (C) ubyte emscripten_atomic_load_u8(const void* addr) @nogc nothrow pure; + extern (C) ushort emscripten_atomic_load_u16(const void* addr) @nogc nothrow pure; + extern (C) uint emscripten_atomic_load_u32(const void* addr) @nogc nothrow pure; + + extern (C) ubyte emscripten_atomic_store_u8(void* addr, ubyte val) @nogc nothrow pure; + extern (C) ushort emscripten_atomic_store_u16(void* addr, ushort val) @nogc nothrow pure; + extern (C) uint emscripten_atomic_store_u32(void* addr, uint val) @nogc nothrow pure; + + extern (C) ubyte emscripten_atomic_add_u8(void* addr, ubyte val) @nogc nothrow pure; + extern (C) ushort emscripten_atomic_add_u16(void* addr, ushort val) @nogc nothrow pure; + extern (C) uint emscripten_atomic_add_u32(void* addr, uint val) @nogc nothrow pure; + + extern (C) ubyte emscripten_atomic_sub_u8(void* addr, ubyte val) @nogc nothrow pure; + extern (C) ushort emscripten_atomic_sub_u16(void* addr, ushort val) @nogc nothrow pure; + extern (C) uint emscripten_atomic_sub_u32(void* addr, uint val) @nogc nothrow pure; + + public pure nothrow @nogc Unqual!T atomicOp(string op, T, V1)(ref shared T val, V1 mod) + { + static if (op == "+=") + { + static if (is(T == byte) || is(T == ubyte)) + return cast(Unqual!T)(emscripten_atomic_add_u8(cast(void*)&val, + cast(Unqual!T) mod) + 1); + else static if (is(T == short) || is(T == ushort)) + return cast(Unqual!T)(emscripten_atomic_add_u16(cast(void*)&val, + cast(Unqual!T) mod) + 1); + else static if (is(T == int) || is(T == uint)) + return cast(Unqual!T)(emscripten_atomic_add_u32(cast(void*)&val, + cast(Unqual!T) mod) + 1); + else + static assert(0); + } + else static if (op == "-=") + { + static if (is(T == byte) || is(T == ubyte)) + return cast(Unqual!T)(emscripten_atomic_sub_u8(cast(void*)&val, + cast(Unqual!T) mod) - 1); + else static if (is(T == short) || is(T == ushort)) + return cast(Unqual!T)(emscripten_atomic_sub_u16(cast(void*)&val, + cast(Unqual!T) mod) - 1); + else static if (is(T == int) || is(T == uint)) + return cast(Unqual!T)(emscripten_atomic_sub_u32(cast(void*)&val, + cast(Unqual!T) mod) - 1); + else + static assert(0); + } + } + + public pure nothrow @nogc @trusted void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref T val, + V newval) + { + alias UT = Unqual!T; + static if (is(UT == bool) || is(UT == byte) || is(UT == ubyte)) + emscripten_atomic_store_u8(cast(void*)&val, cast(UT) newval); + else static if (is(UT == short) || is(UT == ushort)) + emscripten_atomic_store_u16(cast(void*)&val, cast(UT) newval); + else static if (is(UT == int) || is(UT == uint)) + emscripten_atomic_store_u32(cast(void*)&val, cast(UT) newval); + else + static assert(0); + } + + public pure nothrow @nogc @trusted T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)( + ref const T val) + { + alias UT = Unqual!T; + static if (is(UT == bool)) + return emscripten_atomic_load_u8(cast(const void*)&val) != 0; + else static if (is(UT == byte) || is(UT == ubyte)) + return emscripten_atomic_load_u8(cast(const void*)&val); + else static if (is(UT == short) || is(UT == ushort)) + return emscripten_atomic_load_u16(cast(const void*)&val); + else static if (is(UT == int) || is(UT == uint)) + return emscripten_atomic_load_u32(cast(const void*)&val); + else + static assert(0); + } + + public pure nothrow @nogc @trusted bool cas(MemoryOrder succ = MemoryOrder.seq, + MemoryOrder fail = MemoryOrder.seq, T, V1, V2)(T* here, V1 ifThis, V2 writeThis) + { + alias UT = Unqual!T; + static if (is(UT == bool)) + return emscripten_atomic_cas_u8(cast(void*) here, + cast(Unqual!T) ifThis, cast(Unqual!T) writeThis) == ifThis; + else static if (is(UT == byte) || is(UT == ubyte)) + return emscripten_atomic_cas_u8(cast(void*) here, + cast(Unqual!T) ifThis, cast(Unqual!T) writeThis) == ifThis; + else static if (is(UT == short) || is(UT == ushort)) + return emscripten_atomic_cas_u16(cast(void*) here, + cast(Unqual!T) ifThis, cast(Unqual!T) writeThis) == ifThis; + else static if (is(UT == int) || is(UT == uint)) + return emscripten_atomic_cas_u32(cast(void*) here, + cast(Unqual!T) ifThis, cast(Unqual!T) writeThis) == ifThis; + else + static assert(0); + } +} +else +{ + public import core.atomic; +} diff --git a/source/bubel/ecs/entity.d b/source/bubel/ecs/entity.d index 76a8a2f..9b42c31 100644 --- a/source/bubel/ecs/entity.d +++ b/source/bubel/ecs/entity.d @@ -44,7 +44,7 @@ struct Entity return cast(T*)getComponent(becsID!T); } - export void* getComponent(ushort component_id) const + void* getComponent(ushort component_id) const { EntityManager.EntitiesBlock* block = gEntityManager.getMetaData(&this); EntityManager.EntityInfo* info = block.type_info; @@ -54,7 +54,7 @@ struct Entity return (cast(void*)block + info.deltas[component_id] + block.entityIndex(&this) * gEntityManager.components[component_id].size); } - export bool hasComponent(ushort component_id) const + bool hasComponent(ushort component_id) const { EntityManager.EntitiesBlock* block = gEntityManager.getMetaData(&this); EntityManager.EntityInfo* info = block.type_info; @@ -62,7 +62,7 @@ struct Entity return true; } - export EntityMeta getMeta() const + EntityMeta getMeta() const { EntityMeta meta; meta.block = gEntityManager.getMetaData(&this); @@ -85,7 +85,7 @@ struct EntityMeta return cast(T*)getComponent(becsID!T); } - export void* getComponent(ushort component_id) const + void* getComponent(ushort component_id) const { const (EntityManager.EntityInfo)* info = block.type_info; @@ -95,7 +95,7 @@ struct EntityMeta return (cast(void*)block + info.deltas[component_id] + index * gEntityManager.components[component_id].size); } - export bool hasComponent(ushort component_id) const + bool hasComponent(ushort component_id) const { const EntityManager.EntityInfo* info = block.type_info; if (component_id >= info.deltas.length || info.deltas[component_id] == 0)return false; @@ -133,7 +133,7 @@ export struct EntityTemplate /************************************************************************************************************************ Get specified component. If component doesn't exist function return null. Returned pointer is valid during EntityTemplate lifetime. */ - export void* getComponent(ushort component_id) const nothrow @nogc + 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]); diff --git a/source/bubel/ecs/hash_map.d b/source/bubel/ecs/hash_map.d index 7ba6137..66a0756 100755 --- a/source/bubel/ecs/hash_map.d +++ b/source/bubel/ecs/hash_map.d @@ -28,7 +28,7 @@ export ulong defaultHashFunc(T)(auto ref T t) nothrow @nogc } } -export ulong hash(byte[] array) nothrow @nogc +ulong hash(byte[] array) nothrow @nogc { ulong hash = 0; diff --git a/source/bubel/ecs/manager.d b/source/bubel/ecs/manager.d index b5220f4..26db180 100644 --- a/source/bubel/ecs/manager.d +++ b/source/bubel/ecs/manager.d @@ -27,8 +27,6 @@ alias SerializeVector = bubel.ecs.vector.Vector!ubyte; ///Global EntityManager used for everything. export __gshared EntityManager* gEntityManager = null; -version(D_BetterC) version = NoDRuntime; - /************************************************************************************************************************ Entity manager is responsible for everything. @@ -361,7 +359,7 @@ export struct EntityManager void registerSystem(Sys)(int priority, const(char)[] pass_name) { ushort pass = passes_map.get(pass_name, ushort.max); - version (NoDRuntime) + version (D_BetterC) assert(pass != ushort.max, "Update pass doesn't exist."); else assert(pass != ushort.max, "Update pass (Name " ~ pass_name ~ ") doesn't exist."); @@ -383,16 +381,17 @@ export struct EntityManager assert(register_state, "registerSystem must be called between beginRegister() and endRegister()."); - version (NoDRuntime) + version (D_BetterC) assert(pass < passes.length, "Update pass doesn't exist."); else assert(pass < passes.length, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist."); + // enum SystemName = __traits(fullyQualifiedName,Sys); // enum SystemName = fullyQualifiedName!Sys; enum SystemName = fullName!Sys; //enum SystemName = Sys.stringof; - System system = System(); + System system; system.m_pass = pass; // static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort)) @@ -429,7 +428,8 @@ export struct EntityManager { alias EventParamType = Params[1]; enum EventName = fullName!(Unqual!(EventParamType)); - // enum EventName = fullyQualifiedName!(Unqual!(EventParamType));//.stringof; + // enum EventName = __traits(fullyQualifiedName,Unqual!(EventParamType)); + // enum EventName = fullyQualifiedName!(Unqual!(EventParamType)); ushort evt = events_map.get(cast(char[]) EventName, ushort.max); assert(evt != ushort.max, "Can't register system \"" ~ SystemName @@ -491,8 +491,10 @@ export struct EntityManager 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!(typeof(MemberType.init[0]))); + // name = __traits(fullyQualifiedName,Unqual!(ForeachType!MemberType)); + // name = fullyQualifiedName!(Unqual!(ForeachType!MemberType)); + // name = fullName!(Unqual!(typeof(MemberType.init[0]))); + name = fullName!(Unqual!(Unqual!(ForeachType!MemberType))); } bool is_optional; @@ -717,8 +719,9 @@ export struct EntityManager string name; static if (isArray!MemberType) { // Workaround. This code is never called with: not an array type, but compiler prints an error + // name = __traits(fullyQualifiedName,Unqual!(ForeachType!MemberType)); // name = fullyQualifiedName!(Unqual!(ForeachType!MemberType)); - name = fullName!(Unqual!(typeof(MemberType.init[0]))); + name = fullName!(Unqual!(ForeachType!MemberType)); //name = Unqual!(ForeachType!MemberType).stringof; } @@ -842,7 +845,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.req) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - version (NoDRuntime) + version (D_BetterC) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing component."); @@ -854,7 +857,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.excluded) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - version (NoDRuntime) + version (D_BetterC) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing component."); @@ -866,7 +869,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.optional) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - version (NoDRuntime) + version (D_BetterC) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing component."); @@ -878,7 +881,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.readonly) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - version (NoDRuntime) + version (D_BetterC) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing component."); @@ -890,7 +893,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.mutable) { ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max); - version (NoDRuntime) + version (D_BetterC) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing component."); @@ -1200,7 +1203,7 @@ export struct EntityManager { ushort comp = external_dependencies_map.get(cast(const(char)[]) comp_info.type, ushort.max); - version (NoDRuntime) + version (D_BetterC) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing dependency."); @@ -1213,7 +1216,7 @@ export struct EntityManager foreach (iii, comp_info; components_info.writableDeps) { ushort comp = external_dependencies_map.get(cast(char[]) comp_info.type, ushort.max); - version (NoDRuntime) + version (D_BetterC) assert(comp != ushort.max, "Can't register system \"" ~ SystemName ~ "\" due to non existing dependency."); @@ -1298,6 +1301,7 @@ export struct EntityManager { ComponentInfo info; + // enum ComponentName = __traits(fullyQualifiedName,Comp); // enum ComponentName = fullyQualifiedName!Comp; enum ComponentName = fullName!Comp; // enum ComponentName = Comp.stringof; @@ -3357,16 +3361,6 @@ export struct EntityManager export ~this() nothrow @nogc { } - - export void opAssign(ComponentInfo c) - { - size = c.size; - alignment = c.alignment; - init_data = c.init_data; - destroy_callback = c.destroy_callback; - create_callback = c.create_callback; - } - ///Component size ushort size; ///Component data alignment diff --git a/source/bubel/ecs/std.d b/source/bubel/ecs/std.d index 8a3e207..8eb0d48 100644 --- a/source/bubel/ecs/std.d +++ b/source/bubel/ecs/std.d @@ -7,9 +7,11 @@ License: BSD 3-clause, see LICENSE file in project root folder. */ module bubel.ecs.std; +version (Emscripten) version = ECSEmscripten; + import std.traits; -version (Emscripten) +version (ECSEmscripten) { extern (C) struct pthread_mutex_t { @@ -27,6 +29,10 @@ version (Emscripten) extern (C) int memcmp(const void* s1, const void* s2, size_t size); extern (C) void exit(int status) nothrow @nogc; + extern (C) void __assert(const(char)* msg, const(char)* file, uint line) + { + exit(-20); + } extern (C) void free(void*) @nogc nothrow @system; extern (C) void* malloc(size_t size) @nogc nothrow @system; @@ -54,7 +60,7 @@ else public import core.stdc.stdlib : qsort; } -version (Emscripten) +version (ECSEmscripten) { } else version (Windows) @@ -83,7 +89,7 @@ else version (Posix) import core.sys.posix.stdlib : posix_memalign; } -version (Emscripten) +version (ECSEmscripten) { private const uint max_alloca = 10000; private __gshared byte[max_alloca] alloca_array; @@ -288,7 +294,7 @@ static struct Mallocator posix_memalign(&ret, alignment, length); //ret = aligned_alloc(alignment, length); else version (Windows) ret = _aligned_malloc(length, alignment); - else version (Emscripten) + else version (ECSEmscripten) posix_memalign(&ret, alignment, length); //malloc(length); else static assert(0, "Unimplemented platform!"); @@ -335,7 +341,7 @@ static struct Mallocator free(cast(void*) object); else version (Windows) _aligned_free(cast(void*) object); - else version (Emscripten) + else version (ECSEmscripten) free(cast(void*) object); else static assert(0, "Unimplemented platform!"); @@ -345,7 +351,7 @@ static struct Mallocator struct Mutex { - version (Emscripten) + version (ECSEmscripten) { void initialize() nothrow @nogc { diff --git a/source/bubel/ecs/system.d b/source/bubel/ecs/system.d index 310b53a..24098c0 100644 --- a/source/bubel/ecs/system.d +++ b/source/bubel/ecs/system.d @@ -13,14 +13,14 @@ import bubel.ecs.manager; System contain data required to proper glue EntityManager with Systems. System callbacks: $(LIST - * void onUpdate(EntitiesData); + * void onUpdate(EntitesData); * void onEnable() - called inside system.enable() function * void onDisable() - called inside system.disable() function * bool onBegin() - called inside manager.begin() * void onEnd() - called inside manager.end() * void onCreate() - called after registration inside registerSystem function * void onDestroy() - called during re-registration and inside manager destructor - * void onAddEntity(EntitiesData) - called for every entity which are assigned to system (by adding new entity or changing its components) + * void onAddEntity(EntitesData) - called for every entity which are assigned to system (by adding new entity or changing its components) * void onRemoveEntity(EntitiesData) - called for every entity removed from system update process * void onChangeEntity(EntitiesData) - called for every entity which components are changed but it was previously assigned to system * void handleEvent(Entity*, Event) - called for every event supported by system @@ -108,7 +108,7 @@ struct System package: ///destory system. Dispose all data - export void destroy() nothrow @nogc + void destroy() nothrow @nogc { import bubel.ecs.std : Mallocator; diff --git a/source/bubel/ecs/traits.d b/source/bubel/ecs/traits.d index 79901db..24bc698 100644 --- a/source/bubel/ecs/traits.d +++ b/source/bubel/ecs/traits.d @@ -63,34 +63,30 @@ static long getIndexOfTypeInEntitiesData(EntitiesData, Type)() return index; } -static string attachParentName(alias T, string str)() +template fullName(alias T : X!A, alias X, A...) { - alias parent = __traits(parent, T); - enum parent_str = parent.stringof; - static if(parent_str[0..7] == "module ") - { - static if(__traits(compiles, __traits(parent, parent))) - { - return attachParentName!(parent, parent_str[7 .. $] ~ '.' ~ str); - } - else return parent_str[7 .. $] ~ '.' ~ str; - } - else static if(parent_str[0..8] == "package ") - { - static if(__traits(compiles, __traits(parent, parent))) - { - return attachParentName!(parent, parent_str[8 .. $] ~ '.' ~ str); - } - else return parent_str[8 .. $] ~ '.' ~ str; - } - else static if(__traits(compiles, __traits(parent, parent))) - { - return attachParentName!(parent, parent_str ~ '.' ~ str); - } - else return parent_str ~ '.' ~ str; + alias parent = __traits(parent, X); + enum fullName = fullName!parent ~ '.' ~ __traits(identifier, X) ~ "!(" ~ fullName!A ~ ")"; } -static string fullName(T)() +template fullName(T...) { - return attachParentName!(T, T.stringof); + static if(__traits(compiles, __traits(parent, T[0]))) + { + alias parent = __traits(parent, T[0]); + enum fullName = fullName!parent ~ '.' ~ __traits(identifier, T[0]) ~ ", " ~ fullName!(T[1 .. $]); + } + else static if(__traits(compiles, __traits(identifier, T[0])))enum fullName = __traits(identifier, T[0]) ~ ", " ~ fullName!(T[1 .. $]); + else enum fullName = T[0].stringof ~ ", " ~ fullName!(T[1 .. $]); +} + +template fullName(alias T) +{ + static if(__traits(compiles, __traits(parent, T))) + { + alias parent = __traits(parent, T); + enum fullName = fullName!parent ~ '.' ~ __traits(identifier, T); + } + else static if(__traits(compiles, __traits(identifier, T)))enum fullName = __traits(identifier, T); + else enum fullName = T.stringof; } \ No newline at end of file diff --git a/tests/basic.d b/tests/basic.d index ea54382..e353549 100644 --- a/tests/basic.d +++ b/tests/basic.d @@ -160,6 +160,22 @@ void afterEveryTest() gEntityManager.destroy(); } +@("RegisteredNames") +unittest +{ + import bubel.ecs.traits; + + gEntityManager.beginRegister(); + gEntityManager.registerSystem!EmptySystem(0); + gEntityManager.registerSystem!EntityCounterSystem(0); + gEntityManager.endRegister(); + + System* empty_system = gEntityManager.getSystem(becsID!EmptySystem); + System* counter_system = gEntityManager.getSystem(becsID!EntityCounterSystem); + assert(empty_system.name == "tests.basic.EmptySystem", fullName!EmptySystem); + assert(counter_system.name == "tests.basic.EntityCounterSystem", fullName!EntityCounterSystem); +} + @("EntityMeta") unittest { diff --git a/tests/bugs.d b/tests/bugs.d index 10a3c62..5eaa8aa 100644 --- a/tests/bugs.d +++ b/tests/bugs.d @@ -172,4 +172,55 @@ unittest gEntityManager.commit(); gEntityManager.destroy(); -} \ No newline at end of file +} + +@("3-template-system-compilation-file") +unittest +{ + + struct TemplateSystem(T) + { + struct EntitiesData + { + uint length; + } + + T a; + } + + struct TemplateSystem2(T, T2, T3) + { + struct EntitiesData + { + uint length; + } + + T a; + T2 b; + T3 c; + } + + struct TempalteComponent(T) + { + T parameter; + } + + struct TempalteComponent2(T, T2) + { + T parameter; + T2 parameter2; + } + + gEntityManager.initialize(0); + + gEntityManager.beginRegister(); + + gEntityManager.registerComponent!CInt; + gEntityManager.registerComponent!(TempalteComponent!uint); + gEntityManager.registerComponent!(TempalteComponent2!(float,int)); + gEntityManager.registerSystem!(TemplateSystem!CInt)(0); + gEntityManager.registerSystem!(TemplateSystem2!(CInt, uint, float))(0); + + gEntityManager.endRegister(); + +}