Add generic color picker popup to UI, add alpha support

Use the popup system ported from the editor to reimplement the color picker popup.

Remove special handling necessary for the hard-coded color picker.

Add alpha support to the color picker popup.
This commit is contained in:
Robert Müller 2023-06-04 14:17:02 +02:00
parent 938c57e03a
commit e50bd4bb6c
5 changed files with 229 additions and 290 deletions

View file

@ -51,8 +51,6 @@ ColorRGBA CMenus::ms_ColorTabbarInactiveIngame;
ColorRGBA CMenus::ms_ColorTabbarActiveIngame;
ColorRGBA CMenus::ms_ColorTabbarHoverIngame;
SColorPicker CMenus::ms_ColorPicker;
float CMenus::ms_ButtonHeight = 25.0f;
float CMenus::ms_ListheaderHeight = 17.0f;
@ -122,28 +120,11 @@ int CMenus::DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect,
return Active ? UI()->DoButtonLogic(pID, Checked, pRect) : 0;
}
int CMenus::DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName, int Corners, float r, float FontFactor, vec4 ColorHot, vec4 Color, bool CheckForActiveColorPicker)
int CMenus::DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName, int Corners, float r, float FontFactor, vec4 ColorHot, vec4 Color)
{
CUIRect Text = *pRect;
bool MouseInsideColorPicker = false;
if(CheckForActiveColorPicker)
{
if(ms_ColorPicker.m_Active)
{
CUIRect PickerRect;
PickerRect.x = ms_ColorPicker.m_X;
PickerRect.y = ms_ColorPicker.m_Y;
PickerRect.w = ms_ColorPicker.ms_Width;
PickerRect.h = ms_ColorPicker.ms_Height;
MouseInsideColorPicker = UI()->MouseInside(&PickerRect);
}
}
if(!MouseInsideColorPicker)
Color.a *= UI()->ButtonColorMul(pButtonContainer);
Color.a *= UI()->ButtonColorMul(pButtonContainer);
pRect->Draw(Color, Corners, r);
if(pImageName)
@ -170,9 +151,6 @@ int CMenus::DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText,
Text.HMargin((Text.h * FontFactor) / 2.0f, &Text);
UI()->DoLabel(&Text, pText, Text.h * CUI::ms_FontmodHeight, TEXTALIGN_MC);
if(MouseInsideColorPicker)
return 0;
return UI()->DoButtonLogic(pButtonContainer, Checked, pRect);
}
@ -374,7 +352,7 @@ void CMenus::DoLaserPreview(const CUIRect *pRect, const ColorHSLA LaserOutlineCo
}
}
ColorHSLA CMenus::DoLine_ColorPicker(CButtonContainer *pResetID, const float LineSize, const float LabelSize, const float BottomMargin, CUIRect *pMainRect, const char *pText, unsigned int *pColorValue, const ColorRGBA DefaultColor, bool CheckBoxSpacing, int *pCheckBoxValue)
ColorHSLA CMenus::DoLine_ColorPicker(CButtonContainer *pResetID, const float LineSize, const float LabelSize, const float BottomMargin, CUIRect *pMainRect, const char *pText, unsigned int *pColorValue, const ColorRGBA DefaultColor, bool CheckBoxSpacing, int *pCheckBoxValue, bool Alpha)
{
CUIRect Section, ColorPickerButton, ResetButton, Label;
@ -391,9 +369,9 @@ ColorHSLA CMenus::DoLine_ColorPicker(CButtonContainer *pResetID, const float Lin
if(DoButton_CheckBox(pCheckBoxValue, "", *pCheckBoxValue, &CheckBox))
*pCheckBoxValue ^= 1;
}
Section.VSplitLeft(5.0f, nullptr, &Section);
}
Section.VSplitLeft(5.0f, nullptr, &Section);
Section.VSplitMid(&Label, &Section, Section.h);
Section.VSplitRight(60.0f, &Section, &ResetButton);
Section.VSplitRight(8.0f, &Section, nullptr);
@ -401,17 +379,46 @@ ColorHSLA CMenus::DoLine_ColorPicker(CButtonContainer *pResetID, const float Lin
UI()->DoLabel(&Label, pText, LabelSize, TEXTALIGN_ML);
ColorHSLA PickedColor = RenderHSLColorPicker(&ColorPickerButton, pColorValue, false);
ColorHSLA PickedColor = DoButton_ColorPicker(&ColorPickerButton, pColorValue, Alpha);
ResetButton.HMargin(2.0f, &ResetButton);
if(DoButton_Menu(pResetID, Localize("Reset"), 0, &ResetButton, nullptr, IGraphics::CORNER_ALL, 8.0f, 0.0f, vec4(1, 1, 1, 0.5f), vec4(1, 1, 1, 0.25f), true))
if(DoButton_Menu(pResetID, Localize("Reset"), 0, &ResetButton, nullptr, IGraphics::CORNER_ALL, 8.0f, 0.0f, vec4(1, 1, 1, 0.5f), vec4(1, 1, 1, 0.25f)))
{
*pColorValue = color_cast<ColorHSLA>(DefaultColor).Pack(false);
*pColorValue = color_cast<ColorHSLA>(DefaultColor).Pack(Alpha);
}
return PickedColor;
}
ColorHSLA CMenus::DoButton_ColorPicker(const CUIRect *pRect, unsigned int *pColor, bool Alpha)
{
ColorHSLA HSLColor = ColorHSLA(*pColor, Alpha);
ColorRGBA Outline = ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f);
Outline.a *= UI()->ButtonColorMul(pColor);
CUIRect Rect;
pRect->Margin(3.0f, &Rect);
pRect->Draw(Outline, IGraphics::CORNER_ALL, 4.0f);
Rect.Draw(color_cast<ColorRGBA>(HSLColor), IGraphics::CORNER_ALL, 4.0f);
static CUI::SColorPickerPopupContext s_ColorPickerPopupContext;
if(UI()->DoButtonLogic(pColor, 0, pRect))
{
s_ColorPickerPopupContext.m_pColor = pColor;
s_ColorPickerPopupContext.m_HSVColor = color_cast<ColorHSVA>(HSLColor).Pack(Alpha);
s_ColorPickerPopupContext.m_Alpha = Alpha;
UI()->ShowPopupColorPicker(UI()->MouseX(), UI()->MouseY(), &s_ColorPickerPopupContext);
}
else if(UI()->IsPopupOpen(&s_ColorPickerPopupContext) && s_ColorPickerPopupContext.m_pColor == pColor)
{
HSLColor = color_cast<ColorHSLA>(ColorHSVA(s_ColorPickerPopupContext.m_HSVColor, Alpha));
}
return HSLColor;
}
int CMenus::DoButton_CheckBoxAutoVMarginAndSet(const void *pID, const char *pText, int *pValue, CUIRect *pRect, float VMargin)
{
CUIRect CheckBoxRect;
@ -951,196 +958,6 @@ bool CMenus::CanDisplayWarning()
return m_Popup == POPUP_NONE;
}
void CMenus::RenderColorPicker()
{
if(!ms_ColorPicker.m_Active)
return;
if(UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
{
ms_ColorPicker.m_Active = false;
UI()->SetValueSelectorTextMode(false);
UI()->SetActiveItem(nullptr);
return;
}
// First check if we should disable color picker
CUIRect PickerRect;
PickerRect.x = ms_ColorPicker.m_X;
PickerRect.y = ms_ColorPicker.m_Y;
PickerRect.w = ms_ColorPicker.ms_Width;
PickerRect.h = ms_ColorPicker.ms_Height;
if(UI()->MouseButtonClicked(0) && !UI()->MouseInside(&PickerRect) && !UI()->MouseInside(&ms_ColorPicker.m_AttachedRect))
{
ms_ColorPicker.m_Active = false;
UI()->SetValueSelectorTextMode(false);
UI()->SetActiveItem(nullptr);
return;
}
// Prevent activation of UI elements outside of active color picker
if(UI()->MouseInside(&PickerRect))
UI()->SetHotItem(&ms_ColorPicker);
// Render
ColorRGBA BackgroundColor(0.1f, 0.1f, 0.1f, 1.0f);
PickerRect.Draw(BackgroundColor, 0, 0);
CUIRect ColorsArea, HueArea, ValuesHitbox, BottomArea, HueRect, SatRect, ValueRect, HexRect, AlphaRect;
PickerRect.Margin(3, &ColorsArea);
ColorsArea.HSplitBottom(ms_ColorPicker.ms_Height - 140.0f, &ColorsArea, &ValuesHitbox);
ColorsArea.VSplitRight(20, &ColorsArea, &HueArea);
BottomArea = ValuesHitbox;
BottomArea.HSplitTop(3, 0x0, &BottomArea);
HueArea.VSplitLeft(3, 0x0, &HueArea);
BottomArea.HSplitTop(20, &HueRect, &BottomArea);
BottomArea.HSplitTop(3, 0x0, &BottomArea);
constexpr float ValuePadding = 5.0f;
const float HsvValueWidth = (HueRect.w - ValuePadding * 2) / 3.0f;
const float HexValueWidth = HsvValueWidth * 2 + ValuePadding;
HueRect.VSplitLeft(HsvValueWidth, &HueRect, &SatRect);
SatRect.VSplitLeft(ValuePadding, 0x0, &SatRect);
SatRect.VSplitLeft(HsvValueWidth, &SatRect, &ValueRect);
ValueRect.VSplitLeft(ValuePadding, 0x0, &ValueRect);
BottomArea.HSplitTop(20, &HexRect, &BottomArea);
HexRect.VSplitLeft(HexValueWidth, &HexRect, &AlphaRect);
AlphaRect.VSplitLeft(ValuePadding, 0x0, &AlphaRect);
if(UI()->MouseButtonReleased(1) && !UI()->MouseInside(&ValuesHitbox))
{
ms_ColorPicker.m_Active = false;
UI()->SetValueSelectorTextMode(false);
UI()->SetActiveItem(nullptr);
return;
}
ColorRGBA BlackColor(0, 0, 0, 0.5f);
HueArea.Draw(BlackColor, 0, 0);
HueArea.Margin(1, &HueArea);
ColorsArea.Draw(BlackColor, 0, 0);
ColorsArea.Margin(1, &ColorsArea);
ColorHSVA PickerColorHSV(ms_ColorPicker.m_HSVColor);
unsigned H = (unsigned)(PickerColorHSV.x * 255.0f);
unsigned S = (unsigned)(PickerColorHSV.y * 255.0f);
unsigned V = (unsigned)(PickerColorHSV.z * 255.0f);
// Color Area
vec4 TL = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 0.0f, 1.0f));
vec4 TR = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 1.0f, 1.0f));
vec4 BL = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 0.0f, 1.0f));
vec4 BR = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 1.0f, 1.0f));
ColorsArea.Draw4(TL, TR, BL, BR, IGraphics::CORNER_NONE, 0.0f);
TL = vec4(0.0f, 0.0f, 0.0f, 0.0f);
TR = vec4(0.0f, 0.0f, 0.0f, 0.0f);
BL = vec4(0.0f, 0.0f, 0.0f, 1.0f);
BR = vec4(0.0f, 0.0f, 0.0f, 1.0f);
ColorsArea.Draw4(TL, TR, BL, BR, IGraphics::CORNER_NONE, 0.0f);
// Hue Area
static const float s_aColorIndices[7][3] = {
{1.0f, 0.0f, 0.0f}, // red
{1.0f, 0.0f, 1.0f}, // magenta
{0.0f, 0.0f, 1.0f}, // blue
{0.0f, 1.0f, 1.0f}, // cyan
{0.0f, 1.0f, 0.0f}, // green
{1.0f, 1.0f, 0.0f}, // yellow
{1.0f, 0.0f, 0.0f} // red
};
float HuePickerOffset = HueArea.h / 6.0f;
CUIRect HuePartialArea = HueArea;
HuePartialArea.h = HuePickerOffset;
for(int j = 0; j < 6; j++)
{
TL = vec4(s_aColorIndices[j][0], s_aColorIndices[j][1], s_aColorIndices[j][2], 1.0f);
BL = vec4(s_aColorIndices[j + 1][0], s_aColorIndices[j + 1][1], s_aColorIndices[j + 1][2], 1.0f);
HuePartialArea.y = HueArea.y + HuePickerOffset * j;
HuePartialArea.Draw4(TL, TL, BL, BL, IGraphics::CORNER_NONE, 0.0f);
}
// Editboxes Area
static char s_aValueSelectorIds[4];
H = UI()->DoValueSelector(&s_aValueSelectorIds[0], &HueRect, "H:", H, 0, 255);
S = UI()->DoValueSelector(&s_aValueSelectorIds[1], &SatRect, "S:", S, 0, 255);
V = UI()->DoValueSelector(&s_aValueSelectorIds[2], &ValueRect, "V:", V, 0, 255);
PickerColorHSV = ColorHSVA(H / 255.0f, S / 255.0f, V / 255.0f);
SValueSelectorProperties Props;
Props.m_UseScroll = false;
Props.m_IsHex = true;
unsigned int Hex = color_cast<ColorRGBA>(PickerColorHSV).Pack(false);
unsigned int NewHex = UI()->DoValueSelector(&s_aValueSelectorIds[3], &HexRect, "Hex:", Hex, 0, 0xFFFFFF, Props);
if(Hex != NewHex)
PickerColorHSV = color_cast<ColorHSVA>(ColorRGBA(NewHex));
// TODO : ALPHA SUPPORT
UI()->DoLabel(&AlphaRect, "A: 255", 10, TEXTALIGN_MC);
AlphaRect.Draw(ColorRGBA(0, 0, 0, 0.65f), IGraphics::CORNER_ALL, 5.0f);
// Logic
float PickerX, PickerY;
static int s_ColorPickerId = 0;
if(UI()->DoPickerLogic(&s_ColorPickerId, &ColorsArea, &PickerX, &PickerY))
{
PickerColorHSV.y = PickerX / ColorsArea.w;
PickerColorHSV.z = 1.0f - PickerY / ColorsArea.h;
}
static int s_HuePickerId = 0;
if(UI()->DoPickerLogic(&s_HuePickerId, &HueArea, &PickerX, &PickerY))
PickerColorHSV.x = 1.0f - PickerY / HueArea.h;
// Marker Color Area
const float MarkerX = ColorsArea.x + ColorsArea.w * PickerColorHSV.y;
const float MarkerY = ColorsArea.y + ColorsArea.h * (1.0f - PickerColorHSV.z);
const float MarkerOutlineInd = PickerColorHSV.z > 0.5f ? 0.0f : 1.0f;
const ColorRGBA MarkerOutline = ColorRGBA(MarkerOutlineInd, MarkerOutlineInd, MarkerOutlineInd, 1.0f);
Graphics()->TextureClear();
Graphics()->QuadsBegin();
Graphics()->SetColor(MarkerOutline);
Graphics()->DrawCircle(MarkerX, MarkerY, 4.5f, 32);
Graphics()->SetColor(color_cast<ColorRGBA>(PickerColorHSV));
Graphics()->DrawCircle(MarkerX, MarkerY, 3.5f, 32);
Graphics()->QuadsEnd();
// Marker Hue Area
CUIRect HueMarker;
HueArea.Margin(-2.5f, &HueMarker);
HueMarker.h = 6.5f;
HueMarker.y = (HueArea.y + HueArea.h * (1.0f - PickerColorHSV.x)) - HueMarker.h / 2.0f;
const ColorRGBA HueMarkerColor = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 1, 1, 1));
const float HueMarkerOutlineColor = PickerColorHSV.x > 0.75f ? 1.0f : 0.0f;
const ColorRGBA HueMarkerOutline = ColorRGBA(HueMarkerOutlineColor, HueMarkerOutlineColor, HueMarkerOutlineColor, 1);
HueMarker.Draw(HueMarkerOutline, IGraphics::CORNER_ALL, 1.2f);
HueMarker.Margin(1.2f, &HueMarker);
HueMarker.Draw(HueMarkerColor, IGraphics::CORNER_ALL, 1.2f);
ms_ColorPicker.m_HSVColor = PickerColorHSV.Pack(false);
*ms_ColorPicker.m_pColor = color_cast<ColorHSLA>(PickerColorHSV).Pack(false);
}
int CMenus::Render()
{
if(Client()->State() == IClient::STATE_DEMOPLAYBACK && m_Popup == POPUP_NONE)
@ -2048,7 +1865,6 @@ void CMenus::SetActive(bool Active)
{
if(Active != m_MenuActive)
{
ms_ColorPicker.m_Active = false;
UI()->SetHotItem(nullptr);
UI()->SetActiveItem(nullptr);
}

View file

@ -29,22 +29,6 @@ struct CServerProcess
PROCESS m_Process;
};
struct SColorPicker
{
public:
const float ms_Width = 160.0f;
const float ms_Height = 186.0f;
float m_X;
float m_Y;
bool m_Active;
CUIRect m_AttachedRect;
unsigned int *m_pColor;
unsigned int m_HSVColor;
};
// component to fetch keypresses, override all other input
class CMenusKeyBinder : public CComponent
{
@ -71,11 +55,9 @@ class CMenus : public CComponent
static ColorRGBA ms_ColorTabbarActive;
static ColorRGBA ms_ColorTabbarHover;
static SColorPicker ms_ColorPicker;
int DoButton_FontIcon(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, int Corners = IGraphics::CORNER_ALL, bool Enabled = true);
int DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect, bool Active);
int DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName = nullptr, int Corners = IGraphics::CORNER_ALL, float r = 5.0f, float FontFactor = 0.0f, vec4 ColorHot = vec4(1.0f, 1.0f, 1.0f, 0.75f), vec4 Color = vec4(1, 1, 1, 0.5f), bool CheckForActiveColorPicker = false);
int DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName = nullptr, int Corners = IGraphics::CORNER_ALL, float r = 5.0f, float FontFactor = 0.0f, vec4 ColorHot = vec4(1.0f, 1.0f, 1.0f, 0.75f), vec4 Color = vec4(1, 1, 1, 0.5f));
int DoButton_MenuTab(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, int Corners, SUIAnimator *pAnimator = nullptr, const ColorRGBA *pDefaultColor = nullptr, const ColorRGBA *pActiveColor = nullptr, const ColorRGBA *pHoverColor = nullptr, float EdgeRounding = 10);
int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect);
@ -83,7 +65,8 @@ class CMenus : public CComponent
int DoButton_CheckBoxAutoVMarginAndSet(const void *pID, const char *pText, int *pValue, CUIRect *pRect, float VMargin);
int DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
ColorHSLA DoLine_ColorPicker(CButtonContainer *pResetID, float LineSize, float LabelSize, float BottomMargin, CUIRect *pMainRect, const char *pText, unsigned int *pColorValue, ColorRGBA DefaultColor, bool CheckBoxSpacing = true, int *pCheckBoxValue = nullptr);
ColorHSLA DoLine_ColorPicker(CButtonContainer *pResetID, float LineSize, float LabelSize, float BottomMargin, CUIRect *pMainRect, const char *pText, unsigned int *pColorValue, ColorRGBA DefaultColor, bool CheckBoxSpacing = true, int *pCheckBoxValue = nullptr, bool Alpha = false);
ColorHSLA DoButton_ColorPicker(const CUIRect *pRect, unsigned int *pColor, bool Alpha);
void DoLaserPreview(const CUIRect *pRect, ColorHSLA OutlineColor, ColorHSLA InnerColor, const int LaserType);
int DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
@ -96,8 +79,6 @@ class CMenus : public CComponent
void DoJoystickAxisPicker(CUIRect View);
void DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, bool Active);
void RenderColorPicker();
void RefreshSkins();
void RandomSkin();
@ -679,7 +660,6 @@ private:
// found in menus_settings.cpp
void RenderSettingsDDNet(CUIRect MainView);
void RenderSettingsAppearance(CUIRect MainView);
ColorHSLA RenderHSLColorPicker(const CUIRect *pRect, unsigned int *pColor, bool Alpha);
ColorHSLA RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool Alpha = false, bool ClampedLight = false);
int RenderDropDown(int &CurDropDownState, CUIRect *pRect, int CurSelection, const void **pIDs, const char **pStr, int PickNum, CButtonContainer *pButtonContainer, float &ScrollVal);

View file

@ -2122,7 +2122,6 @@ void CMenus::RenderSettings(CUIRect MainView)
static CButtonContainer s_aTabButtons[sizeof(apTabs)];
int NumTabs = (int)std::size(apTabs);
int PreviousPage = g_Config.m_UiSettingsPage;
for(int i = 0; i < NumTabs; i++)
{
@ -2132,9 +2131,6 @@ void CMenus::RenderSettings(CUIRect MainView)
g_Config.m_UiSettingsPage = i;
}
if(PreviousPage != g_Config.m_UiSettingsPage)
ms_ColorPicker.m_Active = false;
MainView.Margin(10.0f, &MainView);
if(g_Config.m_UiSettingsPage == SETTINGS_LANGUAGE)
@ -2196,49 +2192,6 @@ void CMenus::RenderSettings(CUIRect MainView)
}
else if(m_NeedRestartGeneral || m_NeedRestartSkins || m_NeedRestartGraphics || m_NeedRestartSound || m_NeedRestartDDNet)
UI()->DoLabel(&RestartWarning, Localize("You must restart the game for all settings to take effect."), 14.0f, TEXTALIGN_ML);
RenderColorPicker();
}
ColorHSLA CMenus::RenderHSLColorPicker(const CUIRect *pRect, unsigned int *pColor, bool Alpha)
{
ColorHSLA HSLColor(*pColor, false);
ColorRGBA RGBColor = color_cast<ColorRGBA>(HSLColor);
ColorRGBA Outline(1, 1, 1, 0.25f);
const float OutlineSize = 3.0f;
Outline.a *= UI()->ButtonColorMul(pColor);
CUIRect Rect;
pRect->Margin(OutlineSize, &Rect);
pRect->Draw(Outline, IGraphics::CORNER_ALL, 4.0f);
Rect.Draw(RGBColor, IGraphics::CORNER_ALL, 4.0f);
if(UI()->DoButtonLogic(pColor, 0, pRect))
{
if(ms_ColorPicker.m_Active)
{
CUIRect PickerRect;
PickerRect.x = ms_ColorPicker.m_X;
PickerRect.y = ms_ColorPicker.m_Y;
PickerRect.w = ms_ColorPicker.ms_Width;
PickerRect.h = ms_ColorPicker.ms_Height;
if(ms_ColorPicker.m_pColor == pColor || UI()->MouseInside(&PickerRect))
return HSLColor;
}
const CUIRect *pScreen = UI()->Screen();
ms_ColorPicker.m_X = minimum(UI()->MouseX(), pScreen->w - ms_ColorPicker.ms_Width);
ms_ColorPicker.m_Y = minimum(UI()->MouseY(), pScreen->h - ms_ColorPicker.ms_Height);
ms_ColorPicker.m_pColor = pColor;
ms_ColorPicker.m_Active = true;
ms_ColorPicker.m_AttachedRect = *pRect;
ms_ColorPicker.m_HSVColor = color_cast<ColorHSVA, ColorHSLA>(HSLColor).Pack(false);
}
return HSLColor;
}
ColorHSLA CMenus::RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool Alpha, bool ClampedLight)

View file

@ -1539,3 +1539,180 @@ void CUI::ShowPopupSelection(float X, float Y, SSelectionPopupContext *pContext)
pContext->m_pSelection = nullptr;
DoPopupMenu(pContext, X, Y, SSelectionPopupContext::POPUP_MAX_WIDTH + 10.0f, PopupHeight, pContext, PopupSelection);
}
CUI::EPopupMenuFunctionResult CUI::PopupColorPicker(void *pContext, CUIRect View, bool Active)
{
SColorPickerPopupContext *pColorPicker = static_cast<SColorPickerPopupContext *>(pContext);
CUI *pUI = pColorPicker->m_pUI;
CUIRect ColorsArea = View, HueArea, BottomArea, HueRect, SatRect, ValueRect, HexRect, AlphaRect;
ColorsArea.HSplitBottom(View.h - 140.0f, &ColorsArea, &BottomArea);
ColorsArea.VSplitRight(20.0f, &ColorsArea, &HueArea);
BottomArea.HSplitTop(3.0f, nullptr, &BottomArea);
HueArea.VSplitLeft(3.0f, nullptr, &HueArea);
BottomArea.HSplitTop(20.0f, &HueRect, &BottomArea);
BottomArea.HSplitTop(3.0f, nullptr, &BottomArea);
constexpr float ValuePadding = 5.0f;
const float HsvValueWidth = (HueRect.w - ValuePadding * 2) / 3.0f;
const float HexValueWidth = HsvValueWidth * 2 + ValuePadding;
HueRect.VSplitLeft(HsvValueWidth, &HueRect, &SatRect);
SatRect.VSplitLeft(ValuePadding, nullptr, &SatRect);
SatRect.VSplitLeft(HsvValueWidth, &SatRect, &ValueRect);
ValueRect.VSplitLeft(ValuePadding, nullptr, &ValueRect);
BottomArea.HSplitTop(20.0f, &HexRect, &BottomArea);
HexRect.VSplitLeft(HexValueWidth, &HexRect, &AlphaRect);
AlphaRect.VSplitLeft(ValuePadding, nullptr, &AlphaRect);
const ColorRGBA BlackColor = ColorRGBA(0.0f, 0.0f, 0.0f, 0.5f);
HueArea.Draw(BlackColor, IGraphics::CORNER_NONE, 0.0f);
HueArea.Margin(1.0f, &HueArea);
ColorsArea.Draw(BlackColor, IGraphics::CORNER_NONE, 0.0f);
ColorsArea.Margin(1.0f, &ColorsArea);
ColorHSVA PickerColorHSV = ColorHSVA(pColorPicker->m_HSVColor, pColorPicker->m_Alpha);
unsigned H = (unsigned)(PickerColorHSV.x * 255.0f);
unsigned S = (unsigned)(PickerColorHSV.y * 255.0f);
unsigned V = (unsigned)(PickerColorHSV.z * 255.0f);
unsigned A = (unsigned)(PickerColorHSV.a * 255.0f);
// Color Area
ColorRGBA TL, TR, BL, BR;
TL = BL = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 0.0f, 1.0f));
TR = BR = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 1.0f, 1.0f));
ColorsArea.Draw4(TL, TR, BL, BR, IGraphics::CORNER_NONE, 0.0f);
TL = TR = ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f);
BL = BR = ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f);
ColorsArea.Draw4(TL, TR, BL, BR, IGraphics::CORNER_NONE, 0.0f);
// Hue Area
static const float s_aaColorIndices[7][3] = {
{1.0f, 0.0f, 0.0f}, // red
{1.0f, 0.0f, 1.0f}, // magenta
{0.0f, 0.0f, 1.0f}, // blue
{0.0f, 1.0f, 1.0f}, // cyan
{0.0f, 1.0f, 0.0f}, // green
{1.0f, 1.0f, 0.0f}, // yellow
{1.0f, 0.0f, 0.0f}, // red
};
const float HuePickerOffset = HueArea.h / 6.0f;
CUIRect HuePartialArea = HueArea;
HuePartialArea.h = HuePickerOffset;
for(size_t j = 0; j < std::size(s_aaColorIndices) - 1; j++)
{
TL = ColorRGBA(s_aaColorIndices[j][0], s_aaColorIndices[j][1], s_aaColorIndices[j][2], 1.0f);
BL = ColorRGBA(s_aaColorIndices[j + 1][0], s_aaColorIndices[j + 1][1], s_aaColorIndices[j + 1][2], 1.0f);
HuePartialArea.y = HueArea.y + HuePickerOffset * j;
HuePartialArea.Draw4(TL, TL, BL, BL, IGraphics::CORNER_NONE, 0.0f);
}
// Editboxes Area
H = pUI->DoValueSelector(&pColorPicker->m_aValueSelectorIds[0], &HueRect, "H:", H, 0, 255);
S = pUI->DoValueSelector(&pColorPicker->m_aValueSelectorIds[1], &SatRect, "S:", S, 0, 255);
V = pUI->DoValueSelector(&pColorPicker->m_aValueSelectorIds[2], &ValueRect, "V:", V, 0, 255);
if(pColorPicker->m_Alpha)
{
A = pUI->DoValueSelector(&pColorPicker->m_aValueSelectorIds[3], &AlphaRect, "A:", A, 0, 255);
}
else
{
char aBuf[8];
str_format(aBuf, sizeof(aBuf), "A: %d", A);
pUI->DoLabel(&AlphaRect, aBuf, 10.0f, TEXTALIGN_MC);
AlphaRect.Draw(ColorRGBA(0.0f, 0.0f, 0.0f, 0.65f), IGraphics::CORNER_ALL, 3.0f);
}
PickerColorHSV = ColorHSVA(H / 255.0f, S / 255.0f, V / 255.0f, A / 255.0f);
const auto RotateByteLeft = [pColorPicker](unsigned Num) {
if(pColorPicker->m_Alpha)
{
// ARGB -> RGBA (internal -> displayed)
return ((Num & 0xFF000000u) >> 24) | (Num << 8);
}
return Num;
};
const auto RotateByteRight = [pColorPicker](unsigned Num) {
if(pColorPicker->m_Alpha)
{
// RGBA -> ARGB (displayed -> internal)
return ((Num & 0xFFu) << 24) | (Num >> 8);
}
return Num;
};
SValueSelectorProperties Props;
Props.m_UseScroll = false;
Props.m_IsHex = true;
Props.m_HexPrefix = pColorPicker->m_Alpha ? 8 : 6;
const unsigned Hex = RotateByteLeft(color_cast<ColorRGBA>(PickerColorHSV).Pack(pColorPicker->m_Alpha));
const unsigned NewHex = pUI->DoValueSelector(&pColorPicker->m_aValueSelectorIds[4], &HexRect, "Hex:", Hex, 0, pColorPicker->m_Alpha ? 0xFFFFFFFFll : 0xFFFFFFll, Props);
if(Hex != NewHex)
{
PickerColorHSV = color_cast<ColorHSVA>(ColorRGBA(RotateByteRight(NewHex), pColorPicker->m_Alpha));
if(!pColorPicker->m_Alpha)
PickerColorHSV.a = A / 255.0f;
}
// Logic
float PickerX, PickerY;
if(pUI->DoPickerLogic(&pColorPicker->m_ColorPickerId, &ColorsArea, &PickerX, &PickerY))
{
PickerColorHSV.y = PickerX / ColorsArea.w;
PickerColorHSV.z = 1.0f - PickerY / ColorsArea.h;
}
if(pUI->DoPickerLogic(&pColorPicker->m_HuePickerId, &HueArea, &PickerX, &PickerY))
PickerColorHSV.x = 1.0f - PickerY / HueArea.h;
// Marker Color Area
const float MarkerX = ColorsArea.x + ColorsArea.w * PickerColorHSV.y;
const float MarkerY = ColorsArea.y + ColorsArea.h * (1.0f - PickerColorHSV.z);
const float MarkerOutlineInd = PickerColorHSV.z > 0.5f ? 0.0f : 1.0f;
const ColorRGBA MarkerOutline = ColorRGBA(MarkerOutlineInd, MarkerOutlineInd, MarkerOutlineInd, 1.0f);
pUI->Graphics()->TextureClear();
pUI->Graphics()->QuadsBegin();
pUI->Graphics()->SetColor(MarkerOutline);
pUI->Graphics()->DrawCircle(MarkerX, MarkerY, 4.5f, 32);
pUI->Graphics()->SetColor(color_cast<ColorRGBA>(PickerColorHSV));
pUI->Graphics()->DrawCircle(MarkerX, MarkerY, 3.5f, 32);
pUI->Graphics()->QuadsEnd();
// Marker Hue Area
CUIRect HueMarker;
HueArea.Margin(-2.5f, &HueMarker);
HueMarker.h = 6.5f;
HueMarker.y = (HueArea.y + HueArea.h * (1.0f - PickerColorHSV.x)) - HueMarker.h / 2.0f;
const ColorRGBA HueMarkerColor = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 1.0f, 1.0f, 1.0f));
const float HueMarkerOutlineColor = PickerColorHSV.x > 0.75f ? 1.0f : 0.0f;
const ColorRGBA HueMarkerOutline = ColorRGBA(HueMarkerOutlineColor, HueMarkerOutlineColor, HueMarkerOutlineColor, 1.0f);
HueMarker.Draw(HueMarkerOutline, IGraphics::CORNER_ALL, 1.2f);
HueMarker.Margin(1.2f, &HueMarker);
HueMarker.Draw(HueMarkerColor, IGraphics::CORNER_ALL, 1.2f);
pColorPicker->m_HSVColor = PickerColorHSV.Pack(pColorPicker->m_Alpha);
*pColorPicker->m_pColor = color_cast<ColorHSLA>(PickerColorHSV).Pack(pColorPicker->m_Alpha);
return CUI::POPUP_KEEP_OPEN;
}
void CUI::ShowPopupColorPicker(float X, float Y, SColorPickerPopupContext *pContext)
{
pContext->m_pUI = this;
DoPopupMenu(pContext, X, Y, 160.0f + 10.0f, 186.0f + 10.0f, pContext, PopupColorPicker);
}

View file

@ -332,6 +332,7 @@ private:
static CUI::EPopupMenuFunctionResult PopupMessage(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupConfirm(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupSelection(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupColorPicker(void *pContext, CUIRect View, bool Active);
IClient *m_pClient;
IGraphics *m_pGraphics;
@ -574,6 +575,18 @@ public:
void Reset();
};
void ShowPopupSelection(float X, float Y, SSelectionPopupContext *pContext);
struct SColorPickerPopupContext : public SPopupMenuId
{
CUI *m_pUI; // set by CUI when popup is shown
bool m_Alpha = false;
unsigned int *m_pColor;
unsigned int m_HSVColor;
const char m_HuePickerId = 0;
const char m_ColorPickerId = 0;
const char m_aValueSelectorIds[5] = {0};
};
void ShowPopupColorPicker(float X, float Y, SColorPickerPopupContext *pContext);
};
#endif