6720: Improve scrollbar option UI and settings, improve joystick settings UI especially on 5:4 and 4:3 resolutions  r=def- a=Robyt3

Screenshots (not an exhaustive list):
- Controls settings:
   - Before:
![controls old](https://github.com/ddnet/ddnet/assets/23437060/357928bd-760c-4345-90fc-6e89a18ca96d)
   - After:
![controls new](https://github.com/ddnet/ddnet/assets/23437060/36864c11-cd23-44c7-9a94-e1fb1790ece6)
- Controls settings (5:4):
   - Before:
![controls_5-4 old](https://github.com/ddnet/ddnet/assets/23437060/4940c770-cbfe-4881-983c-278f11861166)
   - After:
![controls_5-4 new](https://github.com/ddnet/ddnet/assets/23437060/481ae686-7853-4b05-8faa-4a08ae323419)
- General settings:
   - Before:
![general old](https://github.com/ddnet/ddnet/assets/23437060/21324b77-fe49-49fe-8e71-f828a0ed6119)
   - After:
![general new](https://github.com/ddnet/ddnet/assets/23437060/2deffb9a-3cc2-4d25-8a03-c3046843f582)
- Sound settings:
   - Before:
![sound old](https://github.com/ddnet/ddnet/assets/23437060/7278bdcb-52a6-4f33-83bb-2e29ededb1ef)
   - After:
![sound new](https://github.com/ddnet/ddnet/assets/23437060/a3c03ded-88ac-45d6-aace-c76fa77778d6)
- DDNet settings:
   - Before:
![ddnet old](https://github.com/ddnet/ddnet/assets/23437060/f624cde9-f026-4c71-9037-42eaeaccb5d9)
   - After:
![ddnet new](https://github.com/ddnet/ddnet/assets/23437060/6a866cac-3315-43db-82a1-2a6aeac023a5)



## Checklist

- [X] Tested the change ingame
- [X] Provided screenshots if it is a visual change
- [X] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [X] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
bors[bot] 2023-06-08 09:12:18 +00:00 committed by GitHub
commit 6bffc858fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 159 additions and 271 deletions

View file

@ -124,7 +124,10 @@ int CMenus::DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText,
{
CUIRect Text = *pRect;
if(Checked)
Color = ColorRGBA(0.6f, 0.6f, 0.6f, 0.5f);
Color.a *= UI()->ButtonColorMul(pButtonContainer);
pRect->Draw(Color, Corners, r);
if(pImageName)

View file

@ -155,45 +155,29 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
// auto demo settings
{
Right.HSplitTop(40.0f, 0, &Right);
Right.HSplitTop(40.0f, nullptr, &Right);
Right.HSplitTop(20.0f, &Button, &Right);
if(DoButton_CheckBox(&g_Config.m_ClAutoDemoRecord, Localize("Automatically record demos"), g_Config.m_ClAutoDemoRecord, &Button))
g_Config.m_ClAutoDemoRecord ^= 1;
Right.HSplitTop(20.0f, &Label, &Right);
if(g_Config.m_ClAutoDemoMax)
str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Max demos"), g_Config.m_ClAutoDemoMax);
else
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Max demos"), "");
UI()->DoLabel(&Label, aBuf, 13.0f, TEXTALIGN_ML);
Right.HSplitTop(20.0f, &Button, &Right);
g_Config.m_ClAutoDemoMax = static_cast<int>(UI()->DoScrollbarH(&g_Config.m_ClAutoDemoMax, &Button, g_Config.m_ClAutoDemoMax / 1000.0f) * 1000.0f + 0.1f);
Right.HSplitTop(2 * 20.0f, &Button, &Right);
if(g_Config.m_ClAutoDemoRecord)
UI()->DoScrollbarOption(&g_Config.m_ClAutoDemoMax, &g_Config.m_ClAutoDemoMax, &Button, Localize("Max demos"), 1, 1000, &CUI::ms_LinearScrollbarScale, CUI::SCROLLBAR_OPTION_INFINITE | CUI::SCROLLBAR_OPTION_MULTILINE);
Right.HSplitTop(SliderGroupMargin, 0, &Right);
Right.HSplitTop(SliderGroupMargin, nullptr, &Right);
Right.HSplitTop(20.0f, &Button, &Right);
if(DoButton_CheckBox(&g_Config.m_ClAutoScreenshot, Localize("Automatically take game over screenshot"), g_Config.m_ClAutoScreenshot, &Button))
g_Config.m_ClAutoScreenshot ^= 1;
Right.HSplitTop(20.0f, &Label, &Right);
if(g_Config.m_ClAutoScreenshotMax)
str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Max Screenshots"), g_Config.m_ClAutoScreenshotMax);
else
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Max Screenshots"), "");
UI()->DoLabel(&Label, aBuf, 13.0f, TEXTALIGN_ML);
Right.HSplitTop(20.0f, &Button, &Right);
g_Config.m_ClAutoScreenshotMax = static_cast<int>(UI()->DoScrollbarH(&g_Config.m_ClAutoScreenshotMax, &Button, g_Config.m_ClAutoScreenshotMax / 1000.0f) * 1000.0f + 0.1f);
Right.HSplitTop(2 * 20.0f, &Button, &Right);
if(g_Config.m_ClAutoScreenshot)
UI()->DoScrollbarOption(&g_Config.m_ClAutoScreenshotMax, &g_Config.m_ClAutoScreenshotMax, &Button, Localize("Max Screenshots"), 1, 1000, &CUI::ms_LinearScrollbarScale, CUI::SCROLLBAR_OPTION_INFINITE | CUI::SCROLLBAR_OPTION_MULTILINE);
}
Left.HSplitTop(10.0f, 0, &Left);
Left.HSplitTop(20.0f, &Label, &Left);
if(g_Config.m_ClRefreshRate)
str_format(aBuf, sizeof(aBuf), "%s: %i Hz", Localize("Refresh Rate"), g_Config.m_ClRefreshRate);
else
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Refresh Rate"), "");
UI()->DoLabel(&Label, aBuf, 13.0f, TEXTALIGN_ML);
Left.HSplitTop(10.0f, nullptr, &Left);
Left.HSplitTop(20.0f, &Button, &Left);
g_Config.m_ClRefreshRate = static_cast<int>(UI()->DoScrollbarH(&g_Config.m_ClRefreshRate, &Button, g_Config.m_ClRefreshRate / 10000.0f) * 10000.0f + 0.1f);
Left.HSplitTop(5.0f, 0, &Left);
UI()->DoScrollbarOption(&g_Config.m_ClRefreshRate, &g_Config.m_ClRefreshRate, &Button, Localize("Refresh Rate"), 10, 10000, &CUI::ms_LogarithmicScrollbarScale, CUI::SCROLLBAR_OPTION_INFINITE, " Hz");
Left.HSplitTop(5.0f, nullptr, &Left);
Left.HSplitTop(20.0f, &Button, &Left);
int s_LowerRefreshRate;
if(DoButton_CheckBox(&s_LowerRefreshRate, Localize("Save power by lowering refresh rate (higher input latency)"), g_Config.m_ClRefreshRate <= 480 && g_Config.m_ClRefreshRate != 0, &Button))
@ -250,54 +234,30 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
// auto statboard screenshot
{
Right.HSplitTop(SliderGroupMargin, 0, &Right);
Right.HSplitTop(SliderGroupMargin, nullptr, &Right);
Right.HSplitTop(20.0f, &Button, &Right);
if(DoButton_CheckBox(&g_Config.m_ClAutoStatboardScreenshot,
Localize("Automatically take statboard screenshot"),
g_Config.m_ClAutoStatboardScreenshot, &Button))
if(DoButton_CheckBox(&g_Config.m_ClAutoStatboardScreenshot, Localize("Automatically take statboard screenshot"), g_Config.m_ClAutoStatboardScreenshot, &Button))
{
g_Config.m_ClAutoStatboardScreenshot ^= 1;
}
Right.HSplitTop(20.0f, &Label, &Right);
if(g_Config.m_ClAutoStatboardScreenshotMax)
str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Max Screenshots"), g_Config.m_ClAutoStatboardScreenshotMax);
else
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Max Screenshots"), "");
UI()->DoLabel(&Label, aBuf, 13.0f, TEXTALIGN_ML);
Right.HSplitTop(20.0f, &Button, &Right);
g_Config.m_ClAutoStatboardScreenshotMax =
static_cast<int>(UI()->DoScrollbarH(&g_Config.m_ClAutoStatboardScreenshotMax,
&Button,
g_Config.m_ClAutoStatboardScreenshotMax / 1000.0f) *
1000.0f +
0.1f);
Right.HSplitTop(2 * 20.0f, &Button, &Right);
if(g_Config.m_ClAutoStatboardScreenshot)
UI()->DoScrollbarOption(&g_Config.m_ClAutoStatboardScreenshotMax, &g_Config.m_ClAutoStatboardScreenshotMax, &Button, Localize("Max Screenshots"), 1, 1000, &CUI::ms_LinearScrollbarScale, CUI::SCROLLBAR_OPTION_INFINITE | CUI::SCROLLBAR_OPTION_MULTILINE);
}
// auto statboard csv
{
Right.HSplitTop(SliderGroupMargin, 0, &Right); //
Right.HSplitTop(SliderGroupMargin, nullptr, &Right);
Right.HSplitTop(20.0f, &Button, &Right);
if(DoButton_CheckBox(&g_Config.m_ClAutoCSV,
Localize("Automatically create statboard csv"),
g_Config.m_ClAutoCSV, &Button))
if(DoButton_CheckBox(&g_Config.m_ClAutoCSV, Localize("Automatically create statboard csv"), g_Config.m_ClAutoCSV, &Button))
{
g_Config.m_ClAutoCSV ^= 1;
}
Right.HSplitTop(20.0f, &Label, &Right);
if(g_Config.m_ClAutoCSVMax)
str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Max CSVs"), g_Config.m_ClAutoCSVMax);
else
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Max CSVs"), "");
UI()->DoLabel(&Label, aBuf, 13.0f, TEXTALIGN_ML);
Right.HSplitTop(20.0f, &Button, &Right);
g_Config.m_ClAutoCSVMax =
static_cast<int>(UI()->DoScrollbarH(&g_Config.m_ClAutoCSVMax,
&Button,
g_Config.m_ClAutoCSVMax / 1000.0f) *
1000.0f +
0.1f);
Right.HSplitTop(2 * 20.0f, &Button, &Right);
if(g_Config.m_ClAutoCSV)
UI()->DoScrollbarOption(&g_Config.m_ClAutoCSVMax, &g_Config.m_ClAutoCSVMax, &Button, Localize("Max CSVs"), 1, 1000, &CUI::ms_LinearScrollbarScale, CUI::SCROLLBAR_OPTION_INFINITE | CUI::SCROLLBAR_OPTION_MULTILINE);
}
}
}
@ -1099,14 +1059,14 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View)
}
const float ButtonHeight = 20.0f;
const float Spacing = 2.0f;
const float BackgroundHeight = NumOptions * (ButtonHeight + Spacing) + (NumOptions == 1 ? 0 : Spacing);
const float BackgroundHeight = NumOptions * (ButtonHeight + Spacing) + (NumOptions == 1 ? 0.0f : Spacing);
if(View.h < BackgroundHeight)
return BackgroundHeight;
View.HSplitTop(BackgroundHeight, &View, 0);
View.HSplitTop(BackgroundHeight, &View, nullptr);
CUIRect Button;
View.HSplitTop(Spacing, 0, &View);
View.HSplitTop(Spacing, nullptr, &View);
View.HSplitTop(ButtonHeight, &Button, &View);
if(DoButton_CheckBox(&g_Config.m_InpControllerEnable, Localize("Enable controller"), g_Config.m_InpControllerEnable, &Button))
{
@ -1116,50 +1076,69 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View)
{
if(NumJoysticks > 0)
{
// show joystick device selection if more than one available
if(NumJoysticks > 1)
// show joystick device selection if more than one available or just the joystick name if there is only one
{
View.HSplitTop(Spacing, 0, &View);
View.HSplitTop(Spacing, nullptr, &View);
View.HSplitTop(ButtonHeight, &Button, &View);
static CButtonContainer s_ButtonJoystickId;
char aBuf[96];
str_format(aBuf, sizeof(aBuf), Localize("Controller %d: %s"), Input()->GetActiveJoystick()->GetIndex(), Input()->GetActiveJoystick()->GetName());
if(DoButton_Menu(&s_ButtonJoystickId, aBuf, 0, &Button))
Input()->SelectNextJoystick();
GameClient()->m_Tooltips.DoToolTip(&s_ButtonJoystickId, &Button, Localize("Click to cycle through all available controllers."));
if(NumJoysticks > 1)
{
static CButtonContainer s_ButtonJoystickId;
if(DoButton_Menu(&s_ButtonJoystickId, aBuf, 0, &Button))
Input()->SelectNextJoystick();
GameClient()->m_Tooltips.DoToolTip(&s_ButtonJoystickId, &Button, Localize("Click to cycle through all available controllers."));
}
else
{
UI()->DoLabel(&Button, aBuf, 13.0f, TEXTALIGN_ML);
}
}
{
View.HSplitTop(Spacing, 0, &View);
View.HSplitTop(Spacing, nullptr, &View);
View.HSplitTop(ButtonHeight, &Button, &View);
const char *apLabels[] = {Localize("Relative", "Ingame controller mode"), Localize("Absolute", "Ingame controller mode")};
UI()->DoScrollbarOptionLabeled(&g_Config.m_InpControllerAbsolute, &g_Config.m_InpControllerAbsolute, &Button, Localize("Ingame controller mode"), apLabels, std::size(apLabels));
CUIRect Label, ButtonRelative, ButtonAbsolute;
Button.VSplitMid(&Label, &Button, 10.0f);
Button.HMargin(2.0f, &Button);
Button.VSplitMid(&ButtonRelative, &ButtonAbsolute);
UI()->DoLabel(&Label, Localize("Ingame controller mode"), 13.0f, TEXTALIGN_ML);
CButtonContainer s_RelativeButton;
if(DoButton_Menu(&s_RelativeButton, Localize("Relative", "Ingame controller mode"), g_Config.m_InpControllerAbsolute == 0, &ButtonRelative, nullptr, IGraphics::CORNER_L))
{
g_Config.m_InpControllerAbsolute = 0;
}
CButtonContainer s_AbsoluteButton;
if(DoButton_Menu(&s_AbsoluteButton, Localize("Absolute", "Ingame controller mode"), g_Config.m_InpControllerAbsolute == 1, &ButtonAbsolute, nullptr, IGraphics::CORNER_R))
{
g_Config.m_InpControllerAbsolute = 1;
}
}
if(!g_Config.m_InpControllerAbsolute)
{
View.HSplitTop(Spacing, 0, &View);
View.HSplitTop(Spacing, nullptr, &View);
View.HSplitTop(ButtonHeight, &Button, &View);
UI()->DoScrollbarOption(&g_Config.m_InpControllerSens, &g_Config.m_InpControllerSens, &Button, Localize("Ingame controller sens."), 1, 500, &CUI::ms_LogarithmicScrollbarScale, CUI::SCROLLBAR_OPTION_NOCLAMPVALUE);
}
View.HSplitTop(Spacing, 0, &View);
View.HSplitTop(Spacing, nullptr, &View);
View.HSplitTop(ButtonHeight, &Button, &View);
UI()->DoScrollbarOption(&g_Config.m_UiControllerSens, &g_Config.m_UiControllerSens, &Button, Localize("UI controller sens."), 1, 500, &CUI::ms_LogarithmicScrollbarScale, CUI::SCROLLBAR_OPTION_NOCLAMPVALUE);
View.HSplitTop(Spacing, 0, &View);
View.HSplitTop(Spacing, nullptr, &View);
View.HSplitTop(ButtonHeight, &Button, &View);
UI()->DoScrollbarOption(&g_Config.m_InpControllerTolerance, &g_Config.m_InpControllerTolerance, &Button, Localize("Controller jitter tolerance"), 0, 50);
View.HSplitTop(Spacing, 0, &View);
View.HSplitTop(Spacing, nullptr, &View);
View.Draw(ColorRGBA(0.0f, 0.0f, 0.0f, 0.125f), IGraphics::CORNER_ALL, 5.0f);
DoJoystickAxisPicker(View);
}
else
{
View.HSplitTop(View.h - ButtonHeight, 0, &View);
View.HSplitTop(View.h - ButtonHeight, nullptr, &View);
View.HSplitTop(ButtonHeight, &Button, &View);
UI()->DoLabel(&Button, Localize("No controller found. Plug in a controller."), 13.0f, TEXTALIGN_MC);
UI()->DoLabel(&Button, Localize("No controller found. Plug in a controller."), 13.0f, TEXTALIGN_ML);
}
}
@ -1168,68 +1147,70 @@ float CMenus::RenderSettingsControlsJoystick(CUIRect View)
void CMenus::DoJoystickAxisPicker(CUIRect View)
{
float ButtonHeight = 20.0f;
float Spacing = 2.0f;
float DeviceLabelWidth = View.w * 0.30f;
float StatusWidth = View.w * 0.30f;
float BindWidth = View.w * 0.1f;
float StatusMargin = View.w * 0.05f;
const float FontSize = 13.0f;
const float RowHeight = 20.0f;
const float SpacingH = 2.0f;
const float AxisWidth = 0.2f * View.w;
const float StatusWidth = 0.4f * View.w;
const float AimBindWidth = 90.0f;
const float SpacingV = (View.w - AxisWidth - StatusWidth - AimBindWidth) / 2.0f;
CUIRect Row, Button;
View.HSplitTop(Spacing, 0, &View);
View.HSplitTop(ButtonHeight, &Row, &View);
Row.VSplitLeft(StatusWidth, &Button, &Row);
UI()->DoLabel(&Button, Localize("Device"), 13.0f, TEXTALIGN_MC);
Row.VSplitLeft(StatusMargin, 0, &Row);
Row.VSplitLeft(StatusWidth, &Button, &Row);
UI()->DoLabel(&Button, Localize("Status"), 13.0f, TEXTALIGN_MC);
Row.VSplitLeft(2 * StatusMargin, 0, &Row);
Row.VSplitLeft(2 * BindWidth, &Button, &Row);
UI()->DoLabel(&Button, Localize("Aim bind"), 13.0f, TEXTALIGN_MC);
CUIRect Row, Axis, Status, AimBind;
View.HSplitTop(SpacingH, nullptr, &View);
View.HSplitTop(RowHeight, &Row, &View);
Row.VSplitLeft(AxisWidth, &Axis, &Row);
Row.VSplitLeft(SpacingV, nullptr, &Row);
Row.VSplitLeft(StatusWidth, &Status, &Row);
Row.VSplitLeft(SpacingV, nullptr, &Row);
Row.VSplitLeft(AimBindWidth, &AimBind, &Row);
UI()->DoLabel(&Axis, Localize("Axis"), FontSize, TEXTALIGN_MC);
UI()->DoLabel(&Status, Localize("Status"), FontSize, TEXTALIGN_MC);
UI()->DoLabel(&AimBind, Localize("Aim bind"), FontSize, TEXTALIGN_MC);
IInput::IJoystick *pJoystick = Input()->GetActiveJoystick();
static int s_aActive[NUM_JOYSTICK_AXES][2];
for(int i = 0; i < minimum<int>(pJoystick->GetNumAxes(), NUM_JOYSTICK_AXES); i++)
{
bool Active = g_Config.m_InpControllerX == i || g_Config.m_InpControllerY == i;
const bool Active = g_Config.m_InpControllerX == i || g_Config.m_InpControllerY == i;
View.HSplitTop(Spacing, 0, &View);
View.HSplitTop(ButtonHeight, &Row, &View);
View.HSplitTop(SpacingH, nullptr, &View);
View.HSplitTop(RowHeight, &Row, &View);
Row.Draw(ColorRGBA(0.0f, 0.0f, 0.0f, 0.125f), IGraphics::CORNER_ALL, 5.0f);
Row.VSplitLeft(AxisWidth, &Axis, &Row);
Row.VSplitLeft(SpacingV, nullptr, &Row);
Row.VSplitLeft(StatusWidth, &Status, &Row);
Row.VSplitLeft(SpacingV, nullptr, &Row);
Row.VSplitLeft(AimBindWidth, &AimBind, &Row);
// Device label
Row.VSplitLeft(DeviceLabelWidth, &Button, &Row);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), Localize("Controller Axis #%d"), i + 1);
if(!Active)
TextRender()->TextColor(0.7f, 0.7f, 0.7f, 1.0f);
else
// Axis label
char aBuf[16];
str_format(aBuf, sizeof(aBuf), "%d", i + 1);
if(Active)
TextRender()->TextColor(TextRender()->DefaultTextColor());
UI()->DoLabel(&Button, aBuf, 13.0f, TEXTALIGN_MC);
else
TextRender()->TextColor(0.7f, 0.7f, 0.7f, 1.0f);
UI()->DoLabel(&Axis, aBuf, FontSize, TEXTALIGN_MC);
// Device status
Row.VSplitLeft(StatusMargin, 0, &Row);
Row.VSplitLeft(StatusWidth, &Button, &Row);
Button.HMargin((ButtonHeight - 14.0f) / 2.0f, &Button);
DoJoystickBar(&Button, (pJoystick->GetAxisValue(i) + 1.0f) / 2.0f, g_Config.m_InpControllerTolerance / 50.0f, Active);
// Axis status
Status.HMargin(7.0f, &Status);
DoJoystickBar(&Status, (pJoystick->GetAxisValue(i) + 1.0f) / 2.0f, g_Config.m_InpControllerTolerance / 50.0f, Active);
// Bind to X,Y
Row.VSplitLeft(2 * StatusMargin, 0, &Row);
Row.VSplitLeft(BindWidth, &Button, &Row);
if(DoButton_CheckBox(&s_aActive[i][0], "X", g_Config.m_InpControllerX == i, &Button))
// Bind to X/Y
CUIRect AimBindX, AimBindY;
AimBind.VSplitMid(&AimBindX, &AimBindY);
if(DoButton_CheckBox(&s_aActive[i][0], "X", g_Config.m_InpControllerX == i, &AimBindX))
{
if(g_Config.m_InpControllerY == i)
g_Config.m_InpControllerY = g_Config.m_InpControllerX;
g_Config.m_InpControllerX = i;
}
Row.VSplitLeft(BindWidth, &Button, &Row);
if(DoButton_CheckBox(&s_aActive[i][1], "Y", g_Config.m_InpControllerY == i, &Button))
if(DoButton_CheckBox(&s_aActive[i][1], "Y", g_Config.m_InpControllerY == i, &AimBindY))
{
if(g_Config.m_InpControllerX == i)
g_Config.m_InpControllerX = g_Config.m_InpControllerY;
g_Config.m_InpControllerY = i;
}
Row.VSplitLeft(StatusMargin, 0, &Row);
}
TextRender()->TextColor(TextRender()->DefaultTextColor());
}
@ -1237,24 +1218,19 @@ void CMenus::DoJoystickAxisPicker(CUIRect View)
void CMenus::DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, bool Active)
{
CUIRect Handle;
pRect->VSplitLeft(7.0f, &Handle, 0); // Slider size
pRect->VSplitLeft(pRect->h, &Handle, nullptr); // Slider size
Handle.x += (pRect->w - Handle.w) * Current;
CUIRect Rail;
pRect->HMargin(4.0f, &Rail);
Rail.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, Active ? 0.25f : 0.125f), IGraphics::CORNER_ALL, Rail.h / 2.0f);
pRect->Draw(ColorRGBA(1.0f, 1.0f, 1.0f, Active ? 0.25f : 0.125f), IGraphics::CORNER_ALL, pRect->h / 2.0f);
CUIRect ToleranceArea = Rail;
CUIRect ToleranceArea = *pRect;
ToleranceArea.w *= Tolerance;
ToleranceArea.x += (Rail.w - ToleranceArea.w) / 2.0f;
ColorRGBA ToleranceColor = Active ? ColorRGBA(0.8f, 0.35f, 0.35f, 1.0f) : ColorRGBA(0.7f, 0.5f, 0.5f, 1.0f);
ToleranceArea.x += (pRect->w - ToleranceArea.w) / 2.0f;
const ColorRGBA ToleranceColor = Active ? ColorRGBA(0.8f, 0.35f, 0.35f, 1.0f) : ColorRGBA(0.7f, 0.5f, 0.5f, 1.0f);
ToleranceArea.Draw(ToleranceColor, IGraphics::CORNER_ALL, ToleranceArea.h / 2.0f);
CUIRect Slider = Handle;
Slider.HMargin(4.0f, &Slider);
ColorRGBA SliderColor = Active ? ColorRGBA(0.95f, 0.95f, 0.95f, 1.0f) : ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f);
Slider.Draw(SliderColor, IGraphics::CORNER_ALL, Slider.h / 2.0f);
const ColorRGBA SliderColor = Active ? ColorRGBA(0.95f, 0.95f, 0.95f, 1.0f) : ColorRGBA(0.8f, 0.8f, 0.8f, 1.0f);
Handle.Draw(SliderColor, IGraphics::CORNER_ALL, Handle.h / 2.0f);
}
void CMenus::RenderSettingsControls(CUIRect MainView)
@ -1520,7 +1496,7 @@ int CMenus::RenderDropDown(int &CurDropDownState, CUIRect *pRect, int CurSelecti
void CMenus::RenderSettingsGraphics(CUIRect MainView)
{
CUIRect Button, Label;
CUIRect Button;
char aBuf[128];
bool CheckSettings = false;
@ -1711,16 +1687,8 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
g_Config.m_GfxHighdpi ^= 1;
}
MainView.HSplitTop(20.0f, &Label, &MainView);
Label.VSplitLeft(160.0f, &Label, &Button);
if(g_Config.m_GfxRefreshRate)
str_format(aBuf, sizeof(aBuf), "%s: %i Hz", Localize("Refresh Rate"), g_Config.m_GfxRefreshRate);
else
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Refresh Rate"), "");
UI()->DoLabel(&Label, aBuf, 14.0f, TEXTALIGN_ML);
int NewRefreshRate = static_cast<int>(UI()->DoScrollbarH(&g_Config.m_GfxRefreshRate, &Button, (minimum(g_Config.m_GfxRefreshRate, 1000)) / 1000.0f) * 1000.0f + 0.1f);
if(g_Config.m_GfxRefreshRate <= 1000 || NewRefreshRate < 1000)
g_Config.m_GfxRefreshRate = NewRefreshRate;
MainView.HSplitTop(20.0f, &Button, &MainView);
UI()->DoScrollbarOption(&g_Config.m_GfxRefreshRate, &g_Config.m_GfxRefreshRate, &Button, Localize("Refresh Rate"), 10, 1000, &CUI::ms_LinearScrollbarScale, CUI::SCROLLBAR_OPTION_INFINITE | CUI::SCROLLBAR_OPTION_NOCLAMPVALUE, " Hz");
MainView.HSplitTop(2.0f, nullptr, &MainView);
static CButtonContainer s_UiColorResetId;
@ -1937,9 +1905,9 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
void CMenus::RenderSettingsSound(CUIRect MainView)
{
CUIRect Button, Label;
static int s_SndEnable = g_Config.m_SndEnable;
CUIRect Button;
MainView.HSplitTop(20.0f, &Button, &MainView);
if(DoButton_CheckBox(&g_Config.m_SndEnable, Localize("Use sounds"), g_Config.m_SndEnable, &Button))
{
@ -1994,45 +1962,35 @@ void CMenus::RenderSettingsSound(CUIRect MainView)
{
MainView.HSplitTop(5.0f, nullptr, &MainView);
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(190.0f, &Label, &Button);
UI()->DoLabel(&Label, Localize("Sound volume"), 14.0f, TEXTALIGN_ML);
g_Config.m_SndVolume = (int)(UI()->DoScrollbarH(&g_Config.m_SndVolume, &Button, g_Config.m_SndVolume / 100.0f) * 100.0f);
UI()->DoScrollbarOption(&g_Config.m_SndVolume, &g_Config.m_SndVolume, &Button, Localize("Sound volume"), 0, 100, &CUI::ms_LogarithmicScrollbarScale, 0u, "%");
}
// volume slider game sounds
{
MainView.HSplitTop(5.0f, nullptr, &MainView);
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(190.0f, &Label, &Button);
UI()->DoLabel(&Label, Localize("Game sound volume"), 14.0f, TEXTALIGN_ML);
g_Config.m_SndGameSoundVolume = (int)(UI()->DoScrollbarH(&g_Config.m_SndGameSoundVolume, &Button, g_Config.m_SndGameSoundVolume / 100.0f) * 100.0f);
UI()->DoScrollbarOption(&g_Config.m_SndGameSoundVolume, &g_Config.m_SndGameSoundVolume, &Button, Localize("Game sound volume"), 0, 100, &CUI::ms_LogarithmicScrollbarScale, 0u, "%");
}
// volume slider gui sounds
{
MainView.HSplitTop(5.0f, nullptr, &MainView);
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(190.0f, &Label, &Button);
UI()->DoLabel(&Label, Localize("Chat sound volume"), 14.0f, TEXTALIGN_ML);
g_Config.m_SndChatSoundVolume = (int)(UI()->DoScrollbarH(&g_Config.m_SndChatSoundVolume, &Button, g_Config.m_SndChatSoundVolume / 100.0f) * 100.0f);
UI()->DoScrollbarOption(&g_Config.m_SndChatSoundVolume, &g_Config.m_SndChatSoundVolume, &Button, Localize("Chat sound volume"), 0, 100, &CUI::ms_LogarithmicScrollbarScale, 0u, "%");
}
// volume slider map sounds
{
MainView.HSplitTop(5.0f, nullptr, &MainView);
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(190.0f, &Label, &Button);
UI()->DoLabel(&Label, Localize("Map sound volume"), 14.0f, TEXTALIGN_ML);
g_Config.m_SndMapSoundVolume = (int)(UI()->DoScrollbarH(&g_Config.m_SndMapSoundVolume, &Button, g_Config.m_SndMapSoundVolume / 100.0f) * 100.0f);
UI()->DoScrollbarOption(&g_Config.m_SndMapSoundVolume, &g_Config.m_SndMapSoundVolume, &Button, Localize("Map sound volume"), 0, 100, &CUI::ms_LogarithmicScrollbarScale, 0u, "%");
}
// volume slider background music
{
MainView.HSplitTop(5.0f, nullptr, &MainView);
MainView.HSplitTop(20.0f, &Button, &MainView);
Button.VSplitLeft(190.0f, &Label, &Button);
UI()->DoLabel(&Label, Localize("Background music volume"), 14.0f, TEXTALIGN_ML);
g_Config.m_SndBackgroundMusicVolume = (int)(UI()->DoScrollbarH(&g_Config.m_SndBackgroundMusicVolume, &Button, g_Config.m_SndBackgroundMusicVolume / 100.0f) * 100.0f);
UI()->DoScrollbarOption(&g_Config.m_SndBackgroundMusicVolume, &g_Config.m_SndBackgroundMusicVolume, &Button, Localize("Background music volume"), 0, 100, &CUI::ms_LogarithmicScrollbarScale, 0u, "%");
}
}
@ -2650,17 +2608,10 @@ void CMenus::RenderSettingsAppearance(CUIRect MainView)
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClShowFreezeBars, Localize("Show freeze bars"), &g_Config.m_ClShowFreezeBars, &Section, LineSize);
{
Section.HSplitTop(2 * LineSize, &Button, &Section);
if(g_Config.m_ClShowFreezeBars)
{
Section.HSplitTop(LineSize, &Label, &Section);
Section.HSplitTop(LineSize, &Button, &Section);
str_format(aBuf, sizeof(aBuf), "%s: %i%%", Localize("Opacity of freeze bars inside freeze"), g_Config.m_ClFreezeBarsAlphaInsideFreeze);
UI()->DoLabel(&Label, aBuf, 13.0f, TEXTALIGN_ML);
g_Config.m_ClFreezeBarsAlphaInsideFreeze = (int)(UI()->DoScrollbarH(&g_Config.m_ClFreezeBarsAlphaInsideFreeze, &Button, g_Config.m_ClFreezeBarsAlphaInsideFreeze / 100.0f) * 100.0f);
}
else
{
Section.HSplitTop(2 * LineSize, 0x0, &Section); // Create empty space for hidden option
UI()->DoScrollbarOption(&g_Config.m_ClFreezeBarsAlphaInsideFreeze, &g_Config.m_ClFreezeBarsAlphaInsideFreeze, &Button, Localize("Opacity of freeze bars inside freeze"), 0, 100, &CUI::ms_LinearScrollbarScale, CUI::SCROLLBAR_OPTION_MULTILINE, "%");
}
}
}
@ -2894,27 +2845,14 @@ void CMenus::RenderSettingsAppearance(CUIRect MainView)
// General chat settings
LeftView.HSplitTop(SectionTotalMargin + 9 * LineSize, &Section, &LeftView);
Section.Margin(SectionMargin, &Section);
{
Section.HSplitTop(LineSize, &Label, &Section);
Section.HSplitTop(LineSize, &Button, &Section);
str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Name plates size"), g_Config.m_ClNameplatesSize);
UI()->DoLabel(&Label, aBuf, 13.0f, TEXTALIGN_ML);
g_Config.m_ClNameplatesSize = (int)(UI()->DoScrollbarH(&g_Config.m_ClNameplatesSize, &Button, g_Config.m_ClNameplatesSize / 100.0f) * 100.0f + 0.1f);
}
Section.HSplitTop(2 * LineSize, &Button, &Section);
UI()->DoScrollbarOption(&g_Config.m_ClNameplatesSize, &g_Config.m_ClNameplatesSize, &Button, Localize("Name plates size"), 0, 100, &CUI::ms_LinearScrollbarScale, CUI::SCROLLBAR_OPTION_MULTILINE);
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClNameplatesClan, Localize("Show clan above name plates"), &g_Config.m_ClNameplatesClan, &Section, LineSize);
Section.HSplitTop(2 * LineSize, &Button, &Section);
if(g_Config.m_ClNameplatesClan)
{
Section.HSplitTop(LineSize, &Label, &Section);
Section.HSplitTop(LineSize, &Button, &Section);
str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Clan plates size"), g_Config.m_ClNameplatesClanSize);
UI()->DoLabel(&Label, aBuf, 13.0f, TEXTALIGN_ML);
g_Config.m_ClNameplatesClanSize = (int)(UI()->DoScrollbarH(&g_Config.m_ClNameplatesClanSize, &Button, g_Config.m_ClNameplatesClanSize / 100.0f) * 100.0f + 0.1f);
}
else
{
Section.HSplitTop(2 * LineSize, 0x0, &Section); // Create empty space for hidden option
UI()->DoScrollbarOption(&g_Config.m_ClNameplatesClanSize, &g_Config.m_ClNameplatesClanSize, &Button, Localize("Clan plates size"), 0, 100, &CUI::ms_LinearScrollbarScale, CUI::SCROLLBAR_OPTION_MULTILINE);
}
DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClNameplatesTeamcolors, Localize("Use team colors for name plates"), &g_Config.m_ClNameplatesTeamcolors, &Section, LineSize);
@ -2951,21 +2889,11 @@ void CMenus::RenderSettingsAppearance(CUIRect MainView)
g_Config.m_ClShowHookCollOther = g_Config.m_ClShowHookCollOther >= 1 ? 0 : 1;
}
{
Section.HSplitTop(LineSize, &Label, &Section);
Section.HSplitTop(LineSize, &Button, &Section);
str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Hook collision line width"), g_Config.m_ClHookCollSize);
UI()->DoLabel(&Label, aBuf, 13.0f, TEXTALIGN_ML);
g_Config.m_ClHookCollSize = (int)(UI()->DoScrollbarH(&g_Config.m_ClHookCollSize, &Button, g_Config.m_ClHookCollSize / 20.0f) * 20.0f);
}
Section.HSplitTop(2 * LineSize, &Button, &Section);
UI()->DoScrollbarOption(&g_Config.m_ClHookCollSize, &g_Config.m_ClHookCollSize, &Button, Localize("Hook collision line width"), 0, 100, &CUI::ms_LinearScrollbarScale, CUI::SCROLLBAR_OPTION_MULTILINE);
{
Section.HSplitTop(LineSize, &Label, &Section);
Section.HSplitTop(LineSize, &Button, &Section);
str_format(aBuf, sizeof(aBuf), "%s: %i%%", Localize("Hook collision line opacity"), g_Config.m_ClHookCollAlpha);
UI()->DoLabel(&Label, aBuf, 13.0f, TEXTALIGN_ML);
g_Config.m_ClHookCollAlpha = (int)(UI()->DoScrollbarH(&g_Config.m_ClHookCollAlpha, &Button, g_Config.m_ClHookCollAlpha / 100.0f) * 100.0f);
}
Section.HSplitTop(2 * LineSize, &Button, &Section);
UI()->DoScrollbarOption(&g_Config.m_ClHookCollAlpha, &g_Config.m_ClHookCollAlpha, &Button, Localize("Hook collision line opacity"), 0, 100, &CUI::ms_LinearScrollbarScale, CUI::SCROLLBAR_OPTION_MULTILINE, "%");
static CButtonContainer s_HookCollNoCollResetID, s_HookCollHookableCollResetID, s_HookCollTeeCollResetID;
static int s_HookCollToolTip;
@ -3118,14 +3046,8 @@ void CMenus::RenderSettingsDDNet(CUIRect MainView)
}
Left.HSplitTop(20.0f, &Button, &Left);
Button.VSplitLeft(140.0f, &Label, &Button);
char aBuf[256];
str_format(aBuf, sizeof(aBuf), Localize("Default length: %d"), g_Config.m_ClReplayLength);
UI()->DoLabel(&Label, aBuf, 14.0f, TEXTALIGN_ML);
int NewValue = (int)(UI()->DoScrollbarH(&g_Config.m_ClReplayLength, &Button, (minimum(g_Config.m_ClReplayLength, 600) - 10) / 590.0f) * 590.0f) + 10;
if(g_Config.m_ClReplayLength < 600 || NewValue < 600)
g_Config.m_ClReplayLength = minimum(NewValue, 600);
if(g_Config.m_ClReplays)
UI()->DoScrollbarOption(&g_Config.m_ClReplayLength, &g_Config.m_ClReplayLength, &Button, Localize("Default length"), 10, 600, &CUI::ms_LinearScrollbarScale, CUI::SCROLLBAR_OPTION_NOCLAMPVALUE);
}
Right.HSplitTop(20.0f, &Button, &Right);
@ -3161,37 +3083,28 @@ void CMenus::RenderSettingsDDNet(CUIRect MainView)
{
Left.HSplitTop(20.0f, &Button, &Left);
Button.VSplitLeft(120.0f, &Label, &Button);
UI()->DoLabel(&Label, Localize("Overlay entities"), 14.0f, TEXTALIGN_ML);
g_Config.m_ClOverlayEntities = (int)(UI()->DoScrollbarH(&g_Config.m_ClOverlayEntities, &Button, g_Config.m_ClOverlayEntities / 100.0f) * 100.0f);
UI()->DoScrollbarOption(&g_Config.m_ClOverlayEntities, &g_Config.m_ClOverlayEntities, &Button, Localize("Overlay entities"), 0, 100);
}
{
Left.HSplitTop(20.0f, &Button, &Left);
Button.VSplitMid(&LeftLeft, &Button);
Button.VSplitLeft(50.0f, &Label, &Button);
UI()->DoLabel(&Label, Localize("Size"), 14.0f, TEXTALIGN_ML);
g_Config.m_ClTextEntitiesSize = (int)(UI()->DoScrollbarH(&g_Config.m_ClTextEntitiesSize, &Button, g_Config.m_ClTextEntitiesSize / 100.0f) * 100.0f);
if(DoButton_CheckBox(&g_Config.m_ClTextEntities, Localize("Show text entities"), g_Config.m_ClTextEntities, &LeftLeft))
{
g_Config.m_ClTextEntities ^= 1;
}
if(g_Config.m_ClTextEntities)
UI()->DoScrollbarOption(&g_Config.m_ClTextEntitiesSize, &g_Config.m_ClTextEntitiesSize, &Button, Localize("Size"), 0, 100);
}
{
Left.HSplitTop(20.0f, &Button, &Left);
Button.VSplitMid(&LeftLeft, &Button);
Button.VSplitLeft(50.0f, &Label, &Button);
UI()->DoLabel(&Label, Localize("Opacity"), 14.0f, TEXTALIGN_ML);
g_Config.m_ClShowOthersAlpha = (int)(UI()->DoScrollbarH(&g_Config.m_ClShowOthersAlpha, &Button, g_Config.m_ClShowOthersAlpha / 100.0f) * 100.0f);
if(DoButton_CheckBox(&g_Config.m_ClShowOthers, Localize("Show others"), g_Config.m_ClShowOthers == SHOW_OTHERS_ON, &LeftLeft))
{
g_Config.m_ClShowOthers = g_Config.m_ClShowOthers != SHOW_OTHERS_ON ? SHOW_OTHERS_ON : SHOW_OTHERS_OFF;
}
UI()->DoScrollbarOption(&g_Config.m_ClShowOthersAlpha, &g_Config.m_ClShowOthersAlpha, &Button, Localize("Opacity"), 0, 100);
GameClient()->m_Tooltips.DoToolTip(&g_Config.m_ClShowOthersAlpha, &Button, Localize("Adjust the opacity of entities belonging to other teams, such as tees and nameplates"));
}
@ -3210,12 +3123,8 @@ void CMenus::RenderSettingsDDNet(CUIRect MainView)
}
GameClient()->m_Tooltips.DoToolTip(&g_Config.m_ClShowQuads, &Button, Localize("Quads are used for background decoration"));
Right.HSplitTop(20.0f, &Label, &Right);
Label.VSplitLeft(130.0f, &Label, &Button);
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "%s: %i", Localize("Default zoom"), g_Config.m_ClDefaultZoom);
UI()->DoLabel(&Label, aBuf, 14.0f, TEXTALIGN_ML);
g_Config.m_ClDefaultZoom = static_cast<int>(UI()->DoScrollbarH(&g_Config.m_ClDefaultZoom, &Button, g_Config.m_ClDefaultZoom / 20.0f) * 20.0f + 0.1f);
Right.HSplitTop(20.0f, &Button, &Right);
UI()->DoScrollbarOption(&g_Config.m_ClDefaultZoom, &g_Config.m_ClDefaultZoom, &Button, Localize("Default zoom"), 0, 20);
Right.HSplitTop(20.0f, &Button, &Right);
if(DoButton_CheckBox(&g_Config.m_ClAntiPing, Localize("AntiPing"), g_Config.m_ClAntiPing, &Button))
@ -3335,6 +3244,7 @@ void CMenus::RenderSettingsDDNet(CUIRect MainView)
int State = Updater()->GetCurrentState();
// Update Button
char aBuf[256];
if(NeedUpdate && State <= IUpdater::CLEAN)
{
str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is available:"), Client()->LatestVersion());

View file

@ -1224,26 +1224,23 @@ float CUI::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current, co
return ReturnValue;
}
void CUI::DoScrollbarOption(const void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, const IScrollbarScale *pScale, unsigned Flags)
void CUI::DoScrollbarOption(const void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, const IScrollbarScale *pScale, unsigned Flags, const char *pSuffix)
{
const bool Infinite = Flags & CUI::SCROLLBAR_OPTION_INFINITE;
const bool NoClampValue = Flags & CUI::SCROLLBAR_OPTION_NOCLAMPVALUE;
dbg_assert(!(Infinite && NoClampValue), "cannot combine SCROLLBAR_OPTION_INFINITE and SCROLLBAR_OPTION_NOCLAMPVALUE");
const bool MultiLine = Flags & CUI::SCROLLBAR_OPTION_MULTILINE;
int Value = *pOption;
if(Infinite)
{
Min += 1;
Max += 1;
if(Value == 0)
Value = Max;
}
char aBufMax[256];
str_format(aBufMax, sizeof(aBufMax), "%s: %i", pStr, Max);
char aBuf[256];
if(!Infinite || Value != Max)
str_format(aBuf, sizeof(aBuf), "%s: %i", pStr, Value);
str_format(aBuf, sizeof(aBuf), "%s: %i%s", pStr, Value, pSuffix);
else
str_format(aBuf, sizeof(aBuf), "%s: ∞", pStr);
@ -1253,51 +1250,29 @@ void CUI::DoScrollbarOption(const void *pID, int *pOption, const CUIRect *pRect,
Value = clamp(Value, Min, Max);
}
float FontSize = pRect->h * CUI::ms_FontmodHeight * 0.8f;
float VSplitVal = 10.0f + maximum(TextRender()->TextWidth(FontSize, aBuf, -1, std::numeric_limits<float>::max()), TextRender()->TextWidth(FontSize, aBufMax, -1, std::numeric_limits<float>::max()));
CUIRect Label, ScrollBar;
pRect->VSplitLeft(VSplitVal, &Label, &ScrollBar);
if(MultiLine)
pRect->HSplitMid(&Label, &ScrollBar);
else
pRect->VSplitMid(&Label, &ScrollBar, minimum(10.0f, pRect->w * 0.05f));
const float FontSize = Label.h * CUI::ms_FontmodHeight * 0.8f;
DoLabel(&Label, aBuf, FontSize, TEXTALIGN_ML);
Value = pScale->ToAbsolute(DoScrollbarH(pID, &ScrollBar, pScale->ToRelative(Value, Min, Max)), Min, Max);
if(Infinite)
if(NoClampValue && ((Value == Min && *pOption < Min) || (Value == Max && *pOption > Max)))
{
Value = *pOption; // use previous out of range value instead if the scrollbar is at the edge
}
else if(Infinite)
{
if(Value == Max)
Value = 0;
}
else if(NoClampValue)
{
if((Value == Min && *pOption < Min) || (Value == Max && *pOption > Max))
Value = *pOption; // use previous out of range value instead if the scrollbar is at the edge
}
*pOption = Value;
}
void CUI::DoScrollbarOptionLabeled(const void *pID, int *pOption, const CUIRect *pRect, const char *pStr, const char **ppLabels, int NumLabels, const IScrollbarScale *pScale)
{
const int Max = NumLabels - 1;
int Value = clamp(*pOption, 0, Max);
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "%s: %s", pStr, ppLabels[Value]);
float FontSize = pRect->h * CUI::ms_FontmodHeight * 0.8f;
CUIRect Label, ScrollBar;
pRect->VSplitRight(60.0f, &Label, &ScrollBar);
Label.VSplitRight(10.0f, &Label, 0);
DoLabel(&Label, aBuf, FontSize, TEXTALIGN_MC);
Value = pScale->ToAbsolute(DoScrollbarH(pID, &ScrollBar, pScale->ToRelative(Value, 0, Max)), 0, Max);
if(HotItem() != pID && !CheckActiveItem(pID) && MouseHovered(pRect) && MouseButtonClicked(0))
Value = (Value + 1) % NumLabels;
*pOption = clamp(Value, 0, Max);
}
void CUI::DoPopupMenu(const SPopupMenuId *pID, int X, int Y, int Width, int Height, void *pContext, FPopupMenuFunction pfnFunc, int Corners)
{
constexpr float Margin = SPopupMenu::POPUP_BORDER + SPopupMenu::POPUP_MARGIN;

View file

@ -501,13 +501,13 @@ public:
// scrollbars
enum
{
SCROLLBAR_OPTION_INFINITE = 1,
SCROLLBAR_OPTION_NOCLAMPVALUE = 2,
SCROLLBAR_OPTION_INFINITE = 1 << 0,
SCROLLBAR_OPTION_NOCLAMPVALUE = 1 << 1,
SCROLLBAR_OPTION_MULTILINE = 1 << 2,
};
float DoScrollbarV(const void *pID, const CUIRect *pRect, float Current);
float DoScrollbarH(const void *pID, const CUIRect *pRect, float Current, const ColorRGBA *pColorInner = nullptr);
void DoScrollbarOption(const void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, const IScrollbarScale *pScale = &ms_LinearScrollbarScale, unsigned Flags = 0u);
void DoScrollbarOptionLabeled(const void *pID, int *pOption, const CUIRect *pRect, const char *pStr, const char **ppLabels, int NumLabels, const IScrollbarScale *pScale = &ms_LinearScrollbarScale);
void DoScrollbarOption(const void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, const IScrollbarScale *pScale = &ms_LinearScrollbarScale, unsigned Flags = 0u, const char *pSuffix = "");
// popup menu
void DoPopupMenu(const SPopupMenuId *pID, int X, int Y, int Width, int Height, void *pContext, FPopupMenuFunction pfnFunc, int Corners = IGraphics::CORNER_ALL);