OpenTTD Source 20250714-master-g67e56391c7
newgrf_badge_gui.cpp
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD 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.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11
12#include "core/flatset_type.hpp"
13#include "dropdown_type.h"
14#include "dropdown_func.h"
15#include "newgrf.h"
16#include "newgrf_badge.h"
17#include "newgrf_badge_config.h"
18#include "newgrf_badge_gui.h"
19#include "newgrf_badge_type.h"
20#include "settings_gui.h"
21#include "strings_func.h"
23#include "window_gui.h"
24#include "zoom_func.h"
25
26#include "table/strings.h"
27
29
30#include "safeguards.h"
31
32static constexpr uint MAX_BADGE_HEIGHT = 12;
33static constexpr uint MAX_BADGE_WIDTH = MAX_BADGE_HEIGHT * 2;
34
41static Dimension GetBadgeMaximalDimension(BadgeClassID class_index, GrfSpecFeature feature)
42{
43 Dimension d = {0, MAX_BADGE_HEIGHT};
44
45 for (const auto &badge : GetBadges()) {
46 if (badge.class_index != class_index) continue;
47
48 PalSpriteID ps = GetBadgeSprite(badge, feature, std::nullopt, PAL_NONE);
49 if (ps.sprite == 0) continue;
50
51 d.width = std::max(d.width, GetSpriteSize(ps.sprite, nullptr, ZoomLevel::Normal).width);
52 if (d.width > MAX_BADGE_WIDTH) break;
53 }
54
55 d.width = std::min(d.width, MAX_BADGE_WIDTH);
56 return d;
57}
58
59static bool operator<(const GUIBadgeClasses::Element &a, const GUIBadgeClasses::Element &b)
60{
61 if (a.column_group != b.column_group) return a.column_group < b.column_group;
62 if (a.sort_order != b.sort_order) return a.sort_order < b.sort_order;
63 return a.label < b.label;
64}
65
70GUIBadgeClasses::GUIBadgeClasses(GrfSpecFeature feature) : UsedBadgeClasses(feature)
71{
72 /* Get list of classes used by feature. */
73 uint max_column = 0;
74 for (BadgeClassID class_index : this->Classes()) {
75 const Badge *class_badge = GetClassBadge(class_index);
76 if (class_badge->name == STR_NULL) continue;
77
78 Dimension size = GetBadgeMaximalDimension(class_index, feature);
79 if (size.width == 0) continue;
80
81 const auto [config, sort_order] = GetBadgeClassConfigItem(feature, class_badge->label);
82
83 this->gui_classes.emplace_back(class_index, config.column, config.show_icon, sort_order, size, class_badge->label);
84 if (size.width != 0 && config.show_icon) max_column = std::max<uint>(max_column, config.column);
85 }
86
87 std::sort(std::begin(this->gui_classes), std::end(this->gui_classes));
88
89 /* Determine total width of visible badge columns. */
90 this->column_widths.resize(max_column + 1);
91 for (const auto &el : this->gui_classes) {
92 if (!el.visible || el.size.width == 0) continue;
93 this->column_widths[el.column_group] += ScaleGUITrad(el.size.width) + WidgetDimensions::scaled.hsep_normal;
94 }
95
96 /* Replace trailing `hsep_normal` spacer with wider `hsep_wide` spacer. */
97 for (uint &badge_width : this->column_widths) {
98 if (badge_width == 0) continue;
100 }
101}
102
108{
109 return std::accumulate(std::begin(this->column_widths), std::end(this->column_widths), 0U);
110}
111
119int DrawBadgeNameList(Rect r, std::span<const BadgeID> badges, GrfSpecFeature)
120{
121 if (badges.empty()) return r.top;
122
123 FlatSet<BadgeClassID> class_indexes;
124 for (const BadgeID &index : badges) class_indexes.insert(GetBadge(index)->class_index);
125
126 std::string_view list_separator = GetListSeparator();
127 for (const BadgeClassID &class_index : class_indexes) {
128 const Badge *class_badge = GetClassBadge(class_index);
129 if (class_badge == nullptr || class_badge->name == STR_NULL) continue;
130
131 std::string s;
132 for (const BadgeID &index : badges) {
133 const Badge *badge = GetBadge(index);
134 if (badge == nullptr || badge->name == STR_NULL) continue;
135 if (badge->class_index != class_index) continue;
136
137 if (!s.empty()) {
138 if (badge->flags.Test(BadgeFlag::NameListFirstOnly)) continue;
139 s += list_separator;
140 }
141 AppendStringInPlace(s, badge->name);
142 if (badge->flags.Test(BadgeFlag::NameListStop)) break;
143 }
144
145 if (s.empty()) continue;
146
147 r.top = DrawStringMultiLine(r, GetString(STR_BADGE_NAME_LIST, class_badge->name, std::move(s)), TC_BLACK);
148 }
149
150 return r.top;
151}
152
163void DrawBadgeColumn(Rect r, int column_group, const GUIBadgeClasses &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, PaletteID remap)
164{
165 bool rtl = _current_text_dir == TD_RTL;
166 for (const auto &gc : gui_classes.GetClasses()) {
167 if (gc.column_group != column_group) continue;
168 if (!gc.visible) continue;
169
170 int width = ScaleGUITrad(gc.size.width);
171 for (const BadgeID &index : badges) {
172 const Badge &badge = *GetBadge(index);
173 if (badge.class_index != gc.class_index) continue;
174
175 PalSpriteID ps = GetBadgeSprite(badge, feature, introduction_date, remap);
176 if (ps.sprite == 0) continue;
177
178 DrawSpriteIgnorePadding(ps.sprite, ps.pal, r.WithWidth(width, rtl), SA_CENTER);
179 break;
180 }
181
182 r = r.Indent(width + WidgetDimensions::scaled.hsep_normal, rtl);
183 }
184}
185
187template <class TBase, bool TEnd = true, FontSize TFs = FS_NORMAL>
188class DropDownBadges : public TBase {
189public:
190 template <typename... Args>
191 explicit DropDownBadges(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, Args &&...args) :
192 TBase(std::forward<Args>(args)...), gui_classes(gui_classes), badges(badges), feature(feature), introduction_date(introduction_date)
193 {
194 for (const auto &gc : gui_classes->GetClasses()) {
195 if (gc.column_group != 0) continue;
196 dim.width += gc.size.width + WidgetDimensions::scaled.hsep_normal;
197 dim.height = std::max(dim.height, gc.size.height);
198 }
199 }
200
201 uint Height() const override
202 {
203 return std::max<uint>(this->dim.height, this->TBase::Height());
204 }
205
206 uint Width() const override
207 {
208 return this->dim.width + WidgetDimensions::scaled.hsep_wide + this->TBase::Width();
209 }
210
211 int OnClick(const Rect &r, const Point &pt) const override
212 {
213 bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
214 return this->TBase::OnClick(r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_wide, rtl), pt);
215 }
216
217 void Draw(const Rect &full, const Rect &r, bool sel, int click_result, Colours bg_colour) const override
218 {
219 bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
220
221 DrawBadgeColumn(r.WithWidth(this->dim.width, rtl), 0, *this->gui_classes, this->badges, this->feature, this->introduction_date, PAL_NONE);
222
223 this->TBase::Draw(full, r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_wide, rtl), sel, click_result, bg_colour);
224 }
225
226private:
227 std::shared_ptr<GUIBadgeClasses> gui_classes;
228
229 const std::span<const BadgeID> badges;
230 const GrfSpecFeature feature;
231 const std::optional<TimerGameCalendar::Date> introduction_date;
232
233 Dimension dim{};
234};
235
238
239std::unique_ptr<DropDownListItem> MakeDropDownListBadgeItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, std::string &&str, int value, bool masked, bool shaded)
240{
241 return std::make_unique<DropDownListBadgeItem>(gui_classes, badges, feature, introduction_date, std::move(str), value, masked, shaded);
242}
243
244std::unique_ptr<DropDownListItem> MakeDropDownListBadgeIconItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, const Dimension &dim, SpriteID sprite, PaletteID palette, std::string &&str, int value, bool masked, bool shaded)
245{
246 return std::make_unique<DropDownListBadgeIconItem>(gui_classes, badges, feature, introduction_date, dim, sprite, palette, std::move(str), value, masked, shaded);
247}
248
252template <class TBase, bool TEnd = true, FontSize TFs = FS_NORMAL>
253class DropDownMover : public TBase {
254public:
255 template <typename... Args>
256 explicit DropDownMover(int click_up, int click_down, Colours button_colour, Args &&...args)
257 : TBase(std::forward<Args>(args)...), click_up(click_up), click_down(click_down), button_colour(button_colour)
258 {
259 }
260
261 uint Height() const override
262 {
263 return std::max<uint>(SETTING_BUTTON_HEIGHT, this->TBase::Height());
264 }
265
266 uint Width() const override
267 {
268 return SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide + this->TBase::Width();
269 }
270
271 int OnClick(const Rect &r, const Point &pt) const override
272 {
273 bool rtl = (_current_text_dir == TD_RTL);
274 int w = SETTING_BUTTON_WIDTH;
275
276 Rect br = r.WithWidth(w, TEnd ^ rtl).CentreTo(w, SETTING_BUTTON_HEIGHT);
277 if (br.WithWidth(w / 2, rtl).Contains(pt)) return this->click_up;
278 if (br.WithWidth(w / 2, !rtl).Contains(pt)) return this->click_down;
279
280 return this->TBase::OnClick(r.Indent(w + WidgetDimensions::scaled.hsep_wide, TEnd ^ rtl), pt);
281 }
282
283 void Draw(const Rect &full, const Rect &r, bool sel, int click_result, Colours bg_colour) const override
284 {
285 bool rtl = (_current_text_dir == TD_RTL);
286 int w = SETTING_BUTTON_WIDTH;
287
288 int state = 0;
289 if (sel && click_result != 0) {
290 if (click_result == this->click_up) state = 1;
291 if (click_result == this->click_down) state = 2;
292 }
293
294 Rect br = r.WithWidth(w, TEnd ^ rtl).CentreTo(w, SETTING_BUTTON_HEIGHT);
295 DrawUpDownButtons(br.left, br.top, this->button_colour, state, this->click_up != 0, this->click_down != 0);
296
297 this->TBase::Draw(full, r.Indent(w + WidgetDimensions::scaled.hsep_wide, TEnd ^ rtl), sel, click_result, bg_colour);
298 }
299
300private:
304};
305
308
309enum BadgeClick : int {
310 BADGE_CLICK_NONE,
311 BADGE_CLICK_MOVE_UP,
312 BADGE_CLICK_MOVE_DOWN,
313 BADGE_CLICK_TOGGLE_ICON,
314 BADGE_CLICK_TOGGLE_FILTER,
315};
316
317DropDownList BuildBadgeClassConfigurationList(const GUIBadgeClasses &gui_classes, uint columns, std::span<const StringID> column_separators)
318{
319 DropDownList list;
320
321 list.push_back(MakeDropDownListStringItem(STR_BADGE_CONFIG_RESET, INT_MAX));
322 if (gui_classes.GetClasses().empty()) return list;
323 list.push_back(MakeDropDownListDividerItem());
324 list.push_back(std::make_unique<DropDownUnselectable<DropDownListStringItem>>(GetString(STR_BADGE_CONFIG_ICONS), -1));
325
326 const BadgeClassID front = gui_classes.GetClasses().front().class_index;
327 const BadgeClassID back = gui_classes.GetClasses().back().class_index;
328
329 for (uint i = 0; i < columns; ++i) {
330 for (const auto &gc : gui_classes.GetClasses()) {
331 if (gc.column_group != i) continue;
332 if (gc.size.width == 0) continue;
333
334 bool first = (i == 0 && gc.class_index == front);
335 bool last = (i == columns - 1 && gc.class_index == back);
336 list.push_back(std::make_unique<DropDownListToggleMoverItem>(first ? 0 : BADGE_CLICK_MOVE_UP, last ? 0 : BADGE_CLICK_MOVE_DOWN, COLOUR_YELLOW, gc.visible, BADGE_CLICK_TOGGLE_ICON, COLOUR_YELLOW, COLOUR_GREY, GetString(GetClassBadge(gc.class_index)->name), gc.class_index.base()));
337 }
338
339 if (i >= column_separators.size()) continue;
340
341 if (column_separators[i] == STR_NULL) {
342 list.push_back(MakeDropDownListDividerItem());
343 } else {
344 list.push_back(MakeDropDownListStringItem(column_separators[i], INT_MIN + i, false, true));
345 }
346 }
347
348 list.push_back(MakeDropDownListDividerItem());
349 list.push_back(std::make_unique<DropDownUnselectable<DropDownListStringItem>>(GetString(STR_BADGE_CONFIG_FILTERS), -1));
350
351 for (const BadgeClassID &badge_class_index : gui_classes.Classes()) {
352 const Badge *badge = GetClassBadge(badge_class_index);
353 if (!badge->flags.Test(BadgeFlag::HasText)) continue;
354
355 const auto [config, _] = GetBadgeClassConfigItem(gui_classes.GetFeature(), badge->label);
356 list.push_back(std::make_unique<DropDownListToggleItem>(config.show_filter, BADGE_CLICK_TOGGLE_FILTER, COLOUR_YELLOW, COLOUR_GREY, GetString(badge->name), (1U << 16) | badge_class_index.base()));
357 }
358
359 return list;
360}
361
368static void BadgeClassToggleVisibility(GrfSpecFeature feature, Badge &class_badge, int click_result, BadgeFilterChoices &choices)
369{
370 auto config = GetBadgeClassConfiguration(feature);
371 auto it = std::ranges::find(config, class_badge.label, &BadgeClassConfigItem::label);
372 if (it == std::end(config)) return;
373
374 if (click_result == BADGE_CLICK_TOGGLE_ICON) it->show_icon = !it->show_icon;
375 if (click_result == BADGE_CLICK_TOGGLE_FILTER) {
376 it->show_filter = !it->show_filter;
377 if (!it->show_filter) ResetBadgeFilter(choices, class_badge.class_index);
378 }
379}
380
386static void BadgeClassMovePrevious(GrfSpecFeature feature, Badge &class_badge)
387{
388 GUIBadgeClasses gui_classes(feature);
389 if (gui_classes.GetClasses().empty()) return;
390
391 auto config = GetBadgeClassConfiguration(feature);
392 auto it = std::ranges::find(config, class_badge.label, &BadgeClassConfigItem::label);
393 if (it == std::end(config)) return;
394
395 auto pos_cur = std::ranges::find(gui_classes.GetClasses(), class_badge.class_index, &GUIBadgeClasses::Element::class_index);
396 if (pos_cur == std::begin(gui_classes.GetClasses())) {
397 if (it->column > 0) --it->column;
398 return;
399 }
400
401 auto pos_prev = std::ranges::find(config, std::prev(pos_cur)->label, &BadgeClassConfigItem::label);
402 if (it->column > pos_prev->column) {
403 --it->column;
404 } else {
405 /* Rotate elements right so that it is placed before pos_prev, maintaining order of non-visible elements. */
406 std::rotate(pos_prev, it, std::next(it));
407 }
408}
409
416static void BadgeClassMoveNext(GrfSpecFeature feature, Badge &class_badge, uint columns)
417{
418 GUIBadgeClasses gui_classes(feature);
419 if (gui_classes.GetClasses().empty()) return;
420
421 auto config = GetBadgeClassConfiguration(feature);
422 auto it = std::ranges::find(config, class_badge.label, &BadgeClassConfigItem::label);
423 if (it == std::end(config)) return;
424
425 auto pos_cur = std::ranges::find(gui_classes.GetClasses(), class_badge.class_index, &GUIBadgeClasses::Element::class_index);
426 if (std::next(pos_cur) == std::end(gui_classes.GetClasses())) {
427 if (it->column < static_cast<int>(columns - 1)) ++it->column;
428 return;
429 }
430
431 auto pos_next = std::ranges::find(config, std::next(pos_cur)->label, &BadgeClassConfigItem::label);
432 if (it->column < pos_next->column) {
433 ++it->column;
434 } else {
435 /* Rotate elements left so that it is placed after pos_next, maintaining order of non-visible elements. */
436 std::rotate(it, std::next(it), std::next(pos_next));
437 }
438}
439
448bool HandleBadgeConfigurationDropDownClick(GrfSpecFeature feature, uint columns, int result, int click_result, BadgeFilterChoices &choices)
449{
450 if (result == INT_MAX) {
452 return true;
453 }
454
455 Badge *class_badge = GetClassBadge(static_cast<BadgeClassID>(result));
456 if (class_badge == nullptr) return false;
457
458 switch (click_result) {
459 case BADGE_CLICK_MOVE_DOWN: // Move down button.
460 BadgeClassMoveNext(feature, *class_badge, columns);
461 break;
462 case BADGE_CLICK_MOVE_UP: // Move up button.
463 BadgeClassMovePrevious(feature, *class_badge);
464 break;
465 case BADGE_CLICK_TOGGLE_ICON:
466 case BADGE_CLICK_TOGGLE_FILTER:
467 BadgeClassToggleVisibility(feature, *class_badge, click_result, choices);
468 break;
469 default:
470 break;
471 }
472
473 return true;
474}
475
476NWidgetBadgeFilter::NWidgetBadgeFilter(Colours colour, WidgetID index, GrfSpecFeature feature, BadgeClassID badge_class)
477 : NWidgetLeaf(WWT_DROPDOWN, colour, index, WidgetData{ .string = STR_JUST_STRING }, STR_NULL)
478 , feature(feature), badge_class(badge_class)
479{
480 this->SetFill(1, 0);
481 this->SetResize(1, 0);
482}
483
484std::string NWidgetBadgeFilter::GetStringParameter(const BadgeFilterChoices &choices) const
485{
486 auto it = choices.find(this->badge_class);
487 if (it == std::end(choices)) {
488 return ::GetString(STR_BADGE_FILTER_ANY_LABEL, GetClassBadge(this->badge_class)->name);
489 }
490
491 return ::GetString(STR_BADGE_FILTER_IS_LABEL, GetClassBadge(it->first)->name, GetBadge(it->second)->name);
492}
493
499{
500 DropDownList list;
501
502 /* Add item for disabling filtering. */
503 list.push_back(MakeDropDownListStringItem(::GetString(STR_BADGE_FILTER_ANY_LABEL, GetClassBadge(this->badge_class)->name), -1));
504 list.push_back(MakeDropDownListDividerItem());
505
506 /* Add badges */
507 Dimension d = GetBadgeMaximalDimension(this->badge_class, this->feature);
508 d.width = ScaleGUITrad(d.width);
509 d.height = ScaleGUITrad(d.height);
510
511 auto start = list.size();
512
513 const auto *bc = GetClassBadge(this->badge_class);
514
515 for (const Badge &badge : GetBadges()) {
516 if (badge.class_index != this->badge_class) continue;
517 if (badge.index == bc->index) continue;
518 if (badge.name == STR_NULL) continue;
519 if (!badge.features.Test(this->feature)) continue;
520
521 PalSpriteID ps = GetBadgeSprite(badge, this->feature, std::nullopt, PAL_NONE);
522 if (ps.sprite == 0) {
523 list.push_back(MakeDropDownListStringItem(badge.name, badge.index.base()));
524 } else {
525 list.push_back(MakeDropDownListIconItem(d, ps.sprite, ps.pal, badge.name, badge.index.base()));
526 }
527 }
528
529 std::sort(std::begin(list) + start, std::end(list), DropDownListStringItem::NatSortFunc);
530
531 return list;
532}
533
542std::pair<WidgetID, WidgetID> AddBadgeDropdownFilters(NWidgetContainer &container, WidgetID widget, Colours colour, GrfSpecFeature feature)
543{
544 container.Clear();
545 WidgetID first = ++widget;
546
547 /* Get list of classes used by feature. */
548 UsedBadgeClasses used(feature);
549
550 for (BadgeClassID class_index : used.Classes()) {
551 const auto [config, _] = GetBadgeClassConfigItem(feature, GetClassBadge(class_index)->label);
552 if (!config.show_filter) continue;
553
554 container.Add(std::make_unique<NWidgetBadgeFilter>(colour, widget, feature, class_index));
555 ++widget;
556 }
557
558 return {first, widget};
559}
560
566void ResetBadgeFilter(BadgeFilterChoices &choices, BadgeClassID badge_class_index)
567{
568 choices.erase(badge_class_index);
569}
570
577void SetBadgeFilter(BadgeFilterChoices &choices, BadgeID badge_index)
578{
579 const Badge *badge = GetBadge(badge_index);
580 assert(badge != nullptr);
581
582 choices[badge->class_index] = badge_index;
583}
std::string label
Class label.
BadgeClassID class_index
Index of class this badge belongs to.
std::string label
Label of badge.
BadgeID index
Index assigned to badge.
BadgeFlags flags
Display flags.
GrfSpecFeatures features
Bitmask of which features use this badge.
StringID name
Short name.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Drop down element that draws a list of badges.
Drop down component that shows extra buttons to indicate that the item can be moved up or down.
int click_down
Click result for down button. Button is inactive if 0.
Colours button_colour
Colour of buttons.
int click_up
Click result for up button. Button is inactive if 0.
static bool NatSortFunc(std::unique_ptr< const DropDownListItem > const &first, std::unique_ptr< const DropDownListItem > const &second)
Natural sorting comparator function for DropDownList::sort().
Drop down boolean toggle component.
Drop down component that makes the item unselectable.
Flat set implementation that uses a sorted vector for storage.
uint GetTotalColumnsWidth() const
Get total width of all columns.
DropDownList GetDropDownList() const
Get the drop down list of badges for this filter.
BadgeClassID badge_class
Badge class of this dropdown.
Baseclass for container widgets.
void Add(std::unique_ptr< NWidgetBase > &&wid)
Append widget wid to container.
Definition widget.cpp:1303
StringID GetString() const
Get the string that has been set for this nested widget.
Definition widget.cpp:1262
Leaf widget.
Utility class to create a list of badge classes used by a feature.
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
int hsep_wide
Wide horizontal spacing.
Definition window_gui.h:62
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:61
Common drop down list components.
Functions related to the drop down widget.
Types related to the drop down widget.
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
Flat set container implementation.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:958
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:775
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:393
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
Base for the NewGRF implementation.
GrfSpecFeature
Definition newgrf.h:69
Badge * GetBadge(BadgeID index)
Get a badge if it exists.
std::span< const Badge > GetBadges()
Get a read-only view of badges.
PalSpriteID GetBadgeSprite(const Badge &badge, GrfSpecFeature feature, std::optional< TimerGameCalendar::Date > introduction_date, PaletteID remap)
Get sprite for the given badge.
Badge * GetClassBadge(BadgeClassID class_index)
Get the badge class of a badge label.
Functions related to NewGRF badges.
void ResetBadgeClassConfiguration(GrfSpecFeature feature)
Reset badge class configuration for a feature.
std::pair< const BadgeClassConfigItem &, int > GetBadgeClassConfigItem(GrfSpecFeature feature, std::string_view label)
Get configuration for a badge class.
std::span< BadgeClassConfigItem > GetBadgeClassConfiguration(GrfSpecFeature feature)
Get the badge user configuration for a feature.
Functions related to NewGRF badge configuration.
Types related to NewGRF badges.
@ NameListStop
Stop adding names to the name list after this badge.
@ NameListFirstOnly
Don't add this name to the name list if not first.
@ HasText
Internal flag set if the badge has text.
A number of safeguards to prevent using unsafe methods.
void DrawUpDownButtons(int x, int y, Colours button_colour, uint8_t state, bool clickable_up, bool clickable_down)
Draw [^][v] buttons.
Functions for setting GUIs.
#define SETTING_BUTTON_WIDTH
Width of setting buttons.
#define SETTING_BUTTON_HEIGHT
Height of setting buttons.
Definition of base types and functions in a cross-platform compatible way.
std::string_view GetListSeparator()
Get the list separator string for the current language.
Definition strings.cpp:300
void AppendStringInPlace(std::string &result, StringID string)
Resolve the given StringID and append in place into an existing std::string with formatting but no pa...
Definition strings.cpp:435
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:425
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:57
Functions related to OTTD's strings.
@ TD_RTL
Text is written right-to-left by default.
Dimensions (a width and height) of a rectangle in 2D.
uint sort_order
Order of element.
std::string_view label
Class label (string owned by the class badge)
BadgeClassID class_index
Badge class index.
uint8_t column_group
Column group in UI. 0 = left, 1 = centre, 2 = right.
Combination of a palette sprite and a 'real' sprite.
Definition gfx_type.h:22
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:23
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition gfx_type.h:24
Coordinates of a point in 2D.
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
Rect CentreTo(int width, int height) const
Centre a dimension within this Rect.
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
bool Contains(const Point &pt) const
Test if a point falls inside this Rect.
Container with the data associated to a single widget.
int16_t Height
Fixed point type for heights.
Definition tgp.cpp:153
Definition of the game-calendar-timer.
static RectPadding ScaleGUITrad(const RectPadding &r)
Scale a RectPadding to GUI zoom level.
Definition widget.cpp:49
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:62
Functions, definitions and such used only by the GUI.
int WidgetID
Widget ID.
Definition window_type.h:20
Functions related to zooming.
@ Normal
The normal zoom level.