diff --git a/demos/assets/shaders/circle.fp b/demos/assets/shaders/circle.fp new file mode 100644 index 0000000..15f46fd --- /dev/null +++ b/demos/assets/shaders/circle.fp @@ -0,0 +1,64 @@ +precision mediump int; +precision mediump float; +precision lowp sampler2D; +precision lowp samplerCube; + + +#ifdef GLES + #define TEX(x,y) texture2D(x,y) + #if __VERSION__ >290 + #define M_IN in mediump + #define L_IN in lowp + #else + #define M_IN varying mediump + #define L_IN varying lowp + #endif +#else + #define TEX(x,y) texture(x,y) + #if __VERSION__ > 320 + #define M_IN in + #define L_IN in + #else + #define M_IN varying + #define L_IN varying + #endif +#endif + +M_IN vec2 pos; +M_IN float edge; +//flat M_IN vec2 fpos; + +//M_IN vec2 uv; +//M_IN vec4 color; +/* +#ifdef GLES + #if __VERSION__ >290 + in mediump vec2 uv; + #else + varying mediump vec2 uv; + #endif +#else + #if __VERSION__ > 320 + in vec2 uv; + #else + varying vec2 uv; + #endif +#endif*/ + +//layout(binding = 0)uniform sampler2D tex; + +//uniform sampler2D tex; + +//layout(location = 0) out vec4 outColor; + +void main() +{ + float len2 = dot(pos,pos); + + if(len2 > 1.0)discard; + + if(len2 > edge)gl_FragColor = vec4(0.4,0.8,1.0,0.8);//TEX(tex,uv) * color; + else gl_FragColor = vec4(0,0.6,1.0,0.35);//TEX(tex,uv) * color; + //gl_FragColor = vec4(pos,0,1); + //if(gl_FragColor.a < 0.01)discard; +} diff --git a/demos/assets/shaders/circle.vp b/demos/assets/shaders/circle.vp new file mode 100644 index 0000000..6997121 --- /dev/null +++ b/demos/assets/shaders/circle.vp @@ -0,0 +1,114 @@ +precision highp float; +precision highp int; +precision lowp sampler2D; +precision lowp samplerCube; +#ifdef GLES + #if __VERSION__ >290 + #define LOC(x) layout(location = x) + #define ATT in + #define M_OUT out mediump + #define L_OUT out lowp + #else + #define LOC(x) + #define ATT attribute + #define M_OUT varying mediump + #define L_OUT varying lowp + #endif +#else + #if __VERSION__ > 320 + #define LOC(x) layout(location = x) + #define ATT in + #define M_OUT out + #define L_OUT out + #else + #define LOC(x) + #define ATT attribute + #define M_OUT varying + #define L_OUT varying + #endif +#endif +/* +#ifdef GLES + #if __VERSION__ >290 + uniform vec4 matrix_1; + uniform vec4 matrix_2; + uniform vec4 uv_transform; + + layout(location = 0) in vec2 positions; + layout(location = 1) in vec2 tex_coords; + + out mediump vec2 uv; + #else + uniform vec4 matrix_1; + uniform vec4 matrix_2; + uniform vec4 uv_transform; + + attribute vec2 positions; + attribute vec2 tex_coords; + + varying mediump vec2 uv; + #endif +#else + #if __VERSION__ > 320 + uniform vec4 matrix_1; + uniform vec4 matrix_2; + uniform vec4 uv_transform; + + layout(location = 0) in vec2 positions; + layout(location = 1) in vec2 tex_coords; + + out vec2 uv; + #else + uniform vec4 matrix_1; + uniform vec4 matrix_2; + uniform vec4 uv_transform; + + attribute vec2 positions; + attribute vec2 tex_coords; + + varying vec2 uv; + #endif +#endif*/ + +//#define VBO_BATCH 1 + +//M_OUT vec2 uv; +//L_OUT vec4 color; +M_OUT vec2 pos; +M_OUT float edge; +//flat M_OUT vec2 fpos; + +LOC(0) ATT vec2 positions; +//LOC(1) ATT vec2 tex_coords; + +#ifdef VBO_BATCH + LOC(2) ATT float depth; + LOC(3) ATT vec4 vcolor; +#else + uniform vec4 matrix_1; + uniform vec4 matrix_2; + //uniform vec4 uv_transform; + //uniform vec4 vcolor; + + //float depth = matrix_2.z; +#endif + +void main() { + //#ifdef VBO_BATCH + // vec3 position = vec3(positions*4.0,1.0); + // uv = tex_coords; + //#else + //edge = mix(0.1, 0.96, (matrix_2.z / 256)); + edge = (matrix_1.w - matrix_2.z) / matrix_1.w;//matrix_2.z;//clamp((matrix_2,0.0,1.0); + edge *= edge; + pos = positions * 2.0;// / matrix_2.zw * 2; + //fpos = positions * matrix_2.xy; + vec3 position = mat3(matrix_1.x,matrix_1.y,0,matrix_1.z,matrix_1.w,0,matrix_2.xy,1.0) * vec3(positions,1.0); + // uv = tex_coords * uv_transform.zw + uv_transform.xy; + //#endif + + //color = vcolor * 2.0; + + gl_Position = vec4(position.xy,0,1.0); + +} diff --git a/demos/assets/textures/atlas.png b/demos/assets/textures/atlas.png index a799eb7..eea925e 100644 Binary files a/demos/assets/textures/atlas.png and b/demos/assets/textures/atlas.png differ diff --git a/demos/compile_android.py b/demos/compile_android.py index 2e3f967..75d6106 100644 --- a/demos/compile_android.py +++ b/demos/compile_android.py @@ -38,7 +38,7 @@ def compile(sources, output): clean = 0 ldc_flags = '--d-version=SDL_209 --d-version=BindSDL_Image --d-version=MM_USE_POSIX_THREADS ' #import_paths = ['source','tests'] -import_paths = ['external','external/sources', 'external/imports', 'external/wasm_imports', '../source', 'utils/source', 'simple/source'] +import_paths = ['external/android','external/sources', 'external/imports', 'external/wasm_imports', '../source', 'utils/source', 'simple/source'] build_tests = 0 for arg in sys.argv[1:]: diff --git a/demos/external/sources/glad/gl/loader.d b/demos/external/sources/glad/gl/loader.d index d640c61..8bc904f 100644 --- a/demos/external/sources/glad/gl/loader.d +++ b/demos/external/sources/glad/gl/loader.d @@ -35,14 +35,14 @@ bool open_gl() @nogc { return false; } else { version(OSX) { - enum const(char)*[] NAMES = [ + enum const(char)*[4] NAMES = [ "../Frameworks/OpenGL.framework/OpenGL", "/Library/Frameworks/OpenGL.framework/OpenGL", "/System/Library/Frameworks/OpenGL.framework/OpenGL", "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL" ]; } else { - enum const(char)*[] NAMES = ["libGL.so.1", "libGL.so"]; + enum const(char)*[2] NAMES = ["libGL.so.1", "libGL.so"]; } foreach(name; NAMES) { diff --git a/demos/source/app.d b/demos/source/app.d index 003922b..808426f 100644 --- a/demos/source/app.d +++ b/demos/source/app.d @@ -4,10 +4,11 @@ import bindbc.sdl; import cimgui.cimgui; +import game_core.basic; import game_core.job_updater; -import bubel.ecs.manager; import bubel.ecs.core; +import bubel.ecs.manager; import bubel.ecs.std; import ecs_utils.gfx.renderer; @@ -21,6 +22,7 @@ import glad.gl.gles2; import glad.gl.loader; import gui.manager; +import gui.tool_circle; extern (C) : @@ -50,7 +52,7 @@ struct Launcher bool function() loop; void function() end; void function(SDL_Event*) event; - void function(vec2, Tool, int) tool; + //void function(vec2, Tool, int, bool) tool; float scalling; ivec2 window_size = ivec2(1024,768); Renderer renderer; @@ -65,9 +67,12 @@ struct Launcher vec2 render_position; Tool used_tool; - int tool_size = 0; + int tool_size = 100; float tool_repeat = 0; float repeat_time = 0; + bool tool_show = true; + bool tool_mode = true; + ToolCircle* tool_circle; bool swap_interval = true; @@ -93,7 +98,7 @@ struct Launcher float draw_time = 0; } - void switchDemo(void function() start, bool function() loop, void function() end, void function(SDL_Event*) event, void function(vec2, Tool, int) tool, const (char)* tips) + void switchDemo(void function() start, bool function() loop, void function() end, void function(SDL_Event*) event, const (char)* tips) { gui_manager.clear(); //launcher.ent @@ -117,7 +122,97 @@ struct Launcher this.end = end; this.event = event; this.tips = tips; - this.tool = tool; + //this.tool = tool; + } + + void processTool(vec2 position, bool mode) + { + static struct Iterator + { + float size2; + vec2 position; + ComponentRef[] add_comps; + ushort[] rem_comps; + + void removeEntity(IteratorSystem.EntitiesData data) + { + foreach(i;0..data.length) + { + vec2 rel_vec = data.location[i] - position; + float length = rel_vec.x * rel_vec.x + rel_vec.y * rel_vec.y; + if(length < size2)gEM.removeEntity(data.entity[i].id); + } + } + + void addComponent(IteratorSystem.EntitiesData data) + { + foreach(i;0..data.length) + { + vec2 rel_vec = data.location[i] - position; + float length = rel_vec.x * rel_vec.x + rel_vec.y * rel_vec.y; + if(length < size2)gEM.addComponents(data.entity[i].id, add_comps); + } + } + + void removeComponent(IteratorSystem.EntitiesData data) + { + foreach(i;0..data.length) + { + vec2 rel_vec = data.location[i] - position; + float length = rel_vec.x * rel_vec.x + rel_vec.y * rel_vec.y; + if(length < size2)gEM.removeComponents(data.entity[i].id, rem_comps); + } + } + } + + float half_size = tool_size * 0.5; + float size2 = half_size * half_size; + Iterator iterator; + iterator.size2 = size2; + iterator.position = position; + + switch(used_tool) + { + case Tool.entity_spawner: + if(mode) + { + if(gui_manager.templates.length == 0)return; + EntityTemplate* tmpl = gui_manager.getSelectedTemplate(); + CLocation* location = tmpl.getComponent!CLocation; + if(location) + { + position += randomCircularSample() * half_size; + if(position.y < 16)position.y = 16; + else if(position.y > 299)position.y = 299; + *location = position; + } + manager.addEntity(tmpl); + } + else + { + manager.callEntitiesFunction!IteratorSystem(&iterator.removeEntity); + } + break; + case Tool.component_manipulator: + { + if(gui_manager.components.length == 0)return; + if(mode) + { + ComponentRef[1] comps = [gui_manager.getSelectedComponent()]; + iterator.add_comps = comps; + manager.callEntitiesFunction!IteratorSystem(&iterator.addComponent); + } + else + { + ushort[1] comps = [gui_manager.getSelectedComponent().component_id]; + iterator.rem_comps = comps; + manager.callEntitiesFunction!IteratorSystem(&iterator.removeComponent); + } + } + break; + default: + break; + } } bool getKeyState(SDL_Scancode key) @@ -184,6 +279,28 @@ struct CleanSystem } } +struct IteratorSystem +{ + mixin ECS.System!1; + + struct EntitiesData + { + uint length; + const (Entity)[] entity; + CLocation[] location; + } + + bool onBegin() + { + return false; + } + + void onUpdate(EntitiesData) + { + + } +} + void mainLoop(void* arg) { __gshared double time = 0; @@ -237,9 +354,12 @@ void mainLoop(void* arg) case SDL_BUTTON_MIDDLE:launcher.mouse.middle = true;break; default:break; } - if(launcher.tool && event.button.button == SDL_BUTTON_LEFT && launcher.tool_repeat == 0 && !igIsWindowHovered(ImGuiHoveredFlags_AnyWindow)) + if(!igIsAnyItemHovered())igSetWindowFocus(); + if(!igIsWindowHovered(ImGuiHoveredFlags_AnyWindow) && !igIsWindowFocused(ImGuiFocusedFlags_AnyWindow)) { - launcher.tool(vec2(event.button.x, launcher.window_size.y - event.button.y) * launcher.scalling - launcher.render_position, launcher.used_tool, launcher.tool_size); + launcher.repeat_time = 0; + if(event.button.button == SDL_BUTTON_LEFT)launcher.processTool(vec2(event.button.x, launcher.window_size.y - event.button.y) * launcher.scalling - launcher.render_position,launcher.tool_mode); + else if(event.button.button == SDL_BUTTON_RIGHT)launcher.processTool(vec2(event.button.x, launcher.window_size.y - event.button.y) * launcher.scalling - launcher.render_position,!launcher.tool_mode); } } else if(event.type == SDL_MOUSEBUTTONUP) @@ -255,17 +375,52 @@ void mainLoop(void* arg) else if(event.type == SDL_MOUSEMOTION) { launcher.mouse.position = vec2(event.motion.x, launcher.window_size.y - event.motion.y); + }else if(event.type == SDL_MOUSEWHEEL) + { + if(!igIsAnyItemHovered() && !igIsWindowHovered(ImGuiHoveredFlags_AnyWindow)) + { + if(SDL_GetModState() & KMOD_CTRL) + { + float sign = 1; + if(event.wheel.y < 0)sign = -1; + float val = sign * event.wheel.y * launcher.tool_repeat * 0.25; + if(val < 0.1)val = 0.1; + launcher.tool_repeat -= sign * val; + if(launcher.tool_repeat < 0)launcher.tool_repeat = 0; + else if(launcher.tool_repeat > 1000)launcher.tool_repeat = 1000; + } + else + { + int sign = 1; + if(event.wheel.y < 0)sign = -1; + int val = sign * event.wheel.y * launcher.tool_size / 4; + if(val < 1)val = 1; + launcher.tool_size -= sign * val; + if(launcher.tool_size < 1)launcher.tool_size = 1; + else if(launcher.tool_size > 256)launcher.tool_size = 256; + } + } } } - if(launcher.tool && launcher.tool_repeat != 0 && launcher.mouse.left && !igIsWindowHovered(ImGuiHoveredFlags_AnyWindow) && !igIsWindowFocused(ImGuiFocusedFlags_AnyWindow)) + if(launcher.tool_repeat != 0 && (launcher.mouse.left || launcher.mouse.right) && !igIsWindowHovered(ImGuiHoveredFlags_AnyWindow) && !igIsWindowFocused(ImGuiFocusedFlags_AnyWindow)) { + bool mode = launcher.tool_mode; + if(launcher.mouse.right)mode = !mode; float range = 500.0 / cast(float)launcher.tool_repeat; launcher.repeat_time += launcher.delta_time; - while(launcher.repeat_time > range) + if(launcher.used_tool != Tool.entity_spawner || !mode) { - launcher.repeat_time -= range; - launcher.tool((launcher.mouse.position*launcher.scalling)-launcher.render_position, launcher.used_tool, launcher.tool_size); + if(launcher.repeat_time > range)launcher.processTool((launcher.mouse.position*launcher.scalling)-launcher.render_position, mode); + while(launcher.repeat_time > range)launcher.repeat_time -= range; + } + else + { + while(launcher.repeat_time > range) + { + launcher.repeat_time -= range; + launcher.processTool((launcher.mouse.position*launcher.scalling)-launcher.render_position, mode); + } } } @@ -300,17 +455,22 @@ void mainLoop(void* arg) if(igMenuItemBool("Simpe",null,false,true)) { import demos.simple; - launcher.switchDemo(&simpleStart,&simpleLoop,&simpleEnd,&simpleEvent,&simpleTool,Simple.tips); + launcher.switchDemo(&simpleStart,&simpleLoop,&simpleEnd,&simpleEvent,Simple.tips); } if(igMenuItemBool("Snake",null,false,true)) { import demos.snake; - launcher.switchDemo(&snakeStart,&snakeLoop,&snakeEnd,&snakeEvent,&snakeTool,Snake.tips); + launcher.switchDemo(&snakeStart,&snakeLoop,&snakeEnd,&snakeEvent,Snake.tips); } if(igMenuItemBool("Space invaders",null,false,true)) { import demos.space_invaders; - launcher.switchDemo(&spaceInvadersStart,&spaceInvadersLoop,&spaceInvadersEnd,&spaceInvadersEvent,&spaceInvadersTool,SpaceInvaders.tips); + launcher.switchDemo(&spaceInvadersStart,&spaceInvadersLoop,&spaceInvadersEnd,&spaceInvadersEvent,SpaceInvaders.tips); + } + if(igMenuItemBool("Particles",null,false,true)) + { + import demos.particles; + launcher.switchDemo(&particlesStart,&particlesLoop,&particlesEnd,&particlesEvent,ParticlesDemo.tips); } igEndMenu(); } @@ -463,20 +623,22 @@ void mainLoop(void* arg) if(launcher.show_demo_wnd) { igSetNextWindowPos(ImVec2(launcher.window_size.x - 260, 30), ImGuiCond_Once, ImVec2(0,0)); - igSetNextWindowSize(ImVec2(250, 500), ImGuiCond_Once); + igSetNextWindowSize(ImVec2(250, launcher.window_size.y - 60), ImGuiCond_Once); if(igBegin("Demo",&launcher.show_demo_wnd,0)) { ImDrawList* draw_list = igGetWindowDrawList(); - //igBeginGroup(); + igBeginGroup(); launcher.gui_manager.gui(); - //igEndGroup(); + igEndGroup(); + ImDrawList_AddRect(draw_list, igGetItemRectMin(), ImVec2(igGetWindowPos().x+igGetWindowWidth()-2,igGetItemRectMax().y), igColorConvertFloat4ToU32(ImVec4(0.4,0.4,0.4,0.4)), 4, ImDrawCornerFlags_All, 1); + //ImDrawList_AddRect(draw_list, igGetItemRectMin(), igGetItemRectMax(), igColorConvertFloat4ToU32(ImVec4(0.4,0.4,0.4,0.4)), -1, 0, 1); //igBeginChildFrame(1,ImVec2(0,-1),ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_ChildWindow); //igBeginChild("Tool frame",ImVec2(-1,-1),true,0); - if(igCollapsingHeader("Tool##ToolHeader", ImGuiTreeNodeFlags_SpanAvailWidth)) + igBeginGroup(); + if(igCollapsingHeader("Tool##ToolHeader", ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_DefaultOpen)) { igIndent(8); - igBeginGroup(); if(igBeginCombo("Tool",tool_strings[launcher.used_tool],0)) { if(igSelectable("Entity spawner",false,0,ImVec2(0,0))) @@ -493,14 +655,20 @@ void mainLoop(void* arg) } igEndCombo(); } + igCheckbox("Show Tool", &launcher.tool_show); + //igSelectable("Selectabe",false,ImGuiSelectableFlags_None,ImVec2(0,0)); + if(igRadioButtonBool("Add", launcher.tool_mode))launcher.tool_mode = true; + igSameLine(0,0); + if(igRadioButtonBool("Remove", !launcher.tool_mode))launcher.tool_mode = false; igSliderInt("Tool size", &launcher.tool_size, 0, 256, null); igSliderFloat("Tool repeat", &launcher.tool_repeat, 0, 1024, null, 4); launcher.gui_manager.toolGui(); - igEndGroup(); - ImDrawList_AddRect(draw_list, igGetItemRectMin(), igGetItemRectMax(), igColorConvertFloat4ToU32(ImVec4(0.4,0.4,0.4,0.4)), 4, ImDrawCornerFlags_All, 1); igUnindent(8); } + igEndGroup(); + ImDrawList_AddRect(draw_list, igGetItemRectMin(), ImVec2(igGetWindowPos().x+igGetWindowWidth()-2,igGetItemRectMax().y), igColorConvertFloat4ToU32(ImVec4(0.4,0.4,0.4,0.4)), 2, ImDrawCornerFlags_All, 1); + //igEndChild(); //igEndChildFrame(); @@ -516,7 +684,8 @@ void mainLoop(void* arg) if(launcher.show_profile_wnd) { - igSetNextWindowPos(ImVec2(launcher.window_size.x - 260, launcher.window_size.y - 280), ImGuiCond_Once, ImVec2(0,0)); + //igSetNextWindowPos(ImVec2(launcher.window_size.x - 260, launcher.window_size.y - 280), ImGuiCond_Once, ImVec2(0,0)); + igSetNextWindowPos(ImVec2(8, launcher.window_size.y - 258), ImGuiCond_Once, ImVec2(0,0)); igSetNextWindowSize(ImVec2(250, 250), ImGuiCond_Once); if(igBegin("Profile",&launcher.show_profile_wnd,0)) { @@ -577,6 +746,10 @@ void mainLoop(void* arg) launcher.renderer.present(); draw_time = launcher.getTime() - draw_time; + //import std.stdio; + //printf("Scalling: %f",launcher.scalling); + if(launcher.tool_show)launcher.tool_circle.draw(&launcher.renderer, (launcher.mouse.position*launcher.scalling)-launcher.render_position, cast(float)launcher.tool_size, launcher.renderer.view_size.y*6*launcher.scalling); + __gshared float plot_time = 0; __gshared uint plot_samples = 0; plot_time += launcher.delta_time; @@ -703,6 +876,7 @@ int app_main(int argc, char** argv) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); launcher.window = SDL_CreateWindow("Simple", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, launcher.window_size.x, launcher.window_size.y, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); + SDL_MaximizeWindow(launcher.window); launcher.gl_context = SDL_GL_CreateContext(launcher.window); launcher.context = igCreateContext(null); @@ -778,8 +952,11 @@ int app_main(int argc, char** argv) launcher.manager.registerPass("clean"); + launcher.manager.registerComponent!CLocation; + launcher.manager.registerSystem!CountSystem(10000); launcher.manager.registerSystem!CleanSystem(0,"clean"); + launcher.manager.registerSystem!IteratorSystem(0,"clean"); launcher.manager.endRegister(); @@ -796,8 +973,10 @@ int app_main(int argc, char** argv) { import demos.simple; import demos.space_invaders; - // launcher.switchDemo(&spaceInvadersStart,&spaceInvadersLoop,&spaceInvadersEnd,&spaceInvadersEvent,&spaceInvadersTool,SpaceInvaders.tips); - launcher.switchDemo(&simpleStart,&simpleLoop,&simpleEnd,&simpleEvent,&simpleTool,Simple.tips); + import demos.particles; + // launcher.switchDemo(&spaceInvadersStart,&spaceInvadersLoop,&spaceInvadersEnd,&spaceInvadersEvent,SpaceInvaders.tips); + // launcher.switchDemo(&particlesStart,&particlesLoop,&particlesEnd,&particlesEvent,ParticlesDemo.tips); + launcher.switchDemo(&simpleStart,&simpleLoop,&simpleEnd,&simpleEvent,Simple.tips); } int key_num; @@ -842,7 +1021,7 @@ void loadGFX() Texture.__loadBackend(); Renderer.__loadBackend(); - GfxConfig.materials = Mallocator.makeArray!Material(1); + GfxConfig.materials = Mallocator.makeArray!Material(3); GfxConfig.meshes = Mallocator.makeArray!Mesh(1); float[16] vertices = [-0.5,-0.5, 0,1, -0.5,0.5, 0,0, 0.5,-0.5, 1,1, 0.5,0.5, 1,0]; @@ -889,7 +1068,84 @@ void loadGFX() GfxConfig.materials[0].data.bindings[0] = GfxConfig.materials[0].getLocation("tex"); + Shader vsh2; + vsh2.create(); + vsh2.load("assets/shaders/circle.vp"); + vsh2.compile(); + + Shader fsh2; + fsh2.create(); + fsh2.load("assets/shaders/circle.fp"); + fsh2.compile(); + + GfxConfig.materials[1].create(); + GfxConfig.materials[1].data.blend_mode = Material.BlendMode.mixed; + GfxConfig.materials[1].data.mode = Material.TransformMode.position; + Material.ShaderModule[1] modules2 = [Material.ShaderModule(vsh2,fsh2)]; + GfxConfig.materials[1].attachModules(modules2); + //GfxConfig.materials[0]. + //GfxConfig.materials[0].load(load_data.materials[i].str); + GfxConfig.materials[1].compile(); + GfxConfig.materials[1].bindAttribLocation("positions",0); + //GfxConfig.materials[1].bindAttribLocation("tex_coords",1); + //GfxConfig.materials[1].bindAttribLocation("depth",2); + //GfxConfig.materials[1].bindAttribLocation("vcolor",3); + GfxConfig.materials[1].link(); + + /* import std.stdio; + writeln("positions ",glGetAttribLocation(GfxConfig.materials[0].data.modules[0].gl_handle,"positions")); + writeln("tex_coords ",glGetAttribLocation(GfxConfig.materials[0].data.modules[0].gl_handle,"tex_coords")); + writeln("depth ",glGetAttribLocation(GfxConfig.materials[0].data.modules[0].gl_handle,"depth")); + writeln("vcolor ",glGetAttribLocation(GfxConfig.materials[0].data.modules[0].gl_handle,"vcolor"));*/ + + GfxConfig.materials[1].data.uniforms = Mallocator.makeArray!(Material.Uniform)(2); + GfxConfig.materials[1].data.uniforms[0] = Material.Uniform(Material.Type.float4, GfxConfig.materials[1].getLocation("matrix_1"), 0); + GfxConfig.materials[1].data.uniforms[1] = Material.Uniform(Material.Type.float4, GfxConfig.materials[1].getLocation("matrix_2"), 16); + //GfxConfig.materials[1].data.uniforms[2] = Material.Uniform(Material.Type.float4, GfxConfig.materials[0].getLocation("uv_transform"), 32); + //GfxConfig.materials[1].data.bindings = Mallocator.makeArray!(int)(1); + //GfxConfig.materials[1].data.bindings[0] = GfxConfig.materials[0].getLocation("tex"); + + + + + + + GfxConfig.materials[2].create(); + GfxConfig.materials[2].data.blend_mode = Material.BlendMode.opaque; + GfxConfig.materials[2].data.mode = Material.TransformMode.position; + //Material.ShaderModule[1] modules = [Material.ShaderModule(vsh,fsh)]; + GfxConfig.materials[2].attachModules(modules); + //GfxConfig.materials[0]. + //GfxConfig.materials[0].load(load_data.materials[i].str); + GfxConfig.materials[2].compile(); + GfxConfig.materials[2].bindAttribLocation("positions",0); + GfxConfig.materials[2].bindAttribLocation("tex_coords",1); + GfxConfig.materials[2].bindAttribLocation("depth",2); + GfxConfig.materials[2].bindAttribLocation("vcolor",3); + GfxConfig.materials[2].link(); + + /* import std.stdio; + writeln("positions ",glGetAttribLocation(GfxConfig.materials[0].data.modules[0].gl_handle,"positions")); + writeln("tex_coords ",glGetAttribLocation(GfxConfig.materials[0].data.modules[0].gl_handle,"tex_coords")); + writeln("depth ",glGetAttribLocation(GfxConfig.materials[0].data.modules[0].gl_handle,"depth")); + writeln("vcolor ",glGetAttribLocation(GfxConfig.materials[0].data.modules[0].gl_handle,"vcolor"));*/ + + GfxConfig.materials[2].data.uniforms = Mallocator.makeArray!(Material.Uniform)(3); + GfxConfig.materials[2].data.uniforms[0] = Material.Uniform(Material.Type.float4, GfxConfig.materials[0].getLocation("matrix_1"), 0); + GfxConfig.materials[2].data.uniforms[1] = Material.Uniform(Material.Type.float4, GfxConfig.materials[0].getLocation("matrix_2"), 16); + GfxConfig.materials[2].data.uniforms[2] = Material.Uniform(Material.Type.float4, GfxConfig.materials[0].getLocation("uv_transform"), 32); + GfxConfig.materials[2].data.bindings = Mallocator.makeArray!(int)(1); + GfxConfig.materials[2].data.bindings[0] = GfxConfig.materials[0].getLocation("tex"); + GfxConfig.materials[2].data.blend_mode = Material.BlendMode.additive; + + + + + + /*glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);*/ + + launcher.tool_circle = Mallocator.make!ToolCircle; } \ No newline at end of file diff --git a/demos/source/demos/particles.d b/demos/source/demos/particles.d new file mode 100644 index 0000000..6ed8ea7 --- /dev/null +++ b/demos/source/demos/particles.d @@ -0,0 +1,545 @@ +module demos.particles; + +import app; + +import bindbc.sdl; + +import cimgui.cimgui; + +import bubel.ecs.attributes; +import bubel.ecs.core; +import bubel.ecs.entity; +import bubel.ecs.manager; +import bubel.ecs.std; + +import ecs_utils.gfx.texture; +import ecs_utils.math.vector; +import ecs_utils.utils; + +import game_core.basic; + +import gui.attributes; + +extern(C): + +private enum float px = 1.0/512.0; + +/*####################################################################################################################### +------------------------------------------------ Components ------------------------------------------------------------------ +#######################################################################################################################*/ + +/*struct CLocation +{ + mixin ECS.Component; + + alias location this; + + vec2 location; +}*/ + +struct CTexCoords +{ + mixin ECS.Component; + + vec4 value; +} + +struct CColor +{ + mixin ECS.Component; + + alias value this; + + @GUIColor uint value = uint.max; +} + +struct CVelocity +{ + mixin ECS.Component; + + alias value this; + + vec2 value = vec2(0); +} + +struct CForceRange +{ + mixin ECS.Component; + + vec2 range = vec2(20,200); +} + +struct CAttractor +{ + mixin ECS.Component; + + //alias value this; + float strength = 0.2; +} + +struct CVortex +{ + mixin ECS.Component; + + float strength = 0.6; +} + +struct CDamping +{ + mixin ECS.Component; + + alias power this; + + @GUIRange(0,9) ubyte power = 0; +} + +struct CGravity +{ + mixin ECS.Component; +} + +struct CParticleLife +{ + mixin ECS.Component; + + this(float life_in_secs) + { + life = cast(int)(life_in_secs * 1000_000); + } + + alias life this; + + int life = 1000000; +} + +/*####################################################################################################################### +------------------------------------------------ Systems ------------------------------------------------------------------ +#######################################################################################################################*/ + +struct DrawSystem +{ + mixin ECS.System!32; + + struct EntitiesData + { + uint length; + //uint thread_id; + uint job_id; + //@readonly CTexCoords[] coords; + @readonly CLocation[] locations; + + @optional @readonly CColor[] color; + } + + void onUpdate(EntitiesData data) + { + if(launcher.renderer.prepared_items >= launcher.renderer.MaxObjects)return;//simple leave loop if max visible objects count was reached + + if(!data.color) + { + foreach(i; 0..data.length) + { + launcher.renderer.draw(particles_demo.texture, data.locations[i], vec2(2,2), vec4(246,64,2,2)*px, 0, 0x80808080, 0, 2, 0, data.job_id); + } + } + else + { + foreach(i; 0..data.length) + { + launcher.renderer.draw(particles_demo.texture, data.locations[i], vec2(2,2), vec4(246,64,2,2)*px, 0, data.color[i].value, 0, 2, 0, data.job_id); + } + } + + } +} + +struct MoveSystem +{ + mixin ECS.System!64; + + struct EntitiesData + { + uint length; + CLocation[] locations; + @readonly CVelocity[] velocity; + } + + void onUpdate(EntitiesData data) + { + foreach(i; 0..data.length) + { + data.locations[i] += data.velocity[i] * launcher.delta_time; + } + } +} + +struct MouseAttractSystem +{ + mixin ECS.System!64; + + struct EntitiesData + { + uint length; + @readonly CLocation[] locations; + CVelocity[] velocity; + } + + vec2 mouse_pos; + + bool onBegin() + { + if(!launcher.getKeyState(SDL_SCANCODE_SPACE))return false; + mouse_pos = launcher.mouse.position; + mouse_pos = vec2(mouse_pos.x, mouse_pos.y) * launcher.scalling - launcher.render_position; + return true; + } + + void onUpdate(EntitiesData data) + { + float speed = launcher.delta_time * 0.01; + foreach(i;0..data.length) + { + vec2 rel_pos = mouse_pos - data.locations[i]; + float len2 = rel_pos.x * rel_pos.x + rel_pos.y * rel_pos.y; + if(len2 < 0.1)len2 = 0.1; + data.velocity[i] = data.velocity[i] + rel_pos / len2 * speed; + } + } +} + +struct AttractSystem +{ + mixin ECS.System!64; + + struct EntitiesData + { + uint length; + @readonly CLocation[] locations; + CVelocity[] velocity; + } + + struct Updater + { + AttractSystem.EntitiesData data; + + void onUpdate(AttractorIterator.EntitiesData adata) + { + float speed = launcher.delta_time * 0.00004; + if(adata.vortex) + { + foreach(i;0..data.length) + { + foreach(j;0..adata.length) + { + vec2 rel_pos = data.locations[i] - adata.locations[j]; + float len2 = rel_pos.length2(); + float inv_len = rsqrt(len2); + + if(1 < adata.force_range[j].range.y*inv_len) + { + float dist = (adata.force_range[j].range.y - 0.4)*inv_len - 1; + + vec2 vec = rel_pos * inv_len; + vec2 cvec = vec2(-vec.y,vec.x); + + float sign = -1; + if(1 < adata.force_range[j].range.x*inv_len)sign = 1; + + float str = adata.attractor[j].strength * sign; + float vortex_str = adata.vortex[j].strength; + data.velocity[i] = data.velocity[i] + (rel_pos * str + cvec * vortex_str) * speed * dist; + } + } + } + } + else + { + foreach(i;0..data.length) + { + foreach(j;0..adata.length) + { + vec2 rel_pos = data.locations[i] - adata.locations[j]; + float len2 = rel_pos.length2(); + float inv_len = rsqrt(len2); + + if(1 < adata.force_range[j].range.y*inv_len) + { + float dist = (adata.force_range[j].range.y - 0.4)*inv_len - 1; + + vec2 vec = rel_pos; + + float sign = -1; + if(1 < adata.force_range[j].range.x*inv_len)sign = 1; + + float str = adata.attractor[j].strength * speed * dist * sign; + data.velocity[i] = data.velocity[i] + vec * str; + } + } + } + } + } + } + + void onUpdate(EntitiesData data) + { + Updater updater; + updater.data = data; + launcher.manager.callEntitiesFunction!AttractorIterator(&updater.onUpdate); + } +} + +struct AttractorIterator +{ + mixin ECS.System!1; + + struct EntitiesData + { + uint length; + @readonly CLocation[] locations; + @readonly CAttractor[] attractor; + @readonly CForceRange[] force_range; + @optional @readonly CVortex[] vortex; + } + + bool onBegin() + { + return false; + } + + void onUpdate(EntitiesData data) + { + + } +} + +struct PlayAreaSystem +{ + mixin ECS.System!32; + + struct EntitiesData + { + uint length; + Entity[] entity; + @readonly CLocation[] locations; + } + + void onUpdate(EntitiesData data) + { + foreach(i; 0..data.length) + { + if(data.locations[i].x > 400)launcher.manager.removeEntity(data.entity[i].id); + else if(data.locations[i].x < 0)launcher.manager.removeEntity(data.entity[i].id); + if(data.locations[i].y > 300)launcher.manager.removeEntity(data.entity[i].id); + else if(data.locations[i].y < 0)launcher.manager.removeEntity(data.entity[i].id); + } + } +} + +struct DampingSystem +{ + mixin ECS.System!32; + + struct EntitiesData + { + uint length; + const (Entity)[] entity; + @readonly CDamping[] damping; + CVelocity[] velocity; + } + + float[10] damp = 0; + + bool onBegin() + { + foreach(i;0..10) + { + damp[i] = powf((0.99 - cast(float)i * 0.01),launcher.delta_time*0.1); + } + + return true; + } + + void onUpdate(EntitiesData data) + { + foreach(i; 0..data.length) + { + data.velocity[i] = data.velocity[i] * damp[data.damping[i]]; + } + } +} + +struct ParticleLifeSystem +{ + mixin ECS.System!32; + + struct EntitiesData + { + uint length; + const (Entity)[] entity; + CParticleLife[] life; + } + + int delta_time; + + bool onBegin() + { + delta_time = cast(int)(launcher.delta_time * 1000); + return true; + } + + void onUpdate(EntitiesData data) + { + foreach(i; 0..data.length) + { + data.life[i] -= delta_time; + if(data.life[i] < 0)launcher.manager.removeEntity(data.entity[i].id); + } + } +} + +struct GravitySystem +{ + mixin ECS.System!32; + + struct EntitiesData + { + uint length; + const (Entity)[] entity; + @readonly CGravity[] gravity; + CVelocity[] velocity; + } + + void onUpdate(EntitiesData data) + { + float delta_time = launcher.delta_time * 0.00_092; + foreach(i; 0..data.length) + { + data.velocity[i].y -= delta_time; + } + } +} + +/*####################################################################################################################### +------------------------------------------------ Functions ------------------------------------------------------------------ +#######################################################################################################################*/ + +struct ParticlesDemo +{ + __gshared const (char)* tips = "Use \"space\" to spwan entities.\n\nSystems can be enabled/disabled from \"Simple\" window."; + + Texture texture; +} + +__gshared ParticlesDemo* particles_demo; + +void particlesStart() +{ + particles_demo = Mallocator.make!ParticlesDemo; + + particles_demo.texture.create(); + particles_demo.texture.load("assets/textures/atlas.png"); + + launcher.manager.beginRegister(); + + launcher.manager.registerComponent!CLocation; + launcher.manager.registerComponent!CTexCoords; + launcher.manager.registerComponent!CColor; + launcher.manager.registerComponent!CVelocity; + launcher.manager.registerComponent!CAttractor; + launcher.manager.registerComponent!CDamping; + launcher.manager.registerComponent!CGravity; + launcher.manager.registerComponent!CVortex; + launcher.manager.registerComponent!CParticleLife; + launcher.manager.registerComponent!CForceRange; + + launcher.manager.registerSystem!MoveSystem(0); + launcher.manager.registerSystem!DrawSystem(100); + launcher.manager.registerSystem!PlayAreaSystem(102); + launcher.manager.registerSystem!AttractSystem(-1); + launcher.manager.registerSystem!MouseAttractSystem(1); + launcher.manager.registerSystem!DampingSystem(101); + launcher.manager.registerSystem!ParticleLifeSystem(-10); + launcher.manager.registerSystem!GravitySystem(-2); + + launcher.manager.registerSystem!AttractorIterator(-1); + + launcher.manager.endRegister(); + + launcher.gui_manager.addSystem(MoveSystem.system_id,"Move System"); + launcher.gui_manager.addSystem(DrawSystem.system_id,"Draw System"); + launcher.gui_manager.addSystem(PlayAreaSystem.system_id,"Play Area System"); + launcher.gui_manager.addSystem(AttractSystem.system_id,"Attract System"); + launcher.gui_manager.addSystem(MouseAttractSystem.system_id,"Mouse Attract System"); + launcher.gui_manager.addSystem(DampingSystem.system_id,"Damping System"); + launcher.gui_manager.addSystem(ParticleLifeSystem.system_id,"Particle Life System"); + + launcher.gui_manager.addComponent(CColor(),"Color (white)"); + launcher.gui_manager.addComponent(CColor(0xFF101540),"Color (red)"); + launcher.gui_manager.addComponent(CColor(0xFF251010),"Color (blue)"); + launcher.gui_manager.addComponent(CColor(0xFF102010),"Color (green)"); + launcher.gui_manager.addComponent(CAttractor(0.1),"Attractor (str 0.1)"); + launcher.gui_manager.addComponent(CForceRange(vec2(5,40)),"ForceRange (5,40)"); + launcher.gui_manager.addComponent(CVelocity(),"Velocity"); + launcher.gui_manager.addComponent(CDamping(),"Damping"); + launcher.gui_manager.addComponent(CVortex(),"Vortex"); + launcher.gui_manager.addComponent(CParticleLife(),"Particle Life"); + launcher.gui_manager.addComponent(CGravity(),"Gravity"); + + EntityTemplate* tmpl; + EntityTemplate* base_tmpl = launcher.manager.allocateTemplate([CLocation.component_id, CColor.component_id, CVelocity.component_id, CDamping.component_id].staticArray); + launcher.gui_manager.addTemplate(base_tmpl,"Particle"); + tmpl = launcher.manager.allocateTemplate(base_tmpl); + tmpl.getComponent!CColor().value = 0xFF251010; + launcher.gui_manager.addTemplate(tmpl,"Particle (blue)"); + tmpl = launcher.manager.allocateTemplate(base_tmpl); + tmpl.getComponent!CColor().value = 0xFF102010; + launcher.gui_manager.addTemplate(tmpl,"Particle (green)"); + tmpl = launcher.manager.allocateTemplate(base_tmpl); + tmpl.getComponent!CColor().value = 0xFF101540; + launcher.gui_manager.addTemplate(tmpl,"Particle (red)"); + // tmpl = launcher.manager.allocateTemplate(tmpl, [CDamping.component_id].staticArray); + // launcher.gui_manager.addTemplate(tmpl,"Particle (damping)"); + tmpl = launcher.manager.allocateTemplate(tmpl); + tmpl.getComponent!CDamping().power = 4; + launcher.gui_manager.addTemplate(tmpl,"Particle (damping!)"); + tmpl = launcher.manager.allocateTemplate([CAttractor.component_id, CLocation.component_id, CForceRange.component_id].staticArray); + launcher.gui_manager.addTemplate(tmpl,"Attractor"); + tmpl = launcher.manager.allocateTemplate(tmpl, [CVortex.component_id].staticArray); + launcher.gui_manager.addTemplate(tmpl,"Vortex"); + tmpl = launcher.manager.allocateTemplate(tmpl); + tmpl.getComponent!CVortex().strength = -0.6; + launcher.gui_manager.addTemplate(tmpl,"Vortex (reversed)"); + +} + +void particlesEnd() +{ + particles_demo.texture.destroy(); + + //launcher.manager.freeTemplate(simple.tmpl); + Mallocator.dispose(particles_demo); +} + +void particlesEvent(SDL_Event* event) +{ +} + +bool particlesLoop() +{ + launcher.render_position = (vec2(launcher.window_size.x,launcher.window_size.y)*launcher.scalling - vec2(400,300)) * 0.5; + + launcher.manager.begin(); + if(launcher.multithreading) + { + launcher.job_updater.begin(); + launcher.manager.updateMT(); + launcher.job_updater.call(); + } + else + { + launcher.manager.update(); + } + launcher.manager.end(); + + return true; +} \ No newline at end of file diff --git a/demos/source/demos/simple.d b/demos/source/demos/simple.d index 313cc00..ac3b3f7 100644 --- a/demos/source/demos/simple.d +++ b/demos/source/demos/simple.d @@ -4,46 +4,38 @@ import app; import bindbc.sdl; -import cimgui.cimgui; - import bubel.ecs.attributes; import bubel.ecs.core; import bubel.ecs.entity; import bubel.ecs.manager; import bubel.ecs.std; +import cimgui.cimgui; + import ecs_utils.gfx.texture; import ecs_utils.math.vector; import ecs_utils.utils; +import game_core.basic; + extern(C): -struct Simple -{ - __gshared const (char)* tips = "Use \"space\" to spwan entities.\n\nSystems can be enabled/disabled from \"Simple\" window."; +/*####################################################################################################################### +------------------------------------------------ Components ------------------------------------------------------------------ +#######################################################################################################################*/ - EntityTemplate* tmpl; - Texture texture; - - bool move_system = true; - bool draw_system = true; -} - -struct CLocation +/*struct CLocation { mixin ECS.Component; alias location this; vec2 location; -} +}*/ -struct CTexture -{ - mixin ECS.Component; - - Texture tex; -} +/*####################################################################################################################### +------------------------------------------------ Systems ------------------------------------------------------------------ +#######################################################################################################################*/ struct DrawSystem { @@ -54,7 +46,6 @@ struct DrawSystem uint length; //uint thread_id; uint job_id; - @readonly CTexture[] textures; @readonly CLocation[] locations; } @@ -63,7 +54,7 @@ struct DrawSystem if(launcher.renderer.prepared_items >= launcher.renderer.MaxObjects)return;//simple leave loop if max visible objects count was reached foreach(i; 0..data.length) { - launcher.renderer.draw(data.textures[i].tex, data.locations[i].location, vec2(16,16), vec4(0,0,1,1), cast(ushort)(data.locations[i].y), 0x80808080, 0, 0, 0, data.job_id); + launcher.renderer.draw(simple.texture, data.locations[i], vec2(16,16), vec4(0,0,1,1), cast(ushort)(data.locations[i].y), 0x80808080, 0, 0, 0, data.job_id); // launcher.renderer.draw(data.textures[i].tex, data.locations[i].location, vec2(16,16), vec4(0,0,1,1), 0, 0x80808080, 0, 0, 0, data.job_id); //draw(renderer, data.textures[i].tex, data.locations[i], vec2(32,32), vec4(0,0,1,1)); } @@ -85,12 +76,24 @@ struct MoveSystem { foreach(i; 0..data.length) { - data.locations[i].location.y = data.locations[i].location.y + 1; - if(data.locations[i].location.y > 300)data.locations[i].location.y = 0; + data.locations[i].y = data.locations[i].y + 1; + if(data.locations[i].y > 300)data.locations[i].y = 0; } } } +/*####################################################################################################################### +------------------------------------------------ Functions ------------------------------------------------------------------ +#######################################################################################################################*/ + +struct Simple +{ + __gshared const (char)* tips = "Use \"space\" to spwan entities.\n\nSystems can be enabled/disabled from \"Simple\" window."; + + EntityTemplate* tmpl; + Texture texture; +} + __gshared Simple* simple; void simpleStart() @@ -103,7 +106,6 @@ void simpleStart() launcher.manager.beginRegister(); launcher.manager.registerComponent!CLocation; - launcher.manager.registerComponent!CTexture; launcher.manager.registerSystem!MoveSystem(0); launcher.manager.registerSystem!DrawSystem(1); @@ -113,19 +115,17 @@ void simpleStart() launcher.gui_manager.addSystem(MoveSystem.system_id,"Move System"); launcher.gui_manager.addSystem(DrawSystem.system_id,"Draw System"); - ushort[2] components = [CLocation.component_id, CTexture.component_id]; + ushort[1] components = [CLocation.component_id]; simple.tmpl = launcher.manager.allocateTemplate(components); - CTexture* tex_comp = simple.tmpl.getComponent!CTexture; - tex_comp.tex = simple.texture; - CLocation* loc_comp = simple.tmpl.getComponent!CLocation; + //CLocation* loc_comp = simple.tmpl.getComponent!CLocation; launcher.gui_manager.addTemplate(simple.tmpl, "Basic"); foreach(i; 0..10) foreach(j; 0..10) { - loc_comp.location = vec2(i*16+64,j*16+64); - launcher.manager.addEntity(simple.tmpl); + //loc_comp.value = vec2(i*16+64,j*16+64); + launcher.manager.addEntity(simple.tmpl,[CLocation(vec2(i*16+64,j*16+64)).ref_].staticArray); } } @@ -140,46 +140,15 @@ void simpleEnd() Mallocator.dispose(simple); } -void simpleTool(vec2 position, Tool tool, int size) -{ - switch(tool) - { - case Tool.entity_spawner: - { - EntityTemplate* tmpl = launcher.gui_manager.getSelectedTemplate(); - CLocation* location = tmpl.getComponent!CLocation; - if(location) - { - position.x += (randomf - 0.5) * size; - position.y += (randomf - 0.5) * size; - if(position.x > 400)position.x -= 400; - else if(position.x < 0)position.x += 400; - if(position.y > 300)position.y -= 300; - else if(position.y < 0)position.y += 300; - *location = position; - } - launcher.manager.addEntity(tmpl); - } - break; - default: - break; - } -} - void simpleEvent(SDL_Event* event) { - /*if(event.type == event.button) - { - vec2 position = vec2(event.button.x, event.button.y); - - }*/ } void spawnEntity() { - CLocation* loc_comp = simple.tmpl.getComponent!CLocation; - loc_comp.location = vec2(randomf() * 400,0); - launcher.manager.addEntity(simple.tmpl); + //CLocation* loc_comp = simple.tmpl.getComponent!CLocation; + //loc_comp.value = vec2(randomf() * 400,0); + launcher.manager.addEntity(simple.tmpl,[CLocation(vec2(randomf() * 400,0)).ref_].staticArray); } bool simpleLoop() @@ -188,7 +157,7 @@ bool simpleLoop() if(launcher.getKeyState(SDL_SCANCODE_SPACE)) { - foreach(i;0..1)spawnEntity(); + foreach(i;0..20)spawnEntity(); } launcher.manager.begin(); diff --git a/demos/source/demos/snake.d b/demos/source/demos/snake.d index 01e9a36..f46009c 100644 --- a/demos/source/demos/snake.d +++ b/demos/source/demos/snake.d @@ -4,8 +4,6 @@ import app; import bindbc.sdl; -import cimgui.cimgui; - import bubel.ecs.attributes; import bubel.ecs.core; import bubel.ecs.entity; @@ -13,10 +11,14 @@ import bubel.ecs.manager; import bubel.ecs.std; import bubel.ecs.vector; +import cimgui.cimgui; + import ecs_utils.gfx.texture; import ecs_utils.math.vector; import ecs_utils.utils; +import game_core.basic; + //import std.array : staticArray; enum float px = 1.0/512.0; @@ -31,22 +33,6 @@ struct MapElement apple = 1, wall = 2, snake = 3, - - /* snake_head_up = 5, - snake_head_down = 6, - snake_head_left = 7, - snake_head_right = 8, - snake_tail_up = 9, - snake_tail_down = 10, - snake_tail_left = 11, - snake_tail_right = 12, - snake_turn_ld = 13, - snake_turn_lu = 14, - snake_turn_rd = 15, - snake_turn_ru = 16, - snake_vertical = 17, - snake_horizontal = 18*/ - } Type type; EntityID id; @@ -129,10 +115,7 @@ struct Snake } if(base_pos.x == random_pos.x && base_pos.y == random_pos.y)return; } - //CILocation* location = apple_tmpl.getComponent!CILocation; - //*location = random_pos; - //Entity* apple = - launcher.manager.addEntity(apple_tmpl,[CILocation(random_pos).ref_].staticArray); + launcher.manager.addEntity(apple_tmpl,[CLocation(cast(vec2)(random_pos)*16).ref_].staticArray); } } @@ -158,14 +141,14 @@ struct CILocation ivec2 location; } -struct CLocation -{ - mixin ECS.Component; +// struct CLocation +// { +// mixin ECS.Component; - alias location this; +// alias location this; - vec2 location = vec2(0,0); -} +// vec2 location = vec2(0,0); +// } struct CSnake { @@ -264,8 +247,8 @@ struct AppleSystem struct EntitiesData { uint length; - @readonly Entity[] entities; - @readonly CApple[] movement; + @readonly Entity[] entity; + @readonly CApple[] apple; @readonly CILocation[] location; } @@ -273,7 +256,17 @@ struct AppleSystem { foreach(i;0..data.length) { - snake.element(MapElement(MapElement.Type.apple,data.entities[i].id),data.location[i]); + if(snake.element(data.location[i]).id == EntityID())snake.element(MapElement(MapElement.Type.apple,data.entity[i].id),data.location[i]); + else launcher.manager.removeEntity(data.entity[i].id); + } + } + + void onRemoveEntity(EntitiesData data) + { + foreach(i;0..data.length) + { + if(snake.element(data.location[i].location).id == data.entity[i].id) + snake.element(MapElement(MapElement.Type.empty, EntityID()),data.location[i].location); } } } @@ -315,7 +308,7 @@ struct ParticleMovementSystem { foreach(i;0..data.length) { - data.location[i].location -= data.movement[i].velocity; + data.location[i] -= data.movement[i].velocity; } } } @@ -357,7 +350,7 @@ struct AnimationRenderSystem { foreach(i;0..data.length) { - launcher.renderer.draw(snake.texture, cast(vec2)cast(ivec2)data.location[i].location, vec2(16,16), data.animation[i].frames[cast(int)(data.animation[i].time)], -1, 0x80808080); + launcher.renderer.draw(snake.texture, cast(vec2)cast(ivec2)data.location[i], vec2(16,16), data.animation[i].frames[cast(int)(data.animation[i].time)], -1, 0x80808080); } } } @@ -477,7 +470,12 @@ struct MoveSystem break; case MapElement.Type.apple: launcher.manager.removeEntity(snake.element(data.location[i].location).id); - if(data.snakes[i].parts.length < 100)data.snakes[i].parts.add(new_location); + if(data.snakes[i].parts.length >= 99) + { + snake.addApple(); + goto case(MapElement.Type.empty); + } + data.snakes[i].parts.add(new_location); if(data.snakes[i].parts.length > 1) { @@ -506,7 +504,40 @@ struct MoveSystem } } } - + } +} + +struct SnakeSystem +{ + mixin ECS.System!1; + + struct EntitiesData + { + uint length; + Entity[] entity; + @readonly CSnake[] snake; + @readonly CILocation[] location; + } + + void onAddSystem(EntitiesData data) + { + foreach(i;0..data.length) + { + if(snake.element(data.location[i]).id == EntityID())snake.element(MapElement(MapElement.Type.snake,data.entity[i].id),data.location[i]); + else launcher.manager.removeEntity(data.entity[i].id); + } + } + + void onRemoveEntity(EntitiesData data) + { + foreach(i;0..data.length) + { + if(snake.element(data.location[i].location).id == data.entity[i].id) + snake.element(MapElement(MapElement.Type.empty, EntityID()),data.location[i].location); + foreach(part; data.snake[i].parts.array) + if(snake.element(part).id == data.entity[i].id) + snake.element(MapElement(MapElement.Type.empty, EntityID()),part); + } } } @@ -750,6 +781,35 @@ struct CleanSystem } } +struct CopyLocationSystem +{ + mixin ECS.System!32; + + struct EntitiesData + { + uint length; + const (Entity)[] entity; + CLocation[] location; + @readonly CILocation[] ilocation; + } + + void onAddEntity(EntitiesData data) + { + foreach(i;0..data.length) + { + data.ilocation[i] = cast(ivec2)(data.location[i] / 16); + } + } + + void onUpdate(EntitiesData data) + { + foreach(i;0..data.length) + { + data.location[i] = cast(vec2)(data.ilocation[i] * 16); + } + } +} + __gshared Snake* snake; void snakeStart() @@ -776,7 +836,6 @@ void snakeStart() launcher.manager.registerSystem!MoveSystem(0,"fixed"); launcher.manager.registerSystem!InputSystem(-100); launcher.manager.registerSystem!FixSnakeDirectionSystem(-1,"fixed"); - launcher.manager.registerSystem!AppleSystem(-1,"fixed"); launcher.manager.registerSystem!AnimationRenderSystem(100); launcher.manager.registerSystem!AnimationSystem(-1); launcher.manager.registerSystem!ParticleSystem(-1); @@ -784,8 +843,20 @@ void snakeStart() launcher.manager.registerSystem!DrawAppleSystem(99); launcher.manager.registerSystem!DrawSnakeSystem(101); + launcher.manager.registerSystem!CopyLocationSystem(100); + //launcher.manager.registerSystem!AppleRemoveSystem(100); + launcher.manager.registerSystem!AppleSystem(101); + launcher.manager.registerSystem!SnakeSystem(101); + launcher.manager.endRegister(); + launcher.gui_manager.addComponent(CApple(),"Apple"); + launcher.gui_manager.addComponent(CSnake(),"Snake"); + launcher.gui_manager.addComponent(CParticle(1000),"Particle (1s)"); + launcher.gui_manager.addComponent(CParticleVector(vec2(0,1)),"Particle Vector (UP)"); + launcher.gui_manager.addComponent(CInput(),"Input"); + launcher.gui_manager.addComponent(CMovement(CMovement.Direction.up),"Movement (UP)"); + launcher.gui_manager.addSystem(MoveSystem.system_id,"Move System"); launcher.gui_manager.addSystem(InputSystem.system_id,"Input System"); launcher.gui_manager.addSystem(FixSnakeDirectionSystem.system_id,"Fix Direction System"); @@ -797,15 +868,13 @@ void snakeStart() snake.snake_destroy_particle_frames = Mallocator.makeArray([vec4(64,144,16,16)*px,vec4(80,144,16,16)*px,vec4(96,144,16,16)*px,vec4(112,144,16,16)*px].staticArray); { - ushort[4] components = [CILocation.component_id, CSnake.component_id, CMovement.component_id, CInput.component_id]; + ushort[5] components = [CILocation.component_id, CSnake.component_id, CMovement.component_id, CInput.component_id, CLocation.component_id]; snake.snake_tmpl = launcher.manager.allocateTemplate(components); - //CILocation* loc_comp = snake.snake_tmpl.getComponent!CILocation; - //*loc_comp = ivec2(2,2); launcher.manager.addEntity(snake.snake_tmpl,[CILocation(ivec2(2,2)).ref_].staticArray); } { - snake.snake_destroy_particle = launcher.manager.allocateTemplate([CLocation.component_id, CParticle.component_id, CParticleVector.component_id, CAnimation.component_id].staticArray); + snake.snake_destroy_particle = launcher.manager.allocateTemplate([CLocation.component_id, CParticle.component_id, CParticleVector.component_id, CAnimation.component_id, CLocation.component_id].staticArray); CAnimation* canim = snake.snake_destroy_particle.getComponent!CAnimation; canim.frames = snake.snake_destroy_particle_frames; CParticle* particle = snake.snake_destroy_particle.getComponent!CParticle; @@ -813,7 +882,7 @@ void snakeStart() } { - ushort[2] components = [CILocation.component_id, CApple.component_id]; + ushort[3] components = [CILocation.component_id, CApple.component_id, CLocation.component_id]; snake.apple_tmpl = launcher.manager.allocateTemplate(components); snake.addApple(); } @@ -824,13 +893,6 @@ void snakeStart() MoveSystem* move_system = launcher.manager.getSystem!MoveSystem(); move_system.setTemplates(); - - /*foreach(i; 0..10) - foreach(j; 0..10) - { - loc_compation = vec2(i*32+64,j*32+64); - launcher.manager.addEntity(simple.tmpl); - }*/ } void snakeEnd() @@ -839,39 +901,6 @@ void snakeEnd() Mallocator.dispose(snake); } -void snakeTool(vec2 position, Tool tool, int size) -{ - switch(tool) - { - case Tool.entity_spawner: - { - EntityTemplate* tmpl = launcher.gui_manager.getSelectedTemplate(); - CLocation* location = tmpl.getComponent!CLocation; - if(location) - { - position.x += (randomf() - 0.5) * size; - position.y += (randomf() - 0.5) * size; - *location = position; - } - CILocation* ilocation = tmpl.getComponent!CILocation; - if(ilocation) - { - position.x += (randomf() - 0.5) * size; - position.y += (randomf() - 0.5) * size; - ivec2 ipos; - ipos.x = cast(int)(position.x / 16); - ipos.y = cast(int)(position.y / 16); - *ilocation = ipos; - if(snake.element(ipos).type != MapElement.Type.empty)return; - } - launcher.manager.addEntity(tmpl); - } - break; - default: - break; - } -} - void snakeEvent(SDL_Event* event) { @@ -881,16 +910,16 @@ bool snakeLoop() { launcher.render_position = (vec2(launcher.window_size.x,launcher.window_size.y)*launcher.scalling - vec2(288,288)) * 0.5; - /*if(launcher.show_demo_wnd) - { - igSetNextWindowPos(ImVec2(800 - 260, 30), ImGuiCond_Once, ImVec2(0,0)); - igSetNextWindowSize(ImVec2(250, 0), ImGuiCond_Once); - if(igBegin("Snake",&launcher.show_demo_wnd,0)) - { + // if(launcher.show_demo_wnd) + // { + // igSetNextWindowPos(ImVec2(800 - 260, 30), ImGuiCond_Once, ImVec2(0,0)); + // igSetNextWindowSize(ImVec2(250, 0), ImGuiCond_Once); + // if(igBegin("Snake",&launcher.show_demo_wnd,0)) + // { - } - igEnd(); - }*/ + // } + // igEnd(); + // } launcher.manager.begin(); @@ -912,7 +941,5 @@ bool snakeLoop() launcher.manager.end(); - //snake.drawMap(); - return true; } \ No newline at end of file diff --git a/demos/source/demos/space_invaders.d b/demos/source/demos/space_invaders.d index 45dd06d..ce2cd6a 100644 --- a/demos/source/demos/space_invaders.d +++ b/demos/source/demos/space_invaders.d @@ -4,25 +4,26 @@ import app; import bindbc.sdl; -import cimgui.cimgui; - import bubel.ecs.attributes; import bubel.ecs.core; import bubel.ecs.entity; import bubel.ecs.manager; import bubel.ecs.std; +import cimgui.cimgui; + import ecs_utils.gfx.texture; import ecs_utils.math.vector; import ecs_utils.utils; +import game_core.basic; + //import std.math : PI; -enum PI = 3.141592653589793238462643383279502884197169399375105820; //import std.array : staticArray; -enum float px = 1.0/512.0; +private enum float px = 1.0/512.0; extern(C): @@ -114,14 +115,14 @@ enum Direction : byte ------------------------------------------------ Components ------------------------------------------------------------------ #######################################################################################################################*/ -struct CLocation +/*struct CLocation { mixin ECS.Component; alias value this; vec2 value = vec2(0); -} +}*/ struct CScale { @@ -273,7 +274,7 @@ struct CTargetParent mixin ECS.Component; EntityID parent; - vec2 rel_pos; + vec2 rel_pos = vec2(0,0); } @@ -699,7 +700,7 @@ struct ShipWeaponSystem Entity[] entity; CInit[] init; //CShip[] ship; - //CChildren[] children; + CChildren[] children; } struct Ship @@ -1062,7 +1063,7 @@ struct CollisionSystem } } -struct LaserShootingSystem +struct ShootingSystem { mixin ECS.System!32; @@ -1187,7 +1188,7 @@ struct LaserShootingSystem else fire_velocity.value = vec2(0,0); fire_location.value = data.location[i]; - if(data.shoot_direction[i].direction == Direction.down) + if(data.shoot_direction && data.shoot_direction[i].direction == Direction.down) { fire_rotation.value = PI; //fire_location.value.y -= 16; @@ -1270,7 +1271,7 @@ struct DampingSystem } } -struct LaserCollisionSystem +struct BulletsCollisionSystem { mixin ECS.System!32; @@ -1423,9 +1424,12 @@ struct UpgradeSystem if(ship) { CChildren* children = entity.getComponent!CChildren; - foreach(child;children.childern) + if(children) { - launcher.manager.sendEvent(child,EUpgrade()); + foreach(child;children.childern) + { + launcher.manager.sendEvent(child,EUpgrade()); + } } } } @@ -1742,7 +1746,7 @@ struct ShootWaveSystem CLocation* location = entity.getComponent!CLocation; CGuild* guild = entity.getComponent!CGuild; - //LaserShootingSystem.bullet_tmpl + //ShootingSystem.bullet_tmpl EntityTemplate* tmpl = space_invaders.bullet_tmpl[wave.bullet_type]; foreach(dir;dirs) { @@ -2180,12 +2184,6 @@ struct CShipIterator //void handleEvent(Entity* entity, ) }//*/ -extern(C) float sqrtf(float x) @nogc nothrow @system; -extern(C) float acosf(float x) @nogc nothrow @system; -extern(C) float sinf(float x) @nogc nothrow @system; -extern(C) float cosf(float x) @nogc nothrow @system; -extern(C) float powf(float x, float y) @nogc nothrow @system; - /** *System is responsible for movement of objects with CInput component. *In this example every entity has same speed when using movement system. @@ -2348,9 +2346,9 @@ void spaceInvadersStart() launcher.manager.registerSystem!InputMovementSystem(-100); launcher.manager.registerSystem!MovementSystem(-99); launcher.manager.registerSystem!ClampPositionSystem(-90); - launcher.manager.registerSystem!LaserShootingSystem(0); + launcher.manager.registerSystem!ShootingSystem(0); launcher.manager.registerSystem!ChangeDirectionSystem(0); - launcher.manager.registerSystem!LaserCollisionSystem(-70); + launcher.manager.registerSystem!BulletsCollisionSystem(-70); launcher.manager.registerSystem!ShootGridManager(-80); launcher.manager.registerSystem!ShootGridCleaner(-101); launcher.manager.registerSystem!HitPointsSystem(0); @@ -2374,13 +2372,49 @@ void spaceInvadersStart() launcher.manager.endRegister(); + launcher.gui_manager.addComponent(CInput(),"Input"); + launcher.gui_manager.addComponent(CShip(),"Ship"); + launcher.gui_manager.addComponent(CEnemy(),"Enemy"); + launcher.gui_manager.addComponent(CAutoShoot(),"Auto Shoot"); + launcher.gui_manager.addComponent(CWeapon(0, CWeapon.Type.laser),"Weapon (laser)"); + launcher.gui_manager.addComponent(CVelocity(vec2(0,0)),"Velocity (0,0)"); + launcher.gui_manager.addComponent(CBullet(),"Bullet (dmg1)"); + launcher.gui_manager.addComponent(CSideMove(),"Side Move"); + launcher.gui_manager.addComponent(CSideMove(0),"Side Move (g1)"); + launcher.gui_manager.addComponent(CSideMove(1),"Side Move (g2)"); + launcher.gui_manager.addComponent(CShootGrid(),"Shoot Grid"); + launcher.gui_manager.addComponent(CGuild(),"Guild (Player)"); + launcher.gui_manager.addComponent(CGuild(1),"Guild (Enemy)"); + launcher.gui_manager.addComponent(CHitPoints(10),"Hit Points (10)"); + launcher.gui_manager.addComponent(CHitMark(),"Hit Mark"); + launcher.gui_manager.addComponent(CUpgrade(CUpgrade.Upgrade.laser),"Upgrade (laser)"); + launcher.gui_manager.addComponent(CParticle(1000),"Particle (1s)"); + //launcher.gui_manager.addComponent(CMaxHitPoints(),"Max Hit Points"); + launcher.gui_manager.addComponent(CDamping(0),"Damping (0)"); + launcher.gui_manager.addComponent(CDamping(4),"Damping (4)"); + launcher.gui_manager.addComponent(CDamping(8),"Damping (8)"); + launcher.gui_manager.addComponent(CTargetParent(),"Target Parent"); + launcher.gui_manager.addComponent(CTargetPlayerShip(),"Target Player Ship"); + launcher.gui_manager.addComponent(CTarget(),"Target"); + launcher.gui_manager.addComponent(CChildren(),"Children"); + launcher.gui_manager.addComponent(CWeaponLocation(vec2(0,16)),"Weapon Location (0,16)"); + launcher.gui_manager.addComponent(CInit(CInit.Type.space_ship),"Init (Ship)"); + launcher.gui_manager.addComponent(CInit(CInit.Type.boss),"Init (Boss)"); + launcher.gui_manager.addComponent(CInit(CInit.Type.tower),"Init (Tower)"); + launcher.gui_manager.addComponent(CBoss(),"Boss"); + launcher.gui_manager.addComponent(CColliderScale(),"Collider Scale"); + launcher.gui_manager.addComponent(CParticleEmitter(),"Particle Emitter"); + launcher.gui_manager.addComponent(CParticleEmitterTime(),"Particle Emitter Time"); + //launcher.gui_manager.addComponent(CSpawnUponDeath(),"Spawn Upon Death"); + launcher.gui_manager.addComponent(CShootWaveUponDeath(CWeapon.Type.canon),"Wave Upon Death"); + launcher.gui_manager.addSystem(DrawSystem.system_id,"Draw System"); launcher.gui_manager.addSystem(InputMovementSystem.system_id,"Input Movement"); - launcher.gui_manager.addSystem(LaserShootingSystem.system_id,"Laser Shooting"); + launcher.gui_manager.addSystem(ShootingSystem.system_id,"Shooting System"); launcher.gui_manager.addSystem(MovementSystem.system_id,"Movement System"); launcher.gui_manager.addSystem(ClampPositionSystem.system_id,"Clamp Position System"); launcher.gui_manager.addSystem(ChangeDirectionSystem.system_id,"Change Direction System"); - launcher.gui_manager.addSystem(LaserCollisionSystem.system_id,"Laser Collision System"); + launcher.gui_manager.addSystem(BulletsCollisionSystem.system_id,"Bullets Collision System"); launcher.gui_manager.addSystem(ShootGridManager.system_id,"Shoot Grid Manager"); launcher.gui_manager.addSystem(ShootGridCleaner.system_id,"Shoot Grid Cleaner"); launcher.gui_manager.addSystem(HitPointsSystem.system_id,"Hit Points System"); @@ -2560,7 +2594,7 @@ void spaceInvadersEnd() { /*launcher.manager.getSystem(DrawSystem.system_id).disable(); launcher.manager.getSystem(InputMovementSystem.system_id).disable(); - launcher.manager.getSystem(LaserShootingSystem.system_id).disable(); + launcher.manager.getSystem(ShootingSystem.system_id).disable(); launcher.manager.getSystem(MovementSystem.system_id).disable(); launcher.manager.getSystem(ClampPositionSystem.system_id).disable(); launcher.manager.getSystem(ShootGridCleaner.system_id).disable();*/ @@ -2570,35 +2604,6 @@ void spaceInvadersEnd() space_invaders = null; } -void spaceInvadersTool(vec2 position, Tool tool, int size) -{ - switch(tool) - { - case Tool.entity_spawner: - { - EntityTemplate* tmpl = launcher.gui_manager.getSelectedTemplate(); - CLocation* location = tmpl.getComponent!CLocation; - if(location) - { - position.x += (randomf - 0.5) * size; - position.y += (randomf - 0.5) * size; - if(position.y < 16)position.y = 16; - else if(position.y > 299)position.y = 299; - *location = position; - } - CWeapon* laser_weapon = tmpl.getComponent!CWeapon; - if(laser_weapon) - { - laser_weapon.shoot_time = randomf * CWeapon.levels[laser_weapon.level - 1].reload_time; - } - launcher.manager.addEntity(tmpl); - } - break; - default: - break; - } -} - void spaceInvadersEvent(SDL_Event* event) { diff --git a/demos/source/game_core/basic.d b/demos/source/game_core/basic.d new file mode 100644 index 0000000..993a5aa --- /dev/null +++ b/demos/source/game_core/basic.d @@ -0,0 +1,14 @@ +module game_core.basic; + +import bubel.ecs.core; + +import ecs_utils.math.vector; + +struct CLocation +{ + mixin ECS.Component; + + alias value this; + + vec2 value = vec2(0); +} \ No newline at end of file diff --git a/demos/source/gui/attributes.d b/demos/source/gui/attributes.d new file mode 100644 index 0000000..53605c2 --- /dev/null +++ b/demos/source/gui/attributes.d @@ -0,0 +1,20 @@ +module gui.attributes; + +enum GUIColor = "GUIColor"; + +struct GUIRange +{ + union + { + struct + { + int min; + int max; + } + struct + { + float minf; + float maxf; + } + } +} \ No newline at end of file diff --git a/demos/source/gui/component.d b/demos/source/gui/component.d index bbd7ec5..b19f069 100644 --- a/demos/source/gui/component.d +++ b/demos/source/gui/component.d @@ -1,6 +1,61 @@ -module gui.components; +module gui.component; + +import ecs_utils.utils; struct ComponentGUI { - -} \ No newline at end of file + const (char)* name; + void* data; + ushort component_id; +} + +struct ComponentEditGUI +{ + const (char)* name; + VariableGUI[] variables; + uint used; +} + +struct VariableGUI +{ + struct Int + { + int min; + int max; + } + + struct Float + { + float min; + float max; + } + + struct Enum + { + const (char)[][] strings; + } + + enum Type + { + byte_, + ubyte_, + short_, + ushort_, + int_, + uint_, + float_, + enum_, + color, + vec2, + ivec2 + } + Type type; + const (char)* name; + ushort offset; + union + { + Int int_; + Float float_; + Enum enum_; + } +} diff --git a/demos/source/gui/manager.d b/demos/source/gui/manager.d index 4d452ad..b7c8678 100644 --- a/demos/source/gui/manager.d +++ b/demos/source/gui/manager.d @@ -4,22 +4,32 @@ import app; import cimgui.cimgui; +import bubel.ecs.entity; +import bubel.ecs.manager; import bubel.ecs.std; import bubel.ecs.system; import bubel.ecs.vector; -import bubel.ecs.entity; +import ecs_utils.math.vector; + +import gui.attributes; +import gui.component; import gui.system; import gui.template_; +import std.traits; + extern(C): struct GUIManager { Vector!SystemGUI systems; + Vector!ComponentGUI components; Vector!TemplateGUI templates; + Vector!ComponentEditGUI edit_components; uint selected_tempalte = 0; + uint selected_component = 0; void clear() { @@ -27,10 +37,22 @@ struct GUIManager { launcher.manager.freeTemplate(tmpl.tmpl); } + foreach(comp; components) + { + free(comp.data); + } + foreach(ref comp; edit_components) + { + if(comp.variables)Mallocator.dispose(comp.variables); + comp.variables = null; + comp.used = 0; + } systems.clear(); templates.clear(); + components.clear(); selected_tempalte = 0; + selected_component = 0; } EntityTemplate* getSelectedTemplate() @@ -39,6 +61,12 @@ struct GUIManager else return null; } + ComponentRef getSelectedComponent() + { + if(components.length > selected_component)return ComponentRef(components[selected_component].data, components[selected_component].component_id); + else return ComponentRef(null, ushort.max); + } + void addSystem(ushort id, const (char)* name, bool enabled = true) { System* system = launcher.manager.getSystem(id); @@ -56,9 +84,112 @@ struct GUIManager templates.add(TemplateGUI(name, tmpl)); } + // void addComponent(ComponentRef comp, const (char)* name) + // { + // uint size = EntityManager.instance.components[comp.component_id].size; + // void* data = malloc(size); + // memcpy(data, comp.ptr, size); + // components.add(ComponentGUI(name, data, comp.component_id)); + // } + + void addComponent(T)(T comp, const (char)* name) + { + static assert(hasStaticMember!(T,"component_id")); + uint size = EntityManager.instance.components[comp.component_id].size; + void* data = malloc(size); + memcpy(data, &comp, size); + components.add(ComponentGUI(name, data, comp.component_id)); + + if(edit_components.length <= comp.component_id) + { + edit_components.length = comp.component_id+1;//.extend(comp.component_id + 1); + } + //edit_components[comp.component_id] = ComponentEditGUI(name); + ComponentEditGUI comp_edit; + comp_edit.name = T.stringof; + //enum fields = __traits(allMembers, T); + alias fields = FieldNameTuple!T; + //pragma(msg,fields); + comp_edit.variables = Mallocator.makeArray!VariableGUI(fields.length); + foreach(member_str; fields) + { + alias member = __traits(getMember, T, member_str); + alias member_type = typeof(member); + //pragma(msg,member); + //pragma(msg,member_type); + //pragma(msg,__traits(getMember, T, member).offsetof); + ushort offset = member.offsetof;//cast(ushort)__traits(getMember, T, member).offsetof; + static if(__traits(isIntegral,member_type)) + { + static if(__traits(isUnsigned, member_type)) + { + static if(hasUDA!(member,GUIColor)) + { + comp_edit.variables[comp_edit.used++] = VariableGUI(VariableGUI.Type.color,member_str,offset); + } + else switch(member_type.sizeof) + { + case 1: comp_edit.variables[comp_edit.used++] = VariableGUI(VariableGUI.Type.ubyte_,member_str,offset);break; + case 2: comp_edit.variables[comp_edit.used++] = VariableGUI(VariableGUI.Type.ushort_,member_str,offset);break; + case 4: comp_edit.variables[comp_edit.used++] = VariableGUI(VariableGUI.Type.uint_,member_str,offset);break; + default:break; + } + static if(hasUDA!(member,GUIRange)) + { + comp_edit.variables[comp_edit.used-1].int_.min = getUDAs!(member,GUIRange)[0].min; + comp_edit.variables[comp_edit.used-1].int_.max = getUDAs!(member,GUIRange)[0].max; + } + else + { + comp_edit.variables[comp_edit.used-1].int_.min = 0; + comp_edit.variables[comp_edit.used-1].int_.max = int.max; + } + } + else + { + switch(member_type.sizeof) + { + case 1: comp_edit.variables[comp_edit.used++] = VariableGUI(VariableGUI.Type.byte_,member_str,offset);break; + case 2: comp_edit.variables[comp_edit.used++] = VariableGUI(VariableGUI.Type.short_,member_str,offset);break; + case 4: comp_edit.variables[comp_edit.used++] = VariableGUI(VariableGUI.Type.int_,member_str,offset);break; + default:break; + } + static if(hasUDA!(member,GUIRange)) + { + comp_edit.variables[comp_edit.used-1].int_.min = getUDAs!(member,GUIRange)[0].min; + comp_edit.variables[comp_edit.used-1].int_.max = getUDAs!(member,GUIRange)[1].max; + } + { + comp_edit.variables[comp_edit.used-1].int_.min = int.min; + comp_edit.variables[comp_edit.used-1].int_.max = int.max; + } + } + } + else static if(__traits(isScalar,member_type)) + { + switch(member_type.sizeof) + { + case 4:comp_edit.variables[comp_edit.used++] = VariableGUI(VariableGUI.Type.float_,member_str,offset);break; + case 8: + default:break; + } + static if(hasUDA!(member,GUIRange)) + { + comp_edit.variables[comp_edit.used-1].float_.min = getUDAs!(member,GUIRange)[0].minf; + comp_edit.variables[comp_edit.used-1].float_.max = getUDAs!(member,GUIRange)[1].maxf; + } + { + comp_edit.variables[comp_edit.used-1].float_.min = -float.max; + comp_edit.variables[comp_edit.used-1].float_.max = float.max; + } + } + } + edit_components[comp.component_id] = comp_edit; + } + void gui() { - if(igCollapsingHeader("Systems", ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_FramePadding)) + if(igCollapsingHeader("Systems", ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_DefaultOpen)) { bool true_ = true; igIndent(8); @@ -74,25 +205,177 @@ struct GUIManager } } - void toolGui() + static vec4 colorUintToVec4(uint color) { - if(templates.length) + // color = *cast(uint*)(comp_ptr+var.offset); + return vec4(cast(float)(color & 0xFF) / 255, + cast(float)(color >> 8 & 0xFF) / 255, + cast(float)(color >> 16 & 0xFF) / 255, + cast(float)(color >> 24 & 0xFF) / 255); + } + + static uint colorVec4ToUint(vec4 color) + { + return cast(uint)(color.x * 255) | + cast(uint)(color.y * 255) << 8 | + cast(uint)(color.z * 255) << 16 | + cast(uint)(color.w * 255) << 24; + } + + static bool igDragScalarClamp(const(char)* label, ImGuiDataType data_type, void* v, float v_speed, const(void)* v_min, const(void)* v_max, const(char)* format, float power) + { + ubyte[8] v_backup;// = *v; + final switch(data_type) { - if(igBeginCombo("Template",templates[selected_tempalte].name,0)) - { - foreach(i, tmpl; templates) - { - if(igSelectable(tmpl.name,false,0,ImVec2(0,0))) - { - selected_tempalte = cast(uint)i; - } - } - igEndCombo(); - } + case ImGuiDataType_S8:memcpy(v_backup.ptr, v, 1);break; + case ImGuiDataType_S16:memcpy(v_backup.ptr, v, 2);break; + case ImGuiDataType_S32:memcpy(v_backup.ptr, v, 4);break; + case ImGuiDataType_U8:memcpy(v_backup.ptr, v, 1);break; + case ImGuiDataType_U16:memcpy(v_backup.ptr, v, 2);break; + case ImGuiDataType_U32:memcpy(v_backup.ptr, v, 4);break; + case ImGuiDataType_Float:memcpy(v_backup.ptr, v, 4);break; } - else + if (!igDragScalar(label, data_type, v, v_speed, v_min, v_max, format, power)) + return false; + + final switch(data_type) { - if(igBeginCombo("Template",null,0))igEndCombo(); + case ImGuiDataType_S8: + if(*cast(byte*)v < *cast(byte*)v_min)*cast(byte*)v = *cast(byte*)v_min; + else if(*cast(byte*)v > *cast(byte*)v_max)*cast(byte*)v = *cast(byte*)v_max; + return *cast(byte*)v != *cast(byte*)v_backup.ptr; + case ImGuiDataType_S16: + if(*cast(short*)v < *cast(short*)v_min)*cast(short*)v = *cast(short*)v_min; + else if(*cast(short*)v > *cast(short*)v_max)*cast(short*)v = *cast(short*)v_max; + return *cast(short*)v != *cast(short*)v_backup.ptr; + case ImGuiDataType_S32: + if(*cast(int*)v < *cast(int*)v_min)*cast(int*)v = *cast(int*)v_min; + else if(*cast(int*)v > *cast(int*)v_max)*cast(int*)v = *cast(int*)v_max; + return *cast(int*)v != *cast(int*)v_backup.ptr; + case ImGuiDataType_U8: + if(*cast(ubyte*)v < *cast(ubyte*)v_min)*cast(ubyte*)v = *cast(ubyte*)v_min; + else if(*cast(ubyte*)v > *cast(ubyte*)v_max)*cast(ubyte*)v = *cast(ubyte*)v_max; + return *cast(ubyte*)v != *cast(ubyte*)v_backup.ptr; + case ImGuiDataType_U16: + if(*cast(ushort*)v < *cast(ushort*)v_min)*cast(ushort*)v = *cast(ushort*)v_min; + else if(*cast(ushort*)v > *cast(ushort*)v_max)*cast(ushort*)v = *cast(ushort*)v_max; + return *cast(ushort*)v != *cast(ushort*)v_backup.ptr; + case ImGuiDataType_U32: + if(*cast(uint*)v < *cast(uint*)v_min)*cast(uint*)v = *cast(uint*)v_min; + else if(*cast(uint*)v > *cast(uint*)v_max)*cast(uint*)v = *cast(uint*)v_max; + return *cast(uint*)v != *cast(uint*)v_backup.ptr; + case ImGuiDataType_Float: + if(*cast(float*)v < *cast(float*)v_min)*cast(float*)v = *cast(float*)v_min; + else if(*cast(float*)v > *cast(float*)v_max)*cast(float*)v = *cast(float*)v_max; + return *cast(float*)v != *cast(float*)v_backup.ptr; } } + + void entityComponentsGUI() + { + EntityTemplate* tmpl = templates[selected_tempalte].tmpl; + EntityManager.EntityInfo* info = tmpl.info; + void* data_ptr = tmpl.entity_data.ptr; + vec4 color; + foreach(comp_id; info.components) + { + if(comp_id >= edit_components.length)break; + void* comp_ptr = data_ptr + info.tmpl_deltas[comp_id]; + if(edit_components[comp_id].used) + { + if(igCollapsingHeader(edit_components[comp_id].name, ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_DefaultOpen)) + { + igIndent(8); + foreach(ref VariableGUI var;edit_components[comp_id].variables[0 .. edit_components[comp_id].used]) + { + switch(var.type) + { + case VariableGUI.Type.byte_: + igDragScalarClamp(var.name, ImGuiDataType_S8, comp_ptr+var.offset, 1, cast(void*)&var.int_.min, cast(void*)&var.int_.max, null, 1); + break; + case VariableGUI.Type.ubyte_: + igDragScalarClamp(var.name, ImGuiDataType_U8, comp_ptr+var.offset, 1, cast(void*)&var.int_.min, cast(void*)&var.int_.max, null, 1); + break; + case VariableGUI.Type.short_: + igDragScalarClamp(var.name, ImGuiDataType_S16, comp_ptr+var.offset, 1, cast(void*)&var.int_.min, cast(void*)&var.int_.max, null, 1); + break; + case VariableGUI.Type.ushort_: + igDragScalarClamp(var.name, ImGuiDataType_U16, comp_ptr+var.offset, 1, cast(void*)&var.int_.min, cast(void*)&var.int_.max, null, 1); + break; + case VariableGUI.Type.int_: + igDragScalarClamp(var.name, ImGuiDataType_S32, comp_ptr+var.offset, 1, cast(void*)&var.int_.min, cast(void*)&var.int_.max, null, 1); + break; + case VariableGUI.Type.uint_: + igDragScalarClamp(var.name, ImGuiDataType_U32, comp_ptr+var.offset, 1, cast(void*)&var.int_.min, cast(void*)&var.int_.max, null, 1); + break; + case VariableGUI.Type.float_: + igDragScalarClamp(var.name, ImGuiDataType_Float, comp_ptr+var.offset, 1, cast(void*)&var.float_.min, cast(void*)&var.float_.max, null, 1); + break; + case VariableGUI.Type.color: + color = colorUintToVec4(*cast(uint*)(comp_ptr+var.offset)); + if(igColorEdit4(var.name, color.data, ImGuiColorEditFlags_None)) + *cast(uint*)(comp_ptr+var.offset) = colorVec4ToUint(color); + break; + default:break; + } + } + igUnindent(8); + } + } + } + } + + void toolGui() + { + ImGuiStyle * style = igGetStyle(); + ImVec4 col = style.Colors[ImGuiCol_Header]; + style.Colors[ImGuiCol_Header] = style.Colors[ImGuiCol_TextSelectedBg]; + //style. + //ImDrawList* draw_list = igGetWindowDrawList(); + final switch(launcher.used_tool) + { + case Tool.entity_spawner: + if(templates.length) + { + { + if(igListBoxHeaderInt("Template",cast(int)templates.length,cast(int)templates.length)) + { + foreach(i, tmpl; templates) + { + if(igSelectable(tmpl.name,selected_tempalte == i,ImGuiSelectableFlags_AllowDoubleClick,ImVec2(0,0))) + { + selected_tempalte = cast(uint)i; + } + } + igListBoxFooter(); + } + } + } + style.Colors[ImGuiCol_Header] = col; + entityComponentsGUI(); + break; + case Tool.component_manipulator: + if(components.length) + { + if(igListBoxHeaderInt("Components",cast(int)components.length,cast(int)components.length)) + { + { + foreach(i, comp; components) + { + if(igSelectable(comp.name,selected_component == i,0,ImVec2(0,0))) + { + selected_component = cast(uint)i; + } + } + igListBoxFooter(); + } + } + } + break; + case Tool.selector: + break; + } + + style.Colors[ImGuiCol_Header] = col; + } } \ No newline at end of file diff --git a/demos/source/gui/tool_circle.d b/demos/source/gui/tool_circle.d new file mode 100644 index 0000000..c43ade3 --- /dev/null +++ b/demos/source/gui/tool_circle.d @@ -0,0 +1,52 @@ +module gui.tool_circle; + +import ecs_utils.gfx.buffer; +import ecs_utils.gfx.shader; +import ecs_utils.gfx.config; +import ecs_utils.gfx.renderer; + +import ecs_utils.math.vector; + +version(WebAssembly)import glad.gl.gles2; +else version(Android)import glad.gl.gles2; +else import glad.gl.gl; + +struct ToolCircle +{ + //Buffer vbo; + //Buffer ibo; + + uint material_id = 1; + uint mesh_id = 0; + + /*/void generate() + { + ushort[] + }*/ + + void draw(Renderer* renderer, vec2 position, float size, float edge = 1) + { + position = position * renderer.view_size + renderer.view_pos; + vec2 sizes = renderer.view_size * size; + vec2 sizes2 = vec2(edge,0); + + import core.stdc.string; + ubyte[32] uniform_block; + void* ptr = uniform_block.ptr; + *cast(float*)(ptr) = sizes.x; + *cast(float*)(ptr+4) = 0; + *cast(float*)(ptr+8) = 0; + *cast(float*)(ptr+12) = sizes.y; + memcpy(ptr+16,position.data.ptr,8); + memcpy(ptr+24,sizes2.data.ptr,8); + glEnableVertexAttribArray(0); + + GfxConfig.meshes[mesh_id].bind(); + GfxConfig.materials[material_id].bind(); + GfxConfig.materials[material_id].pushBindings(); + GfxConfig.materials[material_id].pushUniforms(uniform_block.ptr); + //glDisable(GL_DEPTH_TEST); + + glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_SHORT,null); + } +} \ No newline at end of file diff --git a/demos/utils/source/ecs_utils/gfx/buffer.d b/demos/utils/source/ecs_utils/gfx/buffer.d index bfdad62..76cab50 100644 --- a/demos/utils/source/ecs_utils/gfx/buffer.d +++ b/demos/utils/source/ecs_utils/gfx/buffer.d @@ -68,7 +68,7 @@ struct Buffer void map(BindTarget target) nothrow { bind(target); - version(Android){}else data.map_ptr = glMapBuffer(target,GL_WRITE_ONLY); + version(Android){}else version(WebAssembly){}else data.map_ptr = glMapBuffer(target,GL_WRITE_ONLY); } void map(uint offset, uint size, BindTarget target, uint flags = MapFlagBits.write | MapFlagBits.flush_explict | MapFlagBits.invalidate_buffer) nothrow diff --git a/demos/utils/source/ecs_utils/gfx/material.d b/demos/utils/source/ecs_utils/gfx/material.d index 1bde9c8..0fca5fb 100644 --- a/demos/utils/source/ecs_utils/gfx/material.d +++ b/demos/utils/source/ecs_utils/gfx/material.d @@ -78,6 +78,25 @@ struct Material void bind() nothrow { + final switch(data.blend_mode) + { + case BlendMode.mixed: + glDepthMask(0); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + break; + case BlendMode.opaque: + glDepthMask(1); + glDisable(GL_BLEND); + break; + case BlendMode.additive: + glDepthMask(0); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + //glBlendFunc(GL_ONE, GL_ONE); + break; + } + glUseProgram(data.modules[0].gl_handle); } diff --git a/demos/utils/source/ecs_utils/gfx/renderer.d b/demos/utils/source/ecs_utils/gfx/renderer.d index 93d009e..4e34b54 100644 --- a/demos/utils/source/ecs_utils/gfx/renderer.d +++ b/demos/utils/source/ecs_utils/gfx/renderer.d @@ -67,8 +67,10 @@ struct Renderer enum max_items = batch_size;//963; byte[] batch_vertices; ushort[] batch_indices; - void* memory; + void* memory = null; uint items = 0; + uint material_id; + uint texture_id; } Mutex* get_block_mutex; @@ -128,11 +130,11 @@ struct Renderer block_stack_mutex.unlock();*/ foreach(ref Thread thread; threads) { - foreach(VertexBlock block; thread.blocks) + foreach(VertexBlock block; thread.filled_blocks) { allocator.freeBlock(block.memory); } - thread.blocks.clear(); + thread.filled_blocks.clear(); } render_blocks = 0; current_block = 0; @@ -144,13 +146,13 @@ struct Renderer { foreach(ref Thread thread; threads) { - foreach(VertexBlock block; thread.blocks) + foreach(VertexBlock block; thread.filled_blocks) { uint items = block.items; if(items + item_id >= MaxObjects)items = MaxObjects - item_id; batch_vbo[0].bufferSubData(Buffer.BindTarget.array,items*4*14,item_id*4*14,block.batch_vertices.ptr); batch_ibo[0].bufferSubData(Buffer.BindTarget.element_array,items*2*6,item_id*2*6,block.batch_indices.ptr); - draw_list.add(DrawCall(item_id,items)); + draw_list.add(DrawCall(block.texture_id,block.material_id,item_id,items)); item_id += items; } //thread.blocks.clear(); @@ -173,8 +175,15 @@ struct Renderer foreach(i, ref Thread thread; threads) { //pushBlock(thread.block); - thread.blocks.add(thread.block); - thread.block = getBlock(); + foreach(ref block; thread.blocks) + { + if(block.items > 0) + { + thread.filled_blocks.add(block); + block.items = 0; + } + } + //thread.blocks = getBlock(); } } @@ -182,8 +191,8 @@ struct Renderer { //Vector!VertexBlock block; RenderData[] render_list; - VertexBlock block; - Vector!VertexBlock blocks; + VertexBlock[] blocks; + Vector!VertexBlock filled_blocks; } Thread[] threads; @@ -225,6 +234,8 @@ struct Renderer struct DrawCall { + uint texture_id; + uint material_id; uint start; uint count; } @@ -249,6 +260,7 @@ struct Renderer void initialize() { + import ecs_utils.gfx.config; //this.technique = __ecs_used_technique; __initialize(this); @@ -261,7 +273,8 @@ struct Renderer threads = Mallocator.makeArray!Thread(32); foreach(ref Thread thread;threads) { - thread.block = getBlock(); + //thread.blocks = getBlock(); + thread.blocks = Mallocator.makeArray!VertexBlock(GfxConfig.materials.length); } } @@ -494,12 +507,33 @@ struct Renderer private static void __draw_gl_vbo_batch(ref Renderer this_, Texture tex, vec2 pos, vec2 size, vec4 coords, short depth, uint color, float angle, uint material_id, uint mesh_id, uint thread_id = 0) { import ecs_utils.gfx.config; - short[3] mem = [depth, *cast(short*)&color, *(cast(short*)&color + 1)]; + //import core.stdc.string; with(this_) { //if(item_id >= MaxObjects)return; //pos += view_pos; + Thread* thread = &threads[thread_id]; + VertexBlock* block; + assert(thread.blocks.length > material_id); + block = &thread.blocks[material_id]; + if(block.items == 0) + { + thread.blocks[material_id] = getBlock(); + block = &thread.blocks[material_id]; + block.material_id = material_id; + } + else if(block.items >= VertexBlock.max_items) + { + //pushBlock(thread.block); + prepared_items += block.items; + thread.filled_blocks.add(*block); + thread.blocks[material_id] = getBlock(); + block = &thread.blocks[material_id]; + block.material_id = material_id; + } + + short[3] mem = [depth, *cast(short*)&color, *(cast(short*)&color + 1)]; pos.x = pos.x * view_size.x + view_pos.x; pos.y = pos.y * view_size.y + view_pos.y;//*/ @@ -513,8 +547,8 @@ struct Renderer memcpy(ptr+16,pos.data.ptr,8); memcpy(ptr+32,coords.data.ptr,16);*/ - short[] verts = cast(short[])threads[thread_id].block.batch_vertices; - uint item_id = threads[thread_id].block.items; + short[] verts = cast(short[])block.batch_vertices; + uint item_id = block.items; if(angle == 0) { @@ -619,7 +653,7 @@ struct Renderer uint ind_id = (item_id % batch_size)*4; - ushort[] indices = threads[thread_id].block.batch_indices; + ushort[] indices = block.batch_indices; indices[item_id*6] = cast(ushort)(GfxConfig.meshes[mesh_id].indices[0] + ind_id); indices[item_id*6+1] = cast(ushort)(GfxConfig.meshes[mesh_id].indices[1] + ind_id); @@ -634,14 +668,7 @@ struct Renderer //render_list[item_id].mesh_id = mesh_id; //data_index += 1;//data_offset; - threads[thread_id].block.items++; - if(threads[thread_id].block.items >= VertexBlock.max_items) - { - //pushBlock(threads[thread_id].block); - prepared_items += threads[thread_id].block.items; - threads[thread_id].blocks.add(threads[thread_id].block); - threads[thread_id].block = getBlock(); - } + block.items++; } } @@ -659,6 +686,7 @@ struct Renderer { glClearColor(0,0,0,0); glViewport(0,0,this_.resolution.x,this_.resolution.y); + glDepthMask(1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glDisable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST); @@ -828,9 +856,9 @@ struct Renderer //uint items = item_id/batch_size+1; foreach(i; 0..draw_list.length) { - if(material_id != render_list[i].material_id) + if(material_id != draw_list[i].material_id) { - material_id = render_list[i].material_id; + material_id = draw_list[i].material_id; GfxConfig.materials[material_id].bind(); float[3*4] data = [1,0,0,1,0,0,0,0,0,0,1,1]; GfxConfig.materials[material_id].pushUniforms(data.ptr); diff --git a/demos/utils/source/ecs_utils/math/vector.d b/demos/utils/source/ecs_utils/math/vector.d index a8f14f8..adb3a36 100644 --- a/demos/utils/source/ecs_utils/math/vector.d +++ b/demos/utils/source/ecs_utils/math/vector.d @@ -1,5 +1,7 @@ module ecs_utils.math.vector; +import ecs_utils.utils; + struct vec2 { this(float v) @nogc nothrow @@ -71,6 +73,26 @@ struct vec2 } else static assert(0, "Operator "~op~" not implemented"); } + + float length2() + { + return x*x + y*y; + } + + float length() + { + return sqrtf(length2); + } + + float fastSqrLength() + { + return rsqrt(length2); + } + + vec2 normalize() + { + return this * fastSqrLength(); + } } struct vec4 diff --git a/demos/utils/source/ecs_utils/utils.d b/demos/utils/source/ecs_utils/utils.d index 144d24f..da5453f 100644 --- a/demos/utils/source/ecs_utils/utils.d +++ b/demos/utils/source/ecs_utils/utils.d @@ -2,13 +2,24 @@ module ecs_utils.utils; extern(C): -int randomRange(int min, int max) +import ecs_utils.math.vector; + +enum PI = 3.141592653589793238462643383279502884197169399375105820; + +extern(C) float sqrtf(float x) @nogc nothrow @system; +extern(C) float acosf(float x) @nogc nothrow @system; +extern(C) float sinf(float x) @nogc nothrow @system; +extern(C) float cosf(float x) @nogc nothrow @system; +extern(C) float powf(float x, float y) @nogc nothrow @system; +extern(C) float fabs(float x) @nogc nothrow @system; + +int randomRange(int min, int max) nothrow @nogc @trusted { int range = max - min; return rand() % range - min; } -float randomf() +float randomf() nothrow @nogc @trusted { const float scale = 1.0 / 32_767.0; return cast(float)(rand() & 0x007FFF) * scale; @@ -21,6 +32,38 @@ float randomRangef(float min, float max) return rand()%4096; }*/ +float mix(float x, float y, float a) +{ + //return x*a + y*(a-1); + //return x*a + y*a - y; + return x*(a+y) - y; +} + +float rsqrt(float number) +{ + long i; + float x2, y; + const float threehalfs = 1.5F; + + x2 = number * 0.5F; + y = number; + i = * cast( long * ) &y; // evil floating point bit level hacking + i = 0x5f3759df - ( i >> 1 ); // what the fuck? + y = * cast( float * ) &i; + y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration + + return y; +} + +vec2 randomCircularSample() nothrow @nogc @trusted +{ + float angle = 2 * PI * randomf; + float radius = sqrtf(randomf); + float s = sinf(angle); + float c = cosf(angle); + return vec2(c,s)*radius; +} + version(GNU) { public import core.stdc.stdio : printf; @@ -34,7 +77,7 @@ else extern(C) int printf(scope const char* format, ...) @nogc nothrow @system; public import std.array : staticArray; } -extern(C) int rand(); +extern(C) int rand() nothrow @nogc @trusted; version(D_BetterC) {