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); | WorldEntity::TickGame(seconds); | ||||
| m_time += 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 */ | /* Saturate dot color */ | ||||
| float x = std::max(m_color.x, std::max(m_color.y, m_color.z)); | float x = std::max(m_color.x, std::max(m_color.y, m_color.z)); | ||||
| m_color /= x; | m_color /= x; | ||||
| @@ -45,58 +45,63 @@ public: | |||||
| ShaderBlock green_pixel("GreenPixel"); | ShaderBlock green_pixel("GreenPixel"); | ||||
| ShaderBlock blue_pixel("BluePixel"); | 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 | builder << ShaderProgram::Vertex | ||||
| << ¬hing_vertex | |||||
| << nothing_vertex | |||||
| << ShaderProgram::Pixel | << ShaderProgram::Pixel | ||||
| << &red_pixel | |||||
| << &green_pixel | |||||
| << &blue_pixel; | |||||
| << red_pixel | |||||
| << green_pixel | |||||
| << blue_pixel; | |||||
| builder.Build(code); | builder.Build(code); | ||||
| @@ -442,7 +442,7 @@ Shader::Shader(String const &name, | |||||
| int Shader::GetAttribCount() const | int Shader::GetAttribCount() const | ||||
| { | { | ||||
| return data->attrib_locations.count(); | |||||
| return (int)data->attrib_locations.count(); | |||||
| } | } | ||||
| ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const | ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const | ||||
| @@ -469,6 +469,10 @@ ShaderAttrib Shader::GetAttribLocation(VertexUsage usage, int index) const | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| ShaderUniform Shader::GetUniformLocation(String const& uni) const | |||||
| { | |||||
| return GetUniformLocation(uni.C()); | |||||
| } | |||||
| ShaderUniform Shader::GetUniformLocation(char const *uni) const | ShaderUniform Shader::GetUniformLocation(char const *uni) const | ||||
| { | { | ||||
| ShaderUniform ret; | ShaderUniform ret; | ||||
| @@ -514,7 +518,7 @@ void Shader::SetUniform(ShaderUniform const &uni, int i) | |||||
| #if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
| SetUniform(uni, ivec4(i, 0, 0, 0)); | SetUniform(uni, ivec4(i, 0, 0, 0)); | ||||
| #else | #else | ||||
| glUniform1i(uni.frag, i); | |||||
| glUniform1i((GLint)uni.frag, i); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -523,7 +527,7 @@ void Shader::SetUniform(ShaderUniform const &uni, ivec2 const &v) | |||||
| #if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
| SetUniform(uni, ivec4(v, 0, 0)); | SetUniform(uni, ivec4(v, 0, 0)); | ||||
| #else | #else | ||||
| glUniform2i(uni.frag, v.x, v.y); | |||||
| glUniform2i((GLint)uni.frag, v.x, v.y); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -532,7 +536,7 @@ void Shader::SetUniform(ShaderUniform const &uni, ivec3 const &v) | |||||
| #if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
| SetUniform(uni, ivec4(v, 0)); | SetUniform(uni, ivec4(v, 0)); | ||||
| #else | #else | ||||
| glUniform3i(uni.frag, v.x, v.y, v.z); | |||||
| glUniform3i((GLint)uni.frag, v.x, v.y, v.z); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -544,7 +548,7 @@ void Shader::SetUniform(ShaderUniform const &uni, ivec4 const &v) | |||||
| if (uni.flags & 2) | if (uni.flags & 2) | ||||
| data->m_dev->SetVertexShaderConstantI((UINT)uni.vert, &v[0], 1); | data->m_dev->SetVertexShaderConstantI((UINT)uni.vert, &v[0], 1); | ||||
| #else | #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 | #endif | ||||
| } | } | ||||
| @@ -553,7 +557,7 @@ void Shader::SetUniform(ShaderUniform const &uni, float f) | |||||
| #if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
| SetUniform(uni, vec4(f, 0, 0, 0)); | SetUniform(uni, vec4(f, 0, 0, 0)); | ||||
| #else | #else | ||||
| glUniform1f(uni.frag, f); | |||||
| glUniform1f((GLint)uni.frag, f); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -562,7 +566,7 @@ void Shader::SetUniform(ShaderUniform const &uni, vec2 const &v) | |||||
| #if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
| SetUniform(uni, vec4(v, 0, 0)); | SetUniform(uni, vec4(v, 0, 0)); | ||||
| #else | #else | ||||
| glUniform2fv(uni.frag, 1, &v[0]); | |||||
| glUniform2fv((GLint)uni.frag, 1, &v[0]); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -571,7 +575,7 @@ void Shader::SetUniform(ShaderUniform const &uni, vec3 const &v) | |||||
| #if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
| SetUniform(uni, vec4(v, 0)); | SetUniform(uni, vec4(v, 0)); | ||||
| #else | #else | ||||
| glUniform3fv(uni.frag, 1, &v[0]); | |||||
| glUniform3fv((GLint)uni.frag, 1, &v[0]); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -583,7 +587,7 @@ void Shader::SetUniform(ShaderUniform const &uni, vec4 const &v) | |||||
| if (uni.flags & 2) | if (uni.flags & 2) | ||||
| data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &v[0], 1); | data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &v[0], 1); | ||||
| #else | #else | ||||
| glUniform4fv(uni.frag, 1, &v[0]); | |||||
| glUniform4fv((GLint)uni.frag, 1, &v[0]); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -596,7 +600,7 @@ void Shader::SetUniform(ShaderUniform const &uni, mat2 const &m) | |||||
| if (uni.flags & 2) | if (uni.flags & 2) | ||||
| data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 1); | data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 1); | ||||
| #else | #else | ||||
| glUniformMatrix2fv(uni.frag, 1, GL_FALSE, &m[0][0]); | |||||
| glUniformMatrix2fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -611,7 +615,7 @@ void Shader::SetUniform(ShaderUniform const &uni, mat3 const &m) | |||||
| if (uni.flags & 2) | if (uni.flags & 2) | ||||
| data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &tmp[0][0], 3); | data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &tmp[0][0], 3); | ||||
| #else | #else | ||||
| glUniformMatrix3fv(uni.frag, 1, GL_FALSE, &m[0][0]); | |||||
| glUniformMatrix3fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -623,7 +627,7 @@ void Shader::SetUniform(ShaderUniform const &uni, mat4 const &m) | |||||
| if (uni.flags & 2) | if (uni.flags & 2) | ||||
| data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 4); | data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 4); | ||||
| #else | #else | ||||
| glUniformMatrix4fv(uni.frag, 1, GL_FALSE, &m[0][0]); | |||||
| glUniformMatrix4fv((GLint)uni.frag, 1, GL_FALSE, &m[0][0]); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -658,7 +662,7 @@ void Shader::SetUniform(ShaderUniform const &uni, array<float> const &v) | |||||
| data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, | data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, | ||||
| &v[0], v.Count() / 4); | &v[0], v.Count() / 4); | ||||
| #else | #else | ||||
| glUniform1fv(uni.frag, v.Count(), &v[0]); | |||||
| glUniform1fv((GLint)uni.frag, (GLsizei)v.Count(), &v[0]); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -674,7 +678,7 @@ void Shader::SetUniform(ShaderUniform const &uni, array<vec2> const &v) | |||||
| data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, | data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, | ||||
| &v[0][0], v.Count() / 2); | &v[0][0], v.Count() / 2); | ||||
| #else | #else | ||||
| glUniform2fv(uni.frag, v.Count(), &v[0][0]); | |||||
| glUniform2fv((GLint)uni.frag, (GLsizei)v.Count(), &v[0][0]); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -690,7 +694,7 @@ void Shader::SetUniform(ShaderUniform const &uni, array<vec3> const &v) | |||||
| data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, | data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, | ||||
| &v[0][0], v.Count()); | &v[0][0], v.Count()); | ||||
| #else | #else | ||||
| glUniform3fv(uni.frag, v.Count(), &v[0][0]); | |||||
| glUniform3fv((GLint)uni.frag, (GLsizei)v.Count(), &v[0][0]); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -704,7 +708,7 @@ void Shader::SetUniform(ShaderUniform const &uni, array<vec4> const &v) | |||||
| data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, | data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, | ||||
| &v[0][0], v.Count()); | &v[0][0], v.Count()); | ||||
| #else | #else | ||||
| glUniform4fv(uni.frag, v.Count(), &v[0][0]); | |||||
| glUniform4fv((GLint)uni.frag, (GLsizei)v.Count(), &v[0][0]); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -934,6 +938,9 @@ String ShaderData::Patch(String const &code, ShaderType type) | |||||
| } | } | ||||
| static const String g_ret = "\n"; | 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 = " "; | static const String g_tab = " "; | ||||
| //---- | //---- | ||||
| @@ -1008,7 +1015,7 @@ String Shader::GetProgramQualifier(const ShaderProgram program) | |||||
| { | { | ||||
| switch (program.ToScalar()) | 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::Vertex: return String("[vert.glsl]"); | ||||
| case ShaderProgram::Pixel: return String("[frag.glsl]"); | case ShaderProgram::Pixel: return String("[frag.glsl]"); | ||||
| default: return String(); | default: return String(); | ||||
| @@ -1020,7 +1027,7 @@ String Shader::GetProgramOutVariable(const ShaderProgram program) | |||||
| { | { | ||||
| switch (program.ToScalar()) | 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::Vertex: return String("gl_Position"); | ||||
| case ShaderProgram::Pixel: return String("gl_FragColor"); | case ShaderProgram::Pixel: return String("gl_FragColor"); | ||||
| default: return String(); | default: return String(); | ||||
| @@ -1032,29 +1039,44 @@ String Shader::GetProgramOutVariableLocal(const ShaderProgram program) | |||||
| { | { | ||||
| switch (program.ToScalar()) | 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::Vertex: return String("out_position"); | ||||
| case ShaderProgram::Pixel: return String("out_frag_color"); | case ShaderProgram::Pixel: return String("out_frag_color"); | ||||
| default: return String(); | 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 ------------------------------------------- | //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(); | array<String> keys = variables.keys(); | ||||
| for (String key : keys) | for (String key : keys) | ||||
| { | { | ||||
| if (result.Count() > 0) | if (result.Count() > 0) | ||||
| result += ", "; | 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 += Shader::GetFunctionQualifier(type, program) + " "; | ||||
| result += variables[key]; | result += variables[key]; | ||||
| result += String(" "); | result += String(" "); | ||||
| result += Shader::GetVariablePrefix(type); | |||||
| result += key; | result += key; | ||||
| } | } | ||||
| } | } | ||||
| @@ -1085,7 +1106,7 @@ void ShaderBlock::Build(const ShaderProgram program, String& call, String& funct | |||||
| call = call_name + "("; | call = call_name + "("; | ||||
| String call_parameters; | String call_parameters; | ||||
| for (int i = 0; i < ShaderVariable::MAX; i++) | 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 + ");"; | call += call_parameters + ");"; | ||||
| //Build function declaration | //Build function declaration | ||||
| @@ -1133,6 +1154,14 @@ ShaderBuilder& ShaderBuilder::operator<<(ShaderBlock* block) | |||||
| return *this; | 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) | String ShaderBuilder::AddSlotOutVariableLocal(const ShaderProgram program) | ||||
| { | { | ||||
| @@ -1170,8 +1199,11 @@ void ShaderBuilder::MergeParameters(map<String, String>& variables, map<String, | |||||
| for (String key : keys) | for (String key : keys) | ||||
| { | { | ||||
| bool has_key = merged.has_key(key); | bool has_key = merged.has_key(key); | ||||
| //Key exists, check the type to make sure it's the same | //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 | //does not exist, had it | ||||
| if (!has_key) | if (!has_key) | ||||
| @@ -1217,8 +1249,7 @@ void ShaderBuilder::Build(String& code) | |||||
| for (String key : keys) | for (String key : keys) | ||||
| { | { | ||||
| code += Shader::GetVariableQualifier((ShaderVariable)var) + " "; | 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) | if (var + 1 < ShaderVariable::InOut) | ||||
| code += g_ret; | code += g_ret; | ||||
| @@ -1254,8 +1285,7 @@ void ShaderBuilder::Build(String& code) | |||||
| { | { | ||||
| if (keys.Count()) | 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; | 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); | 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 | * Conversion from colours to hexadecimal | ||||
| */ | */ | ||||
| @@ -133,8 +133,8 @@ void Image::DummyFill() | |||||
| void Image::Copy(uint8_t* pixels, ivec2 const& size, PixelFormat fmt) | void Image::Copy(uint8_t* pixels, ivec2 const& size, PixelFormat fmt) | ||||
| { | { | ||||
| ASSERT(fmt != PixelFormat::Unknown); | ASSERT(fmt != PixelFormat::Unknown); | ||||
| SetFormat(fmt); | |||||
| SetSize(size); | SetSize(size); | ||||
| SetFormat(fmt); | |||||
| memcpy(m_data->m_pixels[(int)fmt]->data(), pixels, | memcpy(m_data->m_pixels[(int)fmt]->data(), pixels, | ||||
| size.x * size.y * BytesPerPixel(fmt)); | size.x * size.y * BytesPerPixel(fmt)); | ||||
| } | } | ||||
| @@ -19,13 +19,77 @@ using namespace lol; | |||||
| //----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
| LolImGui::LolImGui() | LolImGui::LolImGui() | ||||
| { | { | ||||
| m_gamegroup = GAMEGROUP_BEFORE; | |||||
| m_drawgroup = DRAWGROUP_HUD; | 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() | LolImGui::~LolImGui() | ||||
| { | { | ||||
| ImGui::GetIO().Fonts->TexID = nullptr; | ImGui::GetIO().Fonts->TexID = nullptr; | ||||
| Ticker::Unref(m_font); | Ticker::Unref(m_font); | ||||
| m_font = nullptr; | m_font = nullptr; | ||||
| Shader::Destroy(m_shader); | |||||
| delete m_vdecl; | |||||
| } | } | ||||
| //------------------------------------------------------------------------- | //------------------------------------------------------------------------- | ||||
| @@ -35,69 +99,34 @@ void LolImGui::Init() | |||||
| Ticker::Ref(g_lolimgui = new LolImGui()); | Ticker::Ref(g_lolimgui = new LolImGui()); | ||||
| ImGuiIO& io = ImGui::GetIO(); | 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 | //Func pointer | ||||
| io.RenderDrawListsFn = LolImGui::RenderDrawLists; | io.RenderDrawListsFn = LolImGui::RenderDrawLists; | ||||
| io.SetClipboardTextFn = LolImGui::SetClipboard; | io.SetClipboardTextFn = LolImGui::SetClipboard; | ||||
| io.GetClipboardTextFn = LolImGui::GetClipboard; | 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 | /* 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) | void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) | ||||
| { | { | ||||
| ImGuiIO& io = ImGui::GetIO(); | ImGuiIO& io = ImGui::GetIO(); | ||||
| @@ -138,25 +167,12 @@ void LolImGui::TickGame(float seconds) | |||||
| // Build texture | // Build texture | ||||
| unsigned char* pixels; | unsigned char* pixels; | ||||
| ivec2 size; | ivec2 size; | ||||
| io.Fonts->GetTexDataAsAlpha8(&pixels, &size.x, &size.y); | |||||
| io.Fonts->GetTexDataAsRGBA32(&pixels, &size.x, &size.y); | |||||
| Image* image = new Image(); | Image* image = new Image(); | ||||
| image->Copy(pixels, size, PixelFormat::RGBA_8); | image->Copy(pixels, size, PixelFormat::RGBA_8); | ||||
| image->SetSize(size); | |||||
| Ticker::Ref(m_font = new TextureImage("", image)); | 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 | //Texture has been created | ||||
| if (m_font && m_font->GetTexture()) | if (m_font && m_font->GetTexture()) | ||||
| @@ -169,40 +185,73 @@ void LolImGui::TickGame(float seconds) | |||||
| video_size = vec2(Video::GetSize()); | video_size = vec2(Video::GetSize()); | ||||
| io.DisplaySize = ImVec2(video_size.x, video_size.y); | io.DisplaySize = ImVec2(video_size.x, video_size.y); | ||||
| // Setup time step | |||||
| //Setup time step | |||||
| io.DeltaTime = seconds; | 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 | // Start the frame | ||||
| ImGui::NewFrame(); | ImGui::NewFrame(); | ||||
| } | } | ||||
| void LolImGui::TickDraw(float seconds, Scene &scene) | void LolImGui::TickDraw(float seconds, Scene &scene) | ||||
| { | { | ||||
| super::TickDraw(seconds, 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) | // - 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) | 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) | if (cmd_lists_count == 0) | ||||
| return; | 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++) | for (int n = 0; n < cmd_lists_count; n++) | ||||
| { | { | ||||
| const ImDrawList* cmd_list = cmd_lists[n]; | const ImDrawList* cmd_list = cmd_lists[n]; | ||||
| const unsigned char* vtx_buffer = (const unsigned char*)&cmd_list->vtx_buffer.front(); | 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; | int vtx_offset = 0; | ||||
| for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++) | for (size_t cmd_i = 0; cmd_i < cmd_list->commands.size(); cmd_i++) | ||||
| { | { | ||||
| const ImDrawCmd* pcmd = &cmd_list->commands[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; | 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(); | ||||
| ~LolImGui(); | ~LolImGui(); | ||||
| @@ -40,8 +146,32 @@ protected: | |||||
| virtual void TickDraw(float seconds, Scene &scene); | virtual void TickDraw(float seconds, Scene &scene); | ||||
| static void RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count); | 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; | 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); | //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 | class Controller : public Entity | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -21,6 +21,9 @@ static String g_name_joystick(const uint64_t num) | |||||
| return String::Printf("Joystick%d", (int)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 | //Mouse default buttons/axis | ||||
| const String g_name_mouse_key_left("Left"); | const String g_name_mouse_key_left("Left"); | ||||
| const String g_name_mouse_key_middle("Middle"); | const String g_name_mouse_key_middle("Middle"); | ||||
| @@ -16,7 +16,7 @@ namespace lol | |||||
| /** Internal class (not public) that allows to construct an InputDevice | /** Internal class (not public) that allows to construct an InputDevice | ||||
| * dynamically, when the keys, axis and cursors are not known at | * dynamically, when the keys, axis and cursors are not known at | ||||
| * compile time. */ | * compile time. */ | ||||
| class InputDeviceInternal : InputDevice | |||||
| class InputDeviceInternal : public InputDevice | |||||
| { | { | ||||
| public: | public: | ||||
| inline InputDeviceInternal(char const * name) : InputDevice(name) { } | inline InputDeviceInternal(char const * name) : InputDevice(name) { } | ||||
| @@ -283,5 +283,10 @@ _SC(282, "", Sleep) | |||||
| _SC(283, "", App1) | _SC(283, "", App1) | ||||
| _SC(284, "", App2) | _SC(284, "", App2) | ||||
| //Custom Lock management | |||||
| _SC(285, "", CapsLockStatus) | |||||
| _SC(286, "", ScrollLockStatus) | |||||
| _SC(287, "", NumLockClearStatus) | |||||
| #undef _SC | #undef _SC | ||||
| @@ -54,6 +54,7 @@ public: | |||||
| /* Allow conversion from int and to the underlying type */ | /* Allow conversion from int and to the underlying type */ | ||||
| inline explicit SafeEnum(int i) : m_value(T(i)) {} | inline explicit SafeEnum(int i) : m_value(T(i)) {} | ||||
| inline Type ToScalar() const { return m_value; } | inline Type ToScalar() const { return m_value; } | ||||
| //inline class String ToString() const { return ToString(); } | |||||
| /* Convert to string stuff */ | /* Convert to string stuff */ | ||||
| inline class String ToString() | inline class String ToString() | ||||
| @@ -127,6 +127,11 @@ public: | |||||
| return String(&(*this)[start], item_count); | 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 | ptrdiff_t index_of(char token) const | ||||
| { | { | ||||
| using namespace std; | using namespace std; | ||||
| @@ -135,6 +140,7 @@ public: | |||||
| return tmp ? (ptrdiff_t)(tmp - C()) : INDEX_NONE; | 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 | ptrdiff_t index_of(char const* token) const | ||||
| { | { | ||||
| using namespace std; | using namespace std; | ||||
| @@ -143,11 +149,6 @@ public: | |||||
| return tmp ? (ptrdiff_t)(tmp - C()) : INDEX_NONE; | 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 | ptrdiff_t last_index_of(char token) const | ||||
| { | { | ||||
| using namespace std; | using namespace std; | ||||
| @@ -156,6 +157,18 @@ public: | |||||
| return tmp ? (ptrdiff_t)(tmp - C()) : INDEX_NONE; | 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, | int replace(char const old_token, char const new_token, | ||||
| bool all_occurrences = false) | bool all_occurrences = false) | ||||
| { | { | ||||
| @@ -173,34 +186,32 @@ public: | |||||
| return res; | return res; | ||||
| } | } | ||||
| /* FIXME: it doesn't sound safe to apply this in place */ | |||||
| inline String& to_lower() | 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; | return *this; | ||||
| } | } | ||||
| inline String& to_upper() | 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; | 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 | bool starts_with(String const &s) const | ||||
| @@ -231,6 +242,12 @@ public: | |||||
| return ret += s; | return ret += s; | ||||
| } | } | ||||
| inline String operator +(char c) const | |||||
| { | |||||
| String ret(*this); | |||||
| return ret += c; | |||||
| } | |||||
| inline String& operator +=(String const &s) | inline String& operator +=(String const &s) | ||||
| { | { | ||||
| using namespace std; | using namespace std; | ||||
| @@ -240,12 +257,6 @@ public: | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| inline String operator +(char c) const | |||||
| { | |||||
| String ret(*this); | |||||
| return ret += c; | |||||
| } | |||||
| inline String& operator +=(char c) | inline String& operator +=(char c) | ||||
| { | { | ||||
| ((super &)*this).last() = c; | ((super &)*this).last() = c; | ||||
| @@ -306,6 +317,7 @@ public: | |||||
| inline void Resize(ptrdiff_t item_count) { return resize(item_count); } | inline void Resize(ptrdiff_t item_count) { return resize(item_count); } | ||||
| inline String& ToLower() { return to_lower(); } | inline String& ToLower() { return to_lower(); } | ||||
| inline String& ToUpper() { return to_upper(); } | 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 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 bool Contains(String const &s) const { return contains(s); } | ||||
| inline ptrdiff_t IndexOf(char token) const { return index_of(token); } | inline ptrdiff_t IndexOf(char token) const { return index_of(token); } | ||||
| @@ -318,6 +330,26 @@ public: | |||||
| inline ptrdiff_t Count() const { return count(); } | 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) | inline bool operator ==(char const* sz, String const &s) | ||||
| { | { | ||||
| return s == sz; | return s == sz; | ||||
| @@ -134,6 +134,134 @@ protected: | |||||
| }; | }; | ||||
| typedef SafeEnum<ShaderProgramBase> ShaderProgram; | 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 --------------------------------------------------------------- | //ShaderUniform --------------------------------------------------------------- | ||||
| struct ShaderUniform | struct ShaderUniform | ||||
| { | { | ||||
| @@ -193,6 +321,7 @@ public: | |||||
| int GetAttribCount() const; | int GetAttribCount() const; | ||||
| ShaderAttrib GetAttribLocation(VertexUsage usage, int index) const; | ShaderAttrib GetAttribLocation(VertexUsage usage, int index) const; | ||||
| ShaderUniform GetUniformLocation(String const& uni) const; | |||||
| ShaderUniform GetUniformLocation(char const *uni) const; | ShaderUniform GetUniformLocation(char const *uni) const; | ||||
| void SetUniform(ShaderUniform const &uni, int i); | void SetUniform(ShaderUniform const &uni, int i); | ||||
| void SetUniform(ShaderUniform const &uni, ivec2 const &v); | void SetUniform(ShaderUniform const &uni, ivec2 const &v); | ||||
| @@ -231,6 +360,39 @@ public: | |||||
| static String GetProgramOutVariableLocal(const ShaderProgram program); | 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 ----------------------------------------------------------------- | //ShaderBlock ----------------------------------------------------------------- | ||||
| class ShaderBlock | class ShaderBlock | ||||
| { | { | ||||
| @@ -260,10 +422,15 @@ public: | |||||
| //Sets custom code that will be put before the main -so functions- | //Sets custom code that will be put before the main -so functions- | ||||
| void SetCustomCode(String const& code_custom) { m_code_custom = code_custom; } | void SetCustomCode(String const& code_custom) { m_code_custom = code_custom; } | ||||
| //Add parameter to the block | //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: | 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 AddDefinitionParameters(const ShaderVariable variable, const ShaderProgram program, map<String, String>& variables, String& result); | ||||
| void Build(const ShaderProgram program, String& call, String& function); | void Build(const ShaderProgram program, String& call, String& function); | ||||
| }; | }; | ||||
| @@ -289,6 +456,7 @@ public: | |||||
| String const& GetName(); | String const& GetName(); | ||||
| ShaderBuilder& operator<<(const ShaderProgram program); | ShaderBuilder& operator<<(const ShaderProgram program); | ||||
| ShaderBuilder& operator<<(ShaderBlock* block); | ShaderBuilder& operator<<(ShaderBlock* block); | ||||
| ShaderBuilder& operator<<(ShaderBlock const& block); | |||||
| protected: | protected: | ||||
| String AddSlotOutVariableLocal(const ShaderProgram program); | String AddSlotOutVariableLocal(const ShaderProgram program); | ||||
| @@ -316,6 +316,22 @@ public: | |||||
| */ | */ | ||||
| static vec3 WavelengthToCIExyY(float nm); | 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. | * Convert colors to hex strings. | ||||
| */ | */ | ||||
| @@ -107,6 +107,7 @@ public: | |||||
| bool GetContent(array<Directory>& directories); | bool GetContent(array<Directory>& directories); | ||||
| bool GetContent(array<String>& files); | bool GetContent(array<String>& files); | ||||
| String GetName(); | String GetName(); | ||||
| long int GetModificationTime(); | |||||
| static String GetCurrent(); | static String GetCurrent(); | ||||
| static bool SetCurrent(String directory); | static bool SetCurrent(String directory); | ||||
| @@ -417,6 +417,9 @@ | |||||
| <ProjectReference Include="bullet\lolbullet.vcxproj"> | <ProjectReference Include="bullet\lolbullet.vcxproj"> | ||||
| <Project>{83d3b207-c601-4025-8f41-01dedc354661}</Project> | <Project>{83d3b207-c601-4025-8f41-01dedc354661}</Project> | ||||
| </ProjectReference> | </ProjectReference> | ||||
| <ProjectReference Include="imgui\lolimgui.vcxproj"> | |||||
| <Project>{a7f6fdf8-937e-41ef-b44d-04cd1a48c179}</Project> | |||||
| </ProjectReference> | |||||
| <ProjectReference Include="lua\lollua.vcxproj"> | <ProjectReference Include="lua\lollua.vcxproj"> | ||||
| <Project>{d84021ca-b233-4e0f-8a52-071b83bbccc4}</Project> | <Project>{d84021ca-b233-4e0f-8a52-071b83bbccc4}</Project> | ||||
| </ProjectReference> | </ProjectReference> | ||||
| @@ -49,6 +49,48 @@ static int sdl12_to_scancode(int ch, int sc) | |||||
| return 0; | 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 | #endif | ||||
| /* | /* | ||||
| @@ -218,30 +260,102 @@ void SdlInputData::Tick(float seconds) | |||||
| case SDL_KEYDOWN: | case SDL_KEYDOWN: | ||||
| case SDL_KEYUP: | 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; | break; | ||||
| # if USE_OLD_SDL | |||||
| case SDL_MOUSEBUTTONDOWN: | case SDL_MOUSEBUTTONDOWN: | ||||
| case SDL_MOUSEBUTTONUP: | case SDL_MOUSEBUTTONUP: | ||||
| { | |||||
| # if USE_OLD_SDL | |||||
| if (event.button.button != SDL_BUTTON_WHEELUP && event.button.button != SDL_BUTTON_WHEELDOWN) | if (event.button.button != SDL_BUTTON_WHEELUP && event.button.button != SDL_BUTTON_WHEELDOWN) | ||||
| m_mouse->SetKey(event.button.button - 1, event.type == SDL_MOUSEBUTTONDOWN); | m_mouse->SetKey(event.button.button - 1, event.type == SDL_MOUSEBUTTONDOWN); | ||||
| else | else | ||||
| m_mouse->SetAxis(4, (event.button.button != SDL_BUTTON_WHEELUP) ? (1) : (-1)); | 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; | break; | ||||
| } | } | ||||
| # endif | |||||
| # if !SDL_FORCE_POLL_JOYSTICK | # if !SDL_FORCE_POLL_JOYSTICK | ||||
| case SDL_JOYAXISMOTION: | case SDL_JOYAXISMOTION: | ||||
| @@ -292,9 +406,7 @@ void SdlInputData::Tick(float seconds) | |||||
| # if !EMSCRIPTEN && USE_OLD_SDL | # if !EMSCRIPTEN && USE_OLD_SDL | ||||
| m_mouse->SetKey(3, !!(SDL_GetAppState() & SDL_APPMOUSEFOCUS)); | m_mouse->SetKey(3, !!(SDL_GetAppState() & SDL_APPMOUSEFOCUS)); | ||||
| # else | # 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 | # endif | ||||
| if (m_mousecapture) | if (m_mousecapture) | ||||
| @@ -197,7 +197,7 @@ class FileData | |||||
| #if __ANDROID__ | #if __ANDROID__ | ||||
| return 0; | return 0; | ||||
| #elif HAVE_STDIO_H | #elif HAVE_STDIO_H | ||||
| return m_stat.st_mtime; | |||||
| return (long int)m_stat.st_mtime; | |||||
| #else | #else | ||||
| return 0; | return 0; | ||||
| #endif | #endif | ||||
| @@ -358,8 +358,10 @@ class DirectoryData | |||||
| filter.Replace('/', '\\', true); | filter.Replace('/', '\\', true); | ||||
| WIN32_FIND_DATA FindFileData; | WIN32_FIND_DATA FindFileData; | ||||
| m_handle = FindFirstFile(filter.C(), &FindFileData); | m_handle = FindFirstFile(filter.C(), &FindFileData); | ||||
| stat(directory.C(), &m_stat); | |||||
| #elif HAVE_STDIO_H | #elif HAVE_STDIO_H | ||||
| m_dd = opendir(directory.C()); | m_dd = opendir(directory.C()); | ||||
| stat(directory.C(), &m_stat); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -440,6 +442,17 @@ class DirectoryData | |||||
| #endif | #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__ | #if __ANDROID__ | ||||
| /* FIXME: not implemented */ | /* FIXME: not implemented */ | ||||
| #elif defined(_WIN32) | #elif defined(_WIN32) | ||||
| @@ -450,6 +463,7 @@ class DirectoryData | |||||
| #endif | #endif | ||||
| std::atomic<int> m_refcount; | std::atomic<int> m_refcount; | ||||
| StreamType m_type; | StreamType m_type; | ||||
| struct stat m_stat; | |||||
| }; | }; | ||||
| //-- DIRECTORY -- | //-- DIRECTORY -- | ||||
| @@ -559,6 +573,12 @@ String Directory::GetName() | |||||
| return m_name; | return m_name; | ||||
| } | } | ||||
| //-- | |||||
| long int Directory::GetModificationTime() | |||||
| { | |||||
| return m_data->GetModificationTime(); | |||||
| } | |||||
| //-- | //-- | ||||
| String Directory::GetCurrent() | String Directory::GetCurrent() | ||||
| { | { | ||||
| @@ -54,7 +54,7 @@ bool BaseThreadManager::Stop() | |||||
| return false; | return false; | ||||
| //Stop all threads | //Stop all threads | ||||
| StopThreads(m_threads.count()); | |||||
| StopThreads((int)m_threads.count()); | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -173,9 +173,9 @@ void BaseThreadManager::TickGame(float seconds) | |||||
| //Resize thread count if needed | //Resize thread count if needed | ||||
| if (m_threads.count() > m_jobqueue.count() && m_threads.count() > m_thread_min) | 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()) | 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 */ | } /* namespace lol */ | ||||