SDL2: Mouse is back ! With correct focus support SDL2: Added typing support with keyboard ShaderBuilder: Refactored and simplified Shader block creation Several warning removal Fixed Image::Copyundefined
| @@ -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; | |||
| @@ -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); | |||
| @@ -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<float> 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<vec2> 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<vec3> 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<vec4> 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<String, String> const& variables, String& result) | |||
| void ShaderBlock::AddCallParameters(map<String, String> const& variables, String& result) | |||
| { | |||
| array<String> 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<String, String>& variables, map<String, | |||
| for (String key : keys) | |||
| { | |||
| bool has_key = merged.has_key(key); | |||
| //Key exists, check the type to make sure it's the same | |||
| ASSERT(!(has_key && merged[key] != variables[key])); | |||
| ASSERT(!has_key || (has_key && merged[key] == variables[key]), | |||
| "has_key=%d, key=%s merged[key]=%s, variables[key]=%s\n", | |||
| (int)has_key, key.C(), merged[key].C(), variables[key].C()); | |||
| //does not exist, had it | |||
| if (!has_key) | |||
| @@ -1217,8 +1249,7 @@ void ShaderBuilder::Build(String& code) | |||
| for (String key : keys) | |||
| { | |||
| code += Shader::GetVariableQualifier((ShaderVariable)var) + " "; | |||
| code += m_parameters[prog][var][key] + " " + | |||
| Shader::GetVariablePrefix((ShaderVariable)var) + key + ";" + g_ret; | |||
| code += m_parameters[prog][var][key] + " " + key + ";" + g_ret; | |||
| } | |||
| if (var + 1 < ShaderVariable::InOut) | |||
| code += g_ret; | |||
| @@ -1254,8 +1285,7 @@ void ShaderBuilder::Build(String& code) | |||
| { | |||
| if (keys.Count()) | |||
| { | |||
| code += g_tab + m_parameters[prog][var][key] + " " + | |||
| Shader::GetVariablePrefix((ShaderVariable)var) + key + ";" + g_ret; | |||
| code += g_tab + m_parameters[prog][var][key] + " " + key + ";" + g_ret; | |||
| } | |||
| } | |||
| code += g_ret; | |||
| @@ -55,6 +55,55 @@ String Color::HexString8Bpp(vec4 c) | |||
| return String::Printf("%02x%2x%02x%02x", c2.r, c2.g, c2.b, c2.a); | |||
| } | |||
| /* | |||
| * Convert uint color to vec4. | |||
| */ | |||
| vec4 Color::FromRGBA32(uint32_t c) | |||
| { | |||
| ivec4 v(c >> 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 | |||
| */ | |||
| @@ -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)); | |||
| } | |||
| @@ -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<vec2, vec2, u8vec4>( | |||
| 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 | |||
| //----------------------------------------------------------------- | |||
| //<Debug render> -------------------------------------------------- | |||
| //----------------------------------------------------------------- | |||
| 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(); | |||
| } | |||
| @@ -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<int64_t, String>& 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<LolImGuiKeyBase> 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<int64_t, String>& enum_map) | |||
| { | |||
| enum_map[Scroll] = g_name_mouse_axis_scroll; | |||
| return true; | |||
| } | |||
| }; | |||
| typedef SafeEnum<LolImGuiAxisBase> 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<ShaderAttrib> m_attribs; | |||
| VertexDeclaration* m_vdecl = nullptr; | |||
| Controller* m_controller = nullptr; | |||
| InputDevice* m_mouse = nullptr; | |||
| InputDevice* m_keyboard = nullptr; | |||
| InputProfile m_profile; | |||
| //map<ImGuiKey_, LolImGuiKey> m_keys; | |||
| }; | |||
| //bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks); | |||
| @@ -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: | |||
| @@ -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"); | |||
| @@ -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) { } | |||
| @@ -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 | |||
| @@ -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() | |||
| @@ -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; | |||
| @@ -134,6 +134,134 @@ protected: | |||
| }; | |||
| typedef SafeEnum<ShaderProgramBase> 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<int64_t, String>& 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<ShaderVariableTypeBase> 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<String, String> const& variables, String& result); | |||
| void AddCallParameters(map<String, String> const& variables, String& result); | |||
| void AddDefinitionParameters(const ShaderVariable variable, const ShaderProgram program, map<String, String>& 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); | |||
| @@ -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. | |||
| */ | |||
| @@ -107,6 +107,7 @@ public: | |||
| bool GetContent(array<Directory>& directories); | |||
| bool GetContent(array<String>& files); | |||
| String GetName(); | |||
| long int GetModificationTime(); | |||
| static String GetCurrent(); | |||
| static bool SetCurrent(String directory); | |||
| @@ -417,6 +417,9 @@ | |||
| <ProjectReference Include="bullet\lolbullet.vcxproj"> | |||
| <Project>{83d3b207-c601-4025-8f41-01dedc354661}</Project> | |||
| </ProjectReference> | |||
| <ProjectReference Include="imgui\lolimgui.vcxproj"> | |||
| <Project>{a7f6fdf8-937e-41ef-b44d-04cd1a48c179}</Project> | |||
| </ProjectReference> | |||
| <ProjectReference Include="lua\lollua.vcxproj"> | |||
| <Project>{d84021ca-b233-4e0f-8a52-071b83bbccc4}</Project> | |||
| </ProjectReference> | |||
| @@ -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) | |||
| @@ -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<int> 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() | |||
| { | |||
| @@ -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 */ | |||