Compare commits
2 commits
master
...
3-template
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a5452d6cc | |||
| 6a600d22c8 |
12 changed files with 260 additions and 78 deletions
|
|
@ -13,7 +13,7 @@ def compile(sources, output):
|
||||||
if file_extension == '.d' and filename != 'package':
|
if file_extension == '.d' and filename != 'package':
|
||||||
files.append(os.path.join(r, file))
|
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:
|
for path in sources:
|
||||||
ldc_cmd += '-I' + path + ' '
|
ldc_cmd += '-I' + path + ' '
|
||||||
|
|
@ -33,7 +33,7 @@ def compile(sources, output):
|
||||||
shared_flags = ''
|
shared_flags = ''
|
||||||
clean = 0
|
clean = 0
|
||||||
emc_flags = ''
|
emc_flags = ''
|
||||||
ldc_flags = ''
|
ldc_flags = '--d-version=ECSEmscripten '
|
||||||
import_paths = ['source','tests']
|
import_paths = ['source','tests']
|
||||||
build_tests = 0
|
build_tests = 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
import ntpath
|
import ntpath
|
||||||
import sys
|
import sys
|
||||||
|
import imp
|
||||||
|
|
||||||
def compile(sources, output):
|
def compile(sources, output):
|
||||||
files = []
|
files = []
|
||||||
|
|
@ -13,7 +14,7 @@ def compile(sources, output):
|
||||||
if file_extension == '.d' and filename != 'package':
|
if file_extension == '.d' and filename != 'package':
|
||||||
files.append(os.path.join(r, file))
|
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:
|
for path in sources:
|
||||||
ldc_cmd += '-I' + path + ' '
|
ldc_cmd += '-I' + path + ' '
|
||||||
|
|
@ -40,7 +41,7 @@ only_bc = 0
|
||||||
multi = 0
|
multi = 0
|
||||||
sources = ['tests', 'source']
|
sources = ['tests', 'source']
|
||||||
emc_flags = '-s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS="[\'png\']" '
|
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']
|
import_paths = ['external/sources', 'external/imports', 'external/wasm_imports', '../source', 'utils/source', 'simple/source']
|
||||||
|
|
||||||
for arg in sys.argv[1:]:
|
for arg in sys.argv[1:]:
|
||||||
|
|
@ -120,9 +121,8 @@ emcc_cmd += 'demo.bc '
|
||||||
|
|
||||||
os.system("mkdir build")
|
os.system("mkdir build")
|
||||||
|
|
||||||
# emscripten = imp.load_source('', os.path.expanduser("~") + '/.emscripten')
|
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 = 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'
|
|
||||||
print('Packafing files: ' + pack_cmd)
|
print('Packafing files: ' + pack_cmd)
|
||||||
|
|
||||||
os.system(pack_cmd)
|
os.system(pack_cmd)
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ threads_dep = dependency('threads')
|
||||||
d_versions = []
|
d_versions = []
|
||||||
deps = []
|
deps = []
|
||||||
if host_machine.cpu_family() == 'wasm32'
|
if host_machine.cpu_family() == 'wasm32'
|
||||||
|
d_versions += 'ECSEmscripten'
|
||||||
else
|
else
|
||||||
# meson incorectly adds "-s USE_PTHREADS=1" to ldc2 invocation whe pthreads is added as dependency
|
# meson incorectly adds "-s USE_PTHREADS=1" to ldc2 invocation whe pthreads is added as dependency
|
||||||
# add it for non wasm builds
|
# add it for non wasm builds
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,124 @@ License: BSD 3-clause, see LICENSE file in project root folder.
|
||||||
*/
|
*/
|
||||||
module bubel.ecs.atomic;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ struct Entity
|
||||||
return cast(T*)getComponent(becsID!T);
|
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.EntitiesBlock* block = gEntityManager.getMetaData(&this);
|
||||||
EntityManager.EntityInfo* info = block.type_info;
|
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);
|
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.EntitiesBlock* block = gEntityManager.getMetaData(&this);
|
||||||
EntityManager.EntityInfo* info = block.type_info;
|
EntityManager.EntityInfo* info = block.type_info;
|
||||||
|
|
@ -62,7 +62,7 @@ struct Entity
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export EntityMeta getMeta() const
|
EntityMeta getMeta() const
|
||||||
{
|
{
|
||||||
EntityMeta meta;
|
EntityMeta meta;
|
||||||
meta.block = gEntityManager.getMetaData(&this);
|
meta.block = gEntityManager.getMetaData(&this);
|
||||||
|
|
@ -85,7 +85,7 @@ struct EntityMeta
|
||||||
return cast(T*)getComponent(becsID!T);
|
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;
|
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);
|
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;
|
const EntityManager.EntityInfo* info = block.type_info;
|
||||||
if (component_id >= info.deltas.length || info.deltas[component_id] == 0)return false;
|
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.
|
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;
|
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]);
|
return cast(void*)(entity_data.ptr + info.tmpl_deltas[component_id]);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
ulong hash = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,6 @@ alias SerializeVector = bubel.ecs.vector.Vector!ubyte;
|
||||||
///Global EntityManager used for everything.
|
///Global EntityManager used for everything.
|
||||||
export __gshared EntityManager* gEntityManager = null;
|
export __gshared EntityManager* gEntityManager = null;
|
||||||
|
|
||||||
version(D_BetterC) version = NoDRuntime;
|
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
Entity manager is responsible for everything.
|
Entity manager is responsible for everything.
|
||||||
|
|
||||||
|
|
@ -361,7 +359,7 @@ export struct 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);
|
||||||
version (NoDRuntime)
|
version (D_BetterC)
|
||||||
assert(pass != ushort.max, "Update pass doesn't exist.");
|
assert(pass != ushort.max, "Update pass doesn't exist.");
|
||||||
else
|
else
|
||||||
assert(pass != ushort.max, "Update pass (Name " ~ pass_name ~ ") doesn't exist.");
|
assert(pass != ushort.max, "Update pass (Name " ~ pass_name ~ ") doesn't exist.");
|
||||||
|
|
@ -383,16 +381,17 @@ export struct EntityManager
|
||||||
|
|
||||||
assert(register_state,
|
assert(register_state,
|
||||||
"registerSystem must be called between beginRegister() and endRegister().");
|
"registerSystem must be called between beginRegister() and endRegister().");
|
||||||
version (NoDRuntime)
|
version (D_BetterC)
|
||||||
assert(pass < passes.length, "Update pass doesn't exist.");
|
assert(pass < passes.length, "Update pass doesn't exist.");
|
||||||
else
|
else
|
||||||
assert(pass < passes.length, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist.");
|
assert(pass < passes.length, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist.");
|
||||||
|
|
||||||
|
// enum SystemName = __traits(fullyQualifiedName,Sys);
|
||||||
// enum SystemName = fullyQualifiedName!Sys;
|
// enum SystemName = fullyQualifiedName!Sys;
|
||||||
enum SystemName = fullName!Sys;
|
enum SystemName = fullName!Sys;
|
||||||
//enum SystemName = Sys.stringof;
|
//enum SystemName = Sys.stringof;
|
||||||
|
|
||||||
System 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))
|
||||||
|
|
@ -429,7 +428,8 @@ export struct EntityManager
|
||||||
{
|
{
|
||||||
alias EventParamType = Params[1];
|
alias EventParamType = Params[1];
|
||||||
enum EventName = fullName!(Unqual!(EventParamType));
|
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);
|
ushort evt = events_map.get(cast(char[]) EventName, ushort.max);
|
||||||
assert(evt != ushort.max,
|
assert(evt != ushort.max,
|
||||||
"Can't register system \"" ~ SystemName
|
"Can't register system \"" ~ SystemName
|
||||||
|
|
@ -491,8 +491,10 @@ export struct EntityManager
|
||||||
string name;
|
string name;
|
||||||
static if (isArray!MemberType)
|
static if (isArray!MemberType)
|
||||||
{ // Workaround. This code is never called with: not an array type, but compiler prints an error
|
{ // Workaround. This code is never called with: not an array type, but compiler prints an error
|
||||||
// name = fullyQualifiedName!(Unqual!(ForeachType!MemberType));//.stringof;
|
// name = __traits(fullyQualifiedName,Unqual!(ForeachType!MemberType));
|
||||||
name = fullName!(Unqual!(typeof(MemberType.init[0])));
|
// name = fullyQualifiedName!(Unqual!(ForeachType!MemberType));
|
||||||
|
// name = fullName!(Unqual!(typeof(MemberType.init[0])));
|
||||||
|
name = fullName!(Unqual!(Unqual!(ForeachType!MemberType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_optional;
|
bool is_optional;
|
||||||
|
|
@ -717,8 +719,9 @@ export struct EntityManager
|
||||||
string name;
|
string name;
|
||||||
static if (isArray!MemberType)
|
static if (isArray!MemberType)
|
||||||
{ // Workaround. This code is never called with: not an array type, but compiler prints an error
|
{ // 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 = fullyQualifiedName!(Unqual!(ForeachType!MemberType));
|
||||||
name = fullName!(Unqual!(typeof(MemberType.init[0])));
|
name = fullName!(Unqual!(ForeachType!MemberType));
|
||||||
//name = Unqual!(ForeachType!MemberType).stringof;
|
//name = Unqual!(ForeachType!MemberType).stringof;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -842,7 +845,7 @@ export struct EntityManager
|
||||||
foreach (iii, comp_info; components_info.req)
|
foreach (iii, comp_info; components_info.req)
|
||||||
{
|
{
|
||||||
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
||||||
version (NoDRuntime)
|
version (D_BetterC)
|
||||||
assert(comp != ushort.max,
|
assert(comp != ushort.max,
|
||||||
"Can't register system \"" ~ SystemName
|
"Can't register system \"" ~ SystemName
|
||||||
~ "\" due to non existing component.");
|
~ "\" due to non existing component.");
|
||||||
|
|
@ -854,7 +857,7 @@ export struct EntityManager
|
||||||
foreach (iii, comp_info; components_info.excluded)
|
foreach (iii, comp_info; components_info.excluded)
|
||||||
{
|
{
|
||||||
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
||||||
version (NoDRuntime)
|
version (D_BetterC)
|
||||||
assert(comp != ushort.max,
|
assert(comp != ushort.max,
|
||||||
"Can't register system \"" ~ SystemName
|
"Can't register system \"" ~ SystemName
|
||||||
~ "\" due to non existing component.");
|
~ "\" due to non existing component.");
|
||||||
|
|
@ -866,7 +869,7 @@ export struct EntityManager
|
||||||
foreach (iii, comp_info; components_info.optional)
|
foreach (iii, comp_info; components_info.optional)
|
||||||
{
|
{
|
||||||
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
||||||
version (NoDRuntime)
|
version (D_BetterC)
|
||||||
assert(comp != ushort.max,
|
assert(comp != ushort.max,
|
||||||
"Can't register system \"" ~ SystemName
|
"Can't register system \"" ~ SystemName
|
||||||
~ "\" due to non existing component.");
|
~ "\" due to non existing component.");
|
||||||
|
|
@ -878,7 +881,7 @@ export struct EntityManager
|
||||||
foreach (iii, comp_info; components_info.readonly)
|
foreach (iii, comp_info; components_info.readonly)
|
||||||
{
|
{
|
||||||
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
||||||
version (NoDRuntime)
|
version (D_BetterC)
|
||||||
assert(comp != ushort.max,
|
assert(comp != ushort.max,
|
||||||
"Can't register system \"" ~ SystemName
|
"Can't register system \"" ~ SystemName
|
||||||
~ "\" due to non existing component.");
|
~ "\" due to non existing component.");
|
||||||
|
|
@ -890,7 +893,7 @@ export struct EntityManager
|
||||||
foreach (iii, comp_info; components_info.mutable)
|
foreach (iii, comp_info; components_info.mutable)
|
||||||
{
|
{
|
||||||
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
|
||||||
version (NoDRuntime)
|
version (D_BetterC)
|
||||||
assert(comp != ushort.max,
|
assert(comp != ushort.max,
|
||||||
"Can't register system \"" ~ SystemName
|
"Can't register system \"" ~ SystemName
|
||||||
~ "\" due to non existing component.");
|
~ "\" 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 comp = external_dependencies_map.get(cast(const(char)[]) comp_info.type,
|
||||||
ushort.max);
|
ushort.max);
|
||||||
version (NoDRuntime)
|
version (D_BetterC)
|
||||||
assert(comp != ushort.max,
|
assert(comp != ushort.max,
|
||||||
"Can't register system \"" ~ SystemName
|
"Can't register system \"" ~ SystemName
|
||||||
~ "\" due to non existing dependency.");
|
~ "\" due to non existing dependency.");
|
||||||
|
|
@ -1213,7 +1216,7 @@ export struct EntityManager
|
||||||
foreach (iii, comp_info; components_info.writableDeps)
|
foreach (iii, comp_info; components_info.writableDeps)
|
||||||
{
|
{
|
||||||
ushort comp = external_dependencies_map.get(cast(char[]) comp_info.type, ushort.max);
|
ushort comp = external_dependencies_map.get(cast(char[]) comp_info.type, ushort.max);
|
||||||
version (NoDRuntime)
|
version (D_BetterC)
|
||||||
assert(comp != ushort.max,
|
assert(comp != ushort.max,
|
||||||
"Can't register system \"" ~ SystemName
|
"Can't register system \"" ~ SystemName
|
||||||
~ "\" due to non existing dependency.");
|
~ "\" due to non existing dependency.");
|
||||||
|
|
@ -1298,6 +1301,7 @@ export struct EntityManager
|
||||||
{
|
{
|
||||||
ComponentInfo info;
|
ComponentInfo info;
|
||||||
|
|
||||||
|
// enum ComponentName = __traits(fullyQualifiedName,Comp);
|
||||||
// enum ComponentName = fullyQualifiedName!Comp;
|
// enum ComponentName = fullyQualifiedName!Comp;
|
||||||
enum ComponentName = fullName!Comp;
|
enum ComponentName = fullName!Comp;
|
||||||
// enum ComponentName = Comp.stringof;
|
// enum ComponentName = Comp.stringof;
|
||||||
|
|
@ -3357,16 +3361,6 @@ export struct EntityManager
|
||||||
export ~this() nothrow @nogc
|
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
|
///Component size
|
||||||
ushort size;
|
ushort size;
|
||||||
///Component data alignment
|
///Component data alignment
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,11 @@ License: BSD 3-clause, see LICENSE file in project root folder.
|
||||||
*/
|
*/
|
||||||
module bubel.ecs.std;
|
module bubel.ecs.std;
|
||||||
|
|
||||||
|
version (Emscripten) version = ECSEmscripten;
|
||||||
|
|
||||||
import std.traits;
|
import std.traits;
|
||||||
|
|
||||||
version (Emscripten)
|
version (ECSEmscripten)
|
||||||
{
|
{
|
||||||
extern (C) struct pthread_mutex_t
|
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) int memcmp(const void* s1, const void* s2, size_t size);
|
||||||
extern (C) void exit(int status) nothrow @nogc;
|
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 free(void*) @nogc nothrow @system;
|
||||||
extern (C) void* malloc(size_t size) @nogc nothrow @system;
|
extern (C) void* malloc(size_t size) @nogc nothrow @system;
|
||||||
|
|
@ -54,7 +60,7 @@ else
|
||||||
public import core.stdc.stdlib : qsort;
|
public import core.stdc.stdlib : qsort;
|
||||||
}
|
}
|
||||||
|
|
||||||
version (Emscripten)
|
version (ECSEmscripten)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else version (Windows)
|
else version (Windows)
|
||||||
|
|
@ -83,7 +89,7 @@ else version (Posix)
|
||||||
import core.sys.posix.stdlib : posix_memalign;
|
import core.sys.posix.stdlib : posix_memalign;
|
||||||
}
|
}
|
||||||
|
|
||||||
version (Emscripten)
|
version (ECSEmscripten)
|
||||||
{
|
{
|
||||||
private const uint max_alloca = 10000;
|
private const uint max_alloca = 10000;
|
||||||
private __gshared byte[max_alloca] alloca_array;
|
private __gshared byte[max_alloca] alloca_array;
|
||||||
|
|
@ -288,7 +294,7 @@ static struct Mallocator
|
||||||
posix_memalign(&ret, alignment, length); //ret = aligned_alloc(alignment, length);
|
posix_memalign(&ret, alignment, length); //ret = aligned_alloc(alignment, length);
|
||||||
else version (Windows)
|
else version (Windows)
|
||||||
ret = _aligned_malloc(length, alignment);
|
ret = _aligned_malloc(length, alignment);
|
||||||
else version (Emscripten)
|
else version (ECSEmscripten)
|
||||||
posix_memalign(&ret, alignment, length); //malloc(length);
|
posix_memalign(&ret, alignment, length); //malloc(length);
|
||||||
else
|
else
|
||||||
static assert(0, "Unimplemented platform!");
|
static assert(0, "Unimplemented platform!");
|
||||||
|
|
@ -335,7 +341,7 @@ static struct Mallocator
|
||||||
free(cast(void*) object);
|
free(cast(void*) object);
|
||||||
else version (Windows)
|
else version (Windows)
|
||||||
_aligned_free(cast(void*) object);
|
_aligned_free(cast(void*) object);
|
||||||
else version (Emscripten)
|
else version (ECSEmscripten)
|
||||||
free(cast(void*) object);
|
free(cast(void*) object);
|
||||||
else
|
else
|
||||||
static assert(0, "Unimplemented platform!");
|
static assert(0, "Unimplemented platform!");
|
||||||
|
|
@ -345,7 +351,7 @@ static struct Mallocator
|
||||||
struct Mutex
|
struct Mutex
|
||||||
{
|
{
|
||||||
|
|
||||||
version (Emscripten)
|
version (ECSEmscripten)
|
||||||
{
|
{
|
||||||
void initialize() nothrow @nogc
|
void initialize() nothrow @nogc
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,14 @@ import bubel.ecs.manager;
|
||||||
System contain data required to proper glue EntityManager with Systems.
|
System contain data required to proper glue EntityManager with Systems.
|
||||||
System callbacks:
|
System callbacks:
|
||||||
$(LIST
|
$(LIST
|
||||||
* void onUpdate(EntitiesData);
|
* void onUpdate(EntitesData);
|
||||||
* void onEnable() - called inside system.enable() function
|
* void onEnable() - called inside system.enable() function
|
||||||
* void onDisable() - called inside system.disable() function
|
* void onDisable() - called inside system.disable() function
|
||||||
* bool onBegin() - called inside manager.begin()
|
* bool onBegin() - called inside manager.begin()
|
||||||
* void onEnd() - called inside manager.end()
|
* void onEnd() - called inside manager.end()
|
||||||
* void onCreate() - called after registration inside registerSystem function
|
* void onCreate() - called after registration inside registerSystem function
|
||||||
* void onDestroy() - called during re-registration and inside manager destructor
|
* 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 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 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
|
* void handleEvent(Entity*, Event) - called for every event supported by system
|
||||||
|
|
@ -108,7 +108,7 @@ struct System
|
||||||
package:
|
package:
|
||||||
|
|
||||||
///destory system. Dispose all data
|
///destory system. Dispose all data
|
||||||
export void destroy() nothrow @nogc
|
void destroy() nothrow @nogc
|
||||||
{
|
{
|
||||||
import bubel.ecs.std : Mallocator;
|
import bubel.ecs.std : Mallocator;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,34 +63,30 @@ static long getIndexOfTypeInEntitiesData(EntitiesData, Type)()
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static string attachParentName(alias T, string str)()
|
template fullName(alias T : X!A, alias X, A...)
|
||||||
{
|
{
|
||||||
alias parent = __traits(parent, T);
|
alias parent = __traits(parent, X);
|
||||||
enum parent_str = parent.stringof;
|
enum fullName = fullName!parent ~ '.' ~ __traits(identifier, X) ~ "!(" ~ fullName!A ~ ")";
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
@ -160,6 +160,22 @@ void afterEveryTest()
|
||||||
gEntityManager.destroy();
|
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")
|
@("EntityMeta")
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
|
|
|
||||||
51
tests/bugs.d
51
tests/bugs.d
|
|
@ -173,3 +173,54 @@ unittest
|
||||||
|
|
||||||
gEntityManager.destroy();
|
gEntityManager.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@("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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue