diff --git a/doc/tutorial/08_fbo.cpp b/doc/tutorial/08_fbo.cpp index 64e127e6..09a545ef 100644 --- a/doc/tutorial/08_fbo.cpp +++ b/doc/tutorial/08_fbo.cpp @@ -39,12 +39,13 @@ public: WorldEntity::TickGame(seconds); m_time += seconds; - m_hotspot = 0.4f * vec3(lol::sin(m_time * 4.f) + lol::cos(m_time * 5.3f), - lol::sin(m_time * 5.7f) + lol::cos(m_time * 4.4f), - lol::sin(m_time * 5.f)); - m_color = 0.25f * vec3(1.1f + lol::sin(m_time * 2.5f + 1.f), - 1.1f + lol::sin(m_time * 2.8f + 1.3f), - 1.1f + lol::sin(m_time * 2.7f)); + m_hotspot = 0.4f * vec3( + lol::sin((float)m_time * 4.f) + lol::cos((float)m_time * 5.3f), + lol::sin((float)m_time * 5.7f) + lol::cos((float)m_time * 4.4f), + lol::sin((float)m_time * 5.f)); + m_color = 0.25f * vec3(1.1f + lol::sin((float)m_time * 2.5f + 1.f), + 1.1f + lol::sin((float)m_time * 2.8f + 1.3f), + 1.1f + lol::sin((float)m_time * 2.7f)); /* Saturate dot color */ float x = std::max(m_color.x, std::max(m_color.y, m_color.z)); m_color /= x; diff --git a/doc/tutorial/13_shader_builder.cpp b/doc/tutorial/13_shader_builder.cpp index d5af6952..2f064217 100644 --- a/doc/tutorial/13_shader_builder.cpp +++ b/doc/tutorial/13_shader_builder.cpp @@ -45,58 +45,63 @@ public: ShaderBlock green_pixel("GreenPixel"); ShaderBlock blue_pixel("BluePixel"); - String vertex_out = Shader::GetProgramOutVariableLocal(ShaderProgram::Vertex); - String pixel_out = Shader::GetProgramOutVariableLocal(ShaderProgram::Pixel); - - String in_position = Shader::GetVariablePrefix(ShaderVariable::Attribute) + "position"; - String in_color = Shader::GetVariablePrefix(ShaderVariable::Attribute) + "color"; - String pass_color = Shader::GetVariablePrefix(ShaderVariable::Varying) + "color"; - - nothing_vertex.Add(ShaderVariable::Attribute, "vec3", "position"); - nothing_vertex.Add(ShaderVariable::Attribute, "vec4", "color"); - nothing_vertex.Add(ShaderVariable::Varying, "vec4", "color"); - nothing_vertex.Add(ShaderVariable::InOut, "vec4", vertex_out); - nothing_vertex.SetMainCode( - String(" ") + pass_color + " = " + in_color + ";\n" + - String(" ") + vertex_out + " = vec4(" + in_position + ", 0.f);\n" + ShaderVar out_vertex = ShaderVar::GetShaderOut(ShaderProgram::Vertex); + ShaderVar out_pixel = ShaderVar::GetShaderOut(ShaderProgram::Pixel); + + ShaderVar in_position = ShaderVar(ShaderVariable::Attribute, ShaderVariableType::Vec3, "position"); + ShaderVar in_color = ShaderVar(ShaderVariable::Attribute, ShaderVariableType::Vec4, "color"); + ShaderVar pass_color = ShaderVar(ShaderVariable::Varying, ShaderVariableType::Vec4, "color"); + + nothing_vertex << in_position + << in_color + << pass_color; + nothing_vertex.AddVar(out_vertex); + nothing_vertex.SetMainCode(String() + + Line(pass_color + " = " + in_color + ";") + + Line(out_vertex + " = vec4(" + in_position + ", 0.f);") ); - red_pixel.Add(ShaderVariable::Varying, "vec4", "color"); - red_pixel.Add(ShaderVariable::InOut, "vec4", pixel_out); - red_pixel.Add(ShaderVariable::InOut, "vec4", "ambient"); - red_pixel.SetMainCode( - String(" ") + pixel_out + " = " + pass_color + ";\n" + - String(" ") + pixel_out + ".r = 1.0;\n" + - String(" ") + "ambient = vec4(1.0);\n" + ShaderVar ambient = ShaderVar(ShaderVariable::InOut, ShaderVariableType::Vec4, "ambient"); + + red_pixel.AddVar(pass_color); + red_pixel.AddVar(out_pixel); + red_pixel.AddVar(ambient); + red_pixel.SetMainCode(String() + + out_pixel + " = " + pass_color + ";\n" + + out_pixel + ".r = 1.0;\n" + + "ambient = vec4(1.0);\n" ); - green_pixel.Add(ShaderVariable::Varying, "vec4", "color"); - green_pixel.Add(ShaderVariable::InOut, "vec4", pixel_out); - green_pixel.Add(ShaderVariable::InOut, "vec4", "ambient"); - green_pixel.SetMainCode( - String(" ") + pixel_out + " = " + pass_color + ";\n" + - String(" ") + pixel_out + ".g = 1.0;\n" + - String(" ") + "ambient.r = 0.0;\n" + green_pixel.AddVar(pass_color); + green_pixel.AddVar(out_pixel); + green_pixel.AddVar(ambient); + green_pixel.SetMainCode(String() + + out_pixel + " = " + pass_color + ";\n" + + out_pixel + ".g = 1.0;\n" + + "ambient.r = 0.0;\n" ); - blue_pixel.Add(ShaderVariable::Varying, "vec4", "color"); - blue_pixel.Add(ShaderVariable::InOut, "vec4", pixel_out); - blue_pixel.Add(ShaderVariable::InOut, "vec4", "ambient"); - blue_pixel.SetCustomCode( - String("void SetAmbient(inout vec4 ambient)\n{\n ambient = vec4(1.0, 1.0, 1.0, 1.0);\n}")); - blue_pixel.SetMainCode( - String(" ") + pixel_out + " = " + pass_color + ";\n" + - String(" ") + pixel_out + ".b = 1.0;\n" + - String(" ") + "SetAmbient(ambient);\n" + - String(" ") + pixel_out + " *= ambient;\n" + blue_pixel.AddVar(pass_color); + blue_pixel.AddVar(out_pixel); + blue_pixel.AddVar(ambient); + blue_pixel.SetCustomCode(String() + + "void SetAmbient(inout vec4 ambient)\n" + + "{\n" + + " ambient = vec4(1.0, 1.0, 1.0, 1.0);\n" + + "}\n"); + blue_pixel.SetMainCode(String() + + out_pixel + " = " + pass_color + ";\n" + + out_pixel + ".b = 1.0;\n" + + "SetAmbient(ambient);\n" + + out_pixel + " *= ambient;\n" ); builder << ShaderProgram::Vertex - << ¬hing_vertex + << nothing_vertex << ShaderProgram::Pixel - << &red_pixel - << &green_pixel - << &blue_pixel; + << red_pixel + << green_pixel + << blue_pixel; builder.Build(code); diff --git a/src/gpu/shader.cpp b/src/gpu/shader.cpp index e1023d07..4c61bd92 100644 --- a/src/gpu/shader.cpp +++ b/src/gpu/shader.cpp @@ -442,7 +442,7 @@ Shader::Shader(String const &name, int Shader::GetAttribCount() const { - return data->attrib_locations.count(); + return (int)data->attrib_locations.count(); } ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const @@ -469,6 +469,10 @@ ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const return ret; } +ShaderUniform Shader::GetUniformLocation(String const& uni) const +{ + return GetUniformLocation(uni.C()); +} ShaderUniform Shader::GetUniformLocation(char const *uni) const { ShaderUniform ret; @@ -514,7 +518,7 @@ void Shader::SetUniform(ShaderUniform const &uni, int i) #if defined USE_D3D9 || defined _XBOX SetUniform(uni, ivec4(i, 0, 0, 0)); #else - glUniform1i(uni.frag, i); + glUniform1i((GLint)uni.frag, i); #endif } @@ -523,7 +527,7 @@ void Shader::SetUniform(ShaderUniform const &uni, ivec2 const &v) #if defined USE_D3D9 || defined _XBOX SetUniform(uni, ivec4(v, 0, 0)); #else - glUniform2i(uni.frag, v.x, v.y); + glUniform2i((GLint)uni.frag, v.x, v.y); #endif } @@ -532,7 +536,7 @@ void Shader::SetUniform(ShaderUniform const &uni, ivec3 const &v) #if defined USE_D3D9 || defined _XBOX SetUniform(uni, ivec4(v, 0)); #else - glUniform3i(uni.frag, v.x, v.y, v.z); + glUniform3i((GLint)uni.frag, v.x, v.y, v.z); #endif } @@ -544,7 +548,7 @@ void Shader::SetUniform(ShaderUniform const &uni, ivec4 const &v) if (uni.flags & 2) data->m_dev->SetVertexShaderConstantI((UINT)uni.vert, &v[0], 1); #else - glUniform4i(uni.frag, v.x, v.y, v.z, v.w); + glUniform4i((GLint)uni.frag, v.x, v.y, v.z, v.w); #endif } @@ -553,7 +557,7 @@ void Shader::SetUniform(ShaderUniform const &uni, float f) #if defined USE_D3D9 || defined _XBOX SetUniform(uni, vec4(f, 0, 0, 0)); #else - glUniform1f(uni.frag, f); + glUniform1f((GLint)uni.frag, f); #endif } @@ -562,7 +566,7 @@ void Shader::SetUniform(ShaderUniform const &uni, vec2 const &v) #if defined USE_D3D9 || defined _XBOX SetUniform(uni, vec4(v, 0, 0)); #else - glUniform2fv(uni.frag, 1, &v[0]); + glUniform2fv((GLint)uni.frag, 1, &v[0]); #endif } @@ -571,7 +575,7 @@ void Shader::SetUniform(ShaderUniform const &uni, vec3 const &v) #if defined USE_D3D9 || defined _XBOX SetUniform(uni, vec4(v, 0)); #else - glUniform3fv(uni.frag, 1, &v[0]); + glUniform3fv((GLint)uni.frag, 1, &v[0]); #endif } @@ -583,7 +587,7 @@ void Shader::SetUniform(ShaderUniform const &uni, vec4 const &v) if (uni.flags & 2) data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &v[0], 1); #else - glUniform4fv(uni.frag, 1, &v[0]); + glUniform4fv((GLint)uni.frag, 1, &v[0]); #endif } @@ -596,7 +600,7 @@ void Shader::SetUniform(ShaderUniform const &uni, mat2 const &m) if (uni.flags & 2) data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 1); #else - glUniformMatrix2fv(uni.frag, 1, GL_FALSE, &m[0][0]); + glUniformMatrix2fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]); #endif } @@ -611,7 +615,7 @@ void Shader::SetUniform(ShaderUniform const &uni, mat3 const &m) if (uni.flags & 2) data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &tmp[0][0], 3); #else - glUniformMatrix3fv(uni.frag, 1, GL_FALSE, &m[0][0]); + glUniformMatrix3fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]); #endif } @@ -623,7 +627,7 @@ void Shader::SetUniform(ShaderUniform const &uni, mat4 const &m) if (uni.flags & 2) data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 4); #else - glUniformMatrix4fv(uni.frag, 1, GL_FALSE, &m[0][0]); + glUniformMatrix4fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]); #endif } @@ -658,7 +662,7 @@ void Shader::SetUniform(ShaderUniform const &uni, array const &v) data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &v[0], v.Count() / 4); #else - glUniform1fv(uni.frag, v.Count(), &v[0]); + glUniform1fv((GLint)uni.frag, (GLsizei)v.Count(), &v[0]); #endif } @@ -674,7 +678,7 @@ void Shader::SetUniform(ShaderUniform const &uni, array const &v) data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &v[0][0], v.Count() / 2); #else - glUniform2fv(uni.frag, v.Count(), &v[0][0]); + glUniform2fv((GLint)uni.frag, (GLsizei)v.Count(), &v[0][0]); #endif } @@ -690,7 +694,7 @@ void Shader::SetUniform(ShaderUniform const &uni, array const &v) data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &v[0][0], v.Count()); #else - glUniform3fv(uni.frag, v.Count(), &v[0][0]); + glUniform3fv((GLint)uni.frag, (GLsizei)v.Count(), &v[0][0]); #endif } @@ -704,7 +708,7 @@ void Shader::SetUniform(ShaderUniform const &uni, array const &v) data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &v[0][0], v.Count()); #else - glUniform4fv(uni.frag, v.Count(), &v[0][0]); + glUniform4fv((GLint)uni.frag, (GLsizei)v.Count(), &v[0][0]); #endif } @@ -934,6 +938,9 @@ String ShaderData::Patch(String const &code, ShaderType type) } static const String g_ret = "\n"; +static const String g_eol = ";"; +static const String g_bop = "{"; +static const String g_bcl = "}"; static const String g_tab = " "; //---- @@ -1008,7 +1015,7 @@ String Shader::GetProgramQualifier(const ShaderProgram program) { switch (program.ToScalar()) { - case ShaderProgram::Geometry: return String(); //TODO : L O L ---------------- + case ShaderProgram::Geometry: return String(); //TODO : L O L --------- case ShaderProgram::Vertex: return String("[vert.glsl]"); case ShaderProgram::Pixel: return String("[frag.glsl]"); default: return String(); @@ -1020,7 +1027,7 @@ String Shader::GetProgramOutVariable(const ShaderProgram program) { switch (program.ToScalar()) { - case ShaderProgram::Geometry: return String(); //TODO : L O L ---------------- + case ShaderProgram::Geometry: return String(); //TODO : L O L --------- case ShaderProgram::Vertex: return String("gl_Position"); case ShaderProgram::Pixel: return String("gl_FragColor"); default: return String(); @@ -1032,29 +1039,44 @@ String Shader::GetProgramOutVariableLocal(const ShaderProgram program) { switch (program.ToScalar()) { - case ShaderProgram::Geometry: return String(); //TODO : L O L ---------------- + case ShaderProgram::Geometry: return String(); //TODO : L O L --------- case ShaderProgram::Vertex: return String("out_position"); case ShaderProgram::Pixel: return String("out_frag_color"); default: return String(); } } +//ShaderVar ------------------------------------------------------------------- +ShaderVar ShaderVar::GetShaderOut(ShaderProgram program) +{ + switch (program.ToScalar()) + { + case ShaderProgram::Geometry: //TODO : L O L ------------------------------ + default: ASSERT(false); return ShaderVar(); + case ShaderProgram::Vertex: return ShaderVar(ShaderVariable::InOut, ShaderVariableType::Vec4, Shader::GetProgramOutVariableLocal(program)); + case ShaderProgram::Pixel: return ShaderVar(ShaderVariable::InOut, ShaderVariableType::Vec4, Shader::GetProgramOutVariableLocal(program)); + } +} + //Shader Block implementation class ------------------------------------------- -void ShaderBlock::Add(const ShaderVariable parameter, String const &type, String const &name) +void ShaderBlock::AddVar(ShaderVar const& var) { - ASSERT(!m_parameters[parameter.ToScalar()].has_key(name)); - m_parameters[parameter.ToScalar()][name] = type; + ShaderVariable qualifier = var.GetQualifier(); + String type = var.GetType(); + String name = Shader::GetVariablePrefix(qualifier) + var.m_name; + ASSERT(!m_parameters[qualifier.ToScalar()].has_key(name)); + m_parameters[qualifier.ToScalar()][name] = type; } //---- -void ShaderBlock::AddCallParameters(const ShaderVariable type, map const& variables, String& result) +void ShaderBlock::AddCallParameters(map const& variables, String& result) { array keys = variables.keys(); for (String key : keys) { if (result.Count() > 0) result += ", "; - result += Shader::GetVariablePrefix(type) + key; + result += key; } } @@ -1069,7 +1091,6 @@ void ShaderBlock::AddDefinitionParameters(const ShaderVariable type, const Shade result += Shader::GetFunctionQualifier(type, program) + " "; result += variables[key]; result += String(" "); - result += Shader::GetVariablePrefix(type); result += key; } } @@ -1085,7 +1106,7 @@ void ShaderBlock::Build(const ShaderProgram program, String& call, String& funct call = call_name + "("; String call_parameters; for (int i = 0; i < ShaderVariable::MAX; i++) - AddCallParameters((ShaderVariable)i, m_parameters[i], call_parameters); + AddCallParameters(/*(ShaderVariable)i, */m_parameters[i], call_parameters); call += call_parameters + ");"; //Build function declaration @@ -1133,6 +1154,14 @@ ShaderBuilder& ShaderBuilder::operator<<(ShaderBlock* block) return *this; } +//---- +ShaderBuilder& ShaderBuilder::operator<<(ShaderBlock const& block) +{ + ASSERT(m_current_program != ShaderProgram::MAX); + m_blocks[m_current_program.ToScalar()].PushUnique(new ShaderBlock(block)); + return *this; +} + //---- String ShaderBuilder::AddSlotOutVariableLocal(const ShaderProgram program) { @@ -1170,8 +1199,11 @@ void ShaderBuilder::MergeParameters(map& variables, map> 24, (c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff); + return vec4(v) * (1.f / 255.f); +} +vec4 Color::FromRGB32(uint32_t c) +{ + return Color::FromRGBA32((c << 8) | 0x000000ffu); +} +vec4 Color::FromRGBA16(uint16_t c) +{ + return Color::FromRGBA32 + ( 0x11000000u * (c >> 12) + | 0x00110000u * ((c >> 8) & 0xf) + | 0x00001100u * ((c >> 4) & 0xf) + | 0x00000011u * (c & 0xf)); +} +vec4 Color::FromRGB16(uint16_t c) +{ + return Color::FromRGBA16((c << 4) | 0xfu); +} + +/* +* Convert uint color to vec4. +*/ +uint32_t Color::ToRGBA32(vec4 c) +{ + ivec4 v(c * 0xff); + return (uint32_t)((v.r << 24) | (v.g << 16) | (v.b << 8) | v.a); +} +uint32_t Color::ToRGB32(vec4 c) +{ + ivec4 v(c * 0xff); + return (uint32_t)((v.r << 16) | (v.g << 8) | v.b); +} +uint16_t Color::ToRGBA16(vec4 c) +{ + ivec4 v(c * 0xf); + return (uint16_t)((v.r << 12) | (v.g << 8) | (v.b << 4) | v.a); +} +uint16_t Color::ToRGB16(vec4 c) +{ + ivec4 v(c * 0xf); + return (uint16_t)((v.r << 8) | (v.g << 4) | v.b); +} + /* * Conversion from colours to hexadecimal */ diff --git a/src/image/image.cpp b/src/image/image.cpp index 8fec290e..bfd04865 100644 --- a/src/image/image.cpp +++ b/src/image/image.cpp @@ -133,8 +133,8 @@ void Image::DummyFill() void Image::Copy(uint8_t* pixels, ivec2 const& size, PixelFormat fmt) { ASSERT(fmt != PixelFormat::Unknown); - SetFormat(fmt); SetSize(size); + SetFormat(fmt); memcpy(m_data->m_pixels[(int)fmt]->data(), pixels, size.x * size.y * BytesPerPixel(fmt)); } diff --git a/src/imgui/lolimgui.cpp b/src/imgui/lolimgui.cpp index a32a5646..d114681f 100644 --- a/src/imgui/lolimgui.cpp +++ b/src/imgui/lolimgui.cpp @@ -19,13 +19,77 @@ using namespace lol; //----------------------------------------------------------------------------- LolImGui::LolImGui() { + m_gamegroup = GAMEGROUP_BEFORE; m_drawgroup = DRAWGROUP_HUD; + + //Build shader code ------------------------------------------------------- + ShaderVar out_vertex = ShaderVar::GetShaderOut(ShaderProgram::Vertex); + ShaderVar out_pixel = ShaderVar::GetShaderOut(ShaderProgram::Pixel); + + ShaderVar pass_texcoord = ShaderVar(ShaderVariable::Varying, ShaderVariableType::Vec2, "texcoord"); + ShaderVar pass_color = ShaderVar(ShaderVariable::Varying, ShaderVariableType::Vec4, "color"); + + ShaderVar in_position = ShaderVar(ShaderVariable::Attribute, ShaderVariableType::Vec2, "position"); + ShaderVar in_texcoord = ShaderVar(ShaderVariable::Attribute, ShaderVariableType::Vec2, "texcoord"); + ShaderVar in_color = ShaderVar(ShaderVariable::Attribute, ShaderVariableType::Vec4, "color"); + + m_ortho.m_var = ShaderVar(ShaderVariable::Uniform, ShaderVariableType::Mat4, "ortho"); + m_texture.m_var = ShaderVar(ShaderVariable::Uniform, ShaderVariableType::sampler2D, "texture"); + + ShaderBlock imgui_vertex("imgui_vertex"); + imgui_vertex + << out_vertex << m_ortho << in_position + << pass_texcoord << in_texcoord + << pass_color << in_color; + imgui_vertex.SetMainCode(String() + + Line(out_vertex + " = .5 *" + m_ortho + " * vec4(" + in_position + ", -1.0, 1.0);") + + Line(pass_texcoord + " = " + in_texcoord + ";") + + Line(pass_color + " = " + in_color + ";") + ); + + ShaderBlock imgui_pixel("imgui_pixel"); + imgui_pixel << m_texture << pass_texcoord << pass_color << out_pixel; + imgui_pixel.SetMainCode(String() + + Line(String() + + "vec4 col = " + pass_color + " * texture2D(" + m_texture + ", " + pass_texcoord + ");") + + Line("if (col.a == 0.0) discard; ") + + Line(out_pixel + " = col;") + ); + + m_builder + << ShaderProgram::Vertex << imgui_vertex + << ShaderProgram::Pixel << imgui_pixel; + + //Input Setup ------------------------------------------------------------- + for (int i = LolImGuiKey::KEY_START; i < LolImGuiKey::KEY_END; ++i) + m_profile << InputProfile::Keyboard(i, LolImGuiKey(i).ToString()); + for (int i = LolImGuiKey::MOUSE_KEY_START; i < LolImGuiKey::MOUSE_KEY_END; ++i) + m_profile << InputProfile::MouseKey(i, LolImGuiKey(i).ToString()); + + for (int i = LolImGuiAxis::MOUSE_AXIS_START; i < LolImGuiAxis::MOUSE_AXIS_END; ++i) + m_profile << InputProfile::MouseAxis(i, LolImGuiAxis(i).ToString()); + + Ticker::Ref(m_controller = new Controller("ImGui_Controller")); + m_controller->Init(m_profile); + //InputDevice::CaptureMouse(true); + m_mouse = InputDevice::GetMouse(); + m_keyboard = InputDevice::GetKeyboard(); + + //m_controller->Get + //# define KB InputProfile::Keyboard +// m_profile +// << InputProfile::Keyboard(idx, g_name_key_Left); +//# undef KB + } LolImGui::~LolImGui() { ImGui::GetIO().Fonts->TexID = nullptr; Ticker::Unref(m_font); m_font = nullptr; + + Shader::Destroy(m_shader); + delete m_vdecl; } //------------------------------------------------------------------------- @@ -35,69 +99,34 @@ void LolImGui::Init() Ticker::Ref(g_lolimgui = new LolImGui()); ImGuiIO& io = ImGui::GetIO(); - //io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. - //io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; - //io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; - //io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; - //io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; - //io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; - //io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; - //io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; - //io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; - //io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; - //io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; - //io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; - //io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; - //io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; - //io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; - //io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; - //io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; + //ImFont* font0 = io.Fonts->AddFontDefault(); + + // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_Tab] = LolImGuiKey::Tab; + io.KeyMap[ImGuiKey_LeftArrow] = LolImGuiKey::LeftArrow; + io.KeyMap[ImGuiKey_RightArrow] = LolImGuiKey::RightArrow; + io.KeyMap[ImGuiKey_UpArrow] = LolImGuiKey::UpArrow; + io.KeyMap[ImGuiKey_DownArrow] = LolImGuiKey::DownArrow; + io.KeyMap[ImGuiKey_Home] = LolImGuiKey::Home; + io.KeyMap[ImGuiKey_End] = LolImGuiKey::End; + io.KeyMap[ImGuiKey_Delete] = LolImGuiKey::Delete; + io.KeyMap[ImGuiKey_Backspace] = LolImGuiKey::Backspace; + io.KeyMap[ImGuiKey_Enter] = LolImGuiKey::Enter; + io.KeyMap[ImGuiKey_Escape] = LolImGuiKey::Escape; + io.KeyMap[ImGuiKey_A] = LolImGuiKey::A; + io.KeyMap[ImGuiKey_C] = LolImGuiKey::C; + io.KeyMap[ImGuiKey_V] = LolImGuiKey::V; + io.KeyMap[ImGuiKey_X] = LolImGuiKey::X; + io.KeyMap[ImGuiKey_Y] = LolImGuiKey::Y; + io.KeyMap[ImGuiKey_Z] = LolImGuiKey::Z; //Func pointer io.RenderDrawListsFn = LolImGui::RenderDrawLists; io.SetClipboardTextFn = LolImGui::SetClipboard; io.GetClipboardTextFn = LolImGui::GetClipboard; - - /* nope -#ifdef _MSC_VER - io.ImeWindowHandle = glfwGetWin32Window(g_Window); -#endif - */ - - /* Callback not needed but look into these to send IO stuff - if (install_callbacks) - { - glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); - glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); - glfwSetKeyCallback(window, ImGui_ImplGlFw_KeyCallback); - glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); - } - */ } /* CALLBACKS -void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) -{ -if (action == GLFW_PRESS && button >= 0 && button < 3) -g_MousePressed[button] = true; -} - -void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) -{ -g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. -} - -void ImGui_ImplGlFw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) -{ -ImGuiIO& io = ImGui::GetIO(); -if (action == GLFW_PRESS) -io.KeysDown[key] = true; -if (action == GLFW_RELEASE) -io.KeysDown[key] = false; -io.KeyCtrl = (mods & GLFW_MOD_CONTROL) != 0; -io.KeyShift = (mods & GLFW_MOD_SHIFT) != 0; -} - void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) { ImGuiIO& io = ImGui::GetIO(); @@ -138,25 +167,12 @@ void LolImGui::TickGame(float seconds) // Build texture unsigned char* pixels; ivec2 size; - io.Fonts->GetTexDataAsAlpha8(&pixels, &size.x, &size.y); + io.Fonts->GetTexDataAsRGBA32(&pixels, &size.x, &size.y); Image* image = new Image(); image->Copy(pixels, size, PixelFormat::RGBA_8); - image->SetSize(size); Ticker::Ref(m_font = new TextureImage("", image)); - - //// Create texture - //glGenTextures(1, &g_FontTexture); - //glBindTexture(GL_TEXTURE_2D, g_FontTexture); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - //glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); - - //// Store our identifier - //io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - //return true; } //Texture has been created if (m_font && m_font->GetTexture()) @@ -169,40 +185,73 @@ void LolImGui::TickGame(float seconds) video_size = vec2(Video::GetSize()); io.DisplaySize = ImVec2(video_size.x, video_size.y); - // Setup time step + //Setup time step io.DeltaTime = seconds; + io.MouseDrawCursor = true; - // Setup inputs - // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) - //double mouse_x, mouse_y; - //glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); - //mouse_x *= (float)display_w / w; // Convert mouse coordinates to pixels - //mouse_y *= (float)display_h / h; - //io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) - - /* - for (int i = 0; i < 3; i++) + //Update Keyboard + io.KeyCtrl = false; + io.KeyShift = false; + for (int i = LolImGuiKey::KEY_START; i < LolImGuiKey::KEY_END; ++i) { - io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. - g_MousePressed[i] = false; + switch (i) + { + default: + io.KeysDown[i] = m_controller->GetKey(i).IsPressed(); + break; + case LolImGuiKey::LShift: + case LolImGuiKey::RShift: + io.KeyShift = (io.KeyShift || m_controller->GetKey(i).IsPressed()); + break; + case LolImGuiKey::LCtrl: + case LolImGuiKey::RCtrl: + io.KeyCtrl = (io.KeyCtrl || m_controller->GetKey(i).IsPressed()); + break; + } } - io.MouseWheel = g_MouseWheel; - g_MouseWheel = 0.0f; - */ + //Update text input + String text = m_keyboard->GetText(); + //text.case_change(io.KeyShift); + for (int i = 0; i < text.count(); ++i) + io.AddInputCharacter(text[i]); + + //Update mouse + if (m_mouse) + { + vec2 cursor = m_mouse->GetCursor(0); + cursor.y = 1.f - cursor.y; + cursor *= video_size; + io.MousePos = ImVec2(cursor.x, cursor.y); + io.MouseWheel = m_controller->GetAxis(LolImGuiAxis::Scroll).GetValue(); + + for (int i = LolImGuiKey::MOUSE_KEY_START; i < LolImGuiKey::MOUSE_KEY_END; ++i) + { + switch (i) + { + default: + io.MouseDown[i - LolImGuiKey::MOUSE_KEY_START] = m_controller->GetKey(i).IsPressed(); + break; + case LolImGuiKey::Focus: + if (m_controller->GetKey(i).IsPressed()) + io.MousePos = ImVec2(-1.f, -1.f); + break; + } + } + } // Start the frame ImGui::NewFrame(); - } void LolImGui::TickDraw(float seconds, Scene &scene) { super::TickDraw(seconds, scene); - ImGui::Render(); -} - + ImGuiIO& io = ImGui::GetIO(); + if (io.Fonts->TexID) + ImGui::Render(); +} @@ -219,74 +268,126 @@ void LolImGui::TickDraw(float seconds, Scene &scene) // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) //------------------------------------------------------------------------- void LolImGui::RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) +{ + g_lolimgui->RenderDrawListsMethod(cmd_lists, cmd_lists_count); +} +void LolImGui::RenderDrawListsMethod(ImDrawList** const cmd_lists, int cmd_lists_count) { if (cmd_lists_count == 0) return; - /* - // We are using the OpenGL fixed pipeline to make the example code simpler to read! - // A probable faster way to render would be to collate all vertices from all cmd_lists into a single vertex buffer. - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. - glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glEnable(GL_TEXTURE_2D); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - // Render command lists -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + vec2 size = vec2(Video::GetSize()); + float alpha = 1.f; + mat4 ortho = mat4::ortho(size.x * alpha, size.y * alpha, -1000.f, 1000.f) + * mat4::lookat(vec3::axis_z, vec3::zero, vec3::axis_y) + * mat4::scale(vec3::axis_x - vec3::axis_y - vec3::axis_z) + * mat4::translate(-size.x * .5f * alpha, -size.y * .5f * alpha, 0.f); + + //Create shader + if (!m_shader) + { + String code; + m_builder.Build(code); + + m_shader = Shader::Create(m_builder.GetName(), code); + ASSERT(m_shader); + + m_ortho.m_uniform = m_shader->GetUniformLocation(m_ortho.m_var); + m_texture.m_uniform = m_shader->GetUniformLocation(m_texture.m_var); + + m_attribs + << m_shader->GetAttribLocation(VertexUsage::Position, 0) + << m_shader->GetAttribLocation(VertexUsage::TexCoord, 0) + << m_shader->GetAttribLocation(VertexUsage::Color, 0); + + m_vdecl = new VertexDeclaration( + VertexStream( + VertexUsage::Position, + VertexUsage::TexCoord, + VertexUsage::Color)); + } + + //Do not render without shader + if (!m_shader) + return; + + RenderContext rc; + rc.SetCullMode(CullMode::Disabled); + rc.SetDepthFunc(DepthFunc::Disabled); + + m_shader->Bind(); for (int n = 0; n < cmd_lists_count; n++) { const ImDrawList* cmd_list = cmd_lists[n]; const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->vtx_buffer.front(); - glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, pos))); - glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, uv))); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (void*)(vtx_buffer + OFFSETOF(ImDrawVert, col))); + + //Register uniforms + m_shader->SetUniform(m_ortho, ortho); + m_shader->SetUniform(m_texture, m_font->GetTexture()->GetTextureUniform(), 0); int vtx_offset = 0; for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->commands[cmd_i]; - if (pcmd->user_callback) + + struct Vertex { - pcmd->user_callback(cmd_list, pcmd); - } - else + vec2 pos, tex; + u8vec4 color; + }; + + VertexBuffer* vbo = new VertexBuffer(pcmd->vtx_count * sizeof(Vertex)); + Vertex *vert = (Vertex *)vbo->Lock(0, 0); + +#ifdef SHOW_IMGUI_DEBUG + //----------------------------------------------------------------- + // -------------------------------------------------- + //----------------------------------------------------------------- + float mod = -200.f; + vec3 off = vec3(vec2(-size.x, -size.y), 0.f); + vec3 pos[4] = { + (1.f / mod) * (off + vec3(0.f)), + (1.f / mod) * (off + size.x * vec3::axis_x), + (1.f / mod) * (off + size.x * vec3::axis_x + size.y * vec3::axis_y), + (1.f / mod) * (off + size.y * vec3::axis_y) + }; + for (int i = 0; i < 4; ++i) + Debug::DrawLine(pos[i], pos[(i + 1) % 4], Color::white); + ImDrawVert* buf = (ImDrawVert*)(vtx_buffer + vtx_offset); + for (uint16_t i = 0; i < pcmd->vtx_count; i += 3) { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->texture_id); - glScissor((int)pcmd->clip_rect.x, (int)(height - pcmd->clip_rect.w), (int)(pcmd->clip_rect.z - pcmd->clip_rect.x), (int)(pcmd->clip_rect.w - pcmd->clip_rect.y)); - glDrawArrays(GL_TRIANGLES, vtx_offset, pcmd->vtx_count); + vec2 pos[3]; + pos[0] = vec2(buf[i + 0].pos.x, buf[i + 0].pos.y); + pos[1] = vec2(buf[i + 1].pos.x, buf[i + 1].pos.y); + pos[2] = vec2(buf[i + 2].pos.x, buf[i + 2].pos.y); + vec4 col[3]; + col[0] = vec4(Color::FromRGBA32(buf[i + 0].col).arg, 1.f); + col[1] = vec4(Color::FromRGBA32(buf[i + 1].col).arg, 1.f); + col[2] = vec4(Color::FromRGBA32(buf[i + 2].col).arg, 1.f); + Debug::DrawLine((off + vec3(pos[0], 0.f)) / mod, (off + vec3(pos[1], 0.f)) / mod, col[0]); + Debug::DrawLine((off + vec3(pos[1], 0.f)) / mod, (off + vec3(pos[2], 0.f)) / mod, col[1]); + Debug::DrawLine((off + vec3(pos[2], 0.f)) / mod, (off + vec3(pos[0], 0.f)) / mod, col[2]); } - vtx_offset += pcmd->vtx_count; + //----------------------------------------------------------------- + //<\Debug render> ------------------------------------------------- + //----------------------------------------------------------------- +#endif //SHOW_IMGUI_DEBUG + + memcpy(vert, vtx_buffer + vtx_offset, pcmd->vtx_count * sizeof(Vertex)); + vbo->Unlock(); + + m_font->Bind(); + m_vdecl->Bind(); + m_vdecl->SetStream(vbo, m_attribs[0], m_attribs[1], m_attribs[2]); + m_vdecl->DrawElements(MeshPrimitive::Triangles, 0, pcmd->vtx_count); + m_vdecl->Unbind(); + m_font->Unbind(); + + vtx_offset += pcmd->vtx_count * sizeof(Vertex); + + delete vbo; } } -#undef OFFSETOF - - // Restore modified state - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glPopAttrib(); - */ + m_shader->Unbind(); } diff --git a/src/imgui/lolimgui.h b/src/imgui/lolimgui.h index d8e93759..545bbdf8 100644 --- a/src/imgui/lolimgui.h +++ b/src/imgui/lolimgui.h @@ -22,6 +22,112 @@ class LolImGui : public Entity { typedef Entity super; + //ImGuiKeyBase ------------------------------------------------------------ + struct LolImGuiKeyBase : public StructSafeEnum + { + enum Type + { + KEY_START, + + Tab = KEY_START, + LeftArrow, + RightArrow, + UpArrow, + DownArrow, + Home, + End, + Delete, + Backspace, + Enter, + Escape, + + A, + C, + V, + X, + Y, + Z, + + LShift, + RShift, + LCtrl, + RCtrl, + + KEY_END, + + MOUSE_KEY_START = KEY_END, + + LeftClick = MOUSE_KEY_START, + RightClick, + MiddleClick, + Focus, + + MOUSE_KEY_END, + + MAX = MOUSE_KEY_END, + }; + protected: + virtual bool BuildEnumMap(map& enum_map) + { + enum_map[Tab] = g_name_key_Tab; + enum_map[LeftArrow] = g_name_key_Left; + enum_map[RightArrow] = g_name_key_Right; + enum_map[UpArrow] = g_name_key_Up; + enum_map[DownArrow] = g_name_key_Down; + enum_map[Home] = g_name_key_Home; + enum_map[End] = g_name_key_End; + enum_map[Delete] = g_name_key_Delete; + enum_map[Backspace] = g_name_key_Backspace; + enum_map[Enter] = g_name_key_Return; + enum_map[Escape] = g_name_key_Escape; + + enum_map[A] = g_name_key_A; + enum_map[C] = g_name_key_C; + enum_map[V] = g_name_key_V; + enum_map[X] = g_name_key_X; + enum_map[Y] = g_name_key_Y; + enum_map[Z] = g_name_key_Z; + + enum_map[LShift] = g_name_key_LShift; + enum_map[RShift] = g_name_key_RShift; + enum_map[LCtrl] = g_name_key_LCtrl; + enum_map[RCtrl] = g_name_key_RCtrl; + + enum_map[LeftClick] = g_name_mouse_key_left; + enum_map[RightClick] = g_name_mouse_key_right; + enum_map[MiddleClick] = g_name_mouse_key_middle; + + return true; + } + }; + typedef SafeEnum LolImGuiKey; + + //ImGuiKeyBase ------------------------------------------------------------ + struct LolImGuiAxisBase : public StructSafeEnum + { + enum Type + { + MOUSE_AXIS_START = 0, + + Scroll = MOUSE_AXIS_START, + + MOUSE_AXIS_END, + + MAX = MOUSE_AXIS_END, + }; + protected: + virtual bool BuildEnumMap(map& enum_map) + { + enum_map[Scroll] = g_name_mouse_axis_scroll; + + return true; + } + }; + typedef SafeEnum LolImGuiAxis; + + + +public: //------------------------------------------------------------------------- LolImGui(); ~LolImGui(); @@ -40,8 +146,32 @@ protected: virtual void TickDraw(float seconds, Scene &scene); static void RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count); + void RenderDrawListsMethod(ImDrawList** const cmd_lists, int cmd_lists_count); + struct Uniform + { + Uniform() { } + Uniform(ShaderVar var) { m_var = var; } + operator String() { return m_var; } + operator ShaderVar() { return m_var; } + operator ShaderUniform() { return m_uniform; } + //-- + ShaderVar m_var; + ShaderUniform m_uniform; + }; + //------------------------------------------------------------------------- TextureImage* m_font = nullptr; + ShaderBuilder m_builder = ShaderBuilder("imgui_shader", "120"); + Shader* m_shader = nullptr; + Uniform m_ortho; + Uniform m_texture; + array m_attribs; + VertexDeclaration* m_vdecl = nullptr; + Controller* m_controller = nullptr; + InputDevice* m_mouse = nullptr; + InputDevice* m_keyboard = nullptr; + InputProfile m_profile; + //map m_keys; }; //bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks); diff --git a/src/input/controller.h b/src/input/controller.h index 2e827966..3f6b05a7 100644 --- a/src/input/controller.h +++ b/src/input/controller.h @@ -315,6 +315,7 @@ private: }; //----------------------------------------------------------------------------- +//TODO: Add mask|layer system to prevent several controllers from interfering with another. (input overlay in menus) class Controller : public Entity { public: diff --git a/src/input/input.h b/src/input/input.h index 1b9cad00..414edd5e 100644 --- a/src/input/input.h +++ b/src/input/input.h @@ -21,6 +21,9 @@ static String g_name_joystick(const uint64_t num) return String::Printf("Joystick%d", (int)num); } +# define _SC(id, str, name) const String g_name_key_##name(#name); +# include "input/keys.h" + //Mouse default buttons/axis const String g_name_mouse_key_left("Left"); const String g_name_mouse_key_middle("Middle"); diff --git a/src/input/input_internal.h b/src/input/input_internal.h index c0bdd9bb..d80b79f6 100644 --- a/src/input/input_internal.h +++ b/src/input/input_internal.h @@ -16,7 +16,7 @@ namespace lol /** Internal class (not public) that allows to construct an InputDevice * dynamically, when the keys, axis and cursors are not known at * compile time. */ -class InputDeviceInternal : InputDevice +class InputDeviceInternal : public InputDevice { public: inline InputDeviceInternal(char const * name) : InputDevice(name) { } diff --git a/src/input/keys.h b/src/input/keys.h index 7bb268c2..13eedca3 100644 --- a/src/input/keys.h +++ b/src/input/keys.h @@ -283,5 +283,10 @@ _SC(282, "", Sleep) _SC(283, "", App1) _SC(284, "", App2) +//Custom Lock management +_SC(285, "", CapsLockStatus) +_SC(286, "", ScrollLockStatus) +_SC(287, "", NumLockClearStatus) + #undef _SC diff --git a/src/lol/base/enum.h b/src/lol/base/enum.h index f6c5b59d..4a79564e 100644 --- a/src/lol/base/enum.h +++ b/src/lol/base/enum.h @@ -54,6 +54,7 @@ public: /* Allow conversion from int and to the underlying type */ inline explicit SafeEnum(int i) : m_value(T(i)) {} inline Type ToScalar() const { return m_value; } + //inline class String ToString() const { return ToString(); } /* Convert to string stuff */ inline class String ToString() diff --git a/src/lol/base/string.h b/src/lol/base/string.h index 25db1c61..20ca3bbf 100644 --- a/src/lol/base/string.h +++ b/src/lol/base/string.h @@ -127,6 +127,11 @@ public: return String(&(*this)[start], item_count); } + bool contains(String const &s) const + { + return index_of(s.C()) != INDEX_NONE; + } + ptrdiff_t index_of(char token) const { using namespace std; @@ -135,6 +140,7 @@ public: return tmp ? (ptrdiff_t)(tmp - C()) : INDEX_NONE; } + ptrdiff_t index_of(String const& token) const { return index_of(token.C()); } ptrdiff_t index_of(char const* token) const { using namespace std; @@ -143,11 +149,6 @@ public: return tmp ? (ptrdiff_t)(tmp - C()) : INDEX_NONE; } - bool contains(String const &s) const - { - return index_of(s.C()) != INDEX_NONE; - } - ptrdiff_t last_index_of(char token) const { using namespace std; @@ -156,6 +157,18 @@ public: return tmp ? (ptrdiff_t)(tmp - C()) : INDEX_NONE; } + ptrdiff_t last_index_of(String const& token) const { return last_index_of(token.C()); } + ptrdiff_t last_index_of(char const* token) const + { + using namespace std; + + ptrdiff_t token_len = strlen(token); + for (ptrdiff_t i = count() - token_len; i >= 0; --i) + if (strstr(C() + i, token)) + return i; + return -1; + } + int replace(char const old_token, char const new_token, bool all_occurrences = false) { @@ -173,34 +186,32 @@ public: return res; } - /* FIXME: it doesn't sound safe to apply this in place */ inline String& to_lower() { - char* p = C(); - for (ptrdiff_t i = 0; i < count(); ++i) - if ('A' <= p[i] && p[i] <= 'Z') - p[i] += 'a' - 'A'; + String ret(*this); + for (ptrdiff_t i = 0; i < ret.count(); ++i) + { + if ('A' <= ret[i] && ret[i] <= 'Z') + ret[i] += 'a' - 'A'; + } + *this = ret; return *this; } inline String& to_upper() { - char* p = C(); - for (ptrdiff_t i = 0; i < count(); ++i) - if ('a' <= p[i] && p[i] <= 'z') - p[i] += 'A' - 'a'; + String ret(*this); + for (ptrdiff_t i = 0; i < ret.count(); ++i) + { + if ('a' <= ret[i] && ret[i] <= 'z') + ret[i] += 'A' - 'a'; + } + *this = ret; return *this; } - - ptrdiff_t last_index_of(char const* token) const + inline String& case_change(bool case_to_upper) { - using namespace std; - - ptrdiff_t token_len = strlen(token); - for (ptrdiff_t i = count() - token_len; i >= 0; --i) - if (strstr(C() + i, token)) - return i; - return -1; + return case_to_upper ? to_upper() : to_lower(); } bool starts_with(String const &s) const @@ -231,6 +242,12 @@ public: return ret += s; } + inline String operator +(char c) const + { + String ret(*this); + return ret += c; + } + inline String& operator +=(String const &s) { using namespace std; @@ -240,12 +257,6 @@ public: return *this; } - inline String operator +(char c) const - { - String ret(*this); - return ret += c; - } - inline String& operator +=(char c) { ((super &)*this).last() = c; @@ -306,6 +317,7 @@ public: inline void Resize(ptrdiff_t item_count) { return resize(item_count); } inline String& ToLower() { return to_lower(); } inline String& ToUpper() { return to_upper(); } + inline String& CaseChange(bool case_to_upper) { return case_to_upper ? ToUpper() : ToLower(); } inline String Sub(ptrdiff_t start, ptrdiff_t item_count = -1) const { return sub(start, item_count); } inline bool Contains(String const &s) const { return contains(s); } inline ptrdiff_t IndexOf(char token) const { return index_of(token); } @@ -318,6 +330,26 @@ public: inline ptrdiff_t Count() const { return count(); } }; +class Line +{ +public: + Line(String const& s) + { + m_line = s + "\n"; + } + inline operator String() + { + return m_line; + } + inline operator const char*() + { + return m_line.C(); + } + +private: + String m_line; +}; + inline bool operator ==(char const* sz, String const &s) { return s == sz; diff --git a/src/lol/gpu/shader.h b/src/lol/gpu/shader.h index d497adf8..9a343d34 100644 --- a/src/lol/gpu/shader.h +++ b/src/lol/gpu/shader.h @@ -134,6 +134,134 @@ protected: }; typedef SafeEnum ShaderProgram; +//ShaderProgramBase ----------------------------------------------------------- +struct ShaderVariableTypeBase +{ + enum Type + { + Bool, + Int, UInt, + Float, + Double, + Vec2, Vec3, Vec4, + DVec2, DVec3, DVec4, + BVec2, BVec3, BVec4, + IVec2, IVec3, IVec4, + UVec2, UVec3, UVec4, + + Mat2, Mat3, Mat4, + + sampler1D, + sampler2D, + sampler3D, + samplerCube, + sampler2DRect, + sampler1DArray, + sampler2DArray, + samplerCubeArray, + samplerBuffer, + sampler2DMS, + sampler2DMSArray, + + isampler1D, + isampler2D, + isampler3D, + isamplerCube, + isampler2DRect, + isampler1DArray, + isampler2DArray, + isamplerCubeArray, + isamplerBuffer, + isampler2DMS, + isampler2DMSArray, + + usampler1D, + usampler2D, + usampler3D, + usamplerCube, + usampler2DRect, + usampler1DArray, + usampler2DArray, + usamplerCubeArray, + usamplerBuffer, + usampler2DMS, + usampler2DMSArray, + + sampler1DShadow, + sampler2DShadow, + samplerCubeShadow, + sampler2DRectShadow, + sampler1DArrayShadow, + sampler2DArrayShadow, + samplerCubeArrayShadow, + + MAX + }; +protected: + virtual bool BuildEnumMap(map& enum_map) + { + enum_map[Bool] = "bool"; + enum_map[Int] = "int"; enum_map[UInt] = "uint"; + enum_map[Float] = "float"; + enum_map[Double] = "double"; + enum_map[Vec2] = "vec2"; enum_map[Vec3] = "vec3"; enum_map[Vec4] = "vec4"; + enum_map[DVec2] = "dvec2"; enum_map[DVec3] = "dvec3"; enum_map[DVec4] = "dvec4"; + enum_map[BVec2] = "bvec2"; enum_map[BVec3] = "bvec3"; enum_map[BVec4] = "bvec4"; + enum_map[IVec2] = "ivec2"; enum_map[IVec3] = "ivec3"; enum_map[IVec4] = "ivec4"; + enum_map[UVec2] = "uvec2"; enum_map[UVec3] = "uvec3"; enum_map[UVec4] = "uvec4"; + + enum_map[Mat2] = "mat2"; + enum_map[Mat3] = "mat3"; + enum_map[Mat4] = "mat4"; + + enum_map[sampler1D] = "sampler1D"; + enum_map[sampler2D] = "sampler2D"; + enum_map[sampler3D] = "sampler3D"; + enum_map[samplerCube] = "samplerCube"; + enum_map[sampler2DRect] = "sampler2DRect"; + enum_map[sampler1DArray] = "sampler1DArray"; + enum_map[sampler2DArray] = "sampler2DArray"; + enum_map[samplerCubeArray] = "samplerCubeArray"; + enum_map[samplerBuffer] = "samplerBuffer"; + enum_map[sampler2DMS] = "sampler2DMS"; + enum_map[sampler2DMSArray] = "sampler2DMSArray"; + + enum_map[isampler1D] = "isampler1D"; + enum_map[isampler2D] = "isampler2D"; + enum_map[isampler3D] = "isampler3D"; + enum_map[isamplerCube] = "isamplerCube"; + enum_map[isampler2DRect] = "isampler2DRect"; + enum_map[isampler1DArray] = "isampler1DArray"; + enum_map[isampler2DArray] = "isampler2DArray"; + enum_map[isamplerCubeArray] = "isamplerCubeArray"; + enum_map[isamplerBuffer] = "isamplerBuffer"; + enum_map[isampler2DMS] = "isampler2DMS"; + enum_map[isampler2DMSArray] = "isampler2DMSArray"; + + enum_map[usampler1D] = "usampler1D"; + enum_map[usampler2D] = "usampler2D"; + enum_map[usampler3D] = "usampler3D"; + enum_map[usamplerCube] = "usamplerCube"; + enum_map[usampler2DRect] = "usampler2DRect"; + enum_map[usampler1DArray] = "usampler1DArray"; + enum_map[usampler2DArray] = "usampler2DArray"; + enum_map[usamplerCubeArray] = "usamplerCubeArray"; + enum_map[usamplerBuffer] = "usamplerBuffer"; + enum_map[usampler2DMS] = "usampler2DMS"; + enum_map[usampler2DMSArray] = "usampler2DMSArray"; + + enum_map[sampler1DShadow] = "sampler1DShadow"; + enum_map[sampler2DShadow] = "sampler2DShadow"; + enum_map[samplerCubeShadow] = "samplerCubeShadow"; + enum_map[sampler2DRectShadow] = "sampler2DRectShadow"; + enum_map[sampler1DArrayShadow] = "sampler1DArrayShadow"; + enum_map[sampler2DArrayShadow] = "sampler2DArrayShadow"; + enum_map[samplerCubeArrayShadow] = "samplerCubeArrayShadow"; + return true; + } +}; +typedef SafeEnum ShaderVariableType; + //ShaderUniform --------------------------------------------------------------- struct ShaderUniform { @@ -193,6 +321,7 @@ public: int GetAttribCount() const; ShaderAttrib GetAttribLocation(VertexUsage usage, int index) const; + ShaderUniform GetUniformLocation(String const& uni) const; ShaderUniform GetUniformLocation(char const *uni) const; void SetUniform(ShaderUniform const &uni, int i); void SetUniform(ShaderUniform const &uni, ivec2 const &v); @@ -231,6 +360,39 @@ public: static String GetProgramOutVariableLocal(const ShaderProgram program); }; +//ShaderVar ------------------------------------------------------------------- +class ShaderVar +{ + friend class ShaderBuilder; + friend class ShaderBlock; + +protected: +public: + ShaderVar() { } + ShaderVar(ShaderVariable const& qualifier, String const& type, String const& name) + { + m_qualifier = qualifier; + m_type = type; + m_name = name; + } + ShaderVar(ShaderVariable const& qualifier, ShaderVariableType const& type, String const& name) + : ShaderVar(qualifier, ShaderVariableType(type).ToString(), name) + { } + ~ShaderVar() { } + + inline operator String() const { return Shader::GetVariablePrefix(m_qualifier) + m_name; } + inline ShaderVariable GetQualifier() const { return m_qualifier; } + inline String GetType() const { return m_type; } + inline String operator+(String const& value) { return String() + *this + value; } + + static ShaderVar GetShaderOut(ShaderProgram program); + +protected: + ShaderVariable m_qualifier; + String m_type; + String m_name; +}; + //ShaderBlock ----------------------------------------------------------------- class ShaderBlock { @@ -260,10 +422,15 @@ public: //Sets custom code that will be put before the main -so functions- void SetCustomCode(String const& code_custom) { m_code_custom = code_custom; } //Add parameter to the block - void Add(const ShaderVariable variable, String const& type, String const& name); + void AddVar(ShaderVar const& var); + inline ShaderBlock& operator<<(ShaderVar const& var) + { + AddVar(var); + return *this; + } protected: - void AddCallParameters(const ShaderVariable variable, map const& variables, String& result); + void AddCallParameters(map const& variables, String& result); void AddDefinitionParameters(const ShaderVariable variable, const ShaderProgram program, map& variables, String& result); void Build(const ShaderProgram program, String& call, String& function); }; @@ -289,6 +456,7 @@ public: String const& GetName(); ShaderBuilder& operator<<(const ShaderProgram program); ShaderBuilder& operator<<(ShaderBlock* block); + ShaderBuilder& operator<<(ShaderBlock const& block); protected: String AddSlotOutVariableLocal(const ShaderProgram program); diff --git a/src/lol/image/color.h b/src/lol/image/color.h index 4210dc6e..5aaec6bd 100644 --- a/src/lol/image/color.h +++ b/src/lol/image/color.h @@ -316,6 +316,22 @@ public: */ static vec3 WavelengthToCIExyY(float nm); + /* + * Convert uint color to vec4. + */ + static vec4 FromRGBA32(uint32_t c); + static vec4 FromRGB32(uint32_t c); + static vec4 FromRGBA16(uint16_t c); + static vec4 FromRGB16(uint16_t c); + + /* + * Convert uint color to vec4. + */ + static uint32_t ToRGBA32(vec4 c); + static uint32_t ToRGB32(vec4 c); + static uint16_t ToRGBA16(vec4 c); + static uint16_t ToRGB16(vec4 c); + /* * Convert colors to hex strings. */ diff --git a/src/lol/sys/file.h b/src/lol/sys/file.h index dd427a85..1d0e2bd6 100644 --- a/src/lol/sys/file.h +++ b/src/lol/sys/file.h @@ -107,6 +107,7 @@ public: bool GetContent(array& directories); bool GetContent(array& files); String GetName(); + long int GetModificationTime(); static String GetCurrent(); static bool SetCurrent(String directory); diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj index a19e864f..0053a3b7 100644 --- a/src/lolcore.vcxproj +++ b/src/lolcore.vcxproj @@ -417,6 +417,9 @@ {83d3b207-c601-4025-8f41-01dedc354661} + + {a7f6fdf8-937e-41ef-b44d-04cd1a48c179} + {d84021ca-b233-4e0f-8a52-071b83bbccc4} diff --git a/src/platform/sdl/sdlinput.cpp b/src/platform/sdl/sdlinput.cpp index 3a0ea5e5..a21c7fc7 100644 --- a/src/platform/sdl/sdlinput.cpp +++ b/src/platform/sdl/sdlinput.cpp @@ -49,6 +49,48 @@ static int sdl12_to_scancode(int ch, int sc) return 0; } +#else + //------------------------------------------------------------------------- +# define _SC(id, str, name) static const uint16_t SDLOL_##name = id; +# include "input/keys.h" + //------------------------------------------------------------------------- + static bool ScanCodeIsValid(int sc) + { + switch (sc) + { +# define _SC(id, str, name) \ + case id: return true; +# include "input/keys.h" + default: return false; + } + return false; + } + //------------------------------------------------------------------------- + static String ScanCodeToText(int sc) + { + switch (sc) + { +# define _SC(id, str, name) \ + case id: return String(str); +# include "input/keys.h" + default: + Log::Error(Line("ScanCodeToText unknown scancode %0d."), sc); + } + return String(); + } + //------------------------------------------------------------------------- + static String ScanCodeToName(int sc) + { + switch (sc) + { +# define _SC(id, str, name) \ + case id: return String(#name); +# include "input/keys.h" + default: + Log::Error(Line("ScanCodeToText unknown scancode %0d."), sc); + } + return String(); + } #endif /* @@ -218,30 +260,102 @@ void SdlInputData::Tick(float seconds) case SDL_KEYDOWN: case SDL_KEYUP: -#if USE_OLD_SDL - if (int sc = sdl12_to_scancode(event.key.keysym.sym, - event.key.keysym.scancode)) -#else - if (int sc = event.key.keysym.scancode) -#endif - m_keyboard->SetKey(sc, event.type == SDL_KEYDOWN); - else - Log::Error("unknown keypress (sym 0x%02x, scancode %0d)\n", - event.key.keysym.sym, event.key.keysym.scancode); +# if USE_OLD_SDL + switch (int sc = sdl12_to_scancode(event.key.keysym.sym, + event.key.keysym.scancode)) +# else + switch (int sc = event.key.keysym.scancode) +# endif + { + //Lock management + case SDLOL_CapsLock: + case SDLOL_ScrollLock: + case SDLOL_NumLockClear: + //Update status on key down only + if (event.type == SDL_KEYDOWN) + { + int sc2 = sc; + switch (sc) + { + case SDLOL_CapsLock: + sc2 = SDLOL_CapsLockStatus; + break; + case SDLOL_ScrollLock: + sc2 = SDLOL_ScrollLockStatus; + break; + case SDLOL_NumLockClear: + sc2 = SDLOL_NumLockClearStatus; + break; + } + m_keyboard->SetKey(sc2, !m_keyboard->GetKey(sc2)); + /* DEBUG STUFF + Log::Info(Line("Repeat: 0x%02x : %s/%s/%s/%i"), + (int)m_keyboard, ScanCodeToText(sc2).C(), ScanCodeToName(sc2).C(), + m_keyboard->GetKey(sc2) ? "up" : "down", event.key.repeat); + */ + } + default: + if (ScanCodeIsValid(sc)) + { + m_keyboard->SetKey(sc, event.type == SDL_KEYDOWN); + if (event.type == SDL_KEYDOWN + && !m_keyboard->GetKey(SDLOL_RCtrl) + && !m_keyboard->GetKey(SDLOL_LCtrl) + && !m_keyboard->GetKey(SDLOL_RAlt) + && !m_keyboard->GetKey(SDLOL_LAlt)) + { + String str = ScanCodeToText(sc); + str.CaseChange(m_keyboard->GetKey(SDLOL_CapsLockStatus) + ^ (m_keyboard->GetKey(SDLOL_RShift) + || m_keyboard->GetKey(SDLOL_LShift))); + m_keyboard->AddText(str); + } + /* DEBUG STUFF + Log::Info(Line("Repeat: 0x%02x : %s/%s/%s/%i"), + (int)m_keyboard, ScanCodeToText(sc).C(), ScanCodeToName(sc).C(), + event.type == SDL_KEYDOWN ? "up" : "down", event.key.repeat); + */ + } + /* DEBUG STUFF + else + Log::Error("unknown keypress (sym 0x%02x, scancode %0d)\n", + event.key.keysym.sym, event.key.keysym.scancode); + */ + } break; +# if USE_OLD_SDL case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: - { -# if USE_OLD_SDL if (event.button.button != SDL_BUTTON_WHEELUP && event.button.button != SDL_BUTTON_WHEELDOWN) m_mouse->SetKey(event.button.button - 1, event.type == SDL_MOUSEBUTTONDOWN); else m_mouse->SetAxis(4, (event.button.button != SDL_BUTTON_WHEELUP) ? (1) : (-1)); -# endif - // TODO: mouse wheel as axis + break; +# else + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + m_mouse->SetKey(event.button.button - 1, event.type == SDL_MOUSEBUTTONDOWN); + break; + case SDL_MOUSEWHEEL: + m_mouse->SetAxis(4, (float)event.button.y); + break; + case SDL_WINDOWEVENT: + { + switch (event.window.event) + { + case SDL_WINDOWEVENT_ENTER: + case SDL_WINDOWEVENT_FOCUS_GAINED: + m_mouse->SetKey(3, true); + break; + case SDL_WINDOWEVENT_LEAVE: + case SDL_WINDOWEVENT_FOCUS_LOST: + m_mouse->SetKey(3, false); + break; + } break; } +# endif # if !SDL_FORCE_POLL_JOYSTICK case SDL_JOYAXISMOTION: @@ -292,9 +406,7 @@ void SdlInputData::Tick(float seconds) # if !EMSCRIPTEN && USE_OLD_SDL m_mouse->SetKey(3, !!(SDL_GetAppState() & SDL_APPMOUSEFOCUS)); # else - // Emscripten doesn't seem to handle SDL_APPMOUSEFOCUS - // FIXME: SDL2 doesn't have SDL_APPMOUSEFOCUS either - m_mouse->SetKey(3, true); + //Handled in PollEvent # endif if (m_mousecapture) diff --git a/src/sys/file.cpp b/src/sys/file.cpp index 97535b93..25dc0554 100644 --- a/src/sys/file.cpp +++ b/src/sys/file.cpp @@ -197,7 +197,7 @@ class FileData #if __ANDROID__ return 0; #elif HAVE_STDIO_H - return m_stat.st_mtime; + return (long int)m_stat.st_mtime; #else return 0; #endif @@ -358,8 +358,10 @@ class DirectoryData filter.Replace('/', '\\', true); WIN32_FIND_DATA FindFileData; m_handle = FindFirstFile(filter.C(), &FindFileData); + stat(directory.C(), &m_stat); #elif HAVE_STDIO_H m_dd = opendir(directory.C()); + stat(directory.C(), &m_stat); #endif } @@ -440,6 +442,17 @@ class DirectoryData #endif } + long int GetModificationTime() + { +#if __ANDROID__ + return 0; +#elif HAVE_STDIO_H + return (long int)m_stat.st_mtime; +#else + return 0; +#endif + } + #if __ANDROID__ /* FIXME: not implemented */ #elif defined(_WIN32) @@ -450,6 +463,7 @@ class DirectoryData #endif std::atomic m_refcount; StreamType m_type; + struct stat m_stat; }; //-- DIRECTORY -- @@ -559,6 +573,12 @@ String Directory::GetName() return m_name; } +//-- +long int Directory::GetModificationTime() +{ + return m_data->GetModificationTime(); +} + //-- String Directory::GetCurrent() { diff --git a/src/sys/thread.cpp b/src/sys/thread.cpp index df637606..afe91cc4 100644 --- a/src/sys/thread.cpp +++ b/src/sys/thread.cpp @@ -54,7 +54,7 @@ bool BaseThreadManager::Stop() return false; //Stop all threads - StopThreads(m_threads.count()); + StopThreads((int)m_threads.count()); return true; } @@ -173,9 +173,9 @@ void BaseThreadManager::TickGame(float seconds) //Resize thread count if needed if (m_threads.count() > m_jobqueue.count() && m_threads.count() > m_thread_min) - StopThreads(m_threads.Count() - m_thread_min); + StopThreads((int)(m_threads.Count() - m_thread_min)); else if (m_threads.count() < m_jobqueue.count()) - AddThreads(lol::min(m_jobqueue.count(), (ptrdiff_t)m_thread_count) - m_threads.count()); + AddThreads((int)(lol::min(m_jobqueue.count(), (ptrdiff_t)m_thread_count) - m_threads.count())); } } /* namespace lol */