Compare commits

..

7 commits

Author SHA1 Message Date
0002852303 Added CAPI files
I forgot to add CAPI files to .gitignore with previous commits :/
2021-11-17 15:22:13 +01:00
6e45e7b053 Merge branch 'master' into c-api 2021-11-17 15:15:46 +01:00
59db920a2e -updated CodeCov token because of CodeCov Bash Uploader Security Issue 2021-04-26 17:23:46 +02:00
bbb8144f34 -fixed DMD release compilation 2021-04-26 17:04:39 +02:00
24ef63d505 -added '-pthread' to arguments in 'meson.build' for GDC 2021-03-24 19:29:04 +01:00
70a5388820 -move code from templates to ECS side:
*sendEvent - using EventRef (alias to ComponentRef)
 *ListenerCallData now contain entities count and pointer to EntityInfo
 *Remove system_pointer from SystemCallData (use context instead)
 *Register event
-Now all BECS functinality can be used without templates
-clean code
2021-03-24 18:35:03 +01:00
0d08b8532a -remove "SIMD" option from "compile_wasm.py" (new Emscripten hasn't that option)
-removed some unnecessary variables
-started C-API implemantation:
 * added C-API option to Meson (build included to main library)
 * refactored some code (moved some code form templates to final code, removed delegates from system)
 * moved templates outside EntityManager to make it possible to use in different functions
2021-03-18 19:56:25 +01:00
33 changed files with 2642 additions and 1073 deletions

6
.gitignore vendored
View file

@ -12,4 +12,8 @@
!compile_wasm.py
!compile_android.py
!.gitlab-ci.yml
!LICENSE
!LICENSE
!c-api
!c-api/*.h
!c-api/*.d
!c-api/*.c

View file

@ -23,7 +23,7 @@ build_code:
test_dmd_debug:
stage: test
image: debian:buster-slim
image: frolvlad/alpine-glibc
script:
- binaries/dmd_debug_unittest
artifacts:
@ -31,7 +31,7 @@ test_dmd_debug:
junit: test_report.xml
test_dmd:
stage: test
image: debian:buster-slim
image: frolvlad/alpine-glibc
script:
- binaries/dmd_release_unittest
artifacts:
@ -39,7 +39,7 @@ test_dmd:
junit: test_report.xml
test_dmd_betterC:
stage: test
image: debian:buster-slim
image: frolvlad/alpine-glibc
script:
- binaries/dmd_debug_unittest_bc
artifacts:

View file

@ -10,13 +10,6 @@ Bubel ECS was tested on Linux, Windows, Android and WASM.
**Currently library is in beta stage so some significant API changes can appear.**
Package is available on [DUB package repository](https://code.dlang.org/packages/bubel-ecs). Usage:
```
"dependencies": {
"bubel-ecs": "~>0.1.1"
}
```
## Design
For core information about Entity-Component-System architectural pattern please read definition described at [Wikipedia](https://en.wikipedia.org/wiki/Entity_component_system).

207
c-api/becs.h Normal file
View file

@ -0,0 +1,207 @@
#ifndef __BECS__
#define __BECS__
#include <stdlib.h>
#include <stdalign.h>
#include <stdint.h>
#include <string.h>
typedef struct BECSSystem
{
}BECSSystem;
typedef struct BECSArray
{
size_t size;
void* ptr;
}BECSArray;
typedef struct EntityID
{
///Index to entity in IDManager.
uint32_t id;
///Counter required for reusing ID.
uint32_t counter;
}EntityID;
typedef struct Entity
{
///Entity ID.
EntityID id;
}Entity;
typedef struct ComponentRef
{
///pointer to component
void* ptr;
///component index
uint16_t id;
}ComponentRef;
typedef ComponentRef EventRef;
typedef struct BECSComponentInfo
{
///Component size
uint16_t size;
///Component data alignment
uint16_t alignment;
///Initialization data
BECSArray init_data;
///Pointer to component destroy callback
void* destroy_callback;
///Pointer to component create callback
void* create_callback;
//void* create_callback;
}BECSComponentInfo;
typedef struct BECSEventRegisterInfo
{
///Component size
uint16_t size;
///Component data alignment
uint16_t alignment;
}BECSEventRegisterInfo;
typedef struct EntityTemplate
{
/*///Entity components data
BECSArray entity_data;
///Pointer to entity type info.
void* info;*/
}EntityTemplate;
enum BECSSystemComponentAttribute
{
required = 0,
optional = 1,
excluded = 2
};
enum BECSSystemComponentAccess
{
writable = 0,
readonly = 1
};
typedef struct BECSSystemComponentInfo
{
uint16_t id;
enum BECSSystemComponentAttribute attribute;
enum BECSSystemComponentAccess access;
}BECSSystemComponentInfo;
///C-API structure conatin only subset of real data which can be accessed directly. Component arrays can be retrived using function calls.
typedef struct BECSListenerCallData
{
uint32_t count;
void* context;
}BECSListenerCallData;
///C-API structure conatin only subset of real data which can be accessed directly. Component arrays can be retrived using function calls.
typedef struct BECSSystemCallData
{
uint32_t count;
uint32_t thread_id;
uint32_t job_id;
void* context;
}BECSSystemCallData;
///C-API structure conatin only subset of real data which can be accessed directly. Component arrays can be retrived using function calls.
typedef struct BECSEventCallData
{
Entity* entity;
void* event;
void* context;
}BECSEventCallData;
typedef struct BECSEventCallback
{
uint16_t id;
void (*callback)(BECSEventCallData* data);
}BECSEventCallback;
typedef struct BECSSystemRegisterInfo
{
uint32_t pass_id;
int32_t priority;
uint32_t max_jobs;
size_t components_count;
BECSSystemComponentInfo* components;
size_t event_handlers_count;
BECSEventCallback* event_handlers;
size_t system_size;
void* init_data;
void (*on_update)(BECSSystemCallData* call_data);
void (*on_create)(void* system_pointer);
void (*on_destroy)(void* system_pointer);
void (*on_enable)(void* system_pointer);
void (*on_disable)(void* system_pointer);
char (*on_begin)(void* system_pointer);
void (*on_end)(void* system_pointer);
void (*on_add_entity)(BECSListenerCallData*);
void (*on_remove_entity)(BECSListenerCallData*);
void (*on_change_entity)(BECSListenerCallData*);
void (*filter_entity)(void* system_pointer, void* info);
}BECSSystemRegisterInfo;
void becsInitialize();
void becsDestroy();
void becsBeginRegister();
void becsEndRegister();
void becsBegin();
void becsEnd();
void becsCommit();
void becsUpdate(uint16_t pass_id);
void becsUpdateMT(uint16_t pass_id);
uint16_t becsRegisterComponent(const char* name, BECSComponentInfo info);
uint16_t becsRegisterEvent(const char* name, BECSEventRegisterInfo info);
uint16_t becsRegisterSystem(const char* name, BECSSystemRegisterInfo info);
uint16_t becsRegisterPass(const char* name);
Entity* becsAddEntity(EntityTemplate* template);
Entity* becsAddEntityCopy(EntityID id);
void becsRemoveEntity(EntityID id);
Entity* becsGetEntity(EntityID id);
void becsAddComponents(const EntityID entity_id, size_t length, ComponentRef* comps);
void becsRemoveComponents(const EntityID entity_id, size_t length, uint16_t* comps);
EntityTemplate* becsAllocateTemplate(uint32_t count, uint16_t* components);
EntityTemplate* becsAllocateTemplateFromEntity(EntityID id, uint8_t fill_default);
EntityTemplate* becsAllocateTemplateCopy(EntityTemplate* tmpl);
EntityTemplate* becsAllocateTemplateFromTemplate(EntityTemplate* tmpl, size_t new_count, uint16_t* components, size_t remove_count, uint16_t* remove_components);
void becsFreeTemplate(EntityTemplate* tmpl);
void* becsEntityGetComponent(Entity* entity, uint16_t component_id);
void* becsSystemCallDataGetComponentArray(BECSSystemCallData* data, uint16_t component_id);
Entity* becsSystemCallDataGetEntitiesArray(BECSSystemCallData* data);
void* becsListenerCallDataGetComponentArray(BECSListenerCallData* data, uint16_t component_id);
Entity* becsListenerCallDataGetEntitiesArray(BECSListenerCallData* data);
void becsCallEntitiesFunction(uint16_t system_id, void (*on_update)(BECSSystemCallData* call_data), void* context);
void becsSendEvent(EntityID id, EventRef event);
#define BECS_REGISTER_COMPONENT(comp) \
({ \
void* mem_ptr = malloc(sizeof(comp)); \
memcpy(mem_ptr, &comp, sizeof(comp)); \
becsRegisterComponent(#comp, (BECSComponentInfo){sizeof(comp), alignof(comp), (BECSArray){sizeof(comp), mem_ptr}, 0, 0}); \
})
//BECSComponentInfo(sizeof(comp), 4, 0, 0, 0));
#endif //__BECS__

306
c-api/manager.d Normal file
View file

@ -0,0 +1,306 @@
module manager;
import bubel.ecs.manager;
import bubel.ecs.entity;
import bubel.ecs.events;
import bubel.ecs.system;
import bubel.ecs.std;
import core.stdc.string;
extern (C):
/*
struct BECSComponentInfo
{
///Component size
ushort size;
///Component data alignment
ushort alignment;
///Initialization data
ubyte[] init_data;
///Pointer to component destroy callback
void* destroy_callback;
///Pointer to component create callback
void* create_callback;
//void* create_callback;
}*/
alias BECSComponentInfo = EntityManager.ComponentInfo;
// alias BECSEventCallData = EntityManager.EventCallData;
enum BECSSystemComponentAttribute
{
required = 0,
optional = 1,
excluded = 2
}
enum BECSSystemComponentAccess
{
writable = 0,
readonly = 1
}
struct BECSSystemComponentInfo
{
ushort id;
BECSSystemComponentAttribute attribute;
BECSSystemComponentAccess access;
}
struct BECSEventCallback
{
ushort id;
void function(EntityManager.EventCallData* data) callback;
}
struct BECSSystemRegisterInfo
{
uint pass_id;
int priority;
uint max_jobs;
BECSSystemComponentInfo[] components;
BECSEventCallback[] event_handlers;
byte[] init_data;
void function(EntityManager.SystemCallData* call_data) on_update;
void function(void* system_pointer) on_create;
void function(void* system_pointer) on_destroy;
void function(void* system_pointer) on_enable;
void function(void* system_pointer) on_disable;
bool function(void* system_pointer) on_begin;
void function(void* system_pointer) on_end;
void function(EntityManager.ListenerCallData*) on_add_entity;
void function(EntityManager.ListenerCallData*) on_remove_entity;
void function(EntityManager.ListenerCallData*) on_change_entity;
void function(void* system_pointer, EntityManager.EntityInfo* info) filter_entity;
}
alias BECSEventRegisterInfo = EntityManager.EventRegisterInfo;
void becsInitialize()
{
EntityManager.initialize();
}
void becsDestroy()
{
EntityManager.destroy();
}
void becsBeginRegister()
{
gEntityManager.beginRegister();
}
void becsEndRegister()
{
gEntityManager.endRegister();
}
void becsBegin()
{
gEntityManager.begin();
}
void becsEnd()
{
gEntityManager.end();
}
void becsCommit()
{
gEntityManager.commit();
}
void becsUpdate(ushort pass_id)
{
gEntityManager.update(pass_id);
}
void becsUpdateMT(ushort pass_id)
{
gEntityManager.update(pass_id);
}
ushort becsRegisterPass(const (char)* name)
{
return gEntityManager.registerPass(name[0 .. strlen(name)]);
}
ushort becsRegisterComponent(const(char)* name, BECSComponentInfo info)
{
return gEntityManager.registerComponent(name[0 .. strlen(name)], info);
}
ushort becsRegisterEvent(const(char)* name, BECSEventRegisterInfo info)
{
return gEntityManager.registerEvent(name[0 .. strlen(name)], info);
}
ushort becsRegisterSystem(const(char)* name, BECSSystemRegisterInfo info)
{
System system;
if(info.init_data.length)
{
system.m_system_pointer = malloc(info.init_data.length);
memcpy(system.m_system_pointer, info.init_data.ptr, info.init_data.length);
}
if(info.event_handlers.length)
{
system.m_event_callers = Mallocator.makeArray!(System.EventCaller)(info.event_handlers.length);
foreach(i, BECSEventCallback callback; info.event_handlers)
{
system.m_event_callers[i].id = callback.id;
system.m_event_callers[i].callback = callback.callback;
}
}
system.m_update = info.on_update;
system.m_create = info.on_create;
system.m_destroy = info.on_destroy;
system.m_enable = info.on_enable;
system.m_disable = info.on_disable;
system.m_begin = info.on_begin;
system.m_end = info.on_end;
system.m_add_entity = info.on_add_entity;
system.m_remove_entity = info.on_remove_entity;
system.m_change_entity = info.on_change_entity;
system.m_filter_entity = info.filter_entity;
if(info.components.length)
{
uint req;
uint opt;
foreach(comp; info.components)
{
if(comp.attribute == BECSSystemComponentAttribute.required)req++;
else if(comp.attribute == BECSSystemComponentAttribute.optional)opt++;
}
if(req)system.m_components = Mallocator.makeArray!ushort(req);
if(opt)system.m_optional_components = Mallocator.makeArray!ushort(opt);
req = 0;
opt = 0;
foreach(comp; info.components)
{
if(comp.attribute == BECSSystemComponentAttribute.required)
{
system.m_components[req++] = comp.id;
}
else if(comp.attribute == BECSSystemComponentAttribute.optional)
{
system.m_optional_components[opt++] = comp.id;
}
}
}
else
{
system.m_empty = true;
}
return gEntityManager.registerSystem(name[0 .. strlen(name)], system);
}
EntityTemplate* becsAllocateTemplate(uint count, ushort* components)
{
return gEntityManager.allocateTemplate(components[0 .. count]);
}
EntityTemplate* becsAllocateTemplateFromEntity(EntityID id, bool fill_default)
{
return gEntityManager.allocateTemplate(id, fill_default);
}
EntityTemplate* becsAllocateTemplateCopy(EntityTemplate* tmpl)
{
return gEntityManager.allocateTemplate(tmpl);
}
EntityTemplate* becsAllocateTemplateFromTemplate(EntityTemplate* tmpl, size_t new_count, ushort* components, size_t remove_count, ushort* remove_components)
{
return gEntityManager.allocateTemplate(tmpl, components[0 .. new_count], remove_components[0 .. remove_count]);
}
void becsFreeTemplate(EntityTemplate* tmpl)
{
gEntityManager.freeTemplate(tmpl);
}
Entity* becsAddEntity(EntityTemplate* tmpl)
{
return gEntityManager.addEntity(tmpl);
}
Entity* becsAddEntityCopy(EntityID id)
{
return gEntityManager.addEntityCopy(id);
}
void becsRemoveEntity(EntityID id)
{
gEntityManager.removeEntity(id);
}
Entity* becsGetEntity(EntityID id)
{
return gEntityManager.getEntity(id);
}
void* becsEntityGetComponent(Entity* entity, ushort component_id)
{
return entity.getComponent(component_id);
}
void* becsSystemCallDataGetComponentArray(EntityManager.SystemCallData* data, ushort component_id)
{
if(data.info.deltas.length <= component_id || data.info.deltas[component_id] == 0)return null;
return cast(void*)data.block + data.info.deltas[component_id];
}
Entity* becsSystemCallDataGetEntitiesArray(EntityManager.SystemCallData* data)
{
return cast(Entity*)data.block.dataBegin();
}
void* becsListenerCallDataGetComponentArray(EntityManager.ListenerCallData* data, ushort component_id)
{
if(data.info.deltas.length <= component_id || data.info.deltas[component_id] == 0)return null;
return cast(void*)data.block + data.info.deltas[component_id];
}
Entity* becsListenerCallDataGetEntitiesArray(EntityManager.ListenerCallData* data)
{
return cast(Entity*)data.block.dataBegin();
}
void becsCallEntitiesFunction(ushort system_id, void function(EntityManager.SystemCallData*) callback, void* context)
{
System* system = gEntityManager.getSystem(system_id);
if (!system.m_any_system_caller)
return;
foreach (info; system.m_any_system_caller.infos)
{
EntityManager.CallData data = EntityManager.CallData(system.id, system, info, context, cast(void*)callback);
data.update();
}
}
void becsAddComponents(const EntityID entity_id, ComponentRef[] comps)
{
gEntityManager.addComponents(entity_id, comps);
}
void becsRemoveComponents(const EntityID entity_id, ushort[] comps)
{
gEntityManager.removeComponents(entity_id, comps);
}
void becsSendEvent(EntityID id, EventRef event)
{
gEntityManager.sendEvent(id, event);
}

7
c-api/meson.build Normal file
View file

@ -0,0 +1,7 @@
src += files(
'manager.d'
)
c_src = files(
'test.c'
)

1051
c-api/test.c Normal file

File diff suppressed because it is too large Load diff

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-emscripten -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' '
ldc_cmd = 'ldc2 ' + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-unknown-wasm -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' '
for path in sources:
ldc_cmd += '-I' + path + ' '
@ -33,7 +33,7 @@ def compile(sources, output):
shared_flags = ''
clean = 0
emc_flags = ''
ldc_flags = ''
ldc_flags = '--d-version=ECSEmscripten '
import_paths = ['source','tests']
build_tests = 0

View file

@ -1,6 +1,7 @@
import os
import ntpath
import sys
import imp
def compile(sources, output):
files = []
@ -13,7 +14,7 @@ def compile(sources, output):
if file_extension == '.d' and filename != 'package':
files.append(os.path.join(r, file))
ldc_cmd = compiler + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-emscripten -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' '
ldc_cmd = compiler + shared_flags + ldc_flags + '-oq -mtriple=wasm32-unknown-unknown-wasm -betterC --output-bc --od=.bc --singleobj --checkaction=C --of=' + output + ' '
for path in sources:
ldc_cmd += '-I' + path + ' '
@ -40,7 +41,7 @@ only_bc = 0
multi = 0
sources = ['tests', 'source']
emc_flags = '-s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS="[\'png\']" '
ldc_flags = '--d-version=SDL_209 --d-version=BindSDL_Static --d-version=BindSDL_Image --d-version=MM_USE_POSIX_THREADS '
ldc_flags = '--d-version=ECSEmscripten --d-version=SDL_209 --d-version=BindSDL_Static --d-version=BindSDL_Image --d-version=MM_USE_POSIX_THREADS '
import_paths = ['external/sources', 'external/imports', 'external/wasm_imports', '../source', 'utils/source', 'simple/source']
for arg in sys.argv[1:]:
@ -74,7 +75,7 @@ for arg in sys.argv[1:]:
elif(arg == '-opt'):
shared_flags += '-O3 '
ldc_flags += '-release -enable-inlining '
emc_flags += '--llvm-lto 3 -s SIMD=1 '
emc_flags += '--llvm-lto 3 '
elif(arg == '-quiet'):
emc_flags += "-Wl,--no-check-features "
elif(arg == '--clean'):
@ -120,9 +121,8 @@ emcc_cmd += 'demo.bc '
os.system("mkdir build")
# emscripten = imp.load_source('', os.path.expanduser("~") + '/.emscripten')
# pack_cmd = emscripten.EMSCRIPTEN_ROOT + '/tools/file_packager.py build/assets.data --preload assets --js-output=build/assets.js'
pack_cmd = os.path.expandvars('$EMSDK/upstream/emscripten') + '/tools/file_packager.py build/assets.data --preload assets --js-output=build/assets.js'
emscripten = imp.load_source('', os.path.expanduser("~") + '/.emscripten')
pack_cmd = emscripten.EMSCRIPTEN_ROOT + '/tools/file_packager.py build/assets.data --preload assets --js-output=build/assets.js'
print('Packafing files: ' + pack_cmd)
os.system(pack_cmd)

View file

@ -19,7 +19,7 @@ sdl2_image_dep = dependency('SDL2_image')
subdir('utils') # Utils library
executable('BubelECSDemos', [demos_src, external_src],
executable('decs-demos', [demos_src, external_src],
include_directories : [demos_inc, external_inc],
d_module_versions : versions,
link_with : [ecs_lib, ecs_utils_lib],
@ -27,7 +27,7 @@ executable('BubelECSDemos', [demos_src, external_src],
bindbc_loader_dep,
bindbc_sdl_dep,
cimgui_dep,
bubel_ecs_dep,
decs_dep,
ecs_utils_dep,
sdl2_dep,
sdl2_image_dep,

View file

@ -5,12 +5,12 @@ subdir('source/ecs_utils')
utils_inc = include_directories('source/')
# Dependencies
ecs_utils_lib = library('ECSUtils', utils_src,
ecs_utils_lib = library('ecs_utils', utils_src,
include_directories : [demos_inc, external_inc, utils_inc],
link_args : link_args,
d_module_versions : versions,
dependencies : [
bubel_ecs_dep,
decs_dep,
bindbc_loader_dep,
bindbc_sdl_dep,
]

View file

@ -1,11 +1,11 @@
{
"name": "bubel-ecs",
"targetName" : "BubelECS",
"name": "bubel_ecs",
"targetName" : "bubel_ecs",
"authors": [
"Michał Masiukiewicz", "Dawid Masiukiewicz"
],
"description": "Dynamic Entity Component System",
"copyright": "Copyright © 2018-2023, Michał Masiukiewicz, Dawid Masiukiewicz",
"copyright": "Copyright © 2018-2019, Michał Masiukiewicz, Dawid Masiukiewicz",
"license": "BSD 3-clause",
"sourcePaths" : ["source\/"],
"excludedSourceFiles":[
@ -63,7 +63,7 @@
],
"dflags": [
"-unittest",
"-cov=ctfe"
"-cov"
]
},
{

View file

@ -1,15 +1,17 @@
project('bubel-ecs', 'd', version : '0.5.0')
project('decs', 'd', version : '0.1.0')
# Options
betterC_opt = get_option('betterC')
BuildDemos_opt = get_option('BuildDemos')
BuildTests_opt = get_option('BuildTests')
LTO_otp = get_option('LTO')
C_API_opt = get_option('C-API')
summary('betterC enabled', betterC_opt)
summary('build demos', BuildDemos_opt)
summary('build tests', BuildTests_opt)
summary('LTO enabled', LTO_otp)
summary('C-API enabled', C_API_opt)
meson_minimum_version = '>=0.57.1'
assert(meson.version().version_compare(meson_minimum_version), 'Newer verson of meson required, current version: @0@, required: @1@'.format(meson.version(), meson_minimum_version))
@ -18,7 +20,14 @@ assert(meson.version().version_compare(meson_minimum_version), 'Newer verson of
src = files()
subdir('source')
inc = include_directories('source/')
inc = [include_directories('source/')]
#C API files
if C_API_opt
c_src = files()
subdir('c-api')
inc += include_directories('c-api/')
endif
# Arguments
args = []
@ -43,45 +52,55 @@ if betterC_opt
if comp_id == 'gcc'
args += ['-fno-druntime']
link_args += ['-fno-druntime']
else
else
args += '-betterC'
link_args += '-betterC'
endif
endif
if comp_id == 'gcc'
args+='-pthread'
link_args+='-pthread'
endif
add_project_arguments(args, language : 'd')
add_project_link_arguments(link_args, language : 'd')
# Dependencies
threads_dep = dependency('threads')
d_versions = []
deps = []
if host_machine.cpu_family() == 'wasm32'
else
# meson incorectly adds "-s USE_PTHREADS=1" to ldc2 invocation whe pthreads is added as dependency
# add it for non wasm builds
deps += threads_dep
endif
ecs_lib = library('BubelECS',
ecs_lib = library('decs',
src,
d_module_versions : d_versions,
include_directories : [inc],
)
bubel_ecs_dep = declare_dependency(
decs_dep = declare_dependency(
include_directories : [inc],
link_with : ecs_lib,
dependencies : deps,
dependencies : threads_dep,
)
meson.override_dependency('bubel-ecs', bubel_ecs_dep)
# Tests
if BuildTests_opt
subdir('tests')
executable('d-api-tests',
['tests/tests.d'],
include_directories : [inc],
d_args : args,
link_args : link_args,
dependencies : decs_dep,
)
if C_API_opt
add_languages('c')
executable('c-api-tests',
['c-api/test.c'],
include_directories : [inc],
dependencies : decs_dep,
)
endif
endif
# Demos

View file

@ -2,3 +2,4 @@ option('betterC', type: 'boolean', value: false)
option('BuildDemos', type: 'boolean', value: false)
option('BuildTests', type: 'boolean', value: false)
option('LTO', type: 'boolean', value: false)
option('C-API', type: 'boolean', value: false)

View file

@ -4,10 +4,129 @@ It's internal code. Can be used for atomics if emscripten backend will be used.
This module contain atomic operations which include support for emscripten atomics functions.
Emscripten functions are contained in API similar to druntime.
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
Copyright: Copyright © 2018-2019, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.atomic;
public import core.atomic;
version (Emscripten) version = ECSEmscripten;
version (ECSEmscripten)
{
import std.traits;
enum MemoryOrder
{
acq,
acq_rel,
raw,
rel,
seq
}
extern (C) ubyte emscripten_atomic_cas_u8(void* addr, ubyte oldVal, ubyte newVal) @nogc nothrow pure;
extern (C) ushort emscripten_atomic_cas_u16(void* addr, ushort oldVal, ushort newVal) @nogc nothrow pure;
extern (C) uint emscripten_atomic_cas_u32(void* addr, uint oldVal, uint newVal) @nogc nothrow pure;
extern (C) ubyte emscripten_atomic_load_u8(const void* addr) @nogc nothrow pure;
extern (C) ushort emscripten_atomic_load_u16(const void* addr) @nogc nothrow pure;
extern (C) uint emscripten_atomic_load_u32(const void* addr) @nogc nothrow pure;
extern (C) ubyte emscripten_atomic_store_u8(void* addr, ubyte val) @nogc nothrow pure;
extern (C) ushort emscripten_atomic_store_u16(void* addr, ushort val) @nogc nothrow pure;
extern (C) uint emscripten_atomic_store_u32(void* addr, uint val) @nogc nothrow pure;
extern (C) ubyte emscripten_atomic_add_u8(void* addr, ubyte val) @nogc nothrow pure;
extern (C) ushort emscripten_atomic_add_u16(void* addr, ushort val) @nogc nothrow pure;
extern (C) uint emscripten_atomic_add_u32(void* addr, uint val) @nogc nothrow pure;
extern (C) ubyte emscripten_atomic_sub_u8(void* addr, ubyte val) @nogc nothrow pure;
extern (C) ushort emscripten_atomic_sub_u16(void* addr, ushort val) @nogc nothrow pure;
extern (C) uint emscripten_atomic_sub_u32(void* addr, uint val) @nogc nothrow pure;
public pure nothrow @nogc Unqual!T atomicOp(string op, T, V1)(ref shared T val, V1 mod)
{
static if (op == "+=")
{
static if (is(T == byte) || is(T == ubyte))
return cast(Unqual!T)(emscripten_atomic_add_u8(cast(void*)&val,
cast(Unqual!T) mod) + 1);
else static if (is(T == short) || is(T == ushort))
return cast(Unqual!T)(emscripten_atomic_add_u16(cast(void*)&val,
cast(Unqual!T) mod) + 1);
else static if (is(T == int) || is(T == uint))
return cast(Unqual!T)(emscripten_atomic_add_u32(cast(void*)&val,
cast(Unqual!T) mod) + 1);
else
static assert(0);
}
else static if (op == "-=")
{
static if (is(T == byte) || is(T == ubyte))
return cast(Unqual!T)(emscripten_atomic_sub_u8(cast(void*)&val,
cast(Unqual!T) mod) - 1);
else static if (is(T == short) || is(T == ushort))
return cast(Unqual!T)(emscripten_atomic_sub_u16(cast(void*)&val,
cast(Unqual!T) mod) - 1);
else static if (is(T == int) || is(T == uint))
return cast(Unqual!T)(emscripten_atomic_sub_u32(cast(void*)&val,
cast(Unqual!T) mod) - 1);
else
static assert(0);
}
}
public pure nothrow @nogc @trusted void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref T val,
V newval)
{
alias UT = Unqual!T;
static if (is(UT == bool) || is(UT == byte) || is(UT == ubyte))
emscripten_atomic_store_u8(cast(void*)&val, cast(UT) newval);
else static if (is(UT == short) || is(UT == ushort))
emscripten_atomic_store_u16(cast(void*)&val, cast(UT) newval);
else static if (is(UT == int) || is(UT == uint))
emscripten_atomic_store_u32(cast(void*)&val, cast(UT) newval);
else
static assert(0);
}
public pure nothrow @nogc @trusted T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(
ref const T val)
{
alias UT = Unqual!T;
static if (is(UT == bool))
return emscripten_atomic_load_u8(cast(const void*)&val) != 0;
else static if (is(UT == byte) || is(UT == ubyte))
return emscripten_atomic_load_u8(cast(const void*)&val);
else static if (is(UT == short) || is(UT == ushort))
return emscripten_atomic_load_u16(cast(const void*)&val);
else static if (is(UT == int) || is(UT == uint))
return emscripten_atomic_load_u32(cast(const void*)&val);
else
static assert(0);
}
public pure nothrow @nogc @trusted bool cas(MemoryOrder succ = MemoryOrder.seq,
MemoryOrder fail = MemoryOrder.seq, T, V1, V2)(T* here, V1 ifThis, V2 writeThis)
{
alias UT = Unqual!T;
static if (is(UT == bool))
return emscripten_atomic_cas_u8(cast(void*) here,
cast(Unqual!T) ifThis, cast(Unqual!T) writeThis) == ifThis;
else static if (is(UT == byte) || is(UT == ubyte))
return emscripten_atomic_cas_u8(cast(void*) here,
cast(Unqual!T) ifThis, cast(Unqual!T) writeThis) == ifThis;
else static if (is(UT == short) || is(UT == ushort))
return emscripten_atomic_cas_u16(cast(void*) here,
cast(Unqual!T) ifThis, cast(Unqual!T) writeThis) == ifThis;
else static if (is(UT == int) || is(UT == uint))
return emscripten_atomic_cas_u32(cast(void*) here,
cast(Unqual!T) ifThis, cast(Unqual!T) writeThis) == ifThis;
else
static assert(0);
}
}
else
{
public import core.atomic;
}

View file

@ -17,7 +17,7 @@ Struct EntitiesData
}
---
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
Copyright: Copyright © 2018-2019, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.attributes;

View file

@ -3,7 +3,7 @@ It's internal code.
Module contain memory allocator.
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
Copyright: Copyright © 2018-2019, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.block_allocator;

View file

@ -67,7 +67,7 @@ Struct System1
}
---
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
Copyright: Copyright © 2018-2019, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.core;

View file

@ -1,7 +1,7 @@
/************************************************************************************************************************
Entity module.
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
Copyright: Copyright © 2018-2019, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.entity;
@ -44,7 +44,7 @@ struct Entity
return cast(T*)getComponent(becsID!T);
}
export void* getComponent(ushort component_id) const
void* getComponent(ushort component_id) const
{
EntityManager.EntitiesBlock* block = gEntityManager.getMetaData(&this);
EntityManager.EntityInfo* info = block.type_info;
@ -54,7 +54,7 @@ struct Entity
return (cast(void*)block + info.deltas[component_id] + block.entityIndex(&this) * gEntityManager.components[component_id].size);
}
export bool hasComponent(ushort component_id) const
bool hasComponent(ushort component_id) const
{
EntityManager.EntitiesBlock* block = gEntityManager.getMetaData(&this);
EntityManager.EntityInfo* info = block.type_info;
@ -62,7 +62,7 @@ struct Entity
return true;
}
export EntityMeta getMeta() const
EntityMeta getMeta() const
{
EntityMeta meta;
meta.block = gEntityManager.getMetaData(&this);
@ -85,7 +85,7 @@ struct EntityMeta
return cast(T*)getComponent(becsID!T);
}
export void* getComponent(ushort component_id) const
void* getComponent(ushort component_id) const
{
const (EntityManager.EntityInfo)* info = block.type_info;
@ -95,7 +95,7 @@ struct EntityMeta
return (cast(void*)block + info.deltas[component_id] + index * gEntityManager.components[component_id].size);
}
export bool hasComponent(ushort component_id) const
bool hasComponent(ushort component_id) const
{
const EntityManager.EntityInfo* info = block.type_info;
if (component_id >= info.deltas.length || info.deltas[component_id] == 0)return false;
@ -133,7 +133,7 @@ export struct EntityTemplate
/************************************************************************************************************************
Get specified component. If component doesn't exist function return null. Returned pointer is valid during EntityTemplate lifetime.
*/
export void* getComponent(ushort component_id) const nothrow @nogc
void* getComponent(ushort component_id) const nothrow @nogc
{
if(component_id >= info.tmpl_deltas.length || info.tmpl_deltas[component_id] == ushort.max)return null;
return cast(void*)(entity_data.ptr + info.tmpl_deltas[component_id]);

View file

@ -1,7 +1,3 @@
/************************************************************************************************************************
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.events;
import bubel.ecs.block_allocator;
@ -12,6 +8,8 @@ import bubel.ecs.traits : becsID;
import std.algorithm.comparison : max;
alias EventRef = ComponentRef;
package struct EventManager
{
@ -34,12 +32,17 @@ package struct EventManager
}
export void sendEvent(Ev)(EntityID id, Ev event, uint thread_id = 0) nothrow @nogc
{
sendEvent(id, EventRef(&event, becsID!Ev), thread_id);
}
export void sendEvent(EntityID id, EventRef event, uint thread_id = 0) nothrow @nogc
{
uint block_id = current_index + thread_id;
EventData* data = &events[becsID!Ev];
EventData* data = &events[event.component_id];
EventBlock* block = data.blocks[block_id];
//EntityManager.EventInfo* info = &manager.events[Ev.event_id];
EntityManager.EventInfo* info = &manager.events[event.component_id];
//event.entity_id = id;
if (block is null)
@ -65,10 +68,11 @@ package struct EventManager
data.blocks[block_id] = block;
}
uint size = Ev.sizeof + EntityID.sizeof;
uint size = info.size + EntityID.sizeof;
void* ptr = cast(void*) block + data.data_offset + block.count * size;
*cast(EntityID*)ptr = id;
*cast(Ev*)(ptr + EntityID.sizeof) = event;
memcpy(ptr + EntityID.sizeof, event.ptr, info.size);
//*cast(Ev*)(ptr + EntityID.sizeof) = event;
//Ev* event_array = cast(Ev*)(cast(void*) block + data.data_offset);
//event_array[block.count] = event;
block.count++;

View file

@ -1,8 +1,4 @@
/************************************************************************************************************************
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.hash_map;
module bubel.ecs.hash_map;
import std.traits;
@ -28,7 +24,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;
@ -336,36 +332,36 @@ nothrow:
return result;
}
export int byKey(scope int delegate(ref Key k) dg)
export int byKey(scope int delegate(Key k) nothrow dg)
{
int result;
foreach (ref Key k; this)
{
result = (cast(int delegate(ref Key k) nothrow @nogc)dg)(k);
result = dg(k);
if (result)
break;
}
return result;
}
export int byValue(scope int delegate(ref Value v) dg)
export int byValue(scope int delegate(ref Value k) nothrow dg)
{
int result;
foreach (ref Value v; this)
{
result = (cast(int delegate(ref Value v) nothrow @nogc)dg)(v);
result = dg(v);
if (result)
break;
}
return result;
}
export int byKeyValue(scope int delegate(ref Key k, ref Value v) dg)
export int byKeyValue(scope int delegate(ref Key k, ref Value v) nothrow dg)
{
int result;
foreach (ref Key k, ref Value v; this)
{
result = (cast(int delegate(ref Key k, ref Value v) nothrow @nogc)dg)(k, v);
result = dg(k, v);
if (result)
break;
}

View file

@ -1,7 +1,3 @@
/************************************************************************************************************************
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.id_manager;
import bubel.ecs.entity;

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,3 @@
/************************************************************************************************************************
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module ecs;
public import bubel.ecs.core;

View file

@ -1,7 +1,3 @@
/************************************************************************************************************************
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.simple_vector;
import bubel.ecs.std;

View file

@ -2,14 +2,16 @@
It's internal code!
This module contain implementation of standard functionality.
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
Copyright: Copyright © 2018-2019, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.std;
version (Emscripten) version = ECSEmscripten;
import std.traits;
version (Emscripten)
version (ECSEmscripten)
{
extern (C) struct pthread_mutex_t
{
@ -27,6 +29,10 @@ version (Emscripten)
extern (C) int memcmp(const void* s1, const void* s2, size_t size);
extern (C) void exit(int status) nothrow @nogc;
extern (C) void __assert(const(char)* msg, const(char)* file, uint line)
{
exit(-20);
}
extern (C) void free(void*) @nogc nothrow @system;
extern (C) void* malloc(size_t size) @nogc nothrow @system;
@ -54,7 +60,7 @@ else
public import core.stdc.stdlib : qsort;
}
version (Emscripten)
version (ECSEmscripten)
{
}
else version (Windows)
@ -83,7 +89,7 @@ else version (Posix)
import core.sys.posix.stdlib : posix_memalign;
}
version (Emscripten)
version (ECSEmscripten)
{
private const uint max_alloca = 10000;
private __gshared byte[max_alloca] alloca_array;
@ -288,7 +294,7 @@ static struct Mallocator
posix_memalign(&ret, alignment, length); //ret = aligned_alloc(alignment, length);
else version (Windows)
ret = _aligned_malloc(length, alignment);
else version (Emscripten)
else version (ECSEmscripten)
posix_memalign(&ret, alignment, length); //malloc(length);
else
static assert(0, "Unimplemented platform!");
@ -335,7 +341,7 @@ static struct Mallocator
free(cast(void*) object);
else version (Windows)
_aligned_free(cast(void*) object);
else version (Emscripten)
else version (ECSEmscripten)
free(cast(void*) object);
else
static assert(0, "Unimplemented platform!");
@ -345,7 +351,7 @@ static struct Mallocator
struct Mutex
{
version (Emscripten)
version (ECSEmscripten)
{
void initialize() nothrow @nogc
{

View file

@ -1,7 +1,7 @@
/************************************************************************************************************************
System module.
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
Copyright: Copyright © 2018-2019, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.system;
@ -13,14 +13,14 @@ import bubel.ecs.manager;
System contain data required to proper glue EntityManager with Systems.
System callbacks:
$(LIST
* void onUpdate(EntitiesData);
* void onUpdate(EntitesData);
* void onEnable() - called inside system.enable() function
* void onDisable() - called inside system.disable() function
* bool onBegin() - called inside manager.begin()
* void onEnd() - called inside manager.end()
* void onCreate() - called after registration inside registerSystem function
* void onDestroy() - called during re-registration and inside manager destructor
* void onAddEntity(EntitiesData) - called for every entity which are assigned to system (by adding new entity or changing its components)
* void onAddEntity(EntitesData) - called for every entity which are assigned to system (by adding new entity or changing its components)
* void onRemoveEntity(EntitiesData) - called for every entity removed from system update process
* void onChangeEntity(EntitiesData) - called for every entity which components are changed but it was previously assigned to system
* void handleEvent(Entity*, Event) - called for every event supported by system
@ -89,100 +89,38 @@ struct System
return cast(const(char)[]) m_name;
}
/************************************************************************************************************************
Return false if system was unregistered, true otherwise.
*/
export bool isAlive() nothrow @nogc
{
return m_system_pointer != null;
}
//package:
/************************************************************************************************************************
Return pointer to user side system object
*/
export void* ptr() nothrow @nogc
{
return m_system_pointer;
}
package:
///destory system. Dispose all data
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
void destroy()
{
import bubel.ecs.std : Mallocator;
disable();
if (m_destroy)
{
(cast(void function(void*) nothrow @nogc) m_destroy)(m_system_pointer);
m_destroy = null;
}
(cast(void function(void*)) m_destroy)(m_system_pointer);
if (m_name)
Mallocator.dispose(m_name);
if (m_components)
{
Mallocator.dispose(m_components);
m_components = null;
}
if (m_excluded_components)
{
Mallocator.dispose(m_excluded_components);
m_excluded_components = null;
}
if (m_optional_components)
{
Mallocator.dispose(m_optional_components);
m_optional_components = null;
}
if (jobs)
{
Mallocator.dispose(jobs);
jobs = null;
}
if (m_read_only_components)
{
Mallocator.dispose(m_read_only_components);
m_read_only_components = null;
}
if (m_writable_components)
{
Mallocator.dispose(m_writable_components);
m_writable_components = null;
}
if (m_readonly_dependencies)
{
Mallocator.dispose(m_readonly_dependencies);
m_readonly_dependencies = null;
}
if (m_writable_dependencies)
{
Mallocator.dispose(m_writable_dependencies);
m_writable_dependencies = null;
}
if (m_event_callers)
{
Mallocator.dispose(m_event_callers);
m_event_callers = null;
}
if (m_system_pointer)
{
Mallocator.dispose(m_system_pointer);
m_system_pointer = null;
}
}
struct EventCaller
@ -232,7 +170,7 @@ package:
//void function(ref EntityManager.CallData data) m_update;
void* m_update; ///workaroud for DMD bug with upper line
void delegate() m_update_delegate;
//void delegate() m_update_delegate;
//void function(void* system_pointer) m_enable;
//void function(void* system_pointer) m_disable;
@ -260,6 +198,6 @@ package:
//void function(ref EntityManager.CallData data) m_initialize;
//void function(ref EntityManager.CallData data) m_deinitilize;
void* m_initialize;
void* m_deinitilize;
// void* m_initialize;
// void* m_deinitilize;
}

View file

@ -1,7 +1,3 @@
/************************************************************************************************************************
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.traits;
import std.traits;
@ -11,11 +7,8 @@ import std.traits;
*/
ref ushort becsID(T)()
{
/// Embed id in struct so export can be added to variable definition
static struct LocalStruct {
export __gshared ushort id = ushort.max;
}
return LocalStruct.id;
__gshared ushort id = ushort.max;
return id;
}
/************************************************************************************************************************

View file

@ -1,7 +1,3 @@
/************************************************************************************************************************
Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz
License: BSD 3-clause, see LICENSE file in project root folder.
*/
module bubel.ecs.vector;
import core.bitop;

View file

@ -113,31 +113,6 @@ struct EmptySystem
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()
{
becsID!CUnregistered = ushort.max;
@ -268,82 +243,7 @@ unittest
gEntityManager.commit();
entity3 = gEntityManager.getEntity(id);
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
@ -750,6 +650,8 @@ unittest
void onAddEntity(EntitiesData data)
{
foreach(i; 0..data.length)
data.long_[i] += 1;
add++;
assert(add_order == 1);
add_order++;

View file

@ -142,34 +142,5 @@ unittest
gEntityManager.update();
gEntityManager.end();
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();
}

View file

@ -10,7 +10,7 @@ tests_src = files(
'vector.d'
)
exe = executable('BubelECSTests',
exe = executable('decs-tests',
tests_src,
include_directories : [inc, include_directories('..')],
d_args : args,

View file

@ -283,13 +283,13 @@ struct ChangeTestSystem
bool onBegin()
{
////writeln("On Test System begin.");
// writeln("On Test System begin.");
return true;
}
void onEnd()
{
////writeln("On Test System end.");
// writeln("On Test System end.");
}
void initialize(ref Entity entity, ref TestComp comp)
@ -307,10 +307,10 @@ struct ChangeTestSystem
void onUpdate(EntitiesData data)
{
foreach (i; 0 .. data.length)
/*foreach (i; 0 .. data.length)
{
}
}*/
}
}
@ -318,6 +318,8 @@ struct TestSystem
{
mixin ECS.System!16; //__gshared ushort system_id;
uint print = 1;
void onCreate()
{
//writeln("On Test System create.");
@ -343,13 +345,14 @@ struct TestSystem
bool onBegin()
{
////writeln("On Test System begin.");
if(print)printf("On Test System begin.\n");
return true;
}
void onEnd()
{
////writeln("On Test System end.");
if(print)printf("On Test System end.\n");
print = 0;
}
void initialize(ref Entity entity, ref TestComp comp)
@ -406,7 +409,7 @@ struct TestSystemWithHighPriority
void initialize(ref Entity entity, ref TestComp comp)
{
int o = 1;
}
void onUpdate(EntitiesData data)
@ -844,6 +847,7 @@ else:
//dur = (MonoTime.currTime - time).total!"usecs";
//writeln("Entities adding: ", dur, " usecs");
printf("Entities adding: %f usecs\n", cast(float)(Time.getUSecTime() - time));
Mallocator.dispose(idss);
time = Time.getUSecTime();
uint blocks = 0;
@ -1021,8 +1025,6 @@ else:
gEntityManager.freeTemplate(copy_default_tempalte);
EntityManager.destroy();
Mallocator.dispose(idss);
printf("end\n"); //*/
return 0;