Removed structure top mixins requirement #15

Merged
Mergul merged 3 commits from remove_structure_top_mixin into master 2021-02-27 17:42:50 +01:00
13 changed files with 200 additions and 97 deletions
Showing only changes of commit 8b2793fc57 - Show all commits

View file

@ -213,8 +213,6 @@ void addErr(const(char)* errstr, const(char)* message)
version(Windows)
{
import core.sys.windows.windows;
extern(Windows) @nogc nothrow alias pSetDLLDirectory = BOOL function(const(char)*);
pSetDLLDirectory setDLLDirectory;
void* loadLib(const(char)* name)
{
@ -255,57 +253,6 @@ version(Windows)
}
else strncpy(buf, "Unknown Error\0", len);
}
/**
Adds a path to the default search path on Windows, replacing the path set in a previous
call to the same function.
Any path added to this function will be added to the default DLL search path as documented at
https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setdlldirectoryw.
Generally, when loading DLLs on a path that is not on the search path, e.g., from a subdirectory
of the application, the path should be prepended to the DLL name passed to the load function,
e.g., "dlls\\SDL2.dll". If `setCustomLoaderSearchPath(".\\dlls")` is called first, then the subdirectory
will become part of the DLL search path and the path may be omitted from the load function. (Be
aware that ".\\dlls" is relative to the current working directory, which may not be the application
directory, so the path should be built appropriately.)
Some DLLs may depend on other DLLs, perhaps even attempting to load them dynamically at run time
(e.g., SDL2_image only loads dependencies such as libpng if it is initialized at run time with
PNG support). In this case, if the DLL and its dependencies are placed in a subdirectory and
loaded as e.g., "dlls\\SDL2_image.dll", then it will not be able to find its dependencies; the
system loader will look for them on the regular DLL search path. When that happens, the solution
is to call `setCustomLoaderSearchPath` with the subdirectory before initializing the library.
Calling this function with `null` as the argument will reset the default search path.
When the function returns `false`, the relevant `ErrorInfo` is added to the global error list and can
be retrieved by looping through the array returned by the `errors` function.
When placing DLLs in a subdirectory of the application, it should be considered good practice to
call `setCustomLoaderSearchPath` to ensure all DLLs load properly. It should also be considered good
practice to reset the default search path once all DLLs are loaded.
This function is only available on Windows, so any usage of it should be preceded with
`version(Windows)`.
Params:
path = the path to add to the DLL search path, or `null` to reset the default.
Returns:
`true` if the path was successfully added to the DLL search path, otherwise `false`.
*/
public
bool setCustomLoaderSearchPath(const(char)* path)
{
if(!setDLLDirectory) {
auto lib = load("Kernel32.dll");
if(lib == invalidHandle) return false;
lib.bindSymbol(cast(void**)&setDLLDirectory, "SetDllDirectoryA");
if(!setDLLDirectory) return false;
}
return setDLLDirectory(path) != 0;
}
}
else version(Posix) {
import core.sys.posix.dlfcn;

View file

@ -2,9 +2,17 @@
//based on imgui.h file version "1.73" from Dear ImGui https://github.com/ocornut/imgui
module cimgui.cimgui;
import core.stdc.stdarg;
// import core.stdc.stdarg;
//import core.stdc.stdio;
version(WebAssembly)
{
alias va_list = char*;
pragma(LDC_va_start)
void va_start(T)(out va_list ap, ref T parmn) @nogc;
}
else import core.stdc.stdarg;
extern (C):
//alias ImU64 = ulong;

View file

@ -6,7 +6,11 @@
module bindbc.sdl.bind.sdllog;
import core.stdc.stdarg : va_list;
version(WebAssembly)
{
alias va_list = char*;
}
else import core.stdc.stdarg : va_list;
import bindbc.sdl.config;
enum SDL_MAX_LOG_MESSAGE = 4096;

View file

@ -416,6 +416,8 @@ void brickBreakerStart()
launcher.gui_manager.addComponent(CInput(), "Velocity");
launcher.gui_manager.addComponent(CDamping(), "Damping");
launcher.gui_manager.addComponent(CBall(), "Ball");
launcher.gui_manager.addComponent(CBVH(), "BVH");
launcher.gui_manager.addComponent(CAABB(), "AABB");
launcher.gui_manager.addSystem(becsID!MoveSystem, "Move System");
launcher.gui_manager.addSystem(becsID!EdgeCollisionSystem, "Edge Collision System");

View file

@ -187,6 +187,20 @@ struct Renderer
}
}
struct DrawData
{
Texture texture;
vec2 position;
vec2 size;
vec4 coords;
short depth = 0;
uint color = uint.max;
float angle = 0;
uint material_id = 0;
uint mesh_id = 0;
uint thread_id = 0;
}
struct Thread
{
//Vector!VertexBlock block;
@ -430,20 +444,6 @@ struct Renderer
}
struct DrawData
{
Texture texture;
vec2 position;
vec2 size;
vec4 coords;
short depth = 0;
uint color = uint.max;
float angle = 0;
uint material_id = 0;
uint mesh_id = 0;
uint thread_id = 0;
}
//void draw(Texture tex, vec2 pos, vec2 size, vec4 coords, short depth = 0, uint color = uint.max, float angle = 0, uint material_id = 0, uint mesh_id = 0, uint thread_id = 0)
void draw(scope ref const(DrawData) data)
{
@ -570,7 +570,7 @@ struct Renderer
memcpy(ptr+16,pos.data.ptr,8);
memcpy(ptr+32,coords.data.ptr,16);*/
short[] verts = cast(short[])block.batch_vertices;
short[] verts = (cast(short*)block.batch_vertices.ptr)[0..block.batch_vertices.length>>1];
uint item_id = block.items;
uint mesh_id = data.mesh_id;

View file

@ -77,7 +77,11 @@ version(GNU)
else
{
extern(C) int printf(scope const char* format, ...) @nogc nothrow @system;
public import std.array : staticArray;
// public import std.array : staticArray;
pragma(inline, true) T[n] staticArray(T, size_t n)(auto ref T[n] a)
{
return a;
}
}
extern(C) int rand() nothrow @nogc @trusted;

View file

@ -1,5 +1,6 @@
{
"name": "ecs",
"name": "bubel_ecs",
"targetName" : "ecs",
"authors": [
"Michał Masiukiewicz", "Dawid Masiukiewicz"
],

View file

@ -67,6 +67,8 @@ ecs_lib = library('ecs', src, include_directories : [tests_inc, inc], d_args: ar
executable('tests', tests_src, include_directories : [tests_inc, inc], d_args: args, link_args: link_args, link_with: ecs_lib)
bubel_ecs_dep = declare_dependency(include_directories : [inc], link_with : ecs_lib)
if BuildDemos_opt
subdir('demos/utils')
subdir('demos')

View file

@ -129,6 +129,15 @@ export struct EntityTemplate
if(becsID!T >= info.tmpl_deltas.length || info.tmpl_deltas[becsID!T] == ushort.max)return null;
return cast(T*)(entity_data.ptr + info.tmpl_deltas[becsID!T]);
}
/************************************************************************************************************************
Get specified component. If component doesn't exist function return null. Returned pointer is valid during EntityTemplate lifetime.
*/
void* getComponent(ushort component_id) const nothrow @nogc
{
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

@ -1110,6 +1110,32 @@ export struct EntityManager
}
}
static void catchEntityFilterFunction(string func_name, RetType = void)(void** member)
{
static if (hasMember!(Sys, func_name))
{
foreach (func; __traits(getOverloads, Sys, func_name))
{
static if ((Parameters!(func)).length == 1
&& is(Parameters!(func)[0] == EntityInfo*)
&& is(ReturnType!(func) == RetType))
{
static RetType callFunc(void* system_pointer, EntityInfo* info)
{
Sys* s = cast(Sys*) system_pointer;
static if (is(RetTyp == void))
mixin("s." ~ func_name ~ "(info)");
else
return mixin("s." ~ func_name ~ "(info)");
}
*member = cast(void*)&callFunc;
break;
}
}
}
}
catchFunction!("onEnable")(&system.m_enable);
catchFunction!("onDisable")(&system.m_disable);
catchFunction!("onCreate")(&system.m_create);
@ -1121,6 +1147,8 @@ export struct EntityManager
catchEntityFunction!("onRemoveEntity")(&system.m_remove_entity);
catchEntityFunction!("onChangeEntity")(&system.m_change_entity);
catchEntityFilterFunction!("filterEntity", bool)(&system.m_filter_entity);
system.m_system_pointer = cast(void*) Mallocator.make!Sys;
system.m_priority = priority;
//(cast(Sys*) system.m_system_pointer).__ecsInitialize();
@ -2035,6 +2063,9 @@ export struct EntityManager
is_:
}
///call Custom Entity Filter test if function exists
if(system.m_filter_entity && !(cast(bool function(void* system_pointer, EntityInfo* info) @nogc nothrow)system.m_filter_entity)(system, &entity))return;
entity.systems[system_id] = true;
}
@ -2077,30 +2108,8 @@ export struct EntityManager
{
System* system = &systems[system_id];
if (system.m_excluded_components)
{
foreach (id; system.m_excluded_components)
{
foreach (id2; info.components)
{
if (id == id2)
return;
}
}
}
foreach (id; system.m_components)
{
foreach (i2, id2; info.components)
{
if (id2 == id)
goto is_;
}
return;
is_:
}
info.systems[system_id] = true;
connectListenerToEntityInfo(info, system_id);
if(!info.systems[system_id])return;
uint index = 0;
for (; index < passes[system.m_pass].system_callers.length; index++)
@ -3483,6 +3492,12 @@ export struct EntityManager
return new_info;
}
export bool hasComponent(ushort component_id)
{
if(component_id >= deltas.length || !deltas[component_id])return false;
return true;
}
export ~this() @nogc nothrow
{
if (components)

View file

@ -194,6 +194,8 @@ package:
void* m_remove_entity;
void* m_change_entity;
void* m_filter_entity;
//void function(ref EntityManager.CallData data) m_initialize;
//void function(ref EntityManager.CallData data) m_deinitilize;
void* m_initialize;

View file

@ -139,6 +139,7 @@ void afterEveryTest()
unittest
{
EntityTemplate* tmpl_ = gEM.allocateTemplate([becsID!CInt, becsID!CFloat, becsID!CFlag].staticArray);
scope(exit)gEM.freeTemplate(tmpl_);
Entity* entity = gEM.addEntity(tmpl_);
EntityMeta meta = entity.getMeta();
assert(meta.hasComponent(becsID!CInt));
@ -157,6 +158,7 @@ unittest
unittest
{
EntityTemplate* tmpl_ = gEM.allocateTemplate([becsID!CInt, becsID!CFloat, becsID!CFlag].staticArray);
scope(exit)gEM.freeTemplate(tmpl_);
assert(tmpl_.info.components.length == 3);
assert(tmpl_.info.size == (CInt.sizeof + CFloat.sizeof + EntityID.sizeof));
assert(tmpl_.getComponent!CInt);
@ -345,6 +347,7 @@ unittest
assert(*tmpl_7.getComponent!CLong == 10);
gEM.freeTemplate(tmpl_d);
gEM.freeTemplate(tmpl_cp);
gEM.freeTemplate(tmpl_);
gEM.freeTemplate(tmpl_2);
gEM.freeTemplate(tmpl_3);
@ -368,6 +371,8 @@ unittest
assert(*tmpl_.getComponent!CInt == 1);
assert(*tmpl_.getComponent!CFloat == 2.0);
assert(tmpl_.info == tmpl_2.info);
gEM.freeTemplate(tmpl_);
gEM.freeTemplate(tmpl_2);
}
@("MultiRegister")
@ -1616,3 +1621,106 @@ unittest
assert(pass.system_callers[4].dependencies[0].system_id == becsID!TestSystem2);
assert(pass.system_callers[4].dependencies[1].system_id == becsID!TestSystem4);
}
@("CustomFilter")
unittest
{
struct TestSystem
{
mixin ECS.System;
struct EntitiesData
{
uint length;
@optional CInt[] int_;
@optional CLong[] long_;
@optional CFloat[] float_;
@optional CDouble[] double_;
}
bool filterEntity(EntityManager.EntityInfo* info)
{
if(!info.hasComponent(becsID!CInt))return false;
int one_from = 0;
if(info.hasComponent(becsID!CLong))one_from++;
if(info.hasComponent(becsID!CFloat))one_from++;
if(info.hasComponent(becsID!CDouble))one_from++;
if(one_from == 1)return true;
return false;
}
void onUpdate(EntitiesData entities)
{
updates++;
}
uint updates = 0;
}
struct TestSystem2
{
mixin ECS.System;
struct EntitiesData
{
uint length;
@optional CInt[] int_;
@optional CLong[] long_;
@optional CFloat[] float_;
@optional CDouble[] double_;
}
bool filterEntity(EntityManager.EntityInfo* info)
{
if(info.hasComponent(becsID!CInt) && info.hasComponent(becsID!CFloat) && !info.hasComponent(becsID!CLong) && !info.hasComponent(becsID!CDouble))return true;
if(info.hasComponent(becsID!CLong) && info.hasComponent(becsID!CDouble) && !info.hasComponent(becsID!CInt) && !info.hasComponent(becsID!CFloat))return true;
return false;
}
void onUpdate(EntitiesData entities)
{
updates++;
}
uint updates = 0;
}
gEM.beginRegister();
gEM.registerSystem!TestSystem(0);
gEM.registerSystem!TestSystem2(1);
gEM.endRegister();
EntityTemplate* tmpl_ = gEM.allocateTemplate([becsID!CInt, becsID!CLong, becsID!CFloat, becsID!CDouble].staticArray);
scope(exit)gEM.freeTemplate(tmpl_);
EntityTemplate* tmpl_2 = gEM.allocateTemplate([becsID!CInt, becsID!CFloat].staticArray);
scope(exit)gEM.freeTemplate(tmpl_2);
EntityTemplate* tmpl_3 = gEM.allocateTemplate([becsID!CLong, becsID!CDouble].staticArray);
scope(exit)gEM.freeTemplate(tmpl_3);
EntityTemplate* tmpl_4 = gEM.allocateTemplate([becsID!CInt, becsID!CLong, becsID!CDouble].staticArray);
scope(exit)gEM.freeTemplate(tmpl_4);
EntityTemplate* tmpl_5 = gEM.allocateTemplate([becsID!CInt, becsID!CDouble].staticArray);
scope(exit)gEM.freeTemplate(tmpl_5);
EntityTemplate* tmpl_6 = gEM.allocateTemplate([becsID!CDouble].staticArray);
scope(exit)gEM.freeTemplate(tmpl_6);
gEM.addEntity(tmpl_);
gEM.addEntity(tmpl_2);
gEM.addEntity(tmpl_3);
gEM.addEntity(tmpl_4);
gEM.addEntity(tmpl_5);
gEM.addEntity(tmpl_6);
TestSystem* test_system = gEM.getSystem!TestSystem;
TestSystem2* test_system2 = gEM.getSystem!TestSystem2;
gEM.begin();
gEM.update();
gEM.end();
assert(test_system.updates == 2);
assert(test_system2.updates == 2);
}

View file

@ -1014,6 +1014,7 @@ else:
writeEntityComponents(gEM.getEntity(entity));
//import std.stdio;
////writeln((cast(uint*)tmpl.info.first_block)[0..48]);
gEM.freeTemplate(tmpl_empty);
gEM.freeTemplate(tmpl);
gEM.freeTemplate(tmpl2);
gEM.freeTemplate(copy_tempalte);