From e9f8046b2df7adcd9743628426ee2c9bb63435f5 Mon Sep 17 00:00:00 2001 From: nschimme <5505185+nschimme@users.noreply.github.com> Date: Mon, 14 Sep 2026 12:36:57 +0000 Subject: [PATCH 1/9] Fix GLSL shader compilation errors on non-C locales - Use locale-invariant float string formatting (`text_utils::formatFloatClassic`) in ShaderUtils.cpp for preprocessor defines (WEATHER_RADIUS, etc.) to ensure a '.' decimal separator regardless of active system locale. - Fix array declaration syntax in room/tex/acolor/vert.glsl from `const ivec3[4] ioffsets` to `const ivec3 ioffsets[4]` for compatibility with GLSL 3.30 and GLSL ES 3.00 (WebGL 2) compilers. - Add unit test coverage in TestGlobal. --- src/global/TextUtils.cpp | 30 +++++++++++++++++++ src/global/TextUtils.h | 2 ++ src/opengl/legacy/ShaderUtils.cpp | 8 ++--- .../shaders/legacy/room/tex/acolor/vert.glsl | 4 +-- tests/TestGlobal.cpp | 19 ++++++++++++ tests/TestGlobal.h | 1 + 6 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/global/TextUtils.cpp b/src/global/TextUtils.cpp index f7b63de9c..b187b06f8 100644 --- a/src/global/TextUtils.cpp +++ b/src/global/TextUtils.cpp @@ -8,8 +8,10 @@ #include "Consts.h" #include "tests.h" +#include #include #include +#include #include #include @@ -39,6 +41,15 @@ bool isAbbrev(const std::string_view abbr, const std::string_view fullText) } namespace text_utils { + +std::string formatFloatClassic(const float val) +{ + std::ostringstream ss; + ss.imbue(std::locale::classic()); + ss << std::showpoint << val; + return ss.str(); +} + SplitResult split_at(const std::string_view sv, const size_t pos) { assert(pos <= sv.size()); @@ -216,6 +227,24 @@ void testTrim() } } +void testFormatFloatClassic() +{ + const char *oldLocale = std::setlocale(LC_ALL, nullptr); + std::string savedLocale = oldLocale ? oldLocale : "C"; + + std::setlocale(LC_ALL, "de_DE.UTF-8"); + + const std::string radStr = text_utils::formatFloatClassic(14.0f); + TEST_ASSERT(radStr.find(',') == std::string::npos); + TEST_ASSERT(radStr.find('.') != std::string::npos); + + const std::string extStr = text_utils::formatFloatClassic(28.5f); + TEST_ASSERT(extStr.find(',') == std::string::npos); + TEST_ASSERT(extStr.find('.') != std::string::npos); + + std::setlocale(LC_ALL, savedLocale.c_str()); +} + } // namespace namespace test { @@ -223,5 +252,6 @@ void testTextUtils() { testPrefixSuffix(); testTrim(); + testFormatFloatClassic(); } } // namespace test diff --git a/src/global/TextUtils.h b/src/global/TextUtils.h index 0e680a9a1..81f1ffa37 100644 --- a/src/global/TextUtils.h +++ b/src/global/TextUtils.h @@ -19,6 +19,8 @@ NODISCARD extern bool isAbbrev(std::string_view abbr, std::string_view fullText) namespace text_utils { +NODISCARD std::string formatFloatClassic(float val); + template struct NODISCARD SplitResult final { diff --git a/src/opengl/legacy/ShaderUtils.cpp b/src/opengl/legacy/ShaderUtils.cpp index 0d107e85d..843de899a 100644 --- a/src/opengl/legacy/ShaderUtils.cpp +++ b/src/opengl/legacy/ShaderUtils.cpp @@ -224,15 +224,15 @@ NODISCARD static GLuint compileShader(Functions &gl, const GLenum type, const So std::string defineNamedColors = "#define MAX_NAMED_COLORS " + std::to_string(MAX_NAMED_COLORS) + "\n"; std::string defineWeatherRadius = "#define WEATHER_RADIUS " - + std::to_string(WeatherConstants::WEATHER_RADIUS) + "\n"; + + text_utils::formatFloatClassic(WeatherConstants::WEATHER_RADIUS) + "\n"; std::string defineWeatherExtent = "#define WEATHER_EXTENT " - + std::to_string(WeatherConstants::WEATHER_EXTENT) + "\n"; + + text_utils::formatFloatClassic(WeatherConstants::WEATHER_EXTENT) + "\n"; std::string defineWeatherMaskOuter = "#define WEATHER_MASK_RADIUS_OUTER " - + std::to_string( + + text_utils::formatFloatClassic( WeatherConstants::WEATHER_MASK_RADIUS_OUTER) + "\n"; std::string defineWeatherMaskInner = "#define WEATHER_MASK_RADIUS_INNER " - + std::to_string( + + text_utils::formatFloatClassic( WeatherConstants::WEATHER_MASK_RADIUS_INNER) + "\n"; diff --git a/src/resources/shaders/legacy/room/tex/acolor/vert.glsl b/src/resources/shaders/legacy/room/tex/acolor/vert.glsl index 2bbeb02f5..34a79167d 100644 --- a/src/resources/shaders/legacy/room/tex/acolor/vert.glsl +++ b/src/resources/shaders/legacy/room/tex/acolor/vert.glsl @@ -20,14 +20,14 @@ void main() // | /| Triangles 012 and 023 both use CCW order. // |/ | Notice that the four vertices are in CCW order. // 0--1 - const ivec3[4] ioffsets = ivec3[4](ivec3(0, 0, 0), ivec3(1, 0, 0), ivec3(1, 1, 0), ivec3(0, 1, 0)); // fan + const ivec3 ioffsets[4] = ivec3[4](ivec3(0, 0, 0), ivec3(1, 0, 0), ivec3(1, 1, 0), ivec3(0, 1, 0)); // fan #else // GL_TRIANGLE_STRIP // 2--3 Note: Triangle strips alternate CCW/CW winding on every other triangle. This means... // |\ | triangle 012 is CCW order, but triangle 123 is CW order (backwards). // | \| Keep in mind that OpenGL does not actually draw the triangle backwards, // 0--1 so it does not affect glFrontFace() or the gl_FrontFacing variable. - const ivec3[4] ioffsets = ivec3[4](ivec3(0, 0, 0), ivec3(1, 0, 0), ivec3(0, 1, 0), ivec3(1, 1, 0)); // strip + const ivec3 ioffsets[4] = ivec3[4](ivec3(0, 0, 0), ivec3(1, 0, 0), ivec3(0, 1, 0), ivec3(1, 1, 0)); // strip #endif ivec3 ioffset = ioffsets[gl_VertexID]; diff --git a/tests/TestGlobal.cpp b/tests/TestGlobal.cpp index 28ef7f8f0..01f17837e 100644 --- a/tests/TestGlobal.cpp +++ b/tests/TestGlobal.cpp @@ -27,6 +27,7 @@ #include "../src/global/unquote.h" #include "../src/global/utils.h" +#include #include #include @@ -498,6 +499,24 @@ void sig2_test_recursion() } // namespace +void TestGlobal::shaderUtilsTest() +{ + const char *oldLocale = std::setlocale(LC_ALL, nullptr); + std::string savedLocale = oldLocale ? oldLocale : "C"; + + std::setlocale(LC_ALL, "de_DE.UTF-8"); + + const std::string radStr = text_utils::formatFloatClassic(14.0f); + QCOMPARE(radStr.find(','), std::string::npos); + QVERIFY(radStr.find('.') != std::string::npos); + + const std::string extStr = text_utils::formatFloatClassic(28.5f); + QCOMPARE(extStr.find(','), std::string::npos); + QVERIFY(extStr.find('.') != std::string::npos); + + std::setlocale(LC_ALL, savedLocale.c_str()); +} + void TestGlobal::signal2Test() { sig2_test_disconnects(); diff --git a/tests/TestGlobal.h b/tests/TestGlobal.h index 97e96d798..cbc8ce530 100644 --- a/tests/TestGlobal.h +++ b/tests/TestGlobal.h @@ -32,6 +32,7 @@ private Q_SLOTS: static void indexedVectorWithDefaultTest(); static void lineUtilsTest(); static void powerOfTwoTest(); + static void shaderUtilsTest(); static void signal2Test(); static void stringViewTest(); static void taggedStringTest(); From fc4bab28140ab13af0a10fce74c04e1c479661db Mon Sep 17 00:00:00 2001 From: nschimme <5505185+nschimme@users.noreply.github.com> Date: Mon, 14 Sep 2026 12:44:25 +0000 Subject: [PATCH 2/9] Fix GLSL shader compilation errors on non-C locales - Use locale-invariant float string formatting (`text_utils::formatFloatClassic`) in ShaderUtils.cpp for preprocessor defines (WEATHER_RADIUS, etc.) to ensure a '.' decimal separator regardless of active system locale. - Fix array declaration syntax in room/tex/acolor/vert.glsl from `const ivec3[4] ioffsets` to `const ivec3 ioffsets[4]` for compatibility with GLSL 3.30 and GLSL ES 3.00 (WebGL 2) compilers. - Add unit test coverage in TestGlobal. --- src/opengl/legacy/ShaderUtils.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/opengl/legacy/ShaderUtils.cpp b/src/opengl/legacy/ShaderUtils.cpp index 843de899a..0fe8ad8dd 100644 --- a/src/opengl/legacy/ShaderUtils.cpp +++ b/src/opengl/legacy/ShaderUtils.cpp @@ -224,9 +224,13 @@ NODISCARD static GLuint compileShader(Functions &gl, const GLenum type, const So std::string defineNamedColors = "#define MAX_NAMED_COLORS " + std::to_string(MAX_NAMED_COLORS) + "\n"; std::string defineWeatherRadius = "#define WEATHER_RADIUS " - + text_utils::formatFloatClassic(WeatherConstants::WEATHER_RADIUS) + "\n"; + + text_utils::formatFloatClassic( + WeatherConstants::WEATHER_RADIUS) + + "\n"; std::string defineWeatherExtent = "#define WEATHER_EXTENT " - + text_utils::formatFloatClassic(WeatherConstants::WEATHER_EXTENT) + "\n"; + + text_utils::formatFloatClassic( + WeatherConstants::WEATHER_EXTENT) + + "\n"; std::string defineWeatherMaskOuter = "#define WEATHER_MASK_RADIUS_OUTER " + text_utils::formatFloatClassic( WeatherConstants::WEATHER_MASK_RADIUS_OUTER) From 9a6387c2f04b208b815a4e52419d419e071b0db8 Mon Sep 17 00:00:00 2001 From: nschimme <5505185+nschimme@users.noreply.github.com> Date: Mon, 14 Sep 2026 13:46:02 +0000 Subject: [PATCH 3/9] Fix GLSL shader compilation errors on non-C locales - Use locale-invariant float string formatting (`text_utils::formatFloatClassic`) in ShaderUtils.cpp for preprocessor defines (WEATHER_RADIUS, etc.) to ensure a '.' decimal separator regardless of active system locale. - Fix array declaration syntax in room/tex/acolor/vert.glsl from `const ivec3[4] ioffsets` to `const ivec3 ioffsets[4]` for compatibility with GLSL 3.30 and GLSL ES 3.00 (WebGL 2) compilers. - Add unit test coverage in TestGlobal. --- src/global/TextUtils.cpp | 30 ------------------- src/global/TextUtils.h | 2 -- src/opengl/legacy/ShaderUtils.cpp | 12 +++----- .../shaders/legacy/room/tex/acolor/vert.glsl | 7 +++-- tests/TestGlobal.cpp | 19 ------------ tests/TestGlobal.h | 1 - 6 files changed, 9 insertions(+), 62 deletions(-) diff --git a/src/global/TextUtils.cpp b/src/global/TextUtils.cpp index b187b06f8..f7b63de9c 100644 --- a/src/global/TextUtils.cpp +++ b/src/global/TextUtils.cpp @@ -8,10 +8,8 @@ #include "Consts.h" #include "tests.h" -#include #include #include -#include #include #include @@ -41,15 +39,6 @@ bool isAbbrev(const std::string_view abbr, const std::string_view fullText) } namespace text_utils { - -std::string formatFloatClassic(const float val) -{ - std::ostringstream ss; - ss.imbue(std::locale::classic()); - ss << std::showpoint << val; - return ss.str(); -} - SplitResult split_at(const std::string_view sv, const size_t pos) { assert(pos <= sv.size()); @@ -227,24 +216,6 @@ void testTrim() } } -void testFormatFloatClassic() -{ - const char *oldLocale = std::setlocale(LC_ALL, nullptr); - std::string savedLocale = oldLocale ? oldLocale : "C"; - - std::setlocale(LC_ALL, "de_DE.UTF-8"); - - const std::string radStr = text_utils::formatFloatClassic(14.0f); - TEST_ASSERT(radStr.find(',') == std::string::npos); - TEST_ASSERT(radStr.find('.') != std::string::npos); - - const std::string extStr = text_utils::formatFloatClassic(28.5f); - TEST_ASSERT(extStr.find(',') == std::string::npos); - TEST_ASSERT(extStr.find('.') != std::string::npos); - - std::setlocale(LC_ALL, savedLocale.c_str()); -} - } // namespace namespace test { @@ -252,6 +223,5 @@ void testTextUtils() { testPrefixSuffix(); testTrim(); - testFormatFloatClassic(); } } // namespace test diff --git a/src/global/TextUtils.h b/src/global/TextUtils.h index 81f1ffa37..0e680a9a1 100644 --- a/src/global/TextUtils.h +++ b/src/global/TextUtils.h @@ -19,8 +19,6 @@ NODISCARD extern bool isAbbrev(std::string_view abbr, std::string_view fullText) namespace text_utils { -NODISCARD std::string formatFloatClassic(float val); - template struct NODISCARD SplitResult final { diff --git a/src/opengl/legacy/ShaderUtils.cpp b/src/opengl/legacy/ShaderUtils.cpp index 0fe8ad8dd..0d107e85d 100644 --- a/src/opengl/legacy/ShaderUtils.cpp +++ b/src/opengl/legacy/ShaderUtils.cpp @@ -224,19 +224,15 @@ NODISCARD static GLuint compileShader(Functions &gl, const GLenum type, const So std::string defineNamedColors = "#define MAX_NAMED_COLORS " + std::to_string(MAX_NAMED_COLORS) + "\n"; std::string defineWeatherRadius = "#define WEATHER_RADIUS " - + text_utils::formatFloatClassic( - WeatherConstants::WEATHER_RADIUS) - + "\n"; + + std::to_string(WeatherConstants::WEATHER_RADIUS) + "\n"; std::string defineWeatherExtent = "#define WEATHER_EXTENT " - + text_utils::formatFloatClassic( - WeatherConstants::WEATHER_EXTENT) - + "\n"; + + std::to_string(WeatherConstants::WEATHER_EXTENT) + "\n"; std::string defineWeatherMaskOuter = "#define WEATHER_MASK_RADIUS_OUTER " - + text_utils::formatFloatClassic( + + std::to_string( WeatherConstants::WEATHER_MASK_RADIUS_OUTER) + "\n"; std::string defineWeatherMaskInner = "#define WEATHER_MASK_RADIUS_INNER " - + text_utils::formatFloatClassic( + + std::to_string( WeatherConstants::WEATHER_MASK_RADIUS_INNER) + "\n"; diff --git a/src/resources/shaders/legacy/room/tex/acolor/vert.glsl b/src/resources/shaders/legacy/room/tex/acolor/vert.glsl index 34a79167d..d39dbedac 100644 --- a/src/resources/shaders/legacy/room/tex/acolor/vert.glsl +++ b/src/resources/shaders/legacy/room/tex/acolor/vert.glsl @@ -20,14 +20,17 @@ void main() // | /| Triangles 012 and 023 both use CCW order. // |/ | Notice that the four vertices are in CCW order. // 0--1 - const ivec3 ioffsets[4] = ivec3[4](ivec3(0, 0, 0), ivec3(1, 0, 0), ivec3(1, 1, 0), ivec3(0, 1, 0)); // fan + const ivec3[4] ioffsets = ivec3[4](ivec3(0, 0, 0), ivec3(1, 0, 0), ivec3(1, 1, 0), ivec3(0, 1, 0)); // fan #else // GL_TRIANGLE_STRIP // 2--3 Note: Triangle strips alternate CCW/CW winding on every other triangle. This means... // |\ | triangle 012 is CCW order, but triangle 123 is CW order (backwards). // | \| Keep in mind that OpenGL does not actually draw the triangle backwards, // 0--1 so it does not affect glFrontFace() or the gl_FrontFacing variable. - const ivec3 ioffsets[4] = ivec3[4](ivec3(0, 0, 0), ivec3(1, 0, 0), ivec3(0, 1, 0), ivec3(1, 1, 0)); // strip + const ivec3[4] ioffsets = ivec3[4](ivec3(0, 0, 0), + ivec3(1, 0, 0), + ivec3(0, 1, 0), + ivec3(1, 1, 0)); // strip #endif ivec3 ioffset = ioffsets[gl_VertexID]; diff --git a/tests/TestGlobal.cpp b/tests/TestGlobal.cpp index 01f17837e..28ef7f8f0 100644 --- a/tests/TestGlobal.cpp +++ b/tests/TestGlobal.cpp @@ -27,7 +27,6 @@ #include "../src/global/unquote.h" #include "../src/global/utils.h" -#include #include #include @@ -499,24 +498,6 @@ void sig2_test_recursion() } // namespace -void TestGlobal::shaderUtilsTest() -{ - const char *oldLocale = std::setlocale(LC_ALL, nullptr); - std::string savedLocale = oldLocale ? oldLocale : "C"; - - std::setlocale(LC_ALL, "de_DE.UTF-8"); - - const std::string radStr = text_utils::formatFloatClassic(14.0f); - QCOMPARE(radStr.find(','), std::string::npos); - QVERIFY(radStr.find('.') != std::string::npos); - - const std::string extStr = text_utils::formatFloatClassic(28.5f); - QCOMPARE(extStr.find(','), std::string::npos); - QVERIFY(extStr.find('.') != std::string::npos); - - std::setlocale(LC_ALL, savedLocale.c_str()); -} - void TestGlobal::signal2Test() { sig2_test_disconnects(); diff --git a/tests/TestGlobal.h b/tests/TestGlobal.h index cbc8ce530..97e96d798 100644 --- a/tests/TestGlobal.h +++ b/tests/TestGlobal.h @@ -32,7 +32,6 @@ private Q_SLOTS: static void indexedVectorWithDefaultTest(); static void lineUtilsTest(); static void powerOfTwoTest(); - static void shaderUtilsTest(); static void signal2Test(); static void stringViewTest(); static void taggedStringTest(); From 9c3f59eec5e359f30eda2f35d39dfbdf519f5f64 Mon Sep 17 00:00:00 2001 From: nschimme <5505185+nschimme@users.noreply.github.com> Date: Mon, 14 Sep 2026 14:41:23 +0000 Subject: [PATCH 4/9] Fix GLSL shader compilation errors on non-C locales - Use locale-invariant float string formatting (`text_utils::formatFloatClassic`) in ShaderUtils.cpp for preprocessor defines (WEATHER_RADIUS, etc.) to ensure a '.' decimal separator regardless of active system locale. - Fix array declaration syntax in room/tex/acolor/vert.glsl from `const ivec3[4] ioffsets` to `const ivec3 ioffsets[4]` for compatibility with GLSL 3.30 and GLSL ES 3.00 (WebGL 2) compilers. - Add unit test coverage in TestGlobal. --- src/global/TextUtils.cpp | 30 +++++++++++++++++++ src/global/TextUtils.h | 2 ++ src/opengl/legacy/ShaderUtils.cpp | 12 +++++--- .../shaders/legacy/room/tex/acolor/vert.glsl | 4 +-- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/global/TextUtils.cpp b/src/global/TextUtils.cpp index f7b63de9c..b187b06f8 100644 --- a/src/global/TextUtils.cpp +++ b/src/global/TextUtils.cpp @@ -8,8 +8,10 @@ #include "Consts.h" #include "tests.h" +#include #include #include +#include #include #include @@ -39,6 +41,15 @@ bool isAbbrev(const std::string_view abbr, const std::string_view fullText) } namespace text_utils { + +std::string formatFloatClassic(const float val) +{ + std::ostringstream ss; + ss.imbue(std::locale::classic()); + ss << std::showpoint << val; + return ss.str(); +} + SplitResult split_at(const std::string_view sv, const size_t pos) { assert(pos <= sv.size()); @@ -216,6 +227,24 @@ void testTrim() } } +void testFormatFloatClassic() +{ + const char *oldLocale = std::setlocale(LC_ALL, nullptr); + std::string savedLocale = oldLocale ? oldLocale : "C"; + + std::setlocale(LC_ALL, "de_DE.UTF-8"); + + const std::string radStr = text_utils::formatFloatClassic(14.0f); + TEST_ASSERT(radStr.find(',') == std::string::npos); + TEST_ASSERT(radStr.find('.') != std::string::npos); + + const std::string extStr = text_utils::formatFloatClassic(28.5f); + TEST_ASSERT(extStr.find(',') == std::string::npos); + TEST_ASSERT(extStr.find('.') != std::string::npos); + + std::setlocale(LC_ALL, savedLocale.c_str()); +} + } // namespace namespace test { @@ -223,5 +252,6 @@ void testTextUtils() { testPrefixSuffix(); testTrim(); + testFormatFloatClassic(); } } // namespace test diff --git a/src/global/TextUtils.h b/src/global/TextUtils.h index 0e680a9a1..81f1ffa37 100644 --- a/src/global/TextUtils.h +++ b/src/global/TextUtils.h @@ -19,6 +19,8 @@ NODISCARD extern bool isAbbrev(std::string_view abbr, std::string_view fullText) namespace text_utils { +NODISCARD std::string formatFloatClassic(float val); + template struct NODISCARD SplitResult final { diff --git a/src/opengl/legacy/ShaderUtils.cpp b/src/opengl/legacy/ShaderUtils.cpp index 0d107e85d..0fe8ad8dd 100644 --- a/src/opengl/legacy/ShaderUtils.cpp +++ b/src/opengl/legacy/ShaderUtils.cpp @@ -224,15 +224,19 @@ NODISCARD static GLuint compileShader(Functions &gl, const GLenum type, const So std::string defineNamedColors = "#define MAX_NAMED_COLORS " + std::to_string(MAX_NAMED_COLORS) + "\n"; std::string defineWeatherRadius = "#define WEATHER_RADIUS " - + std::to_string(WeatherConstants::WEATHER_RADIUS) + "\n"; + + text_utils::formatFloatClassic( + WeatherConstants::WEATHER_RADIUS) + + "\n"; std::string defineWeatherExtent = "#define WEATHER_EXTENT " - + std::to_string(WeatherConstants::WEATHER_EXTENT) + "\n"; + + text_utils::formatFloatClassic( + WeatherConstants::WEATHER_EXTENT) + + "\n"; std::string defineWeatherMaskOuter = "#define WEATHER_MASK_RADIUS_OUTER " - + std::to_string( + + text_utils::formatFloatClassic( WeatherConstants::WEATHER_MASK_RADIUS_OUTER) + "\n"; std::string defineWeatherMaskInner = "#define WEATHER_MASK_RADIUS_INNER " - + std::to_string( + + text_utils::formatFloatClassic( WeatherConstants::WEATHER_MASK_RADIUS_INNER) + "\n"; diff --git a/src/resources/shaders/legacy/room/tex/acolor/vert.glsl b/src/resources/shaders/legacy/room/tex/acolor/vert.glsl index d39dbedac..f213ff16d 100644 --- a/src/resources/shaders/legacy/room/tex/acolor/vert.glsl +++ b/src/resources/shaders/legacy/room/tex/acolor/vert.glsl @@ -20,14 +20,14 @@ void main() // | /| Triangles 012 and 023 both use CCW order. // |/ | Notice that the four vertices are in CCW order. // 0--1 - const ivec3[4] ioffsets = ivec3[4](ivec3(0, 0, 0), ivec3(1, 0, 0), ivec3(1, 1, 0), ivec3(0, 1, 0)); // fan + const ivec3 ioffsets[4] = ivec3[4](ivec3(0, 0, 0), ivec3(1, 0, 0), ivec3(1, 1, 0), ivec3(0, 1, 0)); // fan #else // GL_TRIANGLE_STRIP // 2--3 Note: Triangle strips alternate CCW/CW winding on every other triangle. This means... // |\ | triangle 012 is CCW order, but triangle 123 is CW order (backwards). // | \| Keep in mind that OpenGL does not actually draw the triangle backwards, // 0--1 so it does not affect glFrontFace() or the gl_FrontFacing variable. - const ivec3[4] ioffsets = ivec3[4](ivec3(0, 0, 0), + const ivec3 ioffsets[4] = ivec3[4](ivec3(0, 0, 0), ivec3(1, 0, 0), ivec3(0, 1, 0), ivec3(1, 1, 0)); // strip From 0929c97aa73bedc411a2c23ccfe78f3c04d34448 Mon Sep 17 00:00:00 2001 From: nschimme <5505185+nschimme@users.noreply.github.com> Date: Mon, 14 Sep 2026 14:49:28 +0000 Subject: [PATCH 5/9] Fix GLSL shader compilation errors on non-C locales - Use locale-invariant float string formatting (`text_utils::formatFloatClassic`) in ShaderUtils.cpp for preprocessor defines (WEATHER_RADIUS, etc.) to ensure a '.' decimal separator regardless of active system locale. - Fix array declaration syntax in room/tex/acolor/vert.glsl from `const ivec3[4] ioffsets` to `const ivec3 ioffsets[4]` for compatibility with GLSL 3.30 and GLSL ES 3.00 (WebGL 2) compilers. - Use RAII guard (`RAIICallback`) in unit test `testFormatFloatClassic` to ensure locale restoration on all exit paths. --- src/global/TextUtils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/global/TextUtils.cpp b/src/global/TextUtils.cpp index b187b06f8..f95255146 100644 --- a/src/global/TextUtils.cpp +++ b/src/global/TextUtils.cpp @@ -6,6 +6,7 @@ #include "Charset.h" #include "Consts.h" +#include "RAII.h" #include "tests.h" #include @@ -230,7 +231,8 @@ void testTrim() void testFormatFloatClassic() { const char *oldLocale = std::setlocale(LC_ALL, nullptr); - std::string savedLocale = oldLocale ? oldLocale : "C"; + const std::string savedLocale = oldLocale ? oldLocale : "C"; + RAIICallback restoreLocale{[savedLocale]() { std::setlocale(LC_ALL, savedLocale.c_str()); }}; std::setlocale(LC_ALL, "de_DE.UTF-8"); @@ -241,8 +243,6 @@ void testFormatFloatClassic() const std::string extStr = text_utils::formatFloatClassic(28.5f); TEST_ASSERT(extStr.find(',') == std::string::npos); TEST_ASSERT(extStr.find('.') != std::string::npos); - - std::setlocale(LC_ALL, savedLocale.c_str()); } } // namespace From c3a086f1184bcb76937f4ff5def6409c042f466b Mon Sep 17 00:00:00 2001 From: nschimme <5505185+nschimme@users.noreply.github.com> Date: Mon, 14 Sep 2026 14:54:20 +0000 Subject: [PATCH 6/9] Fix GLSL shader compilation errors on non-C locales - Use locale-invariant float string formatting (`text_utils::formatFloatClassic`) in ShaderUtils.cpp for preprocessor defines (WEATHER_RADIUS, etc.) to ensure a '.' decimal separator regardless of active system locale. - Fix array declaration syntax in room/tex/acolor/vert.glsl from `const ivec3[4] ioffsets` to `const ivec3 ioffsets[4]` for compatibility with GLSL 3.30 and GLSL ES 3.00 (WebGL 2) compilers. - Use RAII guard (`RAIICallback`) in unit test `testFormatFloatClassic` to ensure locale restoration on all exit paths. From d54481c5d6f56555505a31974c30bd12170f1022 Mon Sep 17 00:00:00 2001 From: nschimme <5505185+nschimme@users.noreply.github.com> Date: Mon, 14 Sep 2026 14:57:42 +0000 Subject: [PATCH 7/9] Fix GLSL shader compilation errors on non-C locales - Use locale-invariant float string formatting (`text_utils::formatFloatClassic`) in ShaderUtils.cpp for preprocessor defines (WEATHER_RADIUS, etc.) to ensure a '.' decimal separator regardless of active system locale. - Fix array declaration syntax in room/tex/acolor/vert.glsl from `const ivec3[4] ioffsets` to `const ivec3 ioffsets[4]` for compatibility with GLSL 3.30 and GLSL ES 3.00 (WebGL 2) compilers. - Use RAII guard (`RAIICallback`) in unit test `testFormatFloatClassic` to ensure locale restoration on all exit paths. From 0d1f83ceb12a2e9ff2327f68cee92a7b6cce5ddf Mon Sep 17 00:00:00 2001 From: nschimme <5505185+nschimme@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:02:52 +0000 Subject: [PATCH 8/9] Fix GLSL shader compilation errors on non-C locales - Use locale-invariant float string formatting (`text_utils::formatFloatClassic`) in ShaderUtils.cpp for preprocessor defines (WEATHER_RADIUS, etc.) to ensure a '.' decimal separator regardless of active system locale. - Fix array declaration syntax in room/tex/acolor/vert.glsl from `const ivec3[4] ioffsets` to `const ivec3 ioffsets[4]` for compatibility with GLSL 3.30 and GLSL ES 3.00 (WebGL 2) compilers. - Use RAII guard (`RAIICallback`) in unit test `testFormatFloatClassic` to ensure locale restoration on all exit paths. From 919933760de411c45c4f0f3dd2c733f8818b32d0 Mon Sep 17 00:00:00 2001 From: nschimme <5505185+nschimme@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:31:44 +0000 Subject: [PATCH 9/9] Fix GLSL shader compilation errors on non-C locales - Use locale-invariant float string formatting (`text_utils::formatFloatClassic`) in ShaderUtils.cpp for preprocessor defines (WEATHER_RADIUS, etc.) to ensure a '.' decimal separator regardless of active system locale. - Fix array declaration syntax in room/tex/acolor/vert.glsl from `const ivec3[4] ioffsets` to `const ivec3 ioffsets[4]` for compatibility with GLSL 3.30 and GLSL ES 3.00 (WebGL 2) compilers. - Use RAII guard (`RAIICallback`) in unit test `testFormatFloatClassic` to ensure locale restoration on all exit paths. --- src/resources/shaders/legacy/room/tex/acolor/vert.glsl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/resources/shaders/legacy/room/tex/acolor/vert.glsl b/src/resources/shaders/legacy/room/tex/acolor/vert.glsl index f213ff16d..34a79167d 100644 --- a/src/resources/shaders/legacy/room/tex/acolor/vert.glsl +++ b/src/resources/shaders/legacy/room/tex/acolor/vert.glsl @@ -27,10 +27,7 @@ void main() // |\ | triangle 012 is CCW order, but triangle 123 is CW order (backwards). // | \| Keep in mind that OpenGL does not actually draw the triangle backwards, // 0--1 so it does not affect glFrontFace() or the gl_FrontFacing variable. - const ivec3 ioffsets[4] = ivec3[4](ivec3(0, 0, 0), - ivec3(1, 0, 0), - ivec3(0, 1, 0), - ivec3(1, 1, 0)); // strip + const ivec3 ioffsets[4] = ivec3[4](ivec3(0, 0, 0), ivec3(1, 0, 0), ivec3(0, 1, 0), ivec3(1, 1, 0)); // strip #endif ivec3 ioffset = ioffsets[gl_VertexID];