bubel-ecs/demos/source/app.d
Mergul 3b954b732b -update README code example (to one that compile)
-remove Entity.instance and gEM, global manager is now gEntityManager
2021-03-02 19:44:18 +01:00

1453 lines
No EOL
54 KiB
D

module app;
import bindbc.sdl;
import cimgui.cimgui;
import game_core.basic;
import game_core.job_updater;
import bubel.ecs.core;
import bubel.ecs.manager;
import bubel.ecs.std;
import ecs_utils.gfx.renderer;
import ecs_utils.imgui_bind;
import ecs_utils.imgui_styles;
import ecs_utils.math.vector;
import ecs_utils.utils;
import glad.gl.gl;
import glad.gl.gles2;
import glad.gl.loader;
import gui.manager;
import gui.tool_circle;
extern (C) :
enum Tool
{
entity_spawner,
component_manipulator,
selector
}
__gshared const (char)*[3] tool_strings = ["Entity spawner", "Component manipulator", "Selector"];
struct Mouse
{
vec2 position;
bool left, right, middle;
}
struct DemoCallbacks
{
void function() register;
void function() initialize;
void function() deinitialize;
bool function() loop;
void function(SDL_Event*) event;
const (char)* tips;
}
struct Launcher
{
ECSJobUpdater* job_updater;
GUIManager* gui_manager;
ImGuiContext* context;
SDL_Window* window;
SDL_GLContext gl_context;
EntityManager* manager;
/*bool function() loop;
void function() end;
void function(SDL_Event*) event;*/
//void function(vec2, Tool, int, bool) tool;
float scalling;
ivec2 window_size = ivec2(1024,768);
Renderer renderer;
ubyte[] keys;
uint style = 3;
uint entities_count;
bool multithreading;
int threads = 1;
ulong timer_freq;
double delta_time;
uint fps;
vec2 render_position;
bool play = true;
Tool used_tool;
int tool_size = 100;
float tool_repeat = 0;
float repeat_time = 0;
bool tool_show = true;
bool override_ = true;
bool tool_mode = true;
ToolCircle* tool_circle;
bool show_filtered;
EntityID selected_entity;
bool swap_interval = true;
float windows_alpha = 0.75;
//const (char)* tips;
bool show_stat_wnd = true;
bool show_tips = true;
bool show_demo_wnd = true;
bool show_tools_wnd = true;
bool show_virtual_keys_wnd = false;
bool show_profile_wnd = true;
int plot_index;
PlotStruct[] plot_values;
Mouse mouse;
struct PlotStruct
{
float delta_time = 0;
float loop_time = 0;
float draw_time = 0;
}
double deltaTime()
{
return delta_time * play;
}
DemoCallbacks demo;
void switchDemo(DemoCallbacks callbacks)//void function() start, bool function() loop, void function() end, void function(SDL_Event*) event, const (char)* tips)
{
show_tips = true;
gui_manager.clear();
//launcher.ent
manager.begin();
manager.update("clean");
manager.end();
if(this.demo.deinitialize)this.demo.deinitialize();
foreach(ref system; manager.systems)
{
if(system.id != becsID!CountSystem && system.id != becsID!CleanSystem)system.disable();
}
/*launcher.manager.getSystem(becsID!CountSystem).enable();
launcher.manager.getSystem(becsID!CleanSystem).enable();//*/
if(callbacks.register)callbacks.register();
if(callbacks.initialize)callbacks.initialize();
demo = callbacks;
/*this.loop = loop;
this.end = end;
this.event = event;
this.tips = tips;*/
//this.tool = tool;
}
bool filterEntity(ref const Entity entity)
{
EntityMeta meta = entity.getMeta();
foreach(id;gui_manager.filter_list)
{
if(!meta.hasComponent(id))return false;
}
if(used_tool == Tool.component_manipulator)
{
if(!meta.hasComponent(gui_manager.getSelectedComponent().component_id))return false;
}
return true;
}
void processTool(vec2 position, bool mode)
{
static struct Iterator
{
float size2;
vec2 position;
ComponentRef[] add_comps;
ushort[] rem_comps;
ushort[] filter;
float distance = float.max;
bool filterEntity(ref const Entity entity)
{
EntityMeta meta = entity.getMeta();
foreach(id;filter)
{
if(!meta.hasComponent(id))return false;
}
return true;
}
void removeEntity(IteratorSystem.EntitiesData data)
{
if(!filterEntity(data.entity[0]))return;
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)gEntityManager.removeEntity(data.entity[i].id);
}
}
void addComponent(IteratorSystem.EntitiesData data)
{
if(!filterEntity(data.entity[0]))return;
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)gEntityManager.addComponents(data.entity[i].id, add_comps);
}
}
void overrideComponent(IteratorSystem.EntitiesData data)
{
if(!filterEntity(data.entity[0]))return;
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)
{
gEntityManager.removeComponents(data.entity[i].id, rem_comps);
gEntityManager.addComponents(data.entity[i].id, add_comps);
}
}
}
void removeComponent(IteratorSystem.EntitiesData data)
{
if(!filterEntity(data.entity[0]))return;
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)gEntityManager.removeComponents(data.entity[i].id, rem_comps);
}
}
void selectEntity(IteratorSystem.EntitiesData data)
{
if(!filterEntity(data.entity[0]))return;
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 < distance)
{
distance = length;
launcher.selected_entity = data.entity[i].id;
}
}
}
}
float half_size = tool_size * 0.5;
float size2 = half_size * half_size;
Iterator iterator;
iterator.size2 = size2;
iterator.position = position;
iterator.filter = gui_manager.filter_list[];
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;
if(launcher.override_)
{
ushort[1] rcomps = [gui_manager.getSelectedComponent().component_id];
iterator.rem_comps = rcomps;
manager.callEntitiesFunction!IteratorSystem(&iterator.overrideComponent);
}
else manager.callEntitiesFunction!IteratorSystem(&iterator.addComponent);
}
else
{
ushort[1] comps = [gui_manager.getSelectedComponent().component_id];
iterator.rem_comps = comps;
manager.callEntitiesFunction!IteratorSystem(&iterator.removeComponent);
}
}
break;
case Tool.selector:
iterator.distance = size2;
manager.callEntitiesFunction!IteratorSystem(&iterator.selectEntity);
break;
default:
break;
}
}
bool getKeyState(SDL_Scancode key)
{
if(keys[key])return true;
else return false;
}
void setStyle(uint index)
{
style = index;
.setStyle(index);
}
double getTime()
{
ulong local_freq = timer_freq / 1000_000;
//return cast(double)(SDL_GetPerformanceCounter() & 0x00FFFFFF) / timer_freq;
if(local_freq == 0)return cast(double)(SDL_GetPerformanceCounter() / timer_freq * 1000);
else return cast(double)(SDL_GetPerformanceCounter() / local_freq) / 1000;
}
}
__gshared Launcher launcher;
struct CountSystem
{
mixin ECS.System!1;
struct EntitiesData
{
uint length;
const (Entity)[] entity;
}
bool onBegin()
{
launcher.entities_count = 0;
return true;
}
void onUpdate(EntitiesData data)
{
launcher.entities_count += data.length;
}
}
struct CleanSystem
{
mixin ECS.System!64;
struct EntitiesData
{
uint length;
Entity[] entities;
}
void onUpdate(EntitiesData data)
{
foreach(i; 0..data.length)
{
launcher.manager.removeEntity(data.entities[i].id);
}
}
}
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;
launcher.delta_time = launcher.getTime() - time;
time = launcher.getTime();
if(launcher.delta_time > 1000)launcher.delta_time = 1000;
__gshared uint temp_fps = 0;
__gshared double fps_time = 0;
temp_fps++;
fps_time += launcher.delta_time;
while(fps_time > 1000)
{
fps_time -= 1000;
launcher.fps = temp_fps;
temp_fps = 0;
}
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL2_ProcessEvent(&event);
if(launcher.demo.event)launcher.demo.event(&event);
if (event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.scancode == SDL_SCANCODE_ESCAPE)) {
quit();
*cast(bool*)arg = false;
return;
}
else if(event.type == SDL_KEYDOWN)
{
if(event.key.state)
{
if(SDL_GetModState() & KMOD_CTRL)
{
switch(event.key.keysym.scancode)
{
case SDL_SCANCODE_1:launcher.used_tool=Tool.entity_spawner;break;
case SDL_SCANCODE_2:launcher.used_tool=Tool.component_manipulator;break;
case SDL_SCANCODE_3:launcher.used_tool=Tool.selector;break;
default:break;
}
}
else
{
switch(event.key.keysym.scancode)
{
case SDL_SCANCODE_1:break;
case SDL_SCANCODE_2:break;
case SDL_SCANCODE_3:break;
case SDL_SCANCODE_4:break;
default:break;
}
}
}
}
else if(event.type == SDL_WINDOWEVENT)
{
switch(event.window.event)
{
case SDL_WINDOWEVENT_RESIZED:
//launcher.renderer.resize(ivec2(event.window.data1,event.window.data2));
launcher.window_size = ivec2(event.window.data1,event.window.data2);
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
//launcher.renderer.resize(ivec2(event.window.data1,event.window.data2));
launcher.window_size = ivec2(event.window.data1,event.window.data2);
break;
default:break;
}
}
else if(event.type == SDL_MOUSEBUTTONDOWN)
{
switch(event.button.button)
{
case SDL_BUTTON_LEFT:launcher.mouse.left = true;break;
case SDL_BUTTON_RIGHT:launcher.mouse.right = true;break;
case SDL_BUTTON_MIDDLE:launcher.mouse.middle = true;break;
default:break;
}
if(!igIsAnyItemHovered())igSetWindowFocus();
if(!igIsWindowHovered(ImGuiHoveredFlags_AnyWindow) && !igIsWindowFocused(ImGuiFocusedFlags_AnyWindow))
{
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)
{
switch(event.button.button)
{
case SDL_BUTTON_LEFT:launcher.mouse.left = false;break;
case SDL_BUTTON_RIGHT:launcher.mouse.right = false;break;
case SDL_BUTTON_MIDDLE:launcher.mouse.middle = false;break;
default:break;
}
}
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 if(SDL_GetModState() & KMOD_SHIFT)
{
int sign = 1;
if(event.wheel.y < 0)sign = -1;
switch(launcher.used_tool)
{
case Tool.entity_spawner:
launcher.gui_manager.selectTemplate(launcher.gui_manager.selected_template-sign);
break;
case Tool.component_manipulator:
launcher.gui_manager.selectComponent(launcher.gui_manager.selected_component-sign);
break;
default:break;
}
}
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_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;
if(launcher.used_tool != Tool.entity_spawner || !mode)
{
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);
}
}
}
version(WebAssembly)
{
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame(launcher.window);
}
else
{
//ImGuiImplOpenGL2NewFrame();
ImGui_ImplOpenGL3_NewFrame();
ImGuiImplSDL2NewFrame(launcher.window);
}
igNewFrame();
if(igBeginMainMenuBar())
{
if(igBeginMenu("File",true))
{
if(igMenuItemBool("Close","esc",false,true))
{
quit();
*cast(bool*)arg = false;
return;
}
igEndMenu();
}
if(igBeginMenu("Demos",true))
{
if(igMenuItemBool("Simpe",null,false,true))
{
import demos.simple;
launcher.switchDemo(getSimpleDemo());//&simpleStart,&simpleLoop,&simpleEnd,&simpleEvent,Simple.tips);
}
if(igMenuItemBool("Snake",null,false,true))
{
import demos.snake;
launcher.switchDemo(getSnakeDemo());//&snakeStart,&snakeLoop,&snakeEnd,&snakeEvent,Snake.tips);
}
if(igMenuItemBool("Space Invaders",null,false,true))
{
import demos.space_invaders;
launcher.switchDemo(getSpaceInvadersDemo());//&spaceInvadersStart,&spaceInvadersLoop,&spaceInvadersEnd,&spaceInvadersEvent,SpaceInvaders.tips);
}
if(igMenuItemBool("Particles",null,false,true))
{
import demos.particles;
launcher.switchDemo(getParticlesDemo());//&particlesStart,&particlesLoop,&particlesEnd,&particlesEvent,ParticlesDemo.tips);
}
if(igMenuItemBool("Brick Breaker",null,false,true))
{
import demos.brick_breaker;
launcher.switchDemo(getBrickBreakerDemo());//&particlesStart,&particlesLoop,&particlesEnd,&particlesEvent,ParticlesDemo.tips);
}
if(igMenuItemBool("Sandbox",null,false,true))
{
import demos.sandbox;
launcher.switchDemo(getSanboxDemo());//&particlesStart,&particlesLoop,&particlesEnd,&particlesEvent,ParticlesDemo.tips);
}
igEndMenu();
}
if(igBeginMenu("Options",true))
{
if(igMenuItemBool("VSync", null, launcher.swap_interval, true))
{
launcher.swap_interval = !launcher.swap_interval;
SDL_GL_SetSwapInterval(launcher.swap_interval);
}
if(igMenuItemBool("Multithreading", null, launcher.multithreading, true))
{
launcher.multithreading = !launcher.multithreading;
if(launcher.multithreading)
{
launcher.job_updater.pool.setThreadsNum(launcher.threads);
}
else
{
launcher.job_updater.pool.setThreadsNum(1);
}
}
igSetNextItemWidth(0);
igLabelText("Threads:",null);
igSameLine(0,4);
if(igSliderInt("##Threads",&launcher.threads, 1, 32, null))//"Multithreading", null, launcher.multithreading, true))
{
launcher.job_updater.pool.setThreadsNum(launcher.threads);
//launcher.threads = !launcher.multithreading;
}
if(igBeginMenu("Show",true))
{
igMenuItemBoolPtr("Statistics",null,&launcher.show_stat_wnd,true);
igMenuItemBoolPtr("Demo",null,&launcher.show_demo_wnd,true);
igMenuItemBoolPtr("Tips",null,&launcher.show_tips,true);
igMenuItemBoolPtr("Virual keys",null,&launcher.show_virtual_keys_wnd,true);
igMenuItemBoolPtr("Profile",null,&launcher.show_profile_wnd,true);
igEndMenu();
}
if(igBeginMenu("Style",true))
{
if(igMenuItemBool("Classic",null,launcher.style == 0,true))
{
launcher.setStyle(0);
}
else if(igMenuItemBool("Dark",null,launcher.style == 1,true))
{
launcher.setStyle(1);
}
else if(igMenuItemBool("Light",null,launcher.style == 2,true))
{
launcher.setStyle(2);
}
else if(igMenuItemBool("Default",null,launcher.style == 3,true))
{
launcher.setStyle(3);
}
igEndMenu();
}
igEndMenu();
}
igEndMainMenuBar();
}
if(launcher.show_virtual_keys_wnd)
{
igSetNextWindowPos(ImVec2(launcher.window_size.x - 400, launcher.window_size.y - 200), ImGuiCond_Once, ImVec2(0,0));
igSetNextWindowSize(ImVec2(64*4+128, 168), ImGuiCond_Once);
igSetNextWindowBgAlpha(launcher.windows_alpha);
ImGuiStyle * style = igGetStyle();
style.Colors[ImGuiCol_Button].w = 0.8;
if(igBegin("Virtual keys",&launcher.show_virtual_keys_wnd, 0))
{
igColumns(2,null,0);
igSetColumnWidth(0,64*3+16);
igIndent(64+4);
if(igButton("W",ImVec2(64,64)) || igIsItemDeactivated())
{
launcher.keys[SDL_SCANCODE_W] = false;
}
else if(igIsItemActive())
{
launcher.keys[SDL_SCANCODE_W] = true;
}
igUnindent(64+4);
if(igButton("A",ImVec2(64,64)) || igIsItemDeactivated())
{
launcher.keys[SDL_SCANCODE_A] = false;
}
else if(igIsItemActive())
{
launcher.keys[SDL_SCANCODE_A] = true;
}
igSameLine(0,4);
if(igButton("S",ImVec2(64,64)) || igIsItemDeactivated())
{
launcher.keys[SDL_SCANCODE_S] = false;
}
else if(igIsItemActive())
{
launcher.keys[SDL_SCANCODE_S] = true;
}
igSameLine(0,4);
if(igButton("D",ImVec2(64,64)) || igIsItemDeactivated())
{
launcher.keys[SDL_SCANCODE_D] = false;
}
else if(igIsItemActive())
{
launcher.keys[SDL_SCANCODE_D] = true;
}
igNextColumn();
if(igButton("Space",ImVec2(-1,128)) || igIsItemDeactivated())
{
launcher.keys[SDL_SCANCODE_SPACE] = false;
}
else if(igIsItemActive())
{
launcher.keys[SDL_SCANCODE_SPACE] = true;
}
igColumns(1,null,0);
}
igEnd();
style.Colors[ImGuiCol_Button].w = 1.0;
}
if(launcher.show_tips)
{
igSetNextWindowPos(ImVec2(launcher.window_size.x /2 -250, 100), ImGuiCond_Once, ImVec2(0,0));
igSetNextWindowSize(ImVec2(500, -1), ImGuiCond_Once);
igSetNextWindowBgAlpha(0.95);
if(igBegin("Tips",&launcher.show_tips,ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings))
{
// igBeginChild("",ImVec2(0,0),0,0);
igTextWrapped(launcher.demo.tips);
// igEndChild();
}
igEnd();
}
if(launcher.show_demo_wnd)
{
igSetNextWindowPos(ImVec2(launcher.window_size.x - 260, 30), ImGuiCond_Once, ImVec2(0,0));
igSetNextWindowSize(ImVec2(250, 300), ImGuiCond_Once);
if(igBegin("Demo",&launcher.show_demo_wnd,0))
{
igCheckbox("Play",&launcher.play);
ImDrawList* draw_list = igGetWindowDrawList();
igBeginGroup();
launcher.gui_manager.gui();
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);
// igBeginGroup();
// if(igCollapsingHeader("Tool##ToolHeader", ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_DefaultOpen))
// {
// igIndent(8);
/*if(igBeginCombo("Tool",tool_strings[launcher.used_tool],0))
{
if(igSelectable("Entity spawner",false,0,ImVec2(0,0)))
{
launcher.used_tool = Tool.entity_spawner;
}
if(igSelectable("Component manipulator",false,0,ImVec2(0,0)))
{
launcher.used_tool = Tool.component_manipulator;
}
if(igSelectable("Selector",false,0,ImVec2(0,0)))
{
launcher.used_tool = Tool.selector;
}
igEndCombo();
}*/
/*if(igSelectable("Entity spawner",false,0,ImVec2(0,0)))
{
launcher.used_tool = Tool.entity_spawner;
}
if(igSelectable("Component manipulator",false,0,ImVec2(0,0)))
{
launcher.used_tool = Tool.component_manipulator;
}
if(igSelectable("Selector",false,0,ImVec2(0,0)))
{
launcher.used_tool = Tool.selector;
}*/
/*if(igBeginTabBar("Tool",ImGuiTabBarFlags_NoCloseWithMiddleMouseButton))
{
if(igIsItemHovered(0))igSetTooltip("Select tool (CTRL + 1,2,3)");
bool a = 1;
//this is used as hack to make CTRL+1/2/3 tab selection possible
static Tool prev_tool = Tool.entity_spawner;
bool different = prev_tool != launcher.used_tool;
Tool tool;
if(igBeginTabItem("Entity spawner", &a, launcher.used_tool == Tool.entity_spawner && different ? ImGuiTabItemFlags_SetSelected : 0))
{
tool = Tool.entity_spawner;
igEndTabItem();
}
if(igBeginTabItem("Component manipulator", &a, launcher.used_tool == Tool.component_manipulator && different ? ImGuiTabItemFlags_SetSelected : 0))
{
tool = Tool.component_manipulator;
igEndTabItem();
}
if(igBeginTabItem("Selector", &a, launcher.used_tool == Tool.selector && different ? ImGuiTabItemFlags_SetSelected : 0))
{
tool = Tool.selector;
igEndTabItem();
}
launcher.used_tool = tool;
prev_tool = launcher.used_tool;
}
igEndTabBar();
igCheckbox("Show Tool", &launcher.tool_show);
if(igIsItemHovered(0))igSetTooltip("Show/hide graphical tool representation");
igSameLine(0,4);
igCheckbox("Show Filtered", &launcher.show_filtered);
if(igIsItemHovered(0))igSetTooltip("Show/hide filtered entities");
if(launcher.used_tool == Tool.component_manipulator)
{
igCheckbox("Override", &launcher.override_);
}
//igSelectable("Selectabe",false,ImGuiSelectableFlags_None,ImVec2(0,0));
if(launcher.used_tool != Tool.selector)
{
if(igRadioButtonBool("Add", launcher.tool_mode))launcher.tool_mode = true;
if(igIsItemHovered(0))igSetTooltip("Tool should adding (Entities or components)");
igSameLine(0,4);
if(igRadioButtonBool("Remove", !launcher.tool_mode))launcher.tool_mode = false;
if(igIsItemHovered(0))igSetTooltip("Tool should removing (Entities or components)");
}
igSliderInt("Tool size", &launcher.tool_size, 0, 256, null);
igSliderFloat("Tool repeat", &launcher.tool_repeat, 0, 1024, null, 4);
launcher.gui_manager.toolGui();*/
// 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);
//igBeginGroup();
if(igCollapsingHeader("Filter", ImGuiTreeNodeFlags_SpanAvailWidth))
{
igIndent(8);
launcher.gui_manager.filterGUI();
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();
if(igButton("Clear",ImVec2(-1,0)))
{
launcher.manager.begin();
launcher.manager.update("clean");
launcher.manager.end();
}
}
igEnd();
}
if(launcher.show_tools_wnd)
{
igSetNextWindowPos(ImVec2(launcher.window_size.x - 300, 340), ImGuiCond_Once, ImVec2(0,0));
igSetNextWindowSize(ImVec2(300, launcher.window_size.y - 370), ImGuiCond_Once);
if(igBegin("Tools", &launcher.show_tools_wnd, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse))
{
if(igIsItemHovered(0))igSetTooltip("Select tool (CTRL + 1,2,3)");
if(igBeginTabBar("Tool",ImGuiTabBarFlags_NoCloseWithMiddleMouseButton))
{
bool a = 1;
//this is used as hack to make CTRL+1/2/3 tab selection possible
static Tool prev_tool = Tool.entity_spawner;
bool different = prev_tool != launcher.used_tool;
Tool tool;
if(igBeginTabItem("Entity spawner", &a, launcher.used_tool == Tool.entity_spawner && different ? ImGuiTabItemFlags_SetSelected : 0))
{
tool = Tool.entity_spawner;
igEndTabItem();
}
if(igBeginTabItem("Component manipulator", &a, launcher.used_tool == Tool.component_manipulator && different ? ImGuiTabItemFlags_SetSelected : 0))
{
tool = Tool.component_manipulator;
igEndTabItem();
}
if(igBeginTabItem("Selector", &a, launcher.used_tool == Tool.selector && different ? ImGuiTabItemFlags_SetSelected : 0))
{
tool = Tool.selector;
igEndTabItem();
}
launcher.used_tool = tool;
prev_tool = launcher.used_tool;
}
igEndTabBar();
igCheckbox("Show Tool", &launcher.tool_show);
if(igIsItemHovered(0))igSetTooltip("Show/hide graphical tool representation");
igSameLine(0,4);
igCheckbox("Show Filtered", &launcher.show_filtered);
if(igIsItemHovered(0))igSetTooltip("Show/hide filtered entities");
if(launcher.used_tool == Tool.component_manipulator)
{
igCheckbox("Override", &launcher.override_);
}
//igSelectable("Selectabe",false,ImGuiSelectableFlags_None,ImVec2(0,0));
if(launcher.used_tool != Tool.selector)
{
if(igRadioButtonBool("Add", launcher.tool_mode))launcher.tool_mode = true;
if(igIsItemHovered(0))igSetTooltip("Tool should adding (Entities or components)");
igSameLine(0,4);
if(igRadioButtonBool("Remove", !launcher.tool_mode))launcher.tool_mode = false;
if(igIsItemHovered(0))igSetTooltip("Tool should removing (Entities or components)");
}
igSliderInt("Tool size", &launcher.tool_size, 0, 256, null);
igSliderFloat("Tool repeat", &launcher.tool_repeat, 0, 1024, null, 4);
if(igBeginChild("",ImVec2(0,0),1,0))
{
launcher.gui_manager.toolGui();
}
igEndChild();
}
igEnd();
}
if(launcher.show_profile_wnd)
{
//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))
{
if(igBeginTabBar("ProfileTabBar",ImGuiTabBarFlags_FittingPolicyScroll))
{
if(igBeginTabItem("Plots", null, 0))
{
if(igBeginChild("ProfileChild",ImVec2(-1,-1),0,0))
{
igPlotLines("Delta time",&launcher.plot_values[0].delta_time,100,launcher.plot_index,"Delta time",0,float.max,ImVec2(0,64),Launcher.PlotStruct.sizeof);
igPlotLines("Loop time",&launcher.plot_values[0].loop_time,100,launcher.plot_index,"Loop time",0,float.max,ImVec2(0,64),Launcher.PlotStruct.sizeof);
igPlotLines("Draw time",&launcher.plot_values[0].draw_time,100,launcher.plot_index,"Draw time",0,float.max,ImVec2(0,64),Launcher.PlotStruct.sizeof);
}
igEndChild();
igEndTabItem();
}
if(igBeginTabItem("Multithreading graph", null, 0))
{
if(igBeginChild("ProfileChild",ImVec2(-1,-1),0,0))
{
igText("Work in proggress");
}
igEndChild();
igEndTabItem();
}
igEndTabBar();
}
}
igEnd();
}
launcher.renderer.resize(launcher.window_size);
//launcher.renderer.view(vec2(0,0),vec2(launcher.window_size.x,launcher.window_size.y));
//if(384, 768, 1152, 1536)
//576 960 1344 1728
//float scalling;
if(launcher.window_size.y < 360)launcher.scalling = 1;
else launcher.scalling = 1.0 / ((launcher.window_size.y+120)/360);
launcher.renderer.view(launcher.render_position,vec2(launcher.window_size.x,launcher.window_size.y)*launcher.scalling);
//launcher.renderer.view(vec2(0,0),vec2(1024*launcher.window_size.x/launcher.window_size.y,768));
//glClear(GL_COLOR_BUFFER_BIT);
launcher.renderer.clear();
double loop_time = launcher.getTime();
launcher.job_updater.pool.tryWaitCount = 10000;
if(launcher.play)
{
if(launcher.demo.loop && !launcher.demo.loop())
{
quit();
*cast(bool*)arg = false;
}
}
else
{
launcher.manager.begin();
import game_core.rendering;
launcher.manager.callEntitiesFunction!DrawSystem(&(launcher.manager.getSystem!DrawSystem).onUpdate);
launcher.manager.end();
}
launcher.job_updater.pool.tryWaitCount = 0;
loop_time = launcher.getTime() - loop_time;
double draw_time = launcher.getTime();
launcher.renderer.present();
draw_time = launcher.getTime() - draw_time;
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;
plot_samples++;
launcher.plot_values[100].delta_time += launcher.delta_time;
launcher.plot_values[100].loop_time += loop_time;
launcher.plot_values[100].draw_time += draw_time;
if(plot_time > 100)
{
launcher.plot_values[launcher.plot_index].delta_time = launcher.plot_values[100].delta_time / cast(float)plot_samples;
launcher.plot_values[launcher.plot_index].loop_time = launcher.plot_values[100].loop_time / cast(float)plot_samples;
launcher.plot_values[launcher.plot_index].draw_time = launcher.plot_values[100].draw_time / cast(float)plot_samples;
launcher.plot_values[100].delta_time = 0;
launcher.plot_values[100].loop_time = 0;
launcher.plot_values[100].draw_time = 0;
plot_samples = 0;
plot_time -= 100;
launcher.plot_index++;
if(launcher.plot_index >= 100)launcher.plot_index = 0;
}
if(launcher.show_stat_wnd)
{
igSetNextWindowPos(ImVec2(10, 30), ImGuiCond_Appearing, ImVec2(0,0));
igSetNextWindowContentSize(ImVec2(150, 0.0f));
igSetNextWindowBgAlpha(launcher.windows_alpha);
if(igBegin("Statistics", &launcher.show_stat_wnd, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize))
{
igColumns(2,null,0);
igSetColumnWidth(0,100);
igText("FPS: ");
igText("Entities: ");
igText("Loop time: ");
igText("Draw time: ");
igText("Delta time: ");
igNextColumn();
igText("%u",launcher.fps);
igText("%u",launcher.entities_count);
igText("%2.2fms",loop_time);
igText("%2.2fms",draw_time);
igText("%2.2fms",launcher.delta_time);
igColumns(1,null,0);
}
igEnd();
}
glUseProgram(0);
import ecs_utils.gfx.buffer;
Buffer.unbind(Buffer.BindTarget.array);
Buffer.unbind(Buffer.BindTarget.element_array);
igRender();
version(WebAssembly)ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData());
else version(Android)ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData());
else ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData());
//ImGuiImplOpenGL2RenderDrawData(igGetDrawData());
//launcher.renderer.clear();
//launcher.renderer.present();
SDL_GL_SwapWindow(launcher.window);
}
void quit()
{
import game_core.rendering : TexCoordsManager;
launcher.gui_manager.clear();
Mallocator.dispose(launcher.gui_manager);
if(launcher.demo.deinitialize)launcher.demo.deinitialize();
launcher.manager.destroy();
launcher.manager = null;
TexCoordsManager.destroy();
SDL_Quit();
version(WebAssembly)emscripten_cancel_main_loop();
}
version(Android)
{
export extern (C) int SDL_main(int argc, char** args)
{
return app_main(argc,args);
}
import ldc.attributes;
extern (C) __gshared
{
@section(".tdata")
int _tlsstart = 0;
@section(".tcommon")
int _tlsend = 0;
}
}
else
{
extern (C) int main(int argc, char** argv)
{
return app_main(argc,argv);
}
}
int app_main(int argc, char** argv)
//int main(int argc, char** argv)
{
version(BindSDL_Static){}
else
{
loadSDL();
loadSDLImage();
}
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL_Error: %s", SDL_GetError());
return -1;
}
SDL_version sdl_version;
SDL_GetVersion(&sdl_version);
printf("SDL version: %u.%u.%u\n",cast(uint)sdl_version.major,cast(uint)sdl_version.minor,cast(uint)sdl_version.patch);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
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);
launcher.timer_freq = SDL_GetPerformanceFrequency();
launcher.plot_values = Mallocator.makeArray!(Launcher.PlotStruct)(101);
SDL_GetWindowSize(launcher.window, &launcher.window_size.x, &launcher.window_size.y);
version(WebAssembly)
{
gladLoadGLES2(x => SDL_GL_GetProcAddress(x));
if(!ImGui_ImplSDL2_InitForOpenGL(launcher.window,launcher.gl_context))
{
printf("ImGui initialization failed!");
return -2;
}
if(!ImGui_ImplOpenGL3_Init())
{
printf("ImGui OpenGL initialization failed!");
return -3;
}
}
else version(Android)
{
//gladLoadGL();
gladLoadGLES2(x => SDL_GL_GetProcAddress(x));
if(!ImGuiImplSDL2InitForOpenGL(launcher.window,launcher.gl_context))
{
printf("ImGui initialization failed!");
return -2;
}
if(!ImGui_ImplOpenGL3_Init("#version 100"))
{
printf("ImGui OpenGL initialization failed!");
return -3;
}
}
else
{
gladLoadGL();
if(!ImGuiImplSDL2InitForOpenGL(launcher.window,launcher.gl_context))
{
printf("ImGui initialization failed!");
return -2;
}
//if(!ImGuiImplOpenGL2Init())
if(!ImGui_ImplOpenGL3_Init("#version 120"))
{
printf("ImGui OpenGL initialization failed!");
return -3;
}
}
//ImFontConfig* config = ImFontConfig_ImFontConfig();
ImGuiIO* io = igGetIO();
const ushort* font_ranges = ImFontAtlas_GetGlyphRangesDefault(io.Fonts);
ImFontAtlas_AddFontFromFileTTF(io.Fonts,"assets/fonts/Ruda-Bold.ttf", 15.0f, null, font_ranges);
//ImFontConfig_destroy(config);
setStyle(3);
launcher.job_updater = Mallocator.make!ECSJobUpdater(1);
//launcher.job_updater.onCreate();
EntityManager.initialize(32, 1<<16);
launcher.manager = gEntityManager;
//launcher.manager.m_thread_id_func = &launcher.job_updater.getThreadID;
//launcher.manager.setJobDispachFunc(&launcher.job_updater.dispatch);
launcher.manager.setMultithreadingCallbacks(&launcher.job_updater.dispatch, &launcher.job_updater.getThreadID);
launcher.manager.beginRegister();
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();
loadGFX();
launcher.renderer.initialize();
import game_core.rendering : TexCoordsManager;
TexCoordsManager.initialize();
import mmutils.thread_pool : ThreadPool;
launcher.threads = ThreadPool.getCPUCoresCount();
if(launcher.threads < 2)launcher.threads = 2;
launcher.gui_manager = Mallocator.make!GUIManager();
{
import demos.simple;
import demos.space_invaders;
import demos.particles;
import demos.brick_breaker;
// launcher.switchDemo(&spaceInvadersStart,&spaceInvadersLoop,&spaceInvadersEnd,&spaceInvadersEvent,SpaceInvaders.tips);
// launcher.switchDemo(&particlesStart,&particlesLoop,&particlesEnd,&particlesEvent,ParticlesDemo.tips);
// launcher.switchDemo(&simpleStart,&simpleLoop,&simpleEnd,&simpleEvent,Simple.tips);
// launcher.switchDemo(getParticlesDemo());
// launcher.switchDemo(getSimpleDemo());
launcher.switchDemo(getSimpleDemo());
}
int key_num;
ubyte* keys = SDL_GetKeyboardState(&key_num);
launcher.keys = keys[0..key_num];
version(WebAssembly)
{
/*EmscriptenFullscreenStrategy strategy;
strategy.scaleMode = EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH;
strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_NEAREST;*/
//int result = emscripten_request_fullscreen_strategy(null, true, &strategy);
//emscripten_enter_soft_fullscreen(null, &strategy);
//printf("Fullscreen request: %s.\n", emscripten_result_to_string(result));
emscripten_set_main_loop_arg(&mainLoop, null, 0, 1);
}
else
{
bool arg = true;
while(arg == true)
{
mainLoop(&arg);
}
}
return 0;
}
void loadGFX()
{
import ecs_utils.gfx.texture;
import ecs_utils.gfx.vertex;
import ecs_utils.gfx.shader;
import ecs_utils.gfx.material;
import ecs_utils.gfx.config;
import ecs_utils.gfx.mesh;
Texture.__loadBackend();
Renderer.__loadBackend();
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];
GfxConfig.meshes[0].vertices = Mallocator.makeArray(vertices);
ushort[6] indices = [0,1,2,1,2,3];
GfxConfig.meshes[0].indices = Mallocator.makeArray(indices);
GfxConfig.meshes[0].uploadData();
Shader vsh;
vsh.create();
vsh.load("assets/shaders/base.vp");
vsh.compile();
Shader fsh;
fsh.create();
fsh.load("assets/shaders/base.fp");
fsh.compile();
GfxConfig.materials[0].create();
GfxConfig.materials[0].data.blend_mode = Material.BlendMode.opaque;
GfxConfig.materials[0].data.mode = Material.TransformMode.position;
Material.ShaderModule[1] modules = [Material.ShaderModule(vsh,fsh)];
GfxConfig.materials[0].attachModules(modules);
//GfxConfig.materials[0].
//GfxConfig.materials[0].load(load_data.materials[i].str);
GfxConfig.materials[0].compile();
GfxConfig.materials[0].bindAttribLocation("positions",0);
GfxConfig.materials[0].bindAttribLocation("tex_coords",1);
GfxConfig.materials[0].bindAttribLocation("depth",2);
GfxConfig.materials[0].bindAttribLocation("vcolor",3);
GfxConfig.materials[0].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[0].data.uniforms = Mallocator.makeArray!(Material.Uniform)(3);
GfxConfig.materials[0].data.uniforms[0] = Material.Uniform(Material.Type.float4, GfxConfig.materials[0].getLocation("matrix_1"), 0);
GfxConfig.materials[0].data.uniforms[1] = Material.Uniform(Material.Type.float4, GfxConfig.materials[0].getLocation("matrix_2"), 16);
GfxConfig.materials[0].data.uniforms[2] = Material.Uniform(Material.Type.float4, GfxConfig.materials[0].getLocation("uv_transform"), 32);
GfxConfig.materials[0].data.bindings = Mallocator.makeArray!(int)(1);
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");
Shader vsh3;
vsh3.create();
vsh3.load("assets/shaders/additive_particles.vp");
vsh3.compile();
Shader fsh3;
fsh3.create();
fsh3.load("assets/shaders/additive_particles.fp");
fsh3.compile();
GfxConfig.materials[2].create();
GfxConfig.materials[2].data.blend_mode = Material.BlendMode.opaque;
GfxConfig.materials[2].data.mode = Material.TransformMode.position;
Material.ShaderModule[1] modules3 = [Material.ShaderModule(vsh3,fsh3)];
GfxConfig.materials[2].attachModules(modules3);
//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;
}