Compare commits
No commits in common. "master" and "v0.1.1" have entirely different histories.
11 changed files with 217 additions and 309 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;
|
||||||
|
|
||||||
|
|
@ -341,7 +341,7 @@ nothrow:
|
||||||
int result;
|
int result;
|
||||||
foreach (ref Key k; this)
|
foreach (ref Key k; this)
|
||||||
{
|
{
|
||||||
result = (cast(int delegate(ref Key k) nothrow @nogc)dg)(k);
|
result = (cast(int delegate(ref Key k) nothrow)dg)(k);
|
||||||
if (result)
|
if (result)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -353,7 +353,7 @@ nothrow:
|
||||||
int result;
|
int result;
|
||||||
foreach (ref Value v; this)
|
foreach (ref Value v; this)
|
||||||
{
|
{
|
||||||
result = (cast(int delegate(ref Value v) nothrow @nogc)dg)(v);
|
result = (cast(int delegate(ref Value v) nothrow)dg)(v);
|
||||||
if (result)
|
if (result)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -365,7 +365,7 @@ nothrow:
|
||||||
int result;
|
int result;
|
||||||
foreach (ref Key k, ref Value v; this)
|
foreach (ref Key k, ref Value v; this)
|
||||||
{
|
{
|
||||||
result = (cast(int delegate(ref Key k, ref Value v) nothrow @nogc)dg)(k, v);
|
result = (cast(int delegate(ref Key k, ref Value v) nothrow)dg)(k, v);
|
||||||
if (result)
|
if (result)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
@ -78,7 +76,7 @@ export struct EntityManager
|
||||||
UpdatePass* pass = Mallocator.make!UpdatePass;
|
UpdatePass* pass = Mallocator.make!UpdatePass;
|
||||||
pass.name = Mallocator.makeArray(cast(char[]) "update");
|
pass.name = Mallocator.makeArray(cast(char[]) "update");
|
||||||
passes.add(pass);
|
passes.add(pass);
|
||||||
passes_map.add(cast(const(char)[]) pass.name, cast(ushort)(passes.length - 1));
|
passes_map.add(cast(string) pass.name, cast(ushort)(passes.length - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -86,7 +84,7 @@ export struct EntityManager
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
Deinitialize and destroy ECS. This function release whole memory.
|
Deinitialize and destroy ECS. This function release whole memory.
|
||||||
*/
|
*/
|
||||||
export static void destroy() nothrow @nogc
|
export static void destroy()
|
||||||
{
|
{
|
||||||
if (gEntityManager is null)
|
if (gEntityManager is null)
|
||||||
return;
|
return;
|
||||||
|
|
@ -336,23 +334,16 @@ export struct EntityManager
|
||||||
*/
|
*/
|
||||||
void unregisterSystem(Sys)()
|
void unregisterSystem(Sys)()
|
||||||
{
|
{
|
||||||
|
assert(register_state, "unregisterSystem must be called between beginRegister() and endRegister().");
|
||||||
|
|
||||||
ushort system_id = becsID!Sys;
|
ushort system_id = becsID!Sys;
|
||||||
System* system = getSystem(system_id);
|
System* system = getSystem(system_id);
|
||||||
|
|
||||||
unregisterSystem(system);
|
assert(system, "System was not registered");
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************************************************************
|
|
||||||
Unregister given system form EntityManager.
|
|
||||||
*/
|
|
||||||
export void unregisterSystem(System* system) nothrow @nogc
|
|
||||||
{
|
|
||||||
assert(register_state, "unregisterSystem must be called between beginRegister() and endRegister().");
|
|
||||||
assert(system !is null, "System was not registered");
|
|
||||||
assert(system.isAlive, "System already unregistered");
|
assert(system.isAlive, "System already unregistered");
|
||||||
|
|
||||||
//disable, destroy and dispose user created system but keep name and other data
|
system.destroy();
|
||||||
system.destroySystemData();
|
*system = System.init;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
|
|
@ -361,7 +352,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,7 +374,7 @@ 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.");
|
||||||
|
|
@ -392,7 +383,7 @@ export struct EntityManager
|
||||||
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))
|
||||||
|
|
@ -842,7 +833,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 +845,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 +857,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 +869,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 +881,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 +1191,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 +1204,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.");
|
||||||
|
|
@ -1257,8 +1248,7 @@ export struct EntityManager
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************
|
/************************************************************************************************************************
|
||||||
Return system ECS api by id.
|
Return system ECS api by id
|
||||||
System pointer might become invalid after registration process. It should be get once again after new systems are registered.
|
|
||||||
*/
|
*/
|
||||||
export System* getSystem(ushort id) nothrow @nogc
|
export System* getSystem(ushort id) nothrow @nogc
|
||||||
{
|
{
|
||||||
|
|
@ -1858,7 +1848,6 @@ export struct EntityManager
|
||||||
*/
|
*/
|
||||||
export EntityTemplate* allocateTemplate(EntityTemplate* copy_tmpl)
|
export EntityTemplate* allocateTemplate(EntityTemplate* copy_tmpl)
|
||||||
{
|
{
|
||||||
assert(copy_tmpl, "copy_tmpl can't be null");
|
|
||||||
EntityTemplate* tmpl = Mallocator.make!EntityTemplate;
|
EntityTemplate* tmpl = Mallocator.make!EntityTemplate;
|
||||||
tmpl.info = copy_tmpl.info;
|
tmpl.info = copy_tmpl.info;
|
||||||
tmpl.entity_data = Mallocator.makeArray(copy_tmpl.entity_data);
|
tmpl.entity_data = Mallocator.makeArray(copy_tmpl.entity_data);
|
||||||
|
|
@ -1873,29 +1862,19 @@ export struct EntityManager
|
||||||
*/
|
*/
|
||||||
export EntityInfo* getEntityInfo(ushort[] ids)
|
export EntityInfo* getEntityInfo(ushort[] ids)
|
||||||
{
|
{
|
||||||
if(ids.length == 0)ids = null;
|
|
||||||
EntityInfo* info = entities_infos.get(ids, null);
|
EntityInfo* info = entities_infos.get(ids, null);
|
||||||
if (info is null)
|
if (info is null)
|
||||||
{
|
{
|
||||||
info = Mallocator.make!EntityInfo;
|
info = Mallocator.make!EntityInfo;
|
||||||
|
|
||||||
|
info.components = Mallocator.makeArray(ids);
|
||||||
|
info.deltas = Mallocator.makeArray!ushort(ids[$ - 1] + 1);
|
||||||
|
|
||||||
info.size = EntityID.sizeof;
|
info.size = EntityID.sizeof;
|
||||||
info.alignment = EntityID.alignof;
|
info.alignment = EntityID.alignof;
|
||||||
|
|
||||||
if(ids is null)
|
|
||||||
{
|
|
||||||
uint block_memory = cast(uint)(
|
|
||||||
m_page_size - EntitiesBlock.sizeof - info.size);
|
|
||||||
uint entites_in_block = block_memory / info.size;
|
|
||||||
info.max_entities = cast(ushort) entites_in_block;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint components_size = EntityID.sizeof;
|
|
||||||
|
|
||||||
info.components = Mallocator.makeArray(ids);
|
|
||||||
info.deltas = Mallocator.makeArray!ushort(ids[$ - 1] + 1);
|
|
||||||
info.tmpl_deltas = Mallocator.makeArray!ushort(ids[$ - 1] + 1, ushort.max);
|
info.tmpl_deltas = Mallocator.makeArray!ushort(ids[$ - 1] + 1, ushort.max);
|
||||||
|
uint components_size = EntityID.sizeof;
|
||||||
|
|
||||||
foreach (i, id; ids)
|
foreach (i, id; ids)
|
||||||
{
|
{
|
||||||
|
|
@ -1925,16 +1904,6 @@ export struct EntityManager
|
||||||
current_delta += entites_in_block * components[id].size;
|
current_delta += entites_in_block * components[id].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.comp_add_info = Mallocator.makeArray!(EntityInfo*)(info.deltas.length);
|
|
||||||
info.comp_rem_info = Mallocator.makeArray!(EntityInfo*)(info.deltas.length);
|
|
||||||
|
|
||||||
foreach (comp; info.components)
|
|
||||||
{
|
|
||||||
info.comp_add_info[comp] = info;
|
|
||||||
info.comp_rem_info[comp] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
info.systems = Mallocator.makeArray!bool(systems.length);
|
info.systems = Mallocator.makeArray!bool(systems.length);
|
||||||
|
|
||||||
foreach (i, ref system; systems)
|
foreach (i, ref system; systems)
|
||||||
|
|
@ -1953,6 +1922,15 @@ export struct EntityManager
|
||||||
addSystemCaller(*info, cast(uint) i);
|
addSystemCaller(*info, cast(uint) i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info.comp_add_info = Mallocator.makeArray!(EntityInfo*)(info.deltas.length);
|
||||||
|
info.comp_rem_info = Mallocator.makeArray!(EntityInfo*)(info.deltas.length);
|
||||||
|
|
||||||
|
foreach (comp; info.components)
|
||||||
|
{
|
||||||
|
info.comp_add_info[comp] = info;
|
||||||
|
info.comp_rem_info[comp] = null;
|
||||||
|
}
|
||||||
|
|
||||||
entities_infos.add(info.components, info);
|
entities_infos.add(info.components, info);
|
||||||
|
|
||||||
generateListeners(info);
|
generateListeners(info);
|
||||||
|
|
@ -2566,7 +2544,7 @@ export struct EntityManager
|
||||||
use you should save ID instead of pointer.
|
use you should save ID instead of pointer.
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
tmpl = pointer entity template allocated by EntityManager. Can be null in which case empty entity would be added (entity without components)
|
tmpl = pointer entity template allocated by EntityManager.
|
||||||
*/
|
*/
|
||||||
export Entity* addEntity(EntityTemplate* tmpl)
|
export Entity* addEntity(EntityTemplate* tmpl)
|
||||||
{
|
{
|
||||||
|
|
@ -2578,14 +2556,12 @@ export struct EntityManager
|
||||||
use you should save ID instead of pointer.
|
use you should save ID instead of pointer.
|
||||||
|
|
||||||
Params:
|
Params:
|
||||||
tmpl = pointer entity template allocated by EntityManager. Can be null in which case empty entity would be added (entity without components)
|
tmpl = pointer entity template allocated by EntityManager.
|
||||||
replacement = list of components references to used. Memory form list replace data from template inside new entity. Should be used only for data which vary between most entities (like 3D position etc.)
|
replacement = list of components references to used. Memory form list replace data from template inside new entity. Should be used only for data which vary between most entities (like 3D position etc.)
|
||||||
*/
|
*/
|
||||||
export Entity* addEntity(EntityTemplate* tmpl, ComponentRef[] replacement)
|
export Entity* addEntity(EntityTemplate* tmpl, ComponentRef[] replacement)
|
||||||
{
|
{
|
||||||
EntityInfo* info = void;
|
EntityInfo* info = tmpl.info;
|
||||||
if(tmpl)info = tmpl.info;
|
|
||||||
else info = getEntityInfo(null);
|
|
||||||
|
|
||||||
ushort index = 0;
|
ushort index = 0;
|
||||||
EntitiesBlock* block;
|
EntitiesBlock* block;
|
||||||
|
|
@ -3357,16 +3333,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
|
||||||
|
|
@ -3472,7 +3438,7 @@ export struct EntityManager
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (components.length == 0 || id > components[$ - 1])
|
if (id > components[$ - 1])
|
||||||
ids[len++] = id;
|
ids[len++] = id;
|
||||||
|
|
||||||
assert(len == components.length + 1);
|
assert(len == components.length + 1);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -97,92 +97,38 @@ struct System
|
||||||
return m_system_pointer != null;
|
return m_system_pointer != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************************************
|
|
||||||
Return pointer to user side system object
|
|
||||||
*/
|
|
||||||
export void* ptr() nothrow @nogc
|
|
||||||
{
|
|
||||||
return m_system_pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
package:
|
package:
|
||||||
|
|
||||||
///destory system. Dispose all data
|
void destroy()
|
||||||
export void destroy() nothrow @nogc
|
|
||||||
{
|
|
||||||
import bubel.ecs.std : Mallocator;
|
|
||||||
|
|
||||||
destroySystemData();
|
|
||||||
|
|
||||||
if (m_name)
|
|
||||||
{
|
|
||||||
Mallocator.dispose(m_name);
|
|
||||||
m_name = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///destroy all system data but keeps name which is used for case of system re-registration
|
|
||||||
void destroySystemData() nothrow @nogc
|
|
||||||
{
|
{
|
||||||
import bubel.ecs.std : Mallocator;
|
import bubel.ecs.std : Mallocator;
|
||||||
disable();
|
disable();
|
||||||
if (m_destroy)
|
if (m_destroy)
|
||||||
{
|
(cast(void function(void*)) m_destroy)(m_system_pointer);
|
||||||
(cast(void function(void*) nothrow @nogc) m_destroy)(m_system_pointer);
|
|
||||||
m_destroy = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (m_name)
|
||||||
|
Mallocator.dispose(m_name);
|
||||||
if (m_components)
|
if (m_components)
|
||||||
{
|
|
||||||
Mallocator.dispose(m_components);
|
Mallocator.dispose(m_components);
|
||||||
m_components = null;
|
|
||||||
}
|
|
||||||
if (m_excluded_components)
|
if (m_excluded_components)
|
||||||
{
|
|
||||||
Mallocator.dispose(m_excluded_components);
|
Mallocator.dispose(m_excluded_components);
|
||||||
m_excluded_components = null;
|
|
||||||
}
|
|
||||||
if (m_optional_components)
|
if (m_optional_components)
|
||||||
{
|
|
||||||
Mallocator.dispose(m_optional_components);
|
Mallocator.dispose(m_optional_components);
|
||||||
m_optional_components = null;
|
|
||||||
}
|
|
||||||
if (jobs)
|
if (jobs)
|
||||||
{
|
|
||||||
Mallocator.dispose(jobs);
|
Mallocator.dispose(jobs);
|
||||||
jobs = null;
|
|
||||||
}
|
|
||||||
if (m_read_only_components)
|
if (m_read_only_components)
|
||||||
{
|
|
||||||
Mallocator.dispose(m_read_only_components);
|
Mallocator.dispose(m_read_only_components);
|
||||||
m_read_only_components = null;
|
|
||||||
}
|
|
||||||
if (m_writable_components)
|
if (m_writable_components)
|
||||||
{
|
|
||||||
Mallocator.dispose(m_writable_components);
|
Mallocator.dispose(m_writable_components);
|
||||||
m_writable_components = null;
|
|
||||||
}
|
|
||||||
if (m_readonly_dependencies)
|
if (m_readonly_dependencies)
|
||||||
{
|
|
||||||
Mallocator.dispose(m_readonly_dependencies);
|
Mallocator.dispose(m_readonly_dependencies);
|
||||||
m_readonly_dependencies = null;
|
|
||||||
}
|
|
||||||
if (m_writable_dependencies)
|
if (m_writable_dependencies)
|
||||||
{
|
|
||||||
Mallocator.dispose(m_writable_dependencies);
|
Mallocator.dispose(m_writable_dependencies);
|
||||||
m_writable_dependencies = null;
|
|
||||||
}
|
|
||||||
if (m_event_callers)
|
if (m_event_callers)
|
||||||
{
|
|
||||||
Mallocator.dispose(m_event_callers);
|
Mallocator.dispose(m_event_callers);
|
||||||
m_event_callers = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_system_pointer)
|
if (m_system_pointer)
|
||||||
{
|
|
||||||
Mallocator.dispose(m_system_pointer);
|
Mallocator.dispose(m_system_pointer);
|
||||||
m_system_pointer = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EventCaller
|
struct EventCaller
|
||||||
|
|
|
||||||
100
tests/basic.d
100
tests/basic.d
|
|
@ -113,31 +113,6 @@ struct EmptySystem
|
||||||
int count = 0;
|
int count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EntityCounterSystem
|
|
||||||
{
|
|
||||||
mixin ECS.System!1;
|
|
||||||
|
|
||||||
struct EntitiesData
|
|
||||||
{
|
|
||||||
int thread_id;
|
|
||||||
uint length;
|
|
||||||
Entity[] entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool onBegin()
|
|
||||||
{
|
|
||||||
count = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onUpdate(EntitiesData data)
|
|
||||||
{
|
|
||||||
count += data.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void beforeEveryTest()
|
void beforeEveryTest()
|
||||||
{
|
{
|
||||||
becsID!CUnregistered = ushort.max;
|
becsID!CUnregistered = ushort.max;
|
||||||
|
|
@ -268,82 +243,7 @@ unittest
|
||||||
gEntityManager.commit();
|
gEntityManager.commit();
|
||||||
entity3 = gEntityManager.getEntity(id);
|
entity3 = gEntityManager.getEntity(id);
|
||||||
assert(!entity3.getComponent!CUnregistered);
|
assert(!entity3.getComponent!CUnregistered);
|
||||||
}
|
|
||||||
|
|
||||||
@("AddEmptyEntity")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
struct OnAddRemoveChangeCounter
|
|
||||||
{
|
|
||||||
mixin ECS.System!1;
|
|
||||||
|
|
||||||
struct EntitiesData
|
|
||||||
{
|
|
||||||
int thread_id;
|
|
||||||
uint length;
|
|
||||||
Entity[] entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onAddEntity(EntitiesData data)
|
|
||||||
{
|
|
||||||
add += data.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onRemoveEntity(EntitiesData data)
|
|
||||||
{
|
|
||||||
assert(0, "It's impossible to remove entity from being updated by system which accept empty entity");
|
|
||||||
}
|
|
||||||
|
|
||||||
int add = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gEntityManager.beginRegister();
|
|
||||||
|
|
||||||
gEntityManager.registerSystem!EntityCounterSystem(0);
|
|
||||||
gEntityManager.registerSystem!OnAddRemoveChangeCounter(1);
|
|
||||||
|
|
||||||
gEntityManager.endRegister();
|
|
||||||
|
|
||||||
CLong long_component = CLong(3);
|
|
||||||
|
|
||||||
Entity* entity = null;
|
|
||||||
EntityID entity_id = gEntityManager.addEntity(null).id;
|
|
||||||
|
|
||||||
EntityCounterSystem* system = gEntityManager.getSystem!EntityCounterSystem;
|
|
||||||
assert(system !is null);
|
|
||||||
assert(system.count == 0);
|
|
||||||
|
|
||||||
OnAddRemoveChangeCounter* add_remove_change_system = gEntityManager.getSystem!OnAddRemoveChangeCounter;
|
|
||||||
assert(add_remove_change_system !is null);
|
|
||||||
assert(add_remove_change_system.add == 0);
|
|
||||||
|
|
||||||
gEntityManager.commit();
|
|
||||||
assert(add_remove_change_system.add == 1);
|
|
||||||
|
|
||||||
entity = gEntityManager.getEntity(entity_id);
|
|
||||||
assert(!entity.hasComponent(becsID!CLong));
|
|
||||||
assert(entity.getComponent(becsID!CLong) is null);
|
|
||||||
|
|
||||||
|
|
||||||
gEntityManager.begin();
|
|
||||||
gEntityManager.update();
|
|
||||||
assert(system.count == 1);
|
|
||||||
gEntityManager.end();
|
|
||||||
|
|
||||||
gEntityManager.addEntityCopy(entity_id);
|
|
||||||
gEntityManager.addEntityCopy(entity_id);
|
|
||||||
gEntityManager.addComponents(entity_id, [ComponentRef(&long_component, becsID(long_component))].staticArray);
|
|
||||||
gEntityManager.commit();
|
|
||||||
assert(add_remove_change_system.add == 3, "onAddEntity missed");
|
|
||||||
|
|
||||||
entity = gEntityManager.getEntity(entity_id);
|
|
||||||
assert(entity.hasComponent(becsID!CLong));
|
|
||||||
assert(*entity.getComponent!CLong == 3);
|
|
||||||
|
|
||||||
gEntityManager.begin();
|
|
||||||
gEntityManager.update();
|
|
||||||
assert(system.count == 3);
|
|
||||||
gEntityManager.end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//allocate templates
|
//allocate templates
|
||||||
|
|
|
||||||
29
tests/bugs.d
29
tests/bugs.d
|
|
@ -144,32 +144,3 @@ unittest
|
||||||
|
|
||||||
gEntityManager.destroy();
|
gEntityManager.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@("2-empty-entity-crash")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
|
|
||||||
gEntityManager.initialize(0);
|
|
||||||
|
|
||||||
gEntityManager.beginRegister();
|
|
||||||
|
|
||||||
gEntityManager.registerComponent!CInt;
|
|
||||||
gEntityManager.registerComponent!CFloat;
|
|
||||||
|
|
||||||
gEntityManager.endRegister();
|
|
||||||
|
|
||||||
|
|
||||||
EntityTemplate* tmpl = gEntityManager.allocateTemplate([becsID!CInt, becsID!CFloat].staticArray);
|
|
||||||
scope(exit) gEntityManager.freeTemplate(tmpl);
|
|
||||||
|
|
||||||
EntityID id = gEntityManager.addEntity(tmpl).id;
|
|
||||||
// EntityID id2 = gEntityManager.addEntity().id;
|
|
||||||
|
|
||||||
gEntityManager.commit();
|
|
||||||
|
|
||||||
gEntityManager.removeComponents(id, [becsID!CInt, becsID!CFloat].staticArray);
|
|
||||||
|
|
||||||
gEntityManager.commit();
|
|
||||||
|
|
||||||
gEntityManager.destroy();
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue