From 26191110745b24623f09cf6f03634c7ef9a7f5d4 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Sun, 10 Mar 2024 21:28:43 -0400
Subject: [PATCH] Add color table debug floater

---
 indra/llui/lluicolortable.cpp                 |  34 ++
 indra/llui/lluicolortable.h                   |   7 +
 indra/newview/CMakeLists.txt                  |   2 +
 indra/newview/alfloatersettingscolor.cpp      | 333 ++++++++++++++++++
 indra/newview/alfloatersettingscolor.h        |  81 +++++
 .../newview/app_settings/settings_alchemy.xml |  11 +
 indra/newview/llviewerfloaterreg.cpp          |   2 +
 .../default/xui/en/floater_settings_color.xml | 117 ++++++
 .../skins/default/xui/en/menu_login.xml       |   7 +
 .../skins/default/xui/en/menu_viewer.xml      |   9 +-
 10 files changed, 602 insertions(+), 1 deletion(-)
 create mode 100644 indra/newview/alfloatersettingscolor.cpp
 create mode 100644 indra/newview/alfloatersettingscolor.h
 create mode 100644 indra/newview/skins/default/xui/en/floater_settings_color.xml

diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp
index 87d76e84cec..8f660fd3144 100644
--- a/indra/llui/lluicolortable.cpp
+++ b/indra/llui/lluicolortable.cpp
@@ -201,6 +201,40 @@ void LLUIColorTable::setColor(std::string_view name, const LLColor4& color)
 	setColor(name, color, mUserSetColors);
 }
 
+bool LLUIColorTable::isDefault(std::string_view name) const
+{
+	string_color_map_t::const_iterator base_iter = mLoadedColors.find(name);
+	string_color_map_t::const_iterator user_iter = mUserSetColors.find(name);
+	if (base_iter != mLoadedColors.end())
+	{
+		if(user_iter != mUserSetColors.end())
+			return user_iter->second == base_iter->second;
+
+		return true;
+	}
+	else if (user_iter != mUserSetColors.end()) // user only color ???
+	{
+		return true;
+	}
+
+	return false;
+}
+
+void LLUIColorTable::resetToDefault(std::string_view name)
+{
+	string_color_map_t::iterator iter = mUserSetColors.find(name);
+
+	if (iter != mUserSetColors.end())
+	{
+		auto default_iter = mLoadedColors.find(name);
+
+		if (default_iter != mLoadedColors.end())
+		{
+			iter->second = default_iter->second.get();
+		}
+	}
+}
+
 bool LLUIColorTable::loadFromSettings()
 {
 	bool result = false;
diff --git a/indra/llui/lluicolortable.h b/indra/llui/lluicolortable.h
index 7f2ae3150af..6bba1bcae3c 100644
--- a/indra/llui/lluicolortable.h
+++ b/indra/llui/lluicolortable.h
@@ -85,12 +85,19 @@ class LLUIColorTable final : public LLSingleton<LLUIColorTable>
 	// returns true if color_name exists in the table
 	bool colorExists(std::string_view color_name) const;
 
+	bool isDefault(std::string_view color_name) const;
+
+	void resetToDefault(std::string_view color_name);
+
 	// loads colors from settings files
 	bool loadFromSettings();
 
 	// saves colors specified by the user to the users skin directory
 	void saveUserSettings(const bool scrub = false) const;
 
+	const auto& getLoadedColors() { return mLoadedColors; }
+	const auto& getUserColors() { return mUserSetColors; }
+
 private:
 	bool loadFromFilename(const std::string& filename, string_color_map_t& table);
 
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 49fa4980db2..355611a0a84 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -96,6 +96,7 @@ set(viewer_SOURCE_FILES
     alfloaterlightbox.cpp
     alfloaterparticleeditor.cpp
     alfloaterregiontracker.cpp
+    alfloatersettingscolor.cpp
     alpanelaomini.cpp
     alpanelaopulldown.cpp
     alpanelmusicticker.cpp
@@ -831,6 +832,7 @@ set(viewer_HEADER_FILES
     alfloaterlightbox.h
     alfloaterparticleeditor.h
     alfloaterregiontracker.h
+    alfloatersettingscolor.h
     alpanelaomini.h
     alpanelaopulldown.h
     alpanelmusicticker.h
diff --git a/indra/newview/alfloatersettingscolor.cpp b/indra/newview/alfloatersettingscolor.cpp
new file mode 100644
index 00000000000..fc38ffdc80a
--- /dev/null
+++ b/indra/newview/alfloatersettingscolor.cpp
@@ -0,0 +1,333 @@
+/** 
+ * @file alfloatersettingscolor.cpp
+ * @brief floater for debugging internal viewer colors
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Alchemy Viewer Source Code
+ * Copyright (C) 2024, Rye Mutt<rye@alchemyviewer.org>.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "alfloatersettingscolor.h"
+#include "llfloater.h"
+#include "llfiltereditor.h"
+#include "lluictrlfactory.h"
+#include "llcombobox.h"
+// [RLVa:KB] - Patch: RLVa-2.1.0
+#include "llsdserialize.h"
+// [/RLVa:KB]
+#include "llspinctrl.h"
+#include "llcolorswatch.h"
+#include "llviewercontrol.h"
+#include "lltexteditor.h"
+
+
+ALFloaterSettingsColor::ALFloaterSettingsColor(const LLSD& key) 
+:	LLFloater(key),
+    mSettingList(NULL)
+{
+	mCommitCallbackRegistrar.add("CommitSettings",	boost::bind(&ALFloaterSettingsColor::onCommitSettings, this));
+	mCommitCallbackRegistrar.add("ClickDefault",	boost::bind(&ALFloaterSettingsColor::onClickDefault, this));
+}
+
+ALFloaterSettingsColor::~ALFloaterSettingsColor()
+{}
+
+BOOL ALFloaterSettingsColor::postBuild()
+{
+    enableResizeCtrls(true, false, true);
+
+	mAlphaSpinner = getChild<LLSpinCtrl>("alpha_spinner");
+	mColorSwatch = getChild<LLColorSwatchCtrl>("color_swatch");
+
+	mDefaultButton = getChild<LLUICtrl>("default_btn");
+	mSettingNameText = getChild<LLTextBox>("color_name_txt");
+
+    getChild<LLFilterEditor>("filter_input")->setCommitCallback(boost::bind(&ALFloaterSettingsColor::setSearchFilter, this, _2));
+
+    mSettingList = getChild<LLScrollListCtrl>("setting_list");
+    mSettingList->setCommitOnSelectionChange(TRUE);
+    mSettingList->setCommitCallback(boost::bind(&ALFloaterSettingsColor::onSettingSelect, this));
+
+    updateList();
+
+    gSavedSettings.getControl("ColorSettingsHideDefault")->getCommitSignal()->connect(boost::bind(&ALFloaterSettingsColor::updateList, this, false));
+
+	return TRUE;
+}
+
+void ALFloaterSettingsColor::draw()
+{
+    LLScrollListItem* first_selected = mSettingList->getFirstSelected();
+    if (first_selected)
+    {
+		if(auto cell = first_selected->getColumn(1))
+		{
+			updateControl(cell->getValue().asString());
+		}
+    }
+
+	LLFloater::draw();
+}
+
+void ALFloaterSettingsColor::onCommitSettings()
+{
+    LLScrollListItem* first_selected = mSettingList->getFirstSelected();
+    if (!first_selected)
+    {
+        return;
+    }
+    auto cell = first_selected->getColumn(1);
+
+	if (!cell)
+	{
+		return;
+	}
+
+    auto color_name = cell->getValue().asString();
+    if (color_name.empty())
+    {
+        return;
+    }
+
+    LLColor4 col4;
+    LLColor3 col3;
+    col3.setValue(mColorSwatch->getValue());
+    col4 = LLColor4(col3, (F32)mAlphaSpinner->getValue().asReal());
+    LLUIColorTable::instance().setColor(color_name, col4);
+
+    updateDefaultColumn(color_name);
+}
+
+// static
+void ALFloaterSettingsColor::onClickDefault()
+{
+    LLScrollListItem* first_selected = mSettingList->getFirstSelected();
+    if (first_selected)
+    {
+        auto cell = first_selected->getColumn(1);
+        if (cell)
+        {
+            auto name = cell->getValue().asString();
+            LLUIColorTable::instance().resetToDefault(name);
+            updateDefaultColumn(name);
+            updateControl(name);
+        }
+    }
+}
+
+// we've switched controls, or doing per-frame update, so update spinners, etc.
+void ALFloaterSettingsColor::updateControl(const std::string& color_name)
+{
+    hideUIControls();
+
+	if (!isSettingHidden(color_name))
+	{
+        mDefaultButton->setVisible(true);
+        mSettingNameText->setVisible(true);
+        mSettingNameText->setText(color_name);
+        mSettingNameText->setToolTip(color_name);
+
+		LLColor4 clr = LLUIColorTable::instance().getColor(color_name);
+		mColorSwatch->setVisible(TRUE);
+		// only set if changed so color picker doesn't update
+		if (clr != LLColor4(mColorSwatch->getValue()))
+		{
+			mColorSwatch->setOriginal(clr);
+		}
+		mAlphaSpinner->setVisible(TRUE);
+		mAlphaSpinner->setLabel(std::string("Alpha"));
+		if (!mAlphaSpinner->hasFocus())
+		{
+			mAlphaSpinner->setPrecision(3);
+			mAlphaSpinner->setMinValue(0.0);
+			mAlphaSpinner->setMaxValue(1.f);
+			mAlphaSpinner->setValue(clr.mV[VALPHA]);
+		}
+	}
+
+}
+
+void ALFloaterSettingsColor::updateList(bool skip_selection)
+{
+    std::string last_selected;
+    LLScrollListItem* item = mSettingList->getFirstSelected();
+    if (item)
+    {
+        LLScrollListCell* cell = item->getColumn(1);
+        if (cell)
+        {
+            last_selected = cell->getValue().asString();
+         }
+    }
+
+    mSettingList->deleteAllItems();
+
+    const auto& base_colors = LLUIColorTable::instance().getLoadedColors();
+	for (const auto& pair : base_colors)
+	{
+		const auto& name = pair.first;
+		if (matchesSearchFilter(name) && !isSettingHidden(name))
+		{
+			LLSD row;
+
+			row["columns"][0]["column"] = "changed_color";
+			row["columns"][0]["value"] = LLUIColorTable::instance().isDefault(name) ? "" : "*";
+
+			row["columns"][1]["column"] = "color";
+			row["columns"][1]["value"] = name;
+
+			LLScrollListItem* item = mSettingList->addElement(row, ADD_BOTTOM, nullptr);
+			if (!mSearchFilter.empty() && (last_selected == name) && !skip_selection)
+			{
+				std::string lower_name(name);
+				LLStringUtil::toLower(lower_name);
+				if (LLStringUtil::startsWith(lower_name, mSearchFilter))
+				{
+					item->setSelected(true);
+				}
+			}
+		}
+	}
+
+    for (const auto& pair : LLUIColorTable::instance().getUserColors())
+    {
+        const auto& name = pair.first;
+        if (base_colors.find(name) == base_colors.end() && matchesSearchFilter(name) && !isSettingHidden(name))
+        {
+            LLSD row;
+
+            row["columns"][0]["column"] = "changed_color";
+            row["columns"][0]["value"] = LLUIColorTable::instance().isDefault(name) ? "" : "*";
+
+            row["columns"][1]["column"] = "color";
+            row["columns"][1]["value"] = name;
+
+            LLScrollListItem* item = mSettingList->addElement(row, ADD_BOTTOM, nullptr);
+            if (!mSearchFilter.empty() && (last_selected == name) && !skip_selection)
+            {
+                std::string lower_name(name);
+                LLStringUtil::toLower(lower_name);
+                if (LLStringUtil::startsWith(lower_name, mSearchFilter))
+                {
+                    item->setSelected(true);
+                }
+            }
+        }
+    }
+
+    mSettingList->updateSort();
+
+    if (!mSettingList->isEmpty())
+    {
+        if (mSettingList->hasSelectedItem())
+        {
+            mSettingList->scrollToShowSelected();
+        }
+        else if (!mSettingList->hasSelectedItem() && !mSearchFilter.empty() && !skip_selection)
+        {
+            if (!mSettingList->selectItemByPrefix(mSearchFilter, false, 1))
+            {
+                mSettingList->selectFirstItem();
+            }
+            mSettingList->scrollToShowSelected();
+        }
+    }
+    else
+    {
+        LLSD row;
+
+        row["columns"][0]["column"] = "changed_color";
+        row["columns"][0]["value"] = "";
+        row["columns"][1]["column"] = "color";
+        row["columns"][1]["value"] = "No matching colors.";
+
+        mSettingList->addElement(row);
+        hideUIControls();
+    }
+}
+
+void ALFloaterSettingsColor::onSettingSelect()
+{
+    LLScrollListItem* first_selected = mSettingList->getFirstSelected();
+    if (first_selected)
+    {
+		auto cell = first_selected->getColumn(1);
+        if (cell)
+        {
+            updateControl(cell->getValue().asString());
+        }
+    }
+}
+
+void ALFloaterSettingsColor::setSearchFilter(const std::string& filter)
+{
+    if(mSearchFilter == filter)
+        return;
+    mSearchFilter = filter;
+    LLStringUtil::toLower(mSearchFilter);
+    updateList();
+}
+
+bool ALFloaterSettingsColor::matchesSearchFilter(std::string setting_name)
+{
+    // If the search filter is empty, everything passes.
+    if (mSearchFilter.empty()) return true;
+
+    LLStringUtil::toLower(setting_name);
+    std::string::size_type match_name = setting_name.find(mSearchFilter);
+
+    return (std::string::npos != match_name);
+}
+
+bool ALFloaterSettingsColor::isSettingHidden(const std::string& color_name)
+{
+    static LLCachedControl<bool> hide_default(gSavedSettings, "ColorSettingsHideDefault", false);
+    return hide_default && LLUIColorTable::instance().isDefault(color_name);
+}
+
+void ALFloaterSettingsColor::updateDefaultColumn(const std::string& color_name)
+{
+    if (isSettingHidden(color_name))
+    {
+        hideUIControls();
+        updateList(true);
+        return;
+    }
+
+    LLScrollListItem* item = mSettingList->getFirstSelected();
+    if (item)
+    {
+        LLScrollListCell* cell = item->getColumn(0);
+        if (cell)
+        {
+            std::string is_default = LLUIColorTable::instance().isDefault(color_name) ? "" : "*";
+            cell->setValue(is_default);
+        }
+    }
+}
+
+void ALFloaterSettingsColor::hideUIControls()
+{
+    mColorSwatch->setVisible(false);
+    mAlphaSpinner->setVisible(false);
+    mDefaultButton->setVisible(false);
+    mSettingNameText->setVisible(false);
+}
+
diff --git a/indra/newview/alfloatersettingscolor.h b/indra/newview/alfloatersettingscolor.h
new file mode 100644
index 00000000000..9d49e59ca0f
--- /dev/null
+++ b/indra/newview/alfloatersettingscolor.h
@@ -0,0 +1,81 @@
+/**
+ * @file alfloatersettingscolor.h
+ * @brief floater for debugging internal viewer colors
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Alchemy Viewer Source Code
+ * Copyright (C) 2024, Rye Mutt<rye@alchemyviewer.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * $/LicenseInfo$
+ */
+
+#ifndef ALFLOATERCOLORSETTINGS_H
+#define ALFLOATERCOLORSETTINGS_H
+
+#include "llcontrol.h"
+#include "llfloater.h"
+
+class LLColorSwatchCtrl;
+class LLScrollListCtrl;
+class LLSpinCtrl;
+class LLTextBox;
+
+class ALFloaterSettingsColor final
+:	public LLFloater
+{
+	friend class LLFloaterReg;
+
+public:
+
+	virtual BOOL postBuild();
+	virtual void draw();
+
+	void updateControl(const std::string& color_name);
+
+	void onCommitSettings();
+	void onClickDefault();
+
+    bool matchesSearchFilter(std::string setting_name);
+    bool isSettingHidden(const std::string& color_name);
+
+private:
+	// key - selects which settings to show, one of:
+	// "all", "base", "account", "skin"
+	ALFloaterSettingsColor(const LLSD& key);
+	virtual ~ALFloaterSettingsColor();
+
+    void updateList(bool skip_selection = false);
+    void onSettingSelect();
+    void setSearchFilter(const std::string& filter);
+
+    void updateDefaultColumn(const std::string& color_name);
+    void hideUIControls();
+
+    LLScrollListCtrl* mSettingList;
+	
+protected:
+	LLUICtrl*			mDefaultButton = nullptr;
+	LLTextBox*			mSettingNameText = nullptr;
+
+	LLSpinCtrl* mAlphaSpinner = nullptr;
+	LLColorSwatchCtrl* mColorSwatch = nullptr;
+
+    std::string mSearchFilter;
+};
+
+#endif //ALFLOATERCOLORSETTINGS_H
+
diff --git a/indra/newview/app_settings/settings_alchemy.xml b/indra/newview/app_settings/settings_alchemy.xml
index 4920cd6560c..0527b7511ab 100644
--- a/indra/newview/app_settings/settings_alchemy.xml
+++ b/indra/newview/app_settings/settings_alchemy.xml
@@ -1965,5 +1965,16 @@
 			<key>Value</key>
 			<integer>0</integer>
 		</map>
+		<key>ColorSettingsHideDefault</key>
+		<map>
+			<key>Comment</key>
+			<string>Show non-default settings only in Color Settings list</string>
+			<key>Persist</key>
+			<integer>0</integer>
+			<key>Type</key>
+			<string>Boolean</string>
+			<key>Value</key>
+			<integer>0</integer>
+		</map>
 	</map>
 </llsd>
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 6f76d89454d..475688f7bc8 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -37,6 +37,7 @@
 #include "alfloaterlightbox.h"
 #include "alfloaterparticleeditor.h"
 #include "alfloaterregiontracker.h"
+#include "alfloatersettingscolor.h"
 #include "llchatbar.h"
 #include "llcommandhandler.h"
 #include "llcompilequeue.h"
@@ -583,6 +584,7 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("quick_settings", "floater_quick_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
 	LLFloaterReg::add("region_tracker", "floater_region_tracker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<ALFloaterRegionTracker>);
 	LLFloaterReg::add("search", "floater_directory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDirectory>);
+	LLFloaterReg::add("settings_color", "floater_settings_color.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<ALFloaterSettingsColor>);
 	LLFloaterReg::add("sound_explorer", "floater_explore_sounds.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<ALFloaterExploreSounds>);
     LLFloaterReg::add("webprofile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
 
diff --git a/indra/newview/skins/default/xui/en/floater_settings_color.xml b/indra/newview/skins/default/xui/en/floater_settings_color.xml
new file mode 100644
index 00000000000..0722677f1d1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_settings_color.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater
+    legacy_header_height="18"
+    can_minimize="false"
+    height="360"
+    min_height="367"
+    layout="topleft"
+    name="settings_color"
+    help_topic="settings_color"
+    title="COLOR SETTINGS"
+    reuse_instance="true"
+    can_resize="true"
+    min_width="550"
+    width="570">
+    <filter_editor
+        follows="left|top|right"
+        height="23"
+        layout="topleft"
+        left="10"
+        right="-10"
+        label="Enter search text"
+        max_length_chars="300"
+        name="filter_input"
+        text_pad_left="10"
+        top="30" />
+    <scroll_list
+        column_padding="0"
+        draw_heading="true"
+        draw_stripes="false"
+        heading_height="23"
+        height="266"
+        layout="topleft"
+        search_column="1"
+        sort_column="1"
+        left="10"
+        follows="left|top|bottom"
+        name="setting_list"
+        top_pad="2"
+        width="300">
+        <scroll_list.columns
+            name="changed_color"
+            relative_width="0.05" />
+        <scroll_list.columns
+            label="Color"
+            name="color" />
+    </scroll_list>
+    <text
+        type="string"
+        length="1"
+        follows="left|top"
+        height="16"
+        layout="topleft"
+        name="color_name_txt"
+        font="SansSerifSmallBold"
+        top_delta="8"
+        left_pad="10"
+        visible="true"
+        use_ellipses="true"
+        text_color="White"
+        width="240">
+        Color name
+    </text>
+    <color_swatch
+        top_pad="0"
+        left_delta="0"
+        follows="top|left"
+        can_apply_immediately="true"
+        height="180"
+        name="color_swatch"
+        visible="true"
+        layout="topleft"
+        width="240">
+        <color_swatch.commit_callback
+            function="CommitSettings" />
+    </color_swatch>
+    <spinner
+        height="20"
+        label="Alpha"
+        layout="topleft"
+        follows="top|left"
+        left_delta="0"
+        min_val="0"
+        max_val="1"
+        decimal_digits="3"
+        name="alpha_spinner"
+        top_pad="5"
+        visible="true"
+        width="120">
+        <spinner.commit_callback
+            function="CommitSettings" />
+    </spinner>
+    <button
+        height="22"
+        label="Reset to default"
+        follows="left|top"
+        layout="topleft"
+        left_delta="0"
+        name="default_btn"
+        visible="true"
+        top_pad="15"
+        width="150">
+        <button.commit_callback
+            function="ClickDefault" />
+    </button>
+    <check_box
+        control_name="ColorSettingsHideDefault"
+        height="16"
+        initial_value="true"
+        label="Show changed colors only"
+        layout="topleft"
+        top_pad="10"
+        left="10"
+        follows="left|bottom"
+        name="hide_default"
+        width="330">
+    </check_box>
+</floater>
\ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml
index 3d16450fbe3..be5ae7260c7 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -187,6 +187,13 @@
              function="Floater.Toggle"
              parameter="ui_preview" />
         </menu_item_call>
+        <menu_item_call
+        label="Color Settings"
+        name="Color Settings">
+        <menu_item_call.on_click
+         function="Floater.Toggle"
+         parameter="settings_color" />
+       </menu_item_call>
       <menu_item_separator />
       <menu
        create_jump_keys="true"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index f2b9c4bad0a..5bfec207d33 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -4214,7 +4214,7 @@ function="World.EnvPreset"
         </menu>
         <menu
          create_jump_keys="true"
-         label="XUI"
+         label="XUI / Colors"
          name="XUI"
          tear_off="true">
             <menu_item_call
@@ -4224,6 +4224,13 @@ function="World.EnvPreset"
               function="Floater.Toggle"
               parameter="ui_preview" />
             </menu_item_call>
+            <menu_item_call
+             label="Color Settings"
+             name="Color Settings">
+             <menu_item_call.on_click
+              function="Floater.Toggle"
+              parameter="settings_color" />
+            </menu_item_call>
             <menu_item_call
                label="Reload Color Settings"
                name="Reload Color Settings">
-- 
GitLab