From a9a2826b35a1e691488c28791a6d1c37fa74265a Mon Sep 17 00:00:00 2001 From: Federico Romero Date: Thu, 18 Jun 2026 15:51:01 -0300 Subject: [PATCH 1/3] feat(gui): add inline #RRGGBB color code support in CEGUI text Implements GH issue #4433. GUI text elements (labels, buttons, edit boxes, etc.) now parse #RRGGBB sequences as inline color changes. Any '#' not followed by exactly 6 hex digits is treated as a literal character. guiSetText(label, "#FF0000Red #00FF00Green #0000FFBlue") The alpha of the original widget colour is preserved across color changes. Color codes are skipped in getTextExtent() and getCharAtPixel() so they have no visual width and do not affect text layout or cursor positioning. Both left-aligned (drawTextLine) and justified (drawTextLineJustified) rendering paths are covered. --- vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp | 67 ++++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp b/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp index 5122e501efc..81b6739b157 100644 --- a/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp +++ b/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp @@ -223,6 +223,13 @@ float Font::getTextExtent(const String& text, float x_scale) const for (size_t c = 0; c < char_count; ++c) { + float cr, cg, cb; + if (ParseColorCode(text, c, cr, cg, cb)) + { + c += 6; + continue; + } + const SCharSize* pCharSize = MapFind ( d_sizes_map, text[c] ); // Ask sub font if not if ( !pCharSize && !d_is_subfont ) { @@ -284,6 +291,13 @@ size_t Font::getCharAtPixel(const String& text, size_t start_char, float pixel, for (size_t c = start_char; c < char_count; ++c) { + float cr, cg, cb; + if (ParseColorCode(text, c, cr, cg, cb)) + { + c += 6; + continue; + } + pos = d_cp_map.find(text[c]); if (pos != end) @@ -741,6 +755,30 @@ size_t Font::getNextWord(const String& in_string, size_t start_idx, String& out_ /************************************************************************* Draw a line of text. No formatting is applied. *************************************************************************/ +// Returns true and fills r/g/b (0.0-1.0) if text[c] begins a valid #RRGGBB color code. +// A color code is exactly 7 chars: '#' followed by 6 hex digits. If text[c] is '#' +// but the following chars are not all hex digits, the '#' is treated as a literal char. +static bool ParseColorCode(const String& text, size_t c, float& r, float& g, float& b) +{ + if (text[c] != '#' || c + 7 > text.length()) + return false; + + int digits[6]; + for (int k = 0; k < 6; ++k) + { + utf32 ch = text[c + 1 + k]; + if (ch >= '0' && ch <= '9') digits[k] = ch - '0'; + else if (ch >= 'a' && ch <= 'f') digits[k] = ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'F') digits[k] = ch - 'A' + 10; + else return false; + } + + r = static_cast((digits[0] << 4) | digits[1]) / 255.0f; + g = static_cast((digits[2] << 4) | digits[3]) / 255.0f; + b = static_cast((digits[4] << 4) | digits[5]) / 255.0f; + return true; +} + void Font::drawTextLine(const String& text, const Vector3& position, const Rect& clip_rect, const ColourRect& colours, float x_scale, float y_scale) const { Vector3 cur_pos(position); @@ -752,8 +790,19 @@ void Font::drawTextLine(const String& text, const Vector3& position, const Rect& const_cast < Font* > ( this )->refreshStringForGlyphs ( text ); // Refresh our glyph set if there are new characters + ColourRect current_colours = colours; + for (size_t c = 0; c < char_count; ++c) { + // Handle inline #RRGGBB color codes — skip the 7-char sequence and update color. + float cr, cg, cb; + if (ParseColorCode(text, c, cr, cg, cb)) + { + current_colours = ColourRect(colour(cr, cg, cb, colours.d_top_left.getAlpha())); + c += 6; + continue; + } + pos = d_cp_map.find(text[c]); const Image* img; @@ -792,7 +841,7 @@ void Font::drawTextLine(const String& text, const Vector3& position, const Rect& } cur_pos.d_y = base_y - (img->getOffsetY() - img->getOffsetY() * y_scale); Size sz(img->getWidth() * x_scale, img->getHeight() * y_scale); - img->draw(cur_pos, sz, clip_rect, colours); + img->draw(cur_pos, sz, clip_rect, current_colours); cur_pos.d_x += horz_advance * x_scale; } @@ -818,7 +867,11 @@ void Font::drawTextLineJustified(const String& text, const Rect& draw_area, cons uint space_count = 0; size_t c; for (c = 0; c < char_count; ++c) + { + float cr, cg, cb; + if (ParseColorCode(text, c, cr, cg, cb)) { c += 6; continue; } if ((text[c] == ' ') || (text[c] == '\t')) ++space_count; + } // The width that must be added to each space character in order to transform the left aligned text in justified text float shared_lost_space = 0.0; @@ -826,8 +879,18 @@ void Font::drawTextLineJustified(const String& text, const Rect& draw_area, cons const_cast < Font* > ( this )->refreshStringForGlyphs ( text ); // Refresh our glyph set if there are new characters + ColourRect current_colours = colours; + for (c = 0; c < char_count; ++c) { + float cr, cg, cb; + if (ParseColorCode(text, c, cr, cg, cb)) + { + current_colours = ColourRect(colour(cr, cg, cb, colours.d_top_left.getAlpha())); + c += 6; + continue; + } + pos = d_cp_map.find(text[c]); if (pos != end) @@ -835,7 +898,7 @@ void Font::drawTextLineJustified(const String& text, const Rect& draw_area, cons const Image* img = pos->second.d_image; cur_pos.d_y = base_y - (img->getOffsetY() - img->getOffsetY() * y_scale); Size sz(img->getWidth() * x_scale, img->getHeight() * y_scale); - img->draw(cur_pos, sz, clip_rect, colours); + img->draw(cur_pos, sz, clip_rect, current_colours); cur_pos.d_x += (float)pos->second.d_horz_advance * x_scale; // That's where we adjust the size of each space character if ((text[c] == ' ') || (text[c] == '\t')) cur_pos.d_x += shared_lost_space; From 3d4ec8260ceccbb411f6667cdcf99f12a01310ee Mon Sep 17 00:00:00 2001 From: Federico Romero Date: Thu, 18 Jun 2026 16:09:51 -0300 Subject: [PATCH 2/3] feat(gui): add per-element color codes toggle (guiSetColorCodesEnabled) Color codes are now OFF by default, preserving full backward compatibility. Scripts opt in per element: guiSetColorCodesEnabled(element, true) -- enable #RRGGBB parsing guiSetColorCodesEnabled(element, false) -- disable (default) guiGetColorCodesEnabled(element) -- query state element.colorCodesEnabled = true -- OOP style Implementation: Font::s_colorCodesEnabled (default false) is set inside Window::drawSelf() from a per-window UserString before populateRenderCache() is called, then reset to false. This keeps the toggle contained to the render-cache rebuild phase without touching individual widget types. --- Client/gui/CGUIElement_Impl.cpp | 12 +++++ Client/gui/CGUIElement_Impl.h | 3 ++ .../deathmatch/logic/luadefs/CLuaGUIDefs.cpp | 48 +++++++++++++++++++ .../deathmatch/logic/luadefs/CLuaGUIDefs.h | 2 + Client/sdk/gui/CGUIElement.h | 3 ++ vendor/cegui-0.4.0-custom/include/CEGUIFont.h | 5 ++ vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp | 3 ++ vendor/cegui-0.4.0-custom/src/CEGUIWindow.cpp | 6 +++ 8 files changed, 82 insertions(+) diff --git a/Client/gui/CGUIElement_Impl.cpp b/Client/gui/CGUIElement_Impl.cpp index 4c17052ef87..f9643e4de4e 100644 --- a/Client/gui/CGUIElement_Impl.cpp +++ b/Client/gui/CGUIElement_Impl.cpp @@ -733,3 +733,15 @@ inline void CGUIElement_Impl::ForceRedraw() { m_pWindow->forceRedraw(); } + +void CGUIElement_Impl::SetColorCodesEnabled(bool bEnabled) +{ + m_pWindow->setUserString("ColorCodesEnabled", bEnabled ? "True" : "False"); + m_pWindow->forceRedraw(); +} + +bool CGUIElement_Impl::GetColorCodesEnabled() +{ + return m_pWindow->isUserStringDefined("ColorCodesEnabled") && + m_pWindow->getUserString("ColorCodesEnabled") == "True"; +} diff --git a/Client/gui/CGUIElement_Impl.h b/Client/gui/CGUIElement_Impl.h index 9f85a5be0f9..be9900e206f 100644 --- a/Client/gui/CGUIElement_Impl.h +++ b/Client/gui/CGUIElement_Impl.h @@ -100,6 +100,9 @@ class CGUIElement_Impl : public CGUIElement void ForceRedraw(); + void SetColorCodesEnabled(bool bEnabled); + bool GetColorCodesEnabled(); + void SetUserData(void* pData) { m_pData = pData; } void* GetUserData() { return m_pData; } diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp index 5471c8e6089..41df9f217db 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp @@ -139,6 +139,8 @@ void CLuaGUIDefs::LoadFunctions() {"guiGetProperty", GUIGetProperty}, {"guiGetProperties", GUIGetProperties}, {"guiGetAlpha", GUIGetAlpha}, + {"guiSetColorCodesEnabled", GUISetColorCodesEnabled}, + {"guiGetColorCodesEnabled", GUIGetColorCodesEnabled}, {"guiGetText", GUIGetText}, {"guiGetFont", GUIGetFont}, {"guiGetSize", GUIGetSize}, @@ -249,6 +251,7 @@ void CLuaGUIDefs::AddGuiElementClass(lua_State* luaVM) lua_classfunction(luaVM, "getScreenSize", "guiGetScreenSize"); lua_classfunction(luaVM, "getProperties", "guiGetProperties"); lua_classfunction(luaVM, "getAlpha", "guiGetAlpha"); + lua_classfunction(luaVM, "getColorCodesEnabled", "guiGetColorCodesEnabled"); lua_classfunction(luaVM, "getFont", "guiGetFont"); lua_classfunction(luaVM, "getEnabled", "guiGetEnabled"); lua_classfunction(luaVM, "getVisible", "guiGetVisible"); @@ -259,6 +262,7 @@ void CLuaGUIDefs::AddGuiElementClass(lua_State* luaVM) lua_classfunction(luaVM, "setInputEnabled", "guiSetInputEnabled"); lua_classfunction(luaVM, "setAlpha", "guiSetAlpha"); + lua_classfunction(luaVM, "setColorCodesEnabled", "guiSetColorCodesEnabled"); lua_classfunction(luaVM, "setEnabled", "guiSetEnabled"); lua_classfunction(luaVM, "setFont", "guiSetFont"); lua_classfunction(luaVM, "setVisible", "guiSetVisible"); @@ -282,6 +286,7 @@ void CLuaGUIDefs::AddGuiElementClass(lua_State* luaVM) lua_classvariable(luaVM, "visible", "guiSetVisible", "guiGetVisible"); lua_classvariable(luaVM, "properties", NULL, "guiGetProperties"); lua_classvariable(luaVM, "alpha", "guiSetAlpha", "guiGetAlpha"); + lua_classvariable(luaVM, "colorCodesEnabled", "guiSetColorCodesEnabled", "guiGetColorCodesEnabled"); lua_classvariable(luaVM, "enabled", "guiSetEnabled", "guiGetEnabled"); lua_classvariable(luaVM, "text", "guiSetText", "guiGetText"); lua_classvariable(luaVM, "size", "guiSetSize", "guiGetSize"); @@ -1864,6 +1869,49 @@ int CLuaGUIDefs::GUIGetAlpha(lua_State* luaVM) return 1; } +int CLuaGUIDefs::GUISetColorCodesEnabled(lua_State* luaVM) +{ + // bool guiSetColorCodesEnabled ( element guiElement, bool enabled ) + CClientGUIElement* guiElement; + bool bEnabled; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(guiElement); + argStream.ReadBool(bEnabled); + + if (!argStream.HasErrors()) + { + guiElement->GetCGUIElement()->SetColorCodesEnabled(bEnabled); + lua_pushboolean(luaVM, true); + return 1; + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + lua_pushboolean(luaVM, false); + return 1; +} + +int CLuaGUIDefs::GUIGetColorCodesEnabled(lua_State* luaVM) +{ + // bool guiGetColorCodesEnabled ( element guiElement ) + CClientGUIElement* guiElement; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(guiElement); + + if (!argStream.HasErrors()) + { + lua_pushboolean(luaVM, guiElement->GetCGUIElement()->GetColorCodesEnabled()); + return 1; + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaGUIDefs::GUISetVisible(lua_State* luaVM) { // bool guiSetVisible ( element guiElement, bool state ) diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.h index 3fa9b839be2..fabf9ddcde9 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.h @@ -112,6 +112,8 @@ class CLuaGUIDefs : public CLuaDefs LUA_DECLARE(GUIGetPosition); LUA_DECLARE(GUIGetVisible); LUA_DECLARE(GUIGetAlpha); + LUA_DECLARE(GUISetColorCodesEnabled); + LUA_DECLARE(GUIGetColorCodesEnabled); LUA_DECLARE(GUIGetProperty); LUA_DECLARE(GUIGetProperties); LUA_DECLARE(GUICheckBoxGetSelected); diff --git a/Client/sdk/gui/CGUIElement.h b/Client/sdk/gui/CGUIElement.h index 309a2f47360..e1b024adec7 100644 --- a/Client/sdk/gui/CGUIElement.h +++ b/Client/sdk/gui/CGUIElement.h @@ -105,6 +105,9 @@ class CGUIElement virtual void ForceRedraw() = 0; + virtual void SetColorCodesEnabled(bool bEnabled) = 0; + virtual bool GetColorCodesEnabled() = 0; + virtual CRect2D AbsoluteToRelative(const CRect2D& Rect) = 0; virtual CVector2D AbsoluteToRelative(const CVector2D& Vector) = 0; diff --git a/vendor/cegui-0.4.0-custom/include/CEGUIFont.h b/vendor/cegui-0.4.0-custom/include/CEGUIFont.h index a5f8396d877..3ebebd47502 100644 --- a/vendor/cegui-0.4.0-custom/include/CEGUIFont.h +++ b/vendor/cegui-0.4.0-custom/include/CEGUIFont.h @@ -107,6 +107,11 @@ class CEGUIEXPORT Font *************************************************************************/ static const argb_t DefaultColour; //!< Colour value used whenever a colour is not specified. + // When true, drawTextLine/drawTextLineJustified parse inline #RRGGBB color codes. + // CEGUIWindow::drawSelf() sets this per-window before populateRenderCache() and + // resets it to false afterwards, giving per-element opt-in behaviour. + static bool s_colorCodesEnabled; + /************************************************************************* Text drawing methods diff --git a/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp b/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp index 81b6739b157..1bd14a8fe04 100644 --- a/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp +++ b/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp @@ -57,6 +57,7 @@ namespace CEGUI static data definitions *************************************************************************/ const argb_t Font::DefaultColour = 0xFFFFFFFF; +bool Font::s_colorCodesEnabled = false; const uint Font::InterGlyphPadSpace = 2; // XML related strings @@ -760,6 +761,8 @@ size_t Font::getNextWord(const String& in_string, size_t start_idx, String& out_ // but the following chars are not all hex digits, the '#' is treated as a literal char. static bool ParseColorCode(const String& text, size_t c, float& r, float& g, float& b) { + if (!Font::s_colorCodesEnabled) + return false; if (text[c] != '#' || c + 7 > text.length()) return false; diff --git a/vendor/cegui-0.4.0-custom/src/CEGUIWindow.cpp b/vendor/cegui-0.4.0-custom/src/CEGUIWindow.cpp index 2cae857cd62..5fa23860e79 100644 --- a/vendor/cegui-0.4.0-custom/src/CEGUIWindow.cpp +++ b/vendor/cegui-0.4.0-custom/src/CEGUIWindow.cpp @@ -29,6 +29,7 @@ #include "CEGUIWindowManager.h" #include "CEGUISystem.h" #include "CEGUIFontManager.h" +#include "CEGUIFont.h" #include "CEGUIImagesetManager.h" #include "CEGUIImageset.h" #include "CEGUIMouseCursor.h" @@ -1998,8 +1999,13 @@ void Window::drawSelf(float z) { // dispose of already cached imagery. d_renderCache.clearCachedImagery(); + // Set per-window color codes flag before text geometry is generated. + Font::s_colorCodesEnabled = isUserStringDefined("ColorCodesEnabled") && + getUserString("ColorCodesEnabled") == "True"; // get derived class to re-populate cache. populateRenderCache(); + // Reset so other windows default to no color parsing. + Font::s_colorCodesEnabled = false; // mark ourselves as no longer needed a redraw. d_needsRedraw = false; } From f7da2cfd9ed116e39a0120d3909024bf5c7b3b88 Mon Sep 17 00:00:00 2001 From: Federico Romero Date: Thu, 18 Jun 2026 23:21:53 -0300 Subject: [PATCH 3/3] feat(gui): add per-element RGB color codes toggle Adds \guiSetColorCodesEnabled\, allowing RGB color codes to be toggled on a per-element basis. - Fixes issues where complex Falagard widgets (Buttons, Checkboxes) ignored color codes. - Implements inheritance so internal components (Titlebars, TabButtons) respect their parent's setting. - Adds an optional \includeChildren\ parameter to apply the toggle recursively. --- Client/gui/CGUIElement_Impl.cpp | 19 +++++++++-- Client/gui/CGUIElement_Inc.h | 13 ++++++++ Client/gui/CGUITab_Impl.cpp | 20 ++++++++++++ Client/gui/CGUITab_Impl.h | 4 +++ .../deathmatch/logic/luadefs/CLuaGUIDefs.cpp | 28 ++++++++++++++-- .../include/CEGUIRenderCache.h | 1 + vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp | 3 ++ .../src/CEGUIRenderCache.cpp | 3 ++ vendor/cegui-0.4.0-custom/src/CEGUIWindow.cpp | 32 ++++++++++++++++--- 9 files changed, 114 insertions(+), 9 deletions(-) diff --git a/Client/gui/CGUIElement_Impl.cpp b/Client/gui/CGUIElement_Impl.cpp index f9643e4de4e..6e1bd588d4e 100644 --- a/Client/gui/CGUIElement_Impl.cpp +++ b/Client/gui/CGUIElement_Impl.cpp @@ -734,14 +734,29 @@ inline void CGUIElement_Impl::ForceRedraw() m_pWindow->forceRedraw(); } +namespace { + void RecursivelyForceRedrawAutoWindows(CEGUI::Window* pWindow) + { + for (uint i = 0; i < pWindow->getChildCount(); ++i) + { + CEGUI::Window* pChild = pWindow->getChildAtIdx(i); + if (pChild->getName().find("__auto_") != CEGUI::String::npos) + { + pChild->forceRedraw(); + RecursivelyForceRedrawAutoWindows(pChild); + } + } + } +} + void CGUIElement_Impl::SetColorCodesEnabled(bool bEnabled) { m_pWindow->setUserString("ColorCodesEnabled", bEnabled ? "True" : "False"); m_pWindow->forceRedraw(); + RecursivelyForceRedrawAutoWindows(m_pWindow); } bool CGUIElement_Impl::GetColorCodesEnabled() { - return m_pWindow->isUserStringDefined("ColorCodesEnabled") && - m_pWindow->getUserString("ColorCodesEnabled") == "True"; + return m_pWindow->isUserStringDefined("ColorCodesEnabled") && m_pWindow->getUserString("ColorCodesEnabled") == "True"; } diff --git a/Client/gui/CGUIElement_Inc.h b/Client/gui/CGUIElement_Inc.h index 250fa22cfba..92614da56bf 100644 --- a/Client/gui/CGUIElement_Inc.h +++ b/Client/gui/CGUIElement_Inc.h @@ -194,6 +194,19 @@ void ForceRedraw() { CGUIElement_Impl::ForceRedraw(); }; + +// Forwarding methods to the base CGUIElement_Impl implementation to resolve +// diamond multiple-inheritance issues so subclasses aren't treated as abstract. +#ifndef SETCOLORCODESENABLED_HACK +void SetColorCodesEnabled(bool bEnabled) +{ + CGUIElement_Impl::SetColorCodesEnabled(bEnabled); +}; +#endif +bool GetColorCodesEnabled() +{ + return CGUIElement_Impl::GetColorCodesEnabled(); +}; void SetAlwaysOnTop(bool bAlwaysOnTop) { CGUIElement_Impl::SetAlwaysOnTop(bAlwaysOnTop); diff --git a/Client/gui/CGUITab_Impl.cpp b/Client/gui/CGUITab_Impl.cpp index fb5111ef399..b105beddcd3 100644 --- a/Client/gui/CGUITab_Impl.cpp +++ b/Client/gui/CGUITab_Impl.cpp @@ -87,3 +87,23 @@ bool CGUITab_Impl::IsEnabled() CEGUI::TabControl* pControl = reinterpret_cast(((CGUITabPanel_Impl*)pParent)->m_pWindow); return !pControl->getButtonForTabContents(m_pWindow)->isDisabled(); } + +void CGUITab_Impl::SetColorCodesEnabled(bool bEnabled) +{ + CGUIElement_Impl::SetColorCodesEnabled(bEnabled); + + if (m_pParent && m_pParent->GetType() == CGUI_TABPANEL) + { + CGUIElement_Impl* pParent = static_cast(m_pParent); + CEGUI::TabControl* pTabControl = reinterpret_cast(((CGUITabPanel_Impl*)pParent)->m_pWindow); + if (pTabControl) + { + CEGUI::TabButton* pButton = pTabControl->getButtonForTabContents(m_pWindow); + if (pButton) + { + pButton->setUserString("ColorCodesEnabled", bEnabled ? "True" : "False"); + pButton->forceRedraw(); + } + } + } +} diff --git a/Client/gui/CGUITab_Impl.h b/Client/gui/CGUITab_Impl.h index fd30a87c56c..7a24653d297 100644 --- a/Client/gui/CGUITab_Impl.h +++ b/Client/gui/CGUITab_Impl.h @@ -26,7 +26,9 @@ class CGUITab_Impl : public CGUITab, public CGUIElement_Impl, public CGUITabList #define SETVISIBLE_HACK #define SETENABLED_HACK +#define SETCOLORCODESENABLED_HACK #include "CGUIElement_Inc.h" +#undef SETCOLORCODESENABLED_HACK #undef SETENABLED_HACK #undef SETVISIBLE_HACK @@ -34,4 +36,6 @@ class CGUITab_Impl : public CGUITab, public CGUIElement_Impl, public CGUITabList bool IsVisible(); void SetEnabled(bool bEnabled); bool IsEnabled(); + + void SetColorCodesEnabled(bool bEnabled); }; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp index 41df9f217db..c3ed8b9ada5 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaGUIDefs.cpp @@ -1869,19 +1869,43 @@ int CLuaGUIDefs::GUIGetAlpha(lua_State* luaVM) return 1; } +static void RecursivelySetColorCodesEnabled(CClientGUIElement* pElement, bool bEnabled) +{ + pElement->GetCGUIElement()->SetColorCodesEnabled(bEnabled); + CElementListSnapshotRef pSnapshot = pElement->GetChildrenListSnapshot(); + for (CClientEntity* pChild : *pSnapshot) + { + if (pChild->GetType() == CCLIENTGUI) + { + RecursivelySetColorCodesEnabled(static_cast(pChild), bEnabled); + } + } +} + int CLuaGUIDefs::GUISetColorCodesEnabled(lua_State* luaVM) { - // bool guiSetColorCodesEnabled ( element guiElement, bool enabled ) + // bool guiSetColorCodesEnabled ( element guiElement, bool enabled [, bool includeChildren = false ] ) CClientGUIElement* guiElement; bool bEnabled; + bool bIncludeChildren = false; CScriptArgReader argStream(luaVM); argStream.ReadUserData(guiElement); argStream.ReadBool(bEnabled); + if (argStream.NextIsBool()) + argStream.ReadBool(bIncludeChildren); if (!argStream.HasErrors()) { - guiElement->GetCGUIElement()->SetColorCodesEnabled(bEnabled); + if (bIncludeChildren) + { + RecursivelySetColorCodesEnabled(guiElement, bEnabled); + } + else + { + guiElement->GetCGUIElement()->SetColorCodesEnabled(bEnabled); + } + lua_pushboolean(luaVM, true); return 1; } diff --git a/vendor/cegui-0.4.0-custom/include/CEGUIRenderCache.h b/vendor/cegui-0.4.0-custom/include/CEGUIRenderCache.h index bd05ac80591..b6b97d6dc87 100644 --- a/vendor/cegui-0.4.0-custom/include/CEGUIRenderCache.h +++ b/vendor/cegui-0.4.0-custom/include/CEGUIRenderCache.h @@ -188,6 +188,7 @@ namespace CEGUI Rect customClipper; bool usingCustomClipper; bool clipToDisplay; + bool colorCodesEnabled; // Stores whether inline color codes formatting should be parsed when rendering this text. }; typedef std::vector ImageryList; diff --git a/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp b/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp index 1bd14a8fe04..55004cdfdbb 100644 --- a/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp +++ b/vendor/cegui-0.4.0-custom/src/CEGUIFont.cpp @@ -53,6 +53,9 @@ // Start of CEGUI namespace section namespace CEGUI { +// Forward declaration of ParseColorCode to allow calls in early member functions (e.g. getTextExtent, getCharAtPixel) before its definition. +static bool ParseColorCode(const String& text, size_t c, float& r, float& g, float& b); + /************************************************************************* static data definitions *************************************************************************/ diff --git a/vendor/cegui-0.4.0-custom/src/CEGUIRenderCache.cpp b/vendor/cegui-0.4.0-custom/src/CEGUIRenderCache.cpp index dfaada745cc..691147f9708 100644 --- a/vendor/cegui-0.4.0-custom/src/CEGUIRenderCache.cpp +++ b/vendor/cegui-0.4.0-custom/src/CEGUIRenderCache.cpp @@ -84,8 +84,10 @@ namespace CEGUI finalRect = (*text).target_area; finalRect.offset(basePos); + Font::s_colorCodesEnabled = (*text).colorCodesEnabled; // Temporarily restore the color codes toggle state for this text block (*text).source_font->drawText((*text).text, finalRect, baseZ + (*text).z_offset, *finalClipper, (*text).formatting, (*text).colours); } + Font::s_colorCodesEnabled = false; // Reset to default state } @@ -127,6 +129,7 @@ namespace CEGUI txtinf.z_offset = zOffset; txtinf.colours = cols; txtinf.clipToDisplay = clipToDisplay; + txtinf.colorCodesEnabled = Font::s_colorCodesEnabled; // Cache the current color code formatting enablement status if (clipper) { diff --git a/vendor/cegui-0.4.0-custom/src/CEGUIWindow.cpp b/vendor/cegui-0.4.0-custom/src/CEGUIWindow.cpp index 5fa23860e79..8b69d1c33f0 100644 --- a/vendor/cegui-0.4.0-custom/src/CEGUIWindow.cpp +++ b/vendor/cegui-0.4.0-custom/src/CEGUIWindow.cpp @@ -43,6 +43,25 @@ // Start of CEGUI namespace section namespace CEGUI { +namespace { + bool getColorCodesEnabledForWindow(const CEGUI::Window* window) + { + const CEGUI::Window* curr = window; + while (curr) + { + if (curr->isUserStringDefined("ColorCodesEnabled")) + return curr->getUserString("ColorCodesEnabled") == "True"; + + // Stop inheriting if the window is not an auto-window + if (curr->getName().find("__auto_") == CEGUI::String::npos) + break; + + curr = curr->getParent(); + } + return false; + } +} + const String Window::EventNamespace("Window"); /************************************************************************* @@ -1974,7 +1993,15 @@ void Window::render(void) // perform drawing for 'this' Window Renderer* renderer = System::getSingleton().getRenderer(); + + // Set per-window color codes flag before geometry is generated. + // We do this here so widgets that override drawSelf (like Falagard buttons) still respect it. + Font::s_colorCodesEnabled = getColorCodesEnabledForWindow(this); + drawSelf(renderer->getCurrentZ()); + + Font::s_colorCodesEnabled = false; + renderer->advanceZValue(); // render any child windows @@ -1999,13 +2026,8 @@ void Window::drawSelf(float z) { // dispose of already cached imagery. d_renderCache.clearCachedImagery(); - // Set per-window color codes flag before text geometry is generated. - Font::s_colorCodesEnabled = isUserStringDefined("ColorCodesEnabled") && - getUserString("ColorCodesEnabled") == "True"; // get derived class to re-populate cache. populateRenderCache(); - // Reset so other windows default to no color parsing. - Font::s_colorCodesEnabled = false; // mark ourselves as no longer needed a redraw. d_needsRedraw = false; }