Refactor HSLA scrollbar color picker rendering

Rename `CMenus::RenderHSLScrollbars` function to `RenderHslaScrollbars`.

Pass darkest light value as `float` to the `RenderHslaScrollbars` function to add support for different values, instead of enabling the clamping with a `bool` parameter. Previously, this parameter was always set to `true`, as this type of color picker is only used for skins.

Remove unnecessarily complicated code for rendering unclamped lighting scrollbar. The code can be simplified by considering the darkest lighting value as a variable.

Let the `RenderHslaScrollbars` function return `true` if the color was changed to simplify the usage. The function previously returned the color but this value was unused.

Use `IGraphics::SetColor4` function instead of `IGraphics::SetColorVertex` when possible. Rename variables `Array` to `aColorVertices`. Use `std::size` instead of hard-coding array sizes.
This commit is contained in:
Robert Müller 2024-06-26 23:11:56 +02:00
parent 01d2b3e3bc
commit abf8fac568
2 changed files with 91 additions and 194 deletions

View file

@ -791,7 +791,7 @@ private:
// found in menus_settings.cpp
void RenderSettingsDDNet(CUIRect MainView);
void RenderSettingsAppearance(CUIRect MainView);
ColorHSLA RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool Alpha = false, bool ClampedLight = false);
bool RenderHslaScrollbars(CUIRect *pRect, unsigned int *pColor, bool Alpha, float DarkestLight);
CServerProcess m_ServerProcess;
};

View file

@ -758,10 +758,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
{
aRects[i].HSplitTop(20.0f, &Label, &aRects[i]);
Ui()->DoLabel(&Label, apParts[i], 14.0f, TEXTALIGN_ML);
const unsigned PrevColor = *apColors[i];
RenderHSLScrollbars(&aRects[i], apColors[i], false, true);
if(PrevColor != *apColors[i])
if(RenderHslaScrollbars(&aRects[i], apColors[i], false, ColorHSLA::DARKEST_LGT))
{
SetNeedSendInfo();
}
@ -2128,53 +2125,39 @@ void CMenus::RenderSettings(CUIRect MainView)
}
}
ColorHSLA CMenus::RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool Alpha, bool ClampedLight)
bool CMenus::RenderHslaScrollbars(CUIRect *pRect, unsigned int *pColor, bool Alpha, float DarkestLight)
{
const unsigned PrevPackedColor = *pColor;
ColorHSLA Color(*pColor, Alpha);
CUIRect Preview, Button, Label;
char aBuf[32];
float *apComponent[] = {&Color.h, &Color.s, &Color.l, &Color.a};
const ColorHSLA OriginalColor = Color;
const char *apLabels[] = {Localize("Hue"), Localize("Sat."), Localize("Lht."), Localize("Alpha")};
const float SizePerEntry = 20.0f;
const float MarginPerEntry = 5.0f;
const float PreviewMargin = 2.5f;
const float PreviewHeight = 40.0f + 2 * PreviewMargin;
const float OffY = (SizePerEntry + MarginPerEntry) * (3 + (Alpha ? 1 : 0)) - PreviewHeight;
float SizePerEntry = 20.0f;
float MarginPerEntry = 5.0f;
CUIRect Preview;
pRect->VSplitLeft(PreviewHeight, &Preview, pRect);
Preview.HSplitTop(OffY / 2.0f, nullptr, &Preview);
Preview.HSplitTop(PreviewHeight, &Preview, nullptr);
float OffY = (SizePerEntry + MarginPerEntry) * (3 + (Alpha ? 1 : 0)) - 40.0f;
pRect->VSplitLeft(40.0f, &Preview, pRect);
Preview.HSplitTop(OffY / 2.0f, NULL, &Preview);
Preview.HSplitTop(40.0f, &Preview, NULL);
Graphics()->TextureClear();
{
const float SizeBorder = 5.0f;
Graphics()->SetColor(ColorRGBA(0.15f, 0.15f, 0.15f, 1));
int TmpCont = Graphics()->CreateRectQuadContainer(Preview.x - SizeBorder / 2.0f, Preview.y - SizeBorder / 2.0f, Preview.w + SizeBorder, Preview.h + SizeBorder, 4.0f + SizeBorder / 2.0f, IGraphics::CORNER_ALL);
Graphics()->RenderQuadContainer(TmpCont, -1);
Graphics()->DeleteQuadContainer(TmpCont);
}
ColorHSLA RenderColorHSLA(Color.r, Color.g, Color.b, Color.a);
if(ClampedLight)
RenderColorHSLA = RenderColorHSLA.UnclampLighting();
Graphics()->SetColor(color_cast<ColorRGBA>(RenderColorHSLA));
int TmpCont = Graphics()->CreateRectQuadContainer(Preview.x, Preview.y, Preview.w, Preview.h, 4.0f, IGraphics::CORNER_ALL);
Graphics()->RenderQuadContainer(TmpCont, -1);
Graphics()->DeleteQuadContainer(TmpCont);
auto &&RenderHSLColorsRect = [&](CUIRect *pColorRect) {
Graphics()->TextureClear();
Graphics()->TrianglesBegin();
Preview.Draw(ColorRGBA(0.15f, 0.15f, 0.15f, 1.0f), IGraphics::CORNER_ALL, 4.0f + PreviewMargin);
Preview.Margin(PreviewMargin, &Preview);
Preview.Draw(color_cast<ColorRGBA>(Color.UnclampLighting(DarkestLight)), IGraphics::CORNER_ALL, 4.0f + PreviewMargin);
auto &&RenderHueRect = [&](CUIRect *pColorRect) {
float CurXOff = pColorRect->x;
float SizeColor = pColorRect->w / 6;
const float SizeColor = pColorRect->w / 6;
// red to yellow
{
IGraphics::CColorVertex Array[4] = {
IGraphics::CColorVertex aColorVertices[] = {
IGraphics::CColorVertex(0, 1, 0, 0, 1),
IGraphics::CColorVertex(1, 1, 1, 0, 1),
IGraphics::CColorVertex(2, 1, 0, 0, 1),
IGraphics::CColorVertex(3, 1, 1, 0, 1)};
Graphics()->SetColorVertex(Array, 4);
Graphics()->SetColorVertex(aColorVertices, std::size(aColorVertices));
IGraphics::CFreeformItem Freeform(
CurXOff, pColorRect->y,
@ -2187,12 +2170,12 @@ ColorHSLA CMenus::RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool
// yellow to green
CurXOff += SizeColor;
{
IGraphics::CColorVertex Array[4] = {
IGraphics::CColorVertex aColorVertices[] = {
IGraphics::CColorVertex(0, 1, 1, 0, 1),
IGraphics::CColorVertex(1, 0, 1, 0, 1),
IGraphics::CColorVertex(2, 1, 1, 0, 1),
IGraphics::CColorVertex(3, 0, 1, 0, 1)};
Graphics()->SetColorVertex(Array, 4);
Graphics()->SetColorVertex(aColorVertices, std::size(aColorVertices));
IGraphics::CFreeformItem Freeform(
CurXOff, pColorRect->y,
@ -2205,12 +2188,12 @@ ColorHSLA CMenus::RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool
CurXOff += SizeColor;
// green to turquoise
{
IGraphics::CColorVertex Array[4] = {
IGraphics::CColorVertex aColorVertices[] = {
IGraphics::CColorVertex(0, 0, 1, 0, 1),
IGraphics::CColorVertex(1, 0, 1, 1, 1),
IGraphics::CColorVertex(2, 0, 1, 0, 1),
IGraphics::CColorVertex(3, 0, 1, 1, 1)};
Graphics()->SetColorVertex(Array, 4);
Graphics()->SetColorVertex(aColorVertices, std::size(aColorVertices));
IGraphics::CFreeformItem Freeform(
CurXOff, pColorRect->y,
@ -2223,12 +2206,12 @@ ColorHSLA CMenus::RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool
CurXOff += SizeColor;
// turquoise to blue
{
IGraphics::CColorVertex Array[4] = {
IGraphics::CColorVertex aColorVertices[] = {
IGraphics::CColorVertex(0, 0, 1, 1, 1),
IGraphics::CColorVertex(1, 0, 0, 1, 1),
IGraphics::CColorVertex(2, 0, 1, 1, 1),
IGraphics::CColorVertex(3, 0, 0, 1, 1)};
Graphics()->SetColorVertex(Array, 4);
Graphics()->SetColorVertex(aColorVertices, std::size(aColorVertices));
IGraphics::CFreeformItem Freeform(
CurXOff, pColorRect->y,
@ -2241,12 +2224,12 @@ ColorHSLA CMenus::RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool
CurXOff += SizeColor;
// blue to purple
{
IGraphics::CColorVertex Array[4] = {
IGraphics::CColorVertex aColorVertices[] = {
IGraphics::CColorVertex(0, 0, 0, 1, 1),
IGraphics::CColorVertex(1, 1, 0, 1, 1),
IGraphics::CColorVertex(2, 0, 0, 1, 1),
IGraphics::CColorVertex(3, 1, 0, 1, 1)};
Graphics()->SetColorVertex(Array, 4);
Graphics()->SetColorVertex(aColorVertices, std::size(aColorVertices));
IGraphics::CFreeformItem Freeform(
CurXOff, pColorRect->y,
@ -2259,12 +2242,12 @@ ColorHSLA CMenus::RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool
CurXOff += SizeColor;
// purple to red
{
IGraphics::CColorVertex Array[4] = {
IGraphics::CColorVertex aColorVertices[] = {
IGraphics::CColorVertex(0, 1, 0, 1, 1),
IGraphics::CColorVertex(1, 1, 0, 0, 1),
IGraphics::CColorVertex(2, 1, 0, 1, 1),
IGraphics::CColorVertex(3, 1, 0, 0, 1)};
Graphics()->SetColorVertex(Array, 4);
Graphics()->SetColorVertex(aColorVertices, std::size(aColorVertices));
IGraphics::CFreeformItem Freeform(
CurXOff, pColorRect->y,
@ -2273,150 +2256,68 @@ ColorHSLA CMenus::RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool
CurXOff + SizeColor, pColorRect->y + pColorRect->h);
Graphics()->QuadsDrawFreeform(&Freeform, 1);
}
Graphics()->TrianglesEnd();
};
auto &&RenderHSLSatRect = [&](CUIRect *pColorRect, ColorRGBA &CurColor) {
Graphics()->TextureClear();
Graphics()->TrianglesBegin();
float CurXOff = pColorRect->x;
float SizeColor = pColorRect->w;
ColorHSLA RightColor = color_cast<ColorHSLA>(CurColor);
auto &&RenderSaturationRect = [&](CUIRect *pColorRect, const ColorRGBA &CurColor) {
ColorHSLA LeftColor = color_cast<ColorHSLA>(CurColor);
ColorHSLA RightColor = color_cast<ColorHSLA>(CurColor);
LeftColor.g = 0;
RightColor.g = 1;
LeftColor.s = 0.0f;
RightColor.s = 1.0f;
ColorRGBA RightColorRGBA = color_cast<ColorRGBA>(RightColor);
ColorRGBA LeftColorRGBA = color_cast<ColorRGBA>(LeftColor);
const ColorRGBA LeftColorRGBA = color_cast<ColorRGBA>(LeftColor);
const ColorRGBA RightColorRGBA = color_cast<ColorRGBA>(RightColor);
// saturation
{
IGraphics::CColorVertex Array[4] = {
IGraphics::CColorVertex(0, LeftColorRGBA.r, LeftColorRGBA.g, LeftColorRGBA.b, 1),
IGraphics::CColorVertex(1, RightColorRGBA.r, RightColorRGBA.g, RightColorRGBA.b, 1),
IGraphics::CColorVertex(2, LeftColorRGBA.r, LeftColorRGBA.g, LeftColorRGBA.b, 1),
IGraphics::CColorVertex(3, RightColorRGBA.r, RightColorRGBA.g, RightColorRGBA.b, 1)};
Graphics()->SetColorVertex(Array, 4);
Graphics()->SetColor4(LeftColorRGBA, RightColorRGBA, RightColorRGBA, LeftColorRGBA);
IGraphics::CFreeformItem Freeform(
CurXOff, pColorRect->y,
CurXOff + SizeColor, pColorRect->y,
CurXOff, pColorRect->y + pColorRect->h,
CurXOff + SizeColor, pColorRect->y + pColorRect->h);
pColorRect->x, pColorRect->y,
pColorRect->x + pColorRect->w, pColorRect->y,
pColorRect->x, pColorRect->y + pColorRect->h,
pColorRect->x + pColorRect->w, pColorRect->y + pColorRect->h);
Graphics()->QuadsDrawFreeform(&Freeform, 1);
}
Graphics()->TrianglesEnd();
};
auto &&RenderHSLLightRect = [&](CUIRect *pColorRect, ColorRGBA &CurColorSat) {
Graphics()->TextureClear();
Graphics()->TrianglesBegin();
auto &&RenderLightingRect = [&](CUIRect *pColorRect, const ColorRGBA &CurColor) {
ColorHSLA LeftColor = color_cast<ColorHSLA>(CurColor);
ColorHSLA RightColor = color_cast<ColorHSLA>(CurColor);
float CurXOff = pColorRect->x;
float SizeColor = pColorRect->w / (ClampedLight ? 1.0f : 2.0f);
LeftColor.l = DarkestLight;
RightColor.l = 1.0f;
ColorHSLA RightColor = color_cast<ColorHSLA>(CurColorSat);
ColorHSLA LeftColor = color_cast<ColorHSLA>(CurColorSat);
const ColorRGBA LeftColorRGBA = color_cast<ColorRGBA>(LeftColor);
const ColorRGBA RightColorRGBA = color_cast<ColorRGBA>(RightColor);
LeftColor.b = ColorHSLA::DARKEST_LGT;
RightColor.b = 1;
ColorRGBA RightColorRGBA = color_cast<ColorRGBA>(RightColor);
ColorRGBA LeftColorRGBA = color_cast<ColorRGBA>(LeftColor);
if(!ClampedLight)
CurXOff += SizeColor;
// light
{
IGraphics::CColorVertex Array[4] = {
IGraphics::CColorVertex(0, LeftColorRGBA.r, LeftColorRGBA.g, LeftColorRGBA.b, 1),
IGraphics::CColorVertex(1, RightColorRGBA.r, RightColorRGBA.g, RightColorRGBA.b, 1),
IGraphics::CColorVertex(2, LeftColorRGBA.r, LeftColorRGBA.g, LeftColorRGBA.b, 1),
IGraphics::CColorVertex(3, RightColorRGBA.r, RightColorRGBA.g, RightColorRGBA.b, 1)};
Graphics()->SetColorVertex(Array, 4);
Graphics()->SetColor4(LeftColorRGBA, RightColorRGBA, RightColorRGBA, LeftColorRGBA);
IGraphics::CFreeformItem Freeform(
CurXOff, pColorRect->y,
CurXOff + SizeColor, pColorRect->y,
CurXOff, pColorRect->y + pColorRect->h,
CurXOff + SizeColor, pColorRect->y + pColorRect->h);
pColorRect->x, pColorRect->y,
pColorRect->x + pColorRect->w, pColorRect->y,
pColorRect->x, pColorRect->y + pColorRect->h,
pColorRect->x + pColorRect->w, pColorRect->y + pColorRect->h);
Graphics()->QuadsDrawFreeform(&Freeform, 1);
}
if(!ClampedLight)
{
CurXOff -= SizeColor;
LeftColor.b = 0;
RightColor.b = ColorHSLA::DARKEST_LGT;
RightColorRGBA = color_cast<ColorRGBA>(RightColor);
LeftColorRGBA = color_cast<ColorRGBA>(LeftColor);
IGraphics::CColorVertex Array[4] = {
IGraphics::CColorVertex(0, LeftColorRGBA.r, LeftColorRGBA.g, LeftColorRGBA.b, 1),
IGraphics::CColorVertex(1, RightColorRGBA.r, RightColorRGBA.g, RightColorRGBA.b, 1),
IGraphics::CColorVertex(2, LeftColorRGBA.r, LeftColorRGBA.g, LeftColorRGBA.b, 1),
IGraphics::CColorVertex(3, RightColorRGBA.r, RightColorRGBA.g, RightColorRGBA.b, 1)};
Graphics()->SetColorVertex(Array, 4);
IGraphics::CFreeformItem Freeform(
CurXOff, pColorRect->y,
CurXOff + SizeColor, pColorRect->y,
CurXOff, pColorRect->y + pColorRect->h,
CurXOff + SizeColor, pColorRect->y + pColorRect->h);
Graphics()->QuadsDrawFreeform(&Freeform, 1);
}
Graphics()->TrianglesEnd();
};
auto &&RenderHSLAlphaRect = [&](CUIRect *pColorRect, ColorRGBA &CurColorFull) {
Graphics()->TextureClear();
Graphics()->TrianglesBegin();
auto &&RenderAlphaRect = [&](CUIRect *pColorRect, const ColorRGBA &CurColorFull) {
const ColorRGBA LeftColorRGBA = color_cast<ColorRGBA>(color_cast<ColorHSLA>(CurColorFull).WithAlpha(0.0f));
const ColorRGBA RightColorRGBA = color_cast<ColorRGBA>(color_cast<ColorHSLA>(CurColorFull).WithAlpha(1.0f));
float CurXOff = pColorRect->x;
float SizeColor = pColorRect->w;
ColorHSLA RightColor = color_cast<ColorHSLA>(CurColorFull);
ColorHSLA LeftColor = color_cast<ColorHSLA>(CurColorFull);
LeftColor.a = 0;
RightColor.a = 1;
ColorRGBA RightColorRGBA = color_cast<ColorRGBA>(RightColor);
ColorRGBA LeftColorRGBA = color_cast<ColorRGBA>(LeftColor);
// alpha
{
IGraphics::CColorVertex Array[4] = {
IGraphics::CColorVertex(0, LeftColorRGBA.r, LeftColorRGBA.g, LeftColorRGBA.b, LeftColorRGBA.a),
IGraphics::CColorVertex(1, RightColorRGBA.r, RightColorRGBA.g, RightColorRGBA.b, RightColorRGBA.a),
IGraphics::CColorVertex(2, LeftColorRGBA.r, LeftColorRGBA.g, LeftColorRGBA.b, LeftColorRGBA.a),
IGraphics::CColorVertex(3, RightColorRGBA.r, RightColorRGBA.g, RightColorRGBA.b, RightColorRGBA.a)};
Graphics()->SetColorVertex(Array, 4);
Graphics()->SetColor4(LeftColorRGBA, RightColorRGBA, RightColorRGBA, LeftColorRGBA);
IGraphics::CFreeformItem Freeform(
CurXOff, pColorRect->y,
CurXOff + SizeColor, pColorRect->y,
CurXOff, pColorRect->y + pColorRect->h,
CurXOff + SizeColor, pColorRect->y + pColorRect->h);
pColorRect->x, pColorRect->y,
pColorRect->x + pColorRect->w, pColorRect->y,
pColorRect->x, pColorRect->y + pColorRect->h,
pColorRect->x + pColorRect->w, pColorRect->y + pColorRect->h);
Graphics()->QuadsDrawFreeform(&Freeform, 1);
}
Graphics()->TrianglesEnd();
};
for(int i = 0; i < 3 + Alpha; i++)
{
CUIRect Button, Label;
pRect->HSplitTop(SizePerEntry, &Button, pRect);
pRect->HSplitTop(MarginPerEntry, NULL, pRect);
Button.VSplitLeft(10.0f, 0, &Button);
pRect->HSplitTop(MarginPerEntry, nullptr, pRect);
Button.VSplitLeft(10.0f, nullptr, &Button);
Button.VSplitLeft(100.0f, &Label, &Button);
Button.Draw(ColorRGBA(0.15f, 0.15f, 0.15f, 1.0f), IGraphics::CORNER_ALL, 1.0f);
@ -2424,47 +2325,43 @@ ColorHSLA CMenus::RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool
CUIRect Rail;
Button.Margin(2.0f, &Rail);
str_format(aBuf, sizeof(aBuf), "%s: %03d", apLabels[i], (int)(*apComponent[i] * 255));
char aBuf[32];
str_format(aBuf, sizeof(aBuf), "%s: %03d", apLabels[i], round_to_int(Color[i] * 255.0f));
Ui()->DoLabel(&Label, aBuf, 14.0f, TEXTALIGN_ML);
ColorHSLA CurColorPureHSLA(RenderColorHSLA.r, 1, 0.5f, 1);
ColorRGBA CurColorPure = color_cast<ColorRGBA>(CurColorPureHSLA);
ColorRGBA ColorInner(1, 1, 1, 0.25f);
ColorRGBA HandleColor;
Graphics()->TextureClear();
Graphics()->TrianglesBegin();
if(i == 0)
{
ColorInner = CurColorPure;
RenderHSLColorsRect(&Rail);
RenderHueRect(&Rail);
HandleColor = color_cast<ColorRGBA>(ColorHSLA(Color.h, 1.0f, 0.5f, 1.0f));
}
else if(i == 1)
{
RenderHSLSatRect(&Rail, CurColorPure);
ColorInner = color_cast<ColorRGBA>(ColorHSLA(CurColorPureHSLA.r, *apComponent[1], CurColorPureHSLA.b, 1));
RenderSaturationRect(&Rail, color_cast<ColorRGBA>(ColorHSLA(Color.h, 1.0f, 0.5f, 1.0f)));
HandleColor = color_cast<ColorRGBA>(ColorHSLA(Color.h, Color.s, 0.5f, 1.0f));
}
else if(i == 2)
{
ColorRGBA CurColorSat = color_cast<ColorRGBA>(ColorHSLA(CurColorPureHSLA.r, *apComponent[1], 0.5f, 1));
RenderHSLLightRect(&Rail, CurColorSat);
float LightVal = *apComponent[2];
if(ClampedLight)
LightVal = ColorHSLA::DARKEST_LGT + LightVal * (1.0f - ColorHSLA::DARKEST_LGT);
ColorInner = color_cast<ColorRGBA>(ColorHSLA(CurColorPureHSLA.r, *apComponent[1], LightVal, 1));
RenderLightingRect(&Rail, color_cast<ColorRGBA>(ColorHSLA(Color.h, Color.s, 0.5f, 1.0f)));
HandleColor = color_cast<ColorRGBA>(ColorHSLA(Color.h, Color.s, Color.l, 1.0f).UnclampLighting(DarkestLight));
}
else if(i == 3)
{
ColorRGBA CurColorFull = color_cast<ColorRGBA>(ColorHSLA(CurColorPureHSLA.r, *apComponent[1], *apComponent[2], 1));
RenderHSLAlphaRect(&Rail, CurColorFull);
float LightVal = *apComponent[2];
if(ClampedLight)
LightVal = ColorHSLA::DARKEST_LGT + LightVal * (1.0f - ColorHSLA::DARKEST_LGT);
ColorInner = color_cast<ColorRGBA>(ColorHSLA(CurColorPureHSLA.r, *apComponent[1], LightVal, *apComponent[3]));
}
*apComponent[i] = Ui()->DoScrollbarH(&((char *)pColor)[i], &Button, *apComponent[i], &ColorInner);
RenderAlphaRect(&Rail, color_cast<ColorRGBA>(ColorHSLA(Color.h, Color.s, Color.l, 1.0f).UnclampLighting(DarkestLight)));
HandleColor = color_cast<ColorRGBA>(Color.UnclampLighting(DarkestLight));
}
Graphics()->TrianglesEnd();
Color[i] = Ui()->DoScrollbarH(&((char *)pColor)[i], &Button, Color[i], &HandleColor);
}
if(OriginalColor != Color)
{
*pColor = Color.Pack(Alpha);
return Color;
}
return PrevPackedColor != *pColor;
}
enum