mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Use callback function to set labels of slider widget marks.
Slider widgets can only use a predefined list of values and strings to draw labels. This makes it difficult to vary the display by context. Instead of providing a predefined list as a std::map, use a callback function instead. This function can decide what text to display, and can call SetDParam to dynamically set up strings.pull/12619/head
parent
8b6661d486
commit
9d2efd4c96
|
@ -956,11 +956,7 @@ STR_GAME_OPTIONS_VOLUME :Volume
|
||||||
STR_GAME_OPTIONS_SFX_VOLUME :Sound effects
|
STR_GAME_OPTIONS_SFX_VOLUME :Sound effects
|
||||||
STR_GAME_OPTIONS_MUSIC_VOLUME :Music
|
STR_GAME_OPTIONS_MUSIC_VOLUME :Music
|
||||||
|
|
||||||
STR_GAME_OPTIONS_VOLUME_0 :0%
|
STR_GAME_OPTIONS_VOLUME_MARK :{NUM}%
|
||||||
STR_GAME_OPTIONS_VOLUME_25 :25%
|
|
||||||
STR_GAME_OPTIONS_VOLUME_50 :50%
|
|
||||||
STR_GAME_OPTIONS_VOLUME_75 :75%
|
|
||||||
STR_GAME_OPTIONS_VOLUME_100 :100%
|
|
||||||
|
|
||||||
STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME :{BLACK}Currency units
|
STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME :{BLACK}Currency units
|
||||||
STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP :{BLACK}Currency units selection
|
STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP :{BLACK}Currency units selection
|
||||||
|
@ -1058,11 +1054,7 @@ STR_GAME_OPTIONS_GUI_FONT_SPRITE_TOOLTIP :{BLACK}Check th
|
||||||
STR_GAME_OPTIONS_GUI_FONT_AA :{BLACK}Anti-alias fonts
|
STR_GAME_OPTIONS_GUI_FONT_AA :{BLACK}Anti-alias fonts
|
||||||
STR_GAME_OPTIONS_GUI_FONT_AA_TOOLTIP :{BLACK}Check this box to anti-alias resizable fonts
|
STR_GAME_OPTIONS_GUI_FONT_AA_TOOLTIP :{BLACK}Check this box to anti-alias resizable fonts
|
||||||
|
|
||||||
STR_GAME_OPTIONS_GUI_SCALE_1X :1x
|
STR_GAME_OPTIONS_GUI_SCALE_MARK :{DECIMAL}x
|
||||||
STR_GAME_OPTIONS_GUI_SCALE_2X :2x
|
|
||||||
STR_GAME_OPTIONS_GUI_SCALE_3X :3x
|
|
||||||
STR_GAME_OPTIONS_GUI_SCALE_4X :4x
|
|
||||||
STR_GAME_OPTIONS_GUI_SCALE_5X :5x
|
|
||||||
|
|
||||||
STR_GAME_OPTIONS_PARTICIPATE_SURVEY_FRAME :{BLACK}Automated survey
|
STR_GAME_OPTIONS_PARTICIPATE_SURVEY_FRAME :{BLACK}Automated survey
|
||||||
STR_GAME_OPTIONS_PARTICIPATE_SURVEY :{BLACK}Participate in automated survey
|
STR_GAME_OPTIONS_PARTICIPATE_SURVEY :{BLACK}Participate in automated survey
|
||||||
|
|
|
@ -775,11 +775,11 @@ struct MusicWindow : public Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
case WID_M_MUSIC_VOL:
|
case WID_M_MUSIC_VOL:
|
||||||
DrawSliderWidget(r, 0, INT8_MAX, _settings_client.music.music_vol, {});
|
DrawSliderWidget(r, 0, INT8_MAX, 0, _settings_client.music.music_vol, nullptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_M_EFFECT_VOL:
|
case WID_M_EFFECT_VOL:
|
||||||
DrawSliderWidget(r, 0, INT8_MAX, _settings_client.music.effect_vol, {});
|
DrawSliderWidget(r, 0, INT8_MAX, 0, _settings_client.music.effect_vol, nullptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,37 +152,27 @@ static void AddCustomRefreshRates()
|
||||||
std::copy(monitorRates.begin(), monitorRates.end(), std::inserter(_refresh_rates, _refresh_rates.end()));
|
std::copy(monitorRates.begin(), monitorRates.end(), std::inserter(_refresh_rates, _refresh_rates.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::map<int, StringID> _scale_labels = {
|
static const int SCALE_NMARKS = (MAX_INTERFACE_SCALE - MIN_INTERFACE_SCALE) / 25 + 1; // Show marks at 25% increments
|
||||||
{ 100, STR_GAME_OPTIONS_GUI_SCALE_1X },
|
static const int VOLUME_NMARKS = 9; // Show 5 values and 4 empty marks.
|
||||||
{ 125, STR_NULL },
|
|
||||||
{ 150, STR_NULL },
|
|
||||||
{ 175, STR_NULL },
|
|
||||||
{ 200, STR_GAME_OPTIONS_GUI_SCALE_2X },
|
|
||||||
{ 225, STR_NULL },
|
|
||||||
{ 250, STR_NULL },
|
|
||||||
{ 275, STR_NULL },
|
|
||||||
{ 300, STR_GAME_OPTIONS_GUI_SCALE_3X },
|
|
||||||
{ 325, STR_NULL },
|
|
||||||
{ 350, STR_NULL },
|
|
||||||
{ 375, STR_NULL },
|
|
||||||
{ 400, STR_GAME_OPTIONS_GUI_SCALE_4X },
|
|
||||||
{ 425, STR_NULL },
|
|
||||||
{ 450, STR_NULL },
|
|
||||||
{ 475, STR_NULL },
|
|
||||||
{ 500, STR_GAME_OPTIONS_GUI_SCALE_5X },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const std::map<int, StringID> _volume_labels = {
|
static StringID ScaleMarkFunc(int, int, int value)
|
||||||
{ 0, STR_GAME_OPTIONS_VOLUME_0 },
|
{
|
||||||
{ 15, STR_NULL },
|
/* Label only every 100% mark. */
|
||||||
{ 31, STR_GAME_OPTIONS_VOLUME_25 },
|
if (value % 100 != 0) return STR_NULL;
|
||||||
{ 47, STR_NULL },
|
|
||||||
{ 63, STR_GAME_OPTIONS_VOLUME_50 },
|
SetDParam(0, value / 100);
|
||||||
{ 79, STR_NULL },
|
SetDParam(1, 0);
|
||||||
{ 95, STR_GAME_OPTIONS_VOLUME_75 },
|
return STR_GAME_OPTIONS_GUI_SCALE_MARK;
|
||||||
{ 111, STR_NULL },
|
}
|
||||||
{ 127, STR_GAME_OPTIONS_VOLUME_100 },
|
|
||||||
};
|
static StringID VolumeMarkFunc(int, int mark, int value)
|
||||||
|
{
|
||||||
|
/* Label only every other mark. */
|
||||||
|
if (mark % 2 != 0) return STR_NULL;
|
||||||
|
|
||||||
|
SetDParam(0, value / 31 * 25); // 0-127 does not map nicely to 0-100. Dividing first gives us nice round numbers.
|
||||||
|
return STR_GAME_OPTIONS_VOLUME_MARK;
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr NWidgetPart _nested_social_plugins_widgets[] = {
|
static constexpr NWidgetPart _nested_social_plugins_widgets[] = {
|
||||||
NWidget(NWID_HORIZONTAL),
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
@ -572,7 +562,7 @@ struct GameOptionsWindow : Window {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_GO_GUI_SCALE:
|
case WID_GO_GUI_SCALE:
|
||||||
DrawSliderWidget(r, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, this->gui_scale, _scale_labels);
|
DrawSliderWidget(r, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE, SCALE_NMARKS, this->gui_scale, ScaleMarkFunc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_GO_VIDEO_DRIVER_INFO:
|
case WID_GO_VIDEO_DRIVER_INFO:
|
||||||
|
@ -581,11 +571,11 @@ struct GameOptionsWindow : Window {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_GO_BASE_SFX_VOLUME:
|
case WID_GO_BASE_SFX_VOLUME:
|
||||||
DrawSliderWidget(r, 0, INT8_MAX, _settings_client.music.effect_vol, _volume_labels);
|
DrawSliderWidget(r, 0, INT8_MAX, VOLUME_NMARKS, _settings_client.music.effect_vol, VolumeMarkFunc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_GO_BASE_MUSIC_VOLUME:
|
case WID_GO_BASE_MUSIC_VOLUME:
|
||||||
DrawSliderWidget(r, 0, INT8_MAX, _settings_client.music.music_vol, _volume_labels);
|
DrawSliderWidget(r, 0, INT8_MAX, VOLUME_NMARKS, _settings_client.music.music_vol, VolumeMarkFunc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,14 @@ static const int SLIDER_WIDTH = 3;
|
||||||
* @param r Rectangle to draw the widget in
|
* @param r Rectangle to draw the widget in
|
||||||
* @param min_value Minimum value of slider
|
* @param min_value Minimum value of slider
|
||||||
* @param max_value Maximum value of slider
|
* @param max_value Maximum value of slider
|
||||||
|
* @param nmarks Number of marks to display (when mark_func is provided.)
|
||||||
* @param value Value to put the slider at
|
* @param value Value to put the slider at
|
||||||
* @param labels List of positions and labels to draw along the slider.
|
* @param mark_func Callback function to get the StringID to draw on a mark.
|
||||||
*/
|
*/
|
||||||
void DrawSliderWidget(Rect r, int min_value, int max_value, int value, const std::map<int, StringID> &labels)
|
void DrawSliderWidget(Rect r, int min_value, int max_value, int nmarks, int value, SliderMarkFunc *mark_func)
|
||||||
{
|
{
|
||||||
/* Allow space for labels. We assume they are in the small font. */
|
/* Allow space for labels. We assume they are in the small font. */
|
||||||
if (!labels.empty()) r.bottom -= GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.hsep_normal;
|
if (mark_func != nullptr) r.bottom -= GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.hsep_normal;
|
||||||
|
|
||||||
max_value -= min_value;
|
max_value -= min_value;
|
||||||
|
|
||||||
|
@ -51,15 +52,22 @@ void DrawSliderWidget(Rect r, int min_value, int max_value, int value, const std
|
||||||
GfxDrawLine(wedge[0].x, wedge[0].y, wedge[1].x, wedge[1].y, shadow, t);
|
GfxDrawLine(wedge[0].x, wedge[0].y, wedge[1].x, wedge[1].y, shadow, t);
|
||||||
|
|
||||||
int x;
|
int x;
|
||||||
for (auto label : labels) {
|
if (mark_func != nullptr) {
|
||||||
x = label.first - min_value;
|
for (int mark = 0; mark < nmarks; ++mark) {
|
||||||
if (_current_text_dir == TD_RTL) x = max_value - x;
|
const int mark_value = (max_value * mark) / (nmarks - 1);
|
||||||
x = r.left + (x * (r.right - r.left - sw) / max_value) + sw / 2;
|
|
||||||
GfxDrawLine(x, r.bottom - ha + 1, x, r.bottom + (label.second == STR_NULL ? 0 : WidgetDimensions::scaled.hsep_normal), shadow, t);
|
const StringID str = mark_func(nmarks, mark, mark_value + min_value);
|
||||||
if (label.second != STR_NULL) {
|
if (str == INVALID_STRING_ID) continue;
|
||||||
Dimension d = GetStringBoundingBox(label.second, FS_SMALL);
|
|
||||||
|
x = mark_value;
|
||||||
|
if (_current_text_dir == TD_RTL) x = max_value - mark_value;
|
||||||
|
x = r.left + (x * (r.right - r.left - sw) / max_value) + sw / 2;
|
||||||
|
GfxDrawLine(x, r.bottom - ha + 1, x, r.bottom + (str == STR_NULL ? 0 : WidgetDimensions::scaled.hsep_normal), shadow, t);
|
||||||
|
if (str == STR_NULL) continue;
|
||||||
|
|
||||||
|
Dimension d = GetStringBoundingBox(str, FS_SMALL);
|
||||||
x = Clamp(x - d.width / 2, r.left, r.right - d.width);
|
x = Clamp(x - d.width / 2, r.left, r.right - d.width);
|
||||||
DrawString(x, x + d.width, r.bottom + 1 + WidgetDimensions::scaled.hsep_normal, label.second, TC_BLACK, SA_CENTER, false, FS_SMALL);
|
DrawString(x, x + d.width, r.bottom + 1 + WidgetDimensions::scaled.hsep_normal, str, TC_BLACK, SA_CENTER, false, FS_SMALL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@
|
||||||
#include "core/geometry_type.hpp"
|
#include "core/geometry_type.hpp"
|
||||||
#include "strings_type.h"
|
#include "strings_type.h"
|
||||||
|
|
||||||
void DrawSliderWidget(Rect r, int min_value, int max_value, int value, const std::map<int, StringID> &labels);
|
using SliderMarkFunc = StringID(int nmarks, int mark, int value);
|
||||||
|
void DrawSliderWidget(Rect r, int min_value, int max_value, int nmarks, int value, SliderMarkFunc *mark_func);
|
||||||
bool ClickSliderWidget(Rect r, Point pt, int min_value, int max_value, int &value);
|
bool ClickSliderWidget(Rect r, Point pt, int min_value, int max_value, int &value);
|
||||||
|
|
||||||
inline bool ClickSliderWidget(Rect r, Point pt, int min_value, int max_value, uint8_t &value)
|
inline bool ClickSliderWidget(Rect r, Point pt, int min_value, int max_value, uint8_t &value)
|
||||||
|
|
Loading…
Reference in New Issue