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 */ |