Compare commits

...
Sign in to create a new pull request.

4 commits

9 changed files with 47 additions and 160 deletions

View file

@ -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-unknown-wasm -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' '
ldc_cmd = 'ldc2 ' + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-emscripten -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 = '--d-version=ECSEmscripten '
ldc_flags = ''
import_paths = ['source','tests']
build_tests = 0

View file

@ -1,7 +1,6 @@
import os
import ntpath
import sys
import imp
def compile(sources, output):
files = []
@ -14,7 +13,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-unknown-wasm -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' '
ldc_cmd = compiler + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-emscripten -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' '
for path in sources:
ldc_cmd += '-I' + path + ' '
@ -41,7 +40,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=ECSEmscripten --d-version=SDL_209 --d-version=BindSDL_Static --d-version=BindSDL_Image --d-version=MM_USE_POSIX_THREADS '
ldc_flags = '--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:]:
@ -121,8 +120,9 @@ 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'
# 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'
print('Packafing files: ' + pack_cmd)
os.system(pack_cmd)

View file

@ -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

View file

@ -9,124 +9,5 @@ License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.atomic;
version (Emscripten) version = ECSEmscripten;
public import core.atomic;
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;
}

View file

@ -44,7 +44,7 @@ struct Entity
return cast(T*)getComponent(becsID!T);
}
void* getComponent(ushort component_id) const
export 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);
}
bool hasComponent(ushort component_id) const
export 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;
}
EntityMeta getMeta() const
export EntityMeta getMeta() const
{
EntityMeta meta;
meta.block = gEntityManager.getMetaData(&this);
@ -85,7 +85,7 @@ struct EntityMeta
return cast(T*)getComponent(becsID!T);
}
void* getComponent(ushort component_id) const
export 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);
}
bool hasComponent(ushort component_id) const
export 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.
*/
void* getComponent(ushort component_id) const nothrow @nogc
export 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]);

View file

@ -28,7 +28,7 @@ export ulong defaultHashFunc(T)(auto ref T t) nothrow @nogc
}
}
ulong hash(byte[] array) nothrow @nogc
export ulong hash(byte[] array) nothrow @nogc
{
ulong hash = 0;

View file

@ -27,6 +27,8 @@ 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.
@ -359,7 +361,7 @@ export struct EntityManager
void registerSystem(Sys)(int priority, const(char)[] pass_name)
{
ushort pass = passes_map.get(pass_name, ushort.max);
version (D_BetterC)
version (NoDRuntime)
assert(pass != ushort.max, "Update pass doesn't exist.");
else
assert(pass != ushort.max, "Update pass (Name " ~ pass_name ~ ") doesn't exist.");
@ -381,7 +383,7 @@ export struct EntityManager
assert(register_state,
"registerSystem must be called between beginRegister() and endRegister().");
version (D_BetterC)
version (NoDRuntime)
assert(pass < passes.length, "Update pass doesn't exist.");
else
assert(pass < passes.length, "Update pass (ID " ~ pass.to!string ~ ") doesn't exist.");
@ -390,7 +392,7 @@ export struct EntityManager
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))
@ -840,7 +842,7 @@ export struct EntityManager
foreach (iii, comp_info; components_info.req)
{
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
version (D_BetterC)
version (NoDRuntime)
assert(comp != ushort.max,
"Can't register system \"" ~ SystemName
~ "\" due to non existing component.");
@ -852,7 +854,7 @@ export struct EntityManager
foreach (iii, comp_info; components_info.excluded)
{
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
version (D_BetterC)
version (NoDRuntime)
assert(comp != ushort.max,
"Can't register system \"" ~ SystemName
~ "\" due to non existing component.");
@ -864,7 +866,7 @@ export struct EntityManager
foreach (iii, comp_info; components_info.optional)
{
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
version (D_BetterC)
version (NoDRuntime)
assert(comp != ushort.max,
"Can't register system \"" ~ SystemName
~ "\" due to non existing component.");
@ -876,7 +878,7 @@ export struct EntityManager
foreach (iii, comp_info; components_info.readonly)
{
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
version (D_BetterC)
version (NoDRuntime)
assert(comp != ushort.max,
"Can't register system \"" ~ SystemName
~ "\" due to non existing component.");
@ -888,7 +890,7 @@ export struct EntityManager
foreach (iii, comp_info; components_info.mutable)
{
ushort comp = components_map.get(cast(char[]) comp_info.type, ushort.max);
version (D_BetterC)
version (NoDRuntime)
assert(comp != ushort.max,
"Can't register system \"" ~ SystemName
~ "\" due to non existing component.");
@ -1198,7 +1200,7 @@ export struct EntityManager
{
ushort comp = external_dependencies_map.get(cast(const(char)[]) comp_info.type,
ushort.max);
version (D_BetterC)
version (NoDRuntime)
assert(comp != ushort.max,
"Can't register system \"" ~ SystemName
~ "\" due to non existing dependency.");
@ -1211,7 +1213,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 (D_BetterC)
version (NoDRuntime)
assert(comp != ushort.max,
"Can't register system \"" ~ SystemName
~ "\" due to non existing dependency.");
@ -3355,6 +3357,16 @@ 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

View file

@ -7,11 +7,9 @@ License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.std;
version (Emscripten) version = ECSEmscripten;
import std.traits;
version (ECSEmscripten)
version (Emscripten)
{
extern (C) struct pthread_mutex_t
{
@ -29,10 +27,6 @@ version (ECSEmscripten)
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;
@ -60,7 +54,7 @@ else
public import core.stdc.stdlib : qsort;
}
version (ECSEmscripten)
version (Emscripten)
{
}
else version (Windows)
@ -89,7 +83,7 @@ else version (Posix)
import core.sys.posix.stdlib : posix_memalign;
}
version (ECSEmscripten)
version (Emscripten)
{
private const uint max_alloca = 10000;
private __gshared byte[max_alloca] alloca_array;
@ -294,7 +288,7 @@ static struct Mallocator
posix_memalign(&ret, alignment, length); //ret = aligned_alloc(alignment, length);
else version (Windows)
ret = _aligned_malloc(length, alignment);
else version (ECSEmscripten)
else version (Emscripten)
posix_memalign(&ret, alignment, length); //malloc(length);
else
static assert(0, "Unimplemented platform!");
@ -341,7 +335,7 @@ static struct Mallocator
free(cast(void*) object);
else version (Windows)
_aligned_free(cast(void*) object);
else version (ECSEmscripten)
else version (Emscripten)
free(cast(void*) object);
else
static assert(0, "Unimplemented platform!");
@ -351,7 +345,7 @@ static struct Mallocator
struct Mutex
{
version (ECSEmscripten)
version (Emscripten)
{
void initialize() nothrow @nogc
{

View file

@ -13,14 +13,14 @@ import bubel.ecs.manager;
System contain data required to proper glue EntityManager with Systems.
System callbacks:
$(LIST
* void onUpdate(EntitesData);
* void onUpdate(EntitiesData);
* 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(EntitesData) - called for every entity which are assigned to system (by adding new entity or changing its components)
* void onAddEntity(EntitiesData) - 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
void destroy() nothrow @nogc
export void destroy() nothrow @nogc
{
import bubel.ecs.std : Mallocator;