Update to 14.0-beta1

This commit is contained in:
dP
2024-02-04 02:18:17 +05:30
parent 79037e2c65
commit 33ef333b57
1325 changed files with 138465 additions and 70987 deletions

View File

@@ -24,10 +24,11 @@
#include "core/geometry_func.hpp"
#include "newgrf_debug.h"
#include "zoom_func.h"
#include "guitimer_func.h"
#include "viewport_func.h"
#include "landscape_cmd.h"
#include "rev.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
#include "widgets/misc_widget.h"
@@ -47,7 +48,7 @@ enum OskActivation {
};
static const NWidgetPart _nested_land_info_widgets[] = {
static constexpr NWidgetPart _nested_land_info_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_LAND_AREA_INFORMATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
@@ -57,11 +58,11 @@ static const NWidgetPart _nested_land_info_widgets[] = {
NWidget(WWT_PANEL, COLOUR_GREY, WID_LI_BACKGROUND), EndContainer(),
};
static WindowDesc _land_info_desc(
WDP_AUTO, "land_info", 0, 0,
static WindowDesc _land_info_desc(__FILE__, __LINE__,
WDP_AUTO, nullptr, 0, 0,
WC_LAND_INFO, WC_NONE,
0,
_nested_land_info_widgets, lengthof(_nested_land_info_widgets)
std::begin(_nested_land_info_widgets), std::end(_nested_land_info_widgets)
);
class LandInfoWindow : public Window {
@@ -71,14 +72,14 @@ class LandInfoWindow : public Window {
public:
TileIndex tile;
void DrawWidget(const Rect &r, int widget) const override
void DrawWidget(const Rect &r, WidgetID widget) const override
{
if (widget != WID_LI_BACKGROUND) return;
Rect ir = r.Shrink(WidgetDimensions::scaled.frametext);
for (size_t i = 0; i < this->landinfo_data.size(); i++) {
DrawString(ir, this->landinfo_data[i], i == 0 ? TC_LIGHT_BLUE : TC_FROMSTRING, SA_HOR_CENTER);
ir.top += FONT_HEIGHT_NORMAL + (i == 0 ? WidgetDimensions::scaled.vsep_wide : WidgetDimensions::scaled.vsep_normal);
ir.top += GetCharacterHeight(FS_NORMAL) + (i == 0 ? WidgetDimensions::scaled.vsep_wide : WidgetDimensions::scaled.vsep_normal);
}
if (!this->cargo_acceptance.empty()) {
@@ -87,7 +88,7 @@ public:
}
}
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
{
if (widget != WID_LI_BACKGROUND) return;
@@ -96,7 +97,7 @@ public:
uint width = GetStringBoundingBox(this->landinfo_data[i]).width + WidgetDimensions::scaled.frametext.Horizontal();
size->width = std::max(size->width, width);
size->height += FONT_HEIGHT_NORMAL + (i == 0 ? WidgetDimensions::scaled.vsep_wide : WidgetDimensions::scaled.vsep_normal);
size->height += GetCharacterHeight(FS_NORMAL) + (i == 0 ? WidgetDimensions::scaled.vsep_wide : WidgetDimensions::scaled.vsep_normal);
}
if (!this->cargo_acceptance.empty()) {
@@ -107,7 +108,7 @@ public:
}
}
LandInfoWindow(TileIndex tile) : Window(&_land_info_desc), tile(tile)
LandInfoWindow(Tile tile) : Window(&_land_info_desc), tile(tile)
{
this->InitNested();
@@ -116,17 +117,17 @@ public:
#else
# define LANDINFOD_LEVEL 1
#endif
Debug(misc, LANDINFOD_LEVEL, "TILE: {:#x} ({},{})", tile, TileX(tile), TileY(tile));
Debug(misc, LANDINFOD_LEVEL, "type = {:#x}", _m[tile].type);
Debug(misc, LANDINFOD_LEVEL, "height = {:#x}", _m[tile].height);
Debug(misc, LANDINFOD_LEVEL, "m1 = {:#x}", _m[tile].m1);
Debug(misc, LANDINFOD_LEVEL, "m2 = {:#x}", _m[tile].m2);
Debug(misc, LANDINFOD_LEVEL, "m3 = {:#x}", _m[tile].m3);
Debug(misc, LANDINFOD_LEVEL, "m4 = {:#x}", _m[tile].m4);
Debug(misc, LANDINFOD_LEVEL, "m5 = {:#x}", _m[tile].m5);
Debug(misc, LANDINFOD_LEVEL, "m6 = {:#x}", _me[tile].m6);
Debug(misc, LANDINFOD_LEVEL, "m7 = {:#x}", _me[tile].m7);
Debug(misc, LANDINFOD_LEVEL, "m8 = {:#x}", _me[tile].m8);
Debug(misc, LANDINFOD_LEVEL, "TILE: 0x{:x} ({},{})", (TileIndex)tile, TileX(tile), TileY(tile));
Debug(misc, LANDINFOD_LEVEL, "type = 0x{:x}", tile.type());
Debug(misc, LANDINFOD_LEVEL, "height = 0x{:x}", tile.height());
Debug(misc, LANDINFOD_LEVEL, "m1 = 0x{:x}", tile.m1());
Debug(misc, LANDINFOD_LEVEL, "m2 = 0x{:x}", tile.m2());
Debug(misc, LANDINFOD_LEVEL, "m3 = 0x{:x}", tile.m3());
Debug(misc, LANDINFOD_LEVEL, "m4 = 0x{:x}", tile.m4());
Debug(misc, LANDINFOD_LEVEL, "m5 = 0x{:x}", tile.m5());
Debug(misc, LANDINFOD_LEVEL, "m6 = 0x{:x}", tile.m6());
Debug(misc, LANDINFOD_LEVEL, "m7 = 0x{:x}", tile.m7());
Debug(misc, LANDINFOD_LEVEL, "m8 = 0x{:x}", tile.m8());
#undef LANDINFOD_LEVEL
}
@@ -137,7 +138,7 @@ public:
/* Because build_date is not set yet in every TileDesc, we make sure it is empty */
TileDesc td;
td.build_date = INVALID_DATE;
td.build_date = CalendarTime::INVALID_DATE;
/* Most tiles have only one owner, but
* - drivethrough roadstops can be build on town owned roads (up to 2 owners) and
@@ -166,14 +167,14 @@ public:
td.grf = nullptr;
CargoArray acceptance;
CargoArray acceptance{};
AddAcceptedCargo(tile, acceptance, nullptr);
GetTileDesc(tile, &td);
this->landinfo_data.clear();
/* Tiletype */
SetDParam(0, td.dparam[0]);
SetDParam(0, td.dparam);
this->landinfo_data.push_back(GetString(td.str));
/* Up to four owners */
@@ -181,7 +182,7 @@ public:
if (td.owner_type[i] == STR_NULL) continue;
SetDParam(0, STR_LAND_AREA_INFORMATION_OWNER_N_A);
if (td.owner[i] != OWNER_NONE && td.owner[i] != OWNER_WATER) GetNameOfOwner(td.owner[i], tile);
if (td.owner[i] != OWNER_NONE && td.owner[i] != OWNER_WATER) SetDParamsForOwnedBy(td.owner[i], tile);
this->landinfo_data.push_back(GetString(td.owner_type[i]));
}
@@ -206,13 +207,12 @@ public:
/* Location */
std::stringstream tile_ss;
tile_ss << "0x" << std::setfill('0') << std::setw(4) << std::hex << std::uppercase << tile; // 0x%.4X
std::string tile_str = tile_ss.str(); // Can't pass it directly to SetDParamStr as the string is only a temporary and would be destructed before the GetString call.
tile_ss << "0x" << std::setfill('0') << std::setw(4) << std::hex << std::uppercase << tile.base(); // 0x%.4X
SetDParam(0, TileX(tile));
SetDParam(1, TileY(tile));
SetDParam(2, GetTileZ(tile));
SetDParamStr(3, tile_str);
SetDParamStr(3, tile_ss.str());
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_LANDINFO_COORDS));
/* Local authority */
@@ -224,7 +224,7 @@ public:
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY));
/* Build date */
if (td.build_date != INVALID_DATE) {
if (td.build_date != CalendarTime::INVALID_DATE) {
SetDParam(0, td.build_date);
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_BUILD_DATE));
}
@@ -267,7 +267,7 @@ public:
/* Rail speed limit */
if (td.rail_speed != 0) {
SetDParam(0, td.rail_speed);
SetDParam(0, PackVelocity(td.rail_speed, VEH_TRAIN));
this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT));
}
@@ -279,7 +279,7 @@ public:
/* Road speed limit */
if (td.road_speed != 0) {
SetDParam(0, td.road_speed);
SetDParam(0, PackVelocity(td.road_speed, VEH_ROAD));
this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT));
}
@@ -291,7 +291,7 @@ public:
/* Tram speed limit */
if (td.tram_speed != 0) {
SetDParam(0, td.tram_speed);
SetDParam(0, PackVelocity(td.tram_speed, VEH_ROAD));
this->landinfo_data.push_back(GetString(STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT));
}
@@ -306,19 +306,20 @@ public:
line << GetString(STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED);
bool found = false;
for (CargoID i = 0; i < NUM_CARGO; ++i) {
if (acceptance[i] > 0) {
for (const CargoSpec *cs : _sorted_cargo_specs) {
CargoID cid = cs->Index();
if (acceptance[cid] > 0) {
/* Add a comma between each item. */
if (found) line << ", ";
found = true;
/* If the accepted value is less than 8, show it in 1/8:ths */
if (acceptance[i] < 8) {
SetDParam(0, acceptance[i]);
SetDParam(1, CargoSpec::Get(i)->name);
if (acceptance[cid] < 8) {
SetDParam(0, acceptance[cid]);
SetDParam(1, cs->name);
line << GetString(STR_LAND_AREA_INFORMATION_CARGO_EIGHTS);
} else {
line << GetString(CargoSpec::Get(i)->name);
line << GetString(cs->name);
}
}
}
@@ -331,15 +332,15 @@ public:
bool IsNewGRFInspectable() const override
{
return ::IsNewGRFInspectable(GetGrfSpecFeature(this->tile), this->tile);
return ::IsNewGRFInspectable(GetGrfSpecFeature(this->tile), this->tile.base());
}
void ShowNewGRFInspectWindow() const override
{
::ShowNewGRFInspectWindow(GetGrfSpecFeature(this->tile), this->tile);
::ShowNewGRFInspectWindow(GetGrfSpecFeature(this->tile), this->tile.base());
}
void OnClick(Point pt, int widget, int click_count) override
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
switch (widget) {
case WID_LI_LOCATION:
@@ -357,15 +358,12 @@ public:
* @param data Information about the changed data.
* @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
*/
void OnInvalidateData(int data = 0, bool gui_scope = true) override
void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
{
if (!gui_scope) return;
switch (data) {
case 1:
/* ReInit, "debug" sprite might have changed */
this->ReInit();
break;
}
/* ReInit, "debug" sprite might have changed */
if (data == 1) this->ReInit();
}
};
@@ -379,7 +377,7 @@ void ShowLandInfo(TileIndex tile)
new LandInfoWindow(tile);
}
static const NWidgetPart _nested_about_widgets[] = {
static constexpr NWidgetPart _nested_about_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_ABOUT_OPENTTD, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
@@ -390,82 +388,82 @@ static const NWidgetPart _nested_about_widgets[] = {
NWidget(WWT_FRAME, COLOUR_GREY), SetPadding(0, 5, 1, 5),
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_A_SCROLLING_TEXT),
EndContainer(),
NWidget(WWT_LABEL, COLOUR_GREY, WID_A_WEBSITE), SetDataTip(STR_BLACK_RAW_STRING, STR_NULL),
NWidget(WWT_LABEL, COLOUR_GREY, WID_A_WEBSITE), SetDataTip(STR_JUST_RAW_STRING, STR_NULL),
NWidget(WWT_LABEL, COLOUR_GREY, WID_A_COPYRIGHT), SetDataTip(STR_ABOUT_COPYRIGHT_OPENTTD, STR_NULL),
EndContainer(),
};
static WindowDesc _about_desc(
static WindowDesc _about_desc(__FILE__, __LINE__,
WDP_CENTER, nullptr, 0, 0,
WC_GAME_OPTIONS, WC_NONE,
0,
_nested_about_widgets, lengthof(_nested_about_widgets)
std::begin(_nested_about_widgets), std::end(_nested_about_widgets)
);
static const char * const _credits[] = {
u8"Original design by Chris Sawyer",
u8"Original graphics by Simon Foster",
u8"",
u8"The OpenTTD team (in alphabetical order):",
u8" Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)",
u8" Christoph Elsenhans (frosch) - General coding (since 0.6)",
u8" Lo\u00efc Guilloux (glx) - General / Windows Expert (since 0.4.5)",
u8" Charles Pigott (LordAro) - General / Correctness police (since 1.9)",
u8" Michael Lutz (michi_cc) - Path based signals (since 0.7)",
u8" Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)",
u8" Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)",
u8" Peter Nelson (peter1138) - Spiritual descendant from NewGRF gods (since 0.4.5)",
u8" Remko Bijker (Rubidium) - Coder and way more (since 0.4.5)",
u8" Patric Stout (TrueBrain) - NoProgrammer (since 0.3), sys op",
u8" Tyler Trahan (2TallTyler) - General coding (since 13)",
u8"",
u8"Inactive Developers:",
u8" Grzegorz Duczy\u0144ski (adf88) - General coding (1.7 - 1.8)",
u8" Albert Hofkamp (Alberth) - GUI expert (0.7 - 1.9)",
u8" Jean-Fran\u00e7ois Claeys (Belugas) - GUI, NewGRF and more (0.4.5 - 1.0)",
u8" Bjarni Corfitzen (Bjarni) - MacOSX port, coder and vehicles (0.3 - 0.7)",
u8" Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)",
u8" Ulf Hermann (fonsinchen) - Cargo Distribution (1.3 - 1.6)",
u8" Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)",
u8" Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)",
u8" Attila B\u00e1n (MiHaMiX) - Developer WebTranslator 1 and 2 (0.3 - 0.5)",
u8" Ingo von Borstel (planetmaker) - General coding, Support (1.1 - 1.9)",
u8" Zden\u011bk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)",
u8" Jos\u00e9 Soler (Terkhen) - General coding (1.0 - 1.4)",
u8" Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)",
u8" Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)",
u8" Leif Linse (Zuu) - AI/Game Script (1.2 - 1.6)",
u8"",
u8"Retired Developers:",
u8" Tam\u00e1s Farag\u00f3 (Darkvater) - Ex-Lead coder (0.3 - 0.5)",
u8" Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)",
u8" Emil Djupfeld (egladil) - MacOSX (0.4.5 - 0.6)",
u8" Simon Sasburg (HackyKid) - Many bugfixes (0.4 - 0.4.5)",
u8" Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)",
u8" Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)",
u8" Petr Baudi\u0161 (pasky) - Many patches, NewGRF support (0.3 - 0.3)",
u8" Benedikt Br\u00fcggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)",
u8" Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)",
u8"",
u8"Special thanks go out to:",
u8" Josef Drexler - For his great work on TTDPatch",
u8" Marcin Grzegorczyk - Track foundations and for describing TTD internals",
u8" Stefan Mei\u00dfner (sign_de) - For his work on the console",
u8" Mike Ragsdale - OpenTTD installer",
u8" Christian Rosentreter (tokai) - MorphOS / AmigaOS port",
u8" Richard Kempton (richK) - additional airports, initial TGP implementation",
u8" Alberto Demichelis - Squirrel scripting language \u00a9 2003-2008",
u8" L. Peter Deutsch - MD5 implementation \u00a9 1999, 2000, 2002",
u8" Michael Blunck - Pre-signals and semaphores \u00a9 2003",
u8" George - Canal/Lock graphics \u00a9 2003-2004",
u8" Andrew Parkhouse (andythenorth) - River graphics",
u8" David Dallaston (Pikka) - Tram tracks",
u8" All Translators - Who made OpenTTD a truly international game",
u8" Bug Reporters - Without whom OpenTTD would still be full of bugs!",
u8"",
u8"",
u8"And last but not least:",
u8" Chris Sawyer - For an amazing game!"
"Original design by Chris Sawyer",
"Original graphics by Simon Foster",
"",
"The OpenTTD team (in alphabetical order):",
" Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)",
" Christoph Elsenhans (frosch) - General coding (since 0.6)",
" Lo\u00efc Guilloux (glx) - General / Windows Expert (since 0.4.5)",
" Charles Pigott (LordAro) - General / Correctness police (since 1.9)",
" Michael Lutz (michi_cc) - Path based signals (since 0.7)",
" Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)",
" Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)",
" Peter Nelson (peter1138) - Spiritual descendant from NewGRF gods (since 0.4.5)",
" Remko Bijker (Rubidium) - Coder and way more (since 0.4.5)",
" Patric Stout (TrueBrain) - NoProgrammer (since 0.3), sys op",
" Tyler Trahan (2TallTyler) - General coding (since 13)",
"",
"Inactive Developers:",
" Grzegorz Duczy\u0144ski (adf88) - General coding (1.7 - 1.8)",
" Albert Hofkamp (Alberth) - GUI expert (0.7 - 1.9)",
" Jean-Fran\u00e7ois Claeys (Belugas) - GUI, NewGRF and more (0.4.5 - 1.0)",
" Bjarni Corfitzen (Bjarni) - MacOSX port, coder and vehicles (0.3 - 0.7)",
" Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)",
" Ulf Hermann (fonsinchen) - Cargo Distribution (1.3 - 1.6)",
" Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)",
" Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)",
" Attila B\u00e1n (MiHaMiX) - Developer WebTranslator 1 and 2 (0.3 - 0.5)",
" Ingo von Borstel (planetmaker) - General coding, Support (1.1 - 1.9)",
" Zden\u011bk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)",
" Jos\u00e9 Soler (Terkhen) - General coding (1.0 - 1.4)",
" Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)",
" Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)",
" Leif Linse (Zuu) - AI/Game Script (1.2 - 1.6)",
"",
"Retired Developers:",
" Tam\u00e1s Farag\u00f3 (Darkvater) - Ex-Lead coder (0.3 - 0.5)",
" Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)",
" Emil Djupfeld (egladil) - MacOSX (0.4.5 - 0.6)",
" Simon Sasburg (HackyKid) - Many bugfixes (0.4 - 0.4.5)",
" Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)",
" Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)",
" Petr Baudi\u0161 (pasky) - Many patches, NewGRF support (0.3 - 0.3)",
" Benedikt Br\u00fcggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)",
" Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)",
"",
"Special thanks go out to:",
" Josef Drexler - For his great work on TTDPatch",
" Marcin Grzegorczyk - Track foundations and for describing TTD internals",
" Stefan Mei\u00dfner (sign_de) - For his work on the console",
" Mike Ragsdale - OpenTTD installer",
" Christian Rosentreter (tokai) - MorphOS / AmigaOS port",
" Richard Kempton (richK) - additional airports, initial TGP implementation",
" Alberto Demichelis - Squirrel scripting language \u00a9 2003-2008",
" L. Peter Deutsch - MD5 implementation \u00a9 1999, 2000, 2002",
" Michael Blunck - Pre-signals and semaphores \u00a9 2003",
" George - Canal/Lock graphics \u00a9 2003-2004",
" Andrew Parkhouse (andythenorth) - River graphics",
" David Dallaston (Pikka) - Tram tracks",
" All Translators - Who made OpenTTD a truly international game",
" Bug Reporters - Without whom OpenTTD would still be full of bugs!",
"",
"",
"And last but not least:",
" Chris Sawyer - For an amazing game!"
};
struct AboutWindow : public Window {
@@ -473,9 +471,6 @@ struct AboutWindow : public Window {
int line_height; ///< The height of a single line
static const int num_visible_lines = 19; ///< The number of lines visible simultaneously
static const uint TIMER_INTERVAL = 2100; ///< Scrolling interval, scaled by line text line height. This value chosen to maintain parity: 2100 / FONT_HEIGHT_NORMAL = 150ms
GUITimer timer;
AboutWindow() : Window(&_about_desc)
{
this->InitNested(WN_GAME_OPTIONS_ABOUT);
@@ -483,17 +478,17 @@ struct AboutWindow : public Window {
this->text_position = this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y + this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->current_y;
}
void SetStringParameters(int widget) const override
void SetStringParameters(WidgetID widget) const override
{
if (widget == WID_A_WEBSITE) SetDParamStr(0, "Website: https://www.openttd.org");
if (widget == WID_A_COPYRIGHT) SetDParamStr(0, _openttd_revision_year);
}
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
{
if (widget != WID_A_SCROLLING_TEXT) return;
this->line_height = FONT_HEIGHT_NORMAL;
this->line_height = GetCharacterHeight(FS_NORMAL);
Dimension d;
d.height = this->line_height * num_visible_lines;
@@ -503,13 +498,9 @@ struct AboutWindow : public Window {
d.width = std::max(d.width, GetStringBoundingBox(_credits[i]).width);
}
*size = maxdim(*size, d);
/* Set scroll interval based on required speed. To keep scrolling smooth,
* the interval is adjusted rather than the distance moved. */
this->timer.SetInterval(TIMER_INTERVAL / FONT_HEIGHT_NORMAL);
}
void DrawWidget(const Rect &r, int widget) const override
void DrawWidget(const Rect &r, WidgetID widget) const override
{
if (widget != WID_A_SCROLLING_TEXT) return;
@@ -524,18 +515,19 @@ struct AboutWindow : public Window {
}
}
void OnRealtimeTick(uint delta_ms) override
{
uint count = this->timer.CountElapsed(delta_ms);
if (count > 0) {
this->text_position -= count;
/* If the last text has scrolled start a new from the start */
if (this->text_position < (int)(this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y - lengthof(_credits) * this->line_height)) {
this->text_position = this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y + this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->current_y;
}
this->SetWidgetDirty(WID_A_SCROLLING_TEXT);
/**
* Scroll the text in the about window slow.
*
* The interval of 2100ms is chosen to maintain parity: 2100 / GetCharacterHeight(FS_NORMAL) = 150ms.
*/
IntervalTimer<TimerWindow> scroll_interval = {std::chrono::milliseconds(2100) / GetCharacterHeight(FS_NORMAL), [this](uint count) {
this->text_position -= count;
/* If the last text has scrolled start a new from the start */
if (this->text_position < (int)(this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y - lengthof(_credits) * this->line_height)) {
this->text_position = this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->pos_y + this->GetWidget<NWidgetBase>(WID_A_SCROLLING_TEXT)->current_y;
}
}
this->SetWidgetDirty(WID_A_SCROLLING_TEXT);
}};
};
void ShowAboutWindow()
@@ -582,7 +574,7 @@ void ShowCostOrIncomeAnimation(int x, int y, int z, Money cost)
msg = STR_INCOME_FLOAT_INCOME;
}
SetDParam(0, cost);
AddTextEffect(msg, pt.x, pt.y, DAY_TICKS, TE_RISING);
AddTextEffect(msg, pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING);
}
/**
@@ -599,7 +591,7 @@ void ShowFeederIncomeAnimation(int x, int y, int z, Money transfer, Money income
SetDParam(0, transfer);
if (income == 0) {
AddTextEffect(STR_FEEDER, pt.x, pt.y, DAY_TICKS, TE_RISING);
AddTextEffect(STR_FEEDER, pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING);
} else {
StringID msg = STR_FEEDER_COST;
if (income < 0) {
@@ -607,7 +599,7 @@ void ShowFeederIncomeAnimation(int x, int y, int z, Money transfer, Money income
msg = STR_FEEDER_INCOME;
}
SetDParam(1, income);
AddTextEffect(msg, pt.x, pt.y, DAY_TICKS, TE_RISING);
AddTextEffect(msg, pt.x, pt.y, Ticks::DAY_TICKS, TE_RISING);
}
}
@@ -620,7 +612,7 @@ void ShowFeederIncomeAnimation(int x, int y, int z, Money transfer, Money income
* @param string String which is drawn on the map.
* @return TextEffectID to be used for future updates of the loading indicators.
*/
TextEffectID ShowFillingPercent(int x, int y, int z, uint8 percent, StringID string)
TextEffectID ShowFillingPercent(int x, int y, int z, uint8_t percent, StringID string)
{
Point pt = RemapCoords(x, y, z);
@@ -635,7 +627,7 @@ TextEffectID ShowFillingPercent(int x, int y, int z, uint8 percent, StringID str
* @param te_id TextEffectID to be updated.
* @param string String which is printed.
*/
void UpdateFillingPercent(TextEffectID te_id, uint8 percent, StringID string)
void UpdateFillingPercent(TextEffectID te_id, uint8_t percent, StringID string)
{
assert(string != STR_NULL);
@@ -655,37 +647,29 @@ void HideFillingPercent(TextEffectID *te_id)
*te_id = INVALID_TE_ID;
}
static const NWidgetPart _nested_tooltips_widgets[] = {
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_TT_BACKGROUND), EndContainer(),
static constexpr NWidgetPart _nested_tooltips_widgets[] = {
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_TT_BACKGROUND),
};
static WindowDesc _tool_tips_desc(
static WindowDesc _tool_tips_desc(__FILE__, __LINE__,
WDP_MANUAL, nullptr, 0, 0, // Coordinates and sizes are not used,
WC_TOOLTIPS, WC_NONE,
WDF_NO_FOCUS,
_nested_tooltips_widgets, lengthof(_nested_tooltips_widgets)
WDF_NO_FOCUS | WDF_NO_CLOSE,
std::begin(_nested_tooltips_widgets), std::end(_nested_tooltips_widgets)
);
/** Window for displaying a tooltip. */
struct TooltipsWindow : public Window
{
StringID string_id; ///< String to display as tooltip.
byte paramcount; ///< Number of string parameters in #string_id.
uint64 params[8]; ///< The string parameters.
std::vector<StringParameterBackup> params; ///< The string parameters.
TooltipCloseCondition close_cond; ///< Condition for closing the window.
TooltipsWindow(Window *parent, StringID str, uint paramcount, const uint64 params[], TooltipCloseCondition close_tooltip) : Window(&_tool_tips_desc)
TooltipsWindow(Window *parent, StringID str, uint paramcount, TooltipCloseCondition close_tooltip) : Window(&_tool_tips_desc)
{
this->parent = parent;
this->string_id = str;
static_assert(sizeof(this->params[0]) == sizeof(params[0]));
assert(paramcount <= lengthof(this->params));
if (params == nullptr) {
_global_string_params.offset = 0;
params = _global_string_params.GetDataPointer();
}
if (paramcount > 0) memcpy(this->params, params, sizeof(this->params[0]) * paramcount);
this->paramcount = paramcount;
CopyOutDParam(this->params, paramcount);
this->close_cond = close_tooltip;
this->InitNested();
@@ -693,7 +677,7 @@ struct TooltipsWindow : public Window
CLRBITS(this->flags, WF_WHITE_BORDER);
}
Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) override
Point OnInitialPosition([[maybe_unused]] int16_t sm_width, [[maybe_unused]] int16_t sm_height, [[maybe_unused]] int window_number) override
{
/* Find the free screen space between the main toolbar at the top, and the statusbar at the bottom.
* Add a fixed distance 2 so the tooltip floats free from both bars.
@@ -713,10 +697,10 @@ struct TooltipsWindow : public Window
return pt;
}
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
{
/* There is only one widget. */
for (uint i = 0; i != this->paramcount; i++) SetDParam(i, this->params[i]);
if (widget != WID_TT_BACKGROUND) return;
CopyInDParam(this->params);
size->width = std::min<uint>(GetStringBoundingBox(this->string_id).width, ScaleGUITrad(194));
size->height = GetStringHeight(this->string_id, size->width);
@@ -726,16 +710,14 @@ struct TooltipsWindow : public Window
size->height += WidgetDimensions::scaled.framerect.Vertical() + WidgetDimensions::scaled.fullbevel.Vertical();
}
void DrawWidget(const Rect &r, int widget) const override
void DrawWidget(const Rect &r, WidgetID widget) const override
{
/* There is only one widget. */
if (widget != WID_TT_BACKGROUND) return;
GfxFillRect(r, PC_BLACK);
GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), PC_LIGHT_YELLOW);
for (uint arg = 0; arg < this->paramcount; arg++) {
SetDParam(arg, this->params[arg]);
}
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect).Shrink(WidgetDimensions::scaled.fullbevel), this->string_id, TC_FROMSTRING, SA_CENTER);
CopyInDParam(this->params);
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect).Shrink(WidgetDimensions::scaled.fullbevel), this->string_id, TC_BLACK, SA_CENTER);
}
void OnMouseLoop() override
@@ -766,20 +748,19 @@ struct TooltipsWindow : public Window
* Shows a tooltip
* @param parent The window this tooltip is related to.
* @param str String to be displayed
* @param close_tooltip the condition under which the tooltip closes
* @param paramcount number of params to deal with
* @param params (optional) up to 5 pieces of additional information that may be added to a tooltip
* @param close_tooltip when the left (true) or right (false) mouse button is released
*/
void GuiShowTooltips(Window *parent, StringID str, uint paramcount, const uint64 params[], TooltipCloseCondition close_tooltip)
void GuiShowTooltips(Window *parent, StringID str, TooltipCloseCondition close_tooltip, uint paramcount)
{
CloseWindowById(WC_TOOLTIPS, 0);
if (str == STR_NULL || !_cursor.in_window) return;
new TooltipsWindow(parent, str, paramcount, params, close_tooltip);
new TooltipsWindow(parent, str, paramcount, close_tooltip);
}
void QueryString::HandleEditBox(Window *w, int wid)
void QueryString::HandleEditBox(Window *w, WidgetID wid)
{
if (w->IsWidgetGloballyFocused(wid) && this->text.HandleCaret()) {
w->SetWidgetDirty(wid);
@@ -794,14 +775,14 @@ static int GetCaretWidth()
return GetCharacterWidth(FS_NORMAL, '_');
}
void QueryString::DrawEditBox(const Window *w, int wid) const
void QueryString::DrawEditBox(const Window *w, WidgetID wid) const
{
const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
assert((wi->type & WWT_MASK) == WWT_EDITBOX);
bool rtl = _current_text_dir == TD_RTL;
Dimension sprite_size = GetSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
Dimension sprite_size = GetScaledSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal();
Rect r = wi->GetCurrentRect();
@@ -809,7 +790,7 @@ void QueryString::DrawEditBox(const Window *w, int wid) const
Rect fr = r.Indent(clearbtn_width, !rtl);
DrawFrameRect(cr, wi->colour, wi->IsLowered() ? FR_LOWERED : FR_NONE);
DrawSprite(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT, PAL_NONE, cr.left + WidgetDimensions::scaled.imgbtn.left + (wi->IsLowered() ? 1 : 0), CenterBounds(r.top, r.bottom, sprite_size.height) + (wi->IsLowered() ? 1 : 0));
DrawSpriteIgnorePadding(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT, PAL_NONE, cr, SA_CENTER);
if (this->text.bytes == 1) GfxFillRect(cr.Shrink(WidgetDimensions::scaled.bevel), _colour_gradient[wi->colour & 0xF][2], FILLRECT_CHECKER);
DrawFrameRect(fr, wi->colour, FR_LOWERED | FR_DARKENED);
@@ -818,10 +799,9 @@ void QueryString::DrawEditBox(const Window *w, int wid) const
fr = fr.Shrink(WidgetDimensions::scaled.framerect);
/* Limit the drawing of the string inside the widget boundaries */
DrawPixelInfo dpi;
if (!FillDrawPixelInfo(&dpi, fr.left, fr.top, fr.Width(), fr.Height())) return;
if (!FillDrawPixelInfo(&dpi, fr)) return;
DrawPixelInfo *old_dpi = _cur_dpi;
_cur_dpi = &dpi;
AutoRestoreBackup dpi_backup(_cur_dpi, &dpi);
/* We will take the current widget length as maximum width, with a small
* space reserved at the end for the caret to show */
@@ -839,8 +819,6 @@ void QueryString::DrawEditBox(const Window *w, int wid) const
int caret_width = GetStringBoundingBox("_").width;
DrawString(tb->caretxoffs + delta, tb->caretxoffs + delta + caret_width, 0, "_", TC_WHITE);
}
_cur_dpi = old_dpi;
}
/**
@@ -849,14 +827,14 @@ void QueryString::DrawEditBox(const Window *w, int wid) const
* @param wid Widget index.
* @return Top-left location of the caret, relative to the window.
*/
Point QueryString::GetCaretPosition(const Window *w, int wid) const
Point QueryString::GetCaretPosition(const Window *w, WidgetID wid) const
{
const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
assert((wi->type & WWT_MASK) == WWT_EDITBOX);
bool rtl = _current_text_dir == TD_RTL;
Dimension sprite_size = GetSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
Dimension sprite_size = GetScaledSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal();
Rect r = wi->GetCurrentRect().Indent(clearbtn_width, !rtl).Shrink(WidgetDimensions::scaled.framerect);
@@ -878,14 +856,14 @@ Point QueryString::GetCaretPosition(const Window *w, int wid) const
* @param to End of the string range.
* @return Rectangle encompassing the string range, relative to the window.
*/
Rect QueryString::GetBoundingRect(const Window *w, int wid, const char *from, const char *to) const
Rect QueryString::GetBoundingRect(const Window *w, WidgetID wid, const char *from, const char *to) const
{
const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
assert((wi->type & WWT_MASK) == WWT_EDITBOX);
bool rtl = _current_text_dir == TD_RTL;
Dimension sprite_size = GetSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
Dimension sprite_size = GetScaledSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal();
Rect r = wi->GetCurrentRect().Indent(clearbtn_width, !rtl).Shrink(WidgetDimensions::scaled.framerect);
@@ -907,21 +885,21 @@ Rect QueryString::GetBoundingRect(const Window *w, int wid, const char *from, co
* @param w Window the edit box is in.
* @param wid Widget index.
* @param pt Position to test.
* @return Pointer to the character at the position or nullptr if no character is at the position.
* @return Index of the character position or -1 if no character is at the position.
*/
const char *QueryString::GetCharAtPosition(const Window *w, int wid, const Point &pt) const
ptrdiff_t QueryString::GetCharAtPosition(const Window *w, WidgetID wid, const Point &pt) const
{
const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
assert((wi->type & WWT_MASK) == WWT_EDITBOX);
bool rtl = _current_text_dir == TD_RTL;
Dimension sprite_size = GetSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
Dimension sprite_size = GetScaledSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal();
Rect r = wi->GetCurrentRect().Indent(clearbtn_width, !rtl).Shrink(WidgetDimensions::scaled.framerect);
if (!IsInsideMM(pt.y, r.top, r.bottom)) return nullptr;
if (!IsInsideMM(pt.y, r.top, r.bottom)) return -1;
/* Clamp caret position to be inside our current width. */
const Textbuf *tb = &this->text;
@@ -931,14 +909,14 @@ const char *QueryString::GetCharAtPosition(const Window *w, int wid, const Point
return ::GetCharAtPosition(tb->buf, pt.x - delta - r.left);
}
void QueryString::ClickEditBox(Window *w, Point pt, int wid, int click_count, bool focus_changed)
void QueryString::ClickEditBox(Window *w, Point pt, WidgetID wid, int click_count, bool focus_changed)
{
const NWidgetLeaf *wi = w->GetWidget<NWidgetLeaf>(wid);
assert((wi->type & WWT_MASK) == WWT_EDITBOX);
bool rtl = _current_text_dir == TD_RTL;
Dimension sprite_size = GetSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
Dimension sprite_size = GetScaledSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal();
Rect cr = wi->GetCurrentRect().WithWidth(clearbtn_width, !rtl);
@@ -970,19 +948,9 @@ struct QueryStringWindow : public Window
QueryStringWindow(StringID str, StringID caption, uint max_bytes, uint max_chars, WindowDesc *desc, Window *parent, CharSetFilter afilter, QueryStringFlags flags) :
Window(desc), editbox(max_bytes, max_chars)
{
char *last_of = &this->editbox.text.buf[this->editbox.text.max_bytes - 1];
GetString(this->editbox.text.buf, str, last_of);
StrMakeValidInPlace(this->editbox.text.buf, last_of, SVS_NONE);
this->editbox.text.Assign(str);
/* Make sure the name isn't too long for the text buffer in the number of
* characters (not bytes). max_chars also counts the '\0' characters. */
while (Utf8StringLength(this->editbox.text.buf) + 1 > this->editbox.text.max_chars) {
*Utf8PrevChar(this->editbox.text.buf + strlen(this->editbox.text.buf)) = '\0';
}
this->editbox.text.UpdateSize();
if ((flags & QSF_ACCEPT_UNCHANGED) == 0) this->editbox.orig = stredup(this->editbox.text.buf);
if ((flags & QSF_ACCEPT_UNCHANGED) == 0) this->editbox.orig = this->editbox.text.buf;
this->querystrings[WID_QS_TEXT] = &this->editbox;
this->editbox.caption = caption;
@@ -1013,7 +981,7 @@ struct QueryStringWindow : public Window
this->ReInit();
}
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
{
if (widget == WID_QS_DEFAULT && (this->flags & QSF_ENABLE_DEFAULT) == 0) {
/* We don't want this widget to show! */
@@ -1027,7 +995,7 @@ struct QueryStringWindow : public Window
}
}
void DrawWidget(const Rect &r, int widget) const override
void DrawWidget(const Rect &r, WidgetID widget) const override
{
if (widget != WID_QS_WARNING) return;
@@ -1037,14 +1005,14 @@ struct QueryStringWindow : public Window
}
}
void SetStringParameters(int widget) const override
void SetStringParameters(WidgetID widget) const override
{
if (widget == WID_QS_CAPTION) SetDParam(0, this->editbox.caption);
}
void OnOk()
{
if (this->editbox.orig == nullptr || strcmp(this->editbox.text.buf, this->editbox.orig) != 0) {
if (!this->editbox.orig.has_value() || this->editbox.text.buf != this->editbox.orig) {
assert(this->parent != nullptr);
this->parent->OnQueryTextFinished(this->editbox.text.buf);
@@ -1052,16 +1020,16 @@ struct QueryStringWindow : public Window
}
}
void OnClick(Point pt, int widget, int click_count) override
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
switch (widget) {
case WID_QS_DEFAULT:
this->editbox.text.DeleteAll();
FALLTHROUGH;
[[fallthrough]];
case WID_QS_OK:
this->OnOk();
FALLTHROUGH;
[[fallthrough]];
case WID_QS_CANCEL:
this->Close();
@@ -1069,7 +1037,7 @@ struct QueryStringWindow : public Window
}
}
void Close() override
void Close([[maybe_unused]] int data = 0) override
{
if (!this->editbox.handled && this->parent != nullptr) {
Window *parent = this->parent;
@@ -1080,10 +1048,10 @@ struct QueryStringWindow : public Window
}
};
static const NWidgetPart _nested_query_string_widgets[] = {
static constexpr NWidgetPart _nested_query_string_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
NWidget(WWT_CAPTION, COLOUR_GREY, WID_QS_CAPTION), SetDataTip(STR_WHITE_STRING, STR_NULL),
NWidget(WWT_CAPTION, COLOUR_GREY, WID_QS_CAPTION), SetDataTip(STR_JUST_STRING, STR_NULL), SetTextStyle(TC_WHITE),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY),
NWidget(WWT_EDITBOX, COLOUR_GREY, WID_QS_TEXT), SetMinimalSize(256, 12), SetFill(1, 1), SetPadding(2, 2, 2, 2),
@@ -1096,11 +1064,11 @@ static const NWidgetPart _nested_query_string_widgets[] = {
EndContainer(),
};
static WindowDesc _query_string_desc(
WDP_CENTER, "query_string", 0, 0,
static WindowDesc _query_string_desc(__FILE__, __LINE__,
WDP_CENTER, nullptr, 0, 0,
WC_QUERY_STRING, WC_NONE,
0,
_nested_query_string_widgets, lengthof(_nested_query_string_widgets)
std::begin(_nested_query_string_widgets), std::end(_nested_query_string_widgets)
);
/**
@@ -1125,30 +1093,30 @@ void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *paren
*/
struct QueryWindow : public Window {
QueryCallbackProc *proc; ///< callback function executed on closing of popup. Window* points to parent, bool is true if 'yes' clicked, false otherwise
uint64 params[10]; ///< local copy of #_global_string_params
std::vector<StringParameterBackup> params; ///< local copy of #_global_string_params
StringID message; ///< message shown for query window
StringID caption; ///< title of window
QueryWindow(WindowDesc *desc, StringID caption, StringID message, Window *parent, QueryCallbackProc *callback) : Window(desc)
{
/* Create a backup of the variadic arguments to strings because it will be
* overridden pretty often. We will copy these back for drawing */
CopyOutDParam(this->params, 0, lengthof(this->params));
this->caption = caption;
CopyOutDParam(this->params, 10);
this->message = message;
this->proc = callback;
this->parent = parent;
this->InitNested(WN_CONFIRM_POPUP_QUERY);
this->CreateNestedTree();
this->GetWidget<NWidgetCore>(WID_Q_CAPTION)->SetDataTip(caption, STR_NULL);
this->FinishInitNested(WN_CONFIRM_POPUP_QUERY);
}
void Close() override
void Close([[maybe_unused]] int data = 0) override
{
if (this->proc != nullptr) this->proc(this->parent, false);
this->Window::Close();
}
void FindWindowPlacementAndResize(int def_width, int def_height) override
void FindWindowPlacementAndResize([[maybe_unused]] int def_width, [[maybe_unused]] int def_height) override
{
/* Position query window over the calling window, ensuring it's within screen bounds. */
this->left = SoftClamp(parent->left + (parent->width / 2) - (this->width / 2), 0, _screen.width - this->width);
@@ -1156,39 +1124,31 @@ struct QueryWindow : public Window {
this->SetDirty();
}
void SetStringParameters(int widget) const override
void SetStringParameters(WidgetID widget) const override
{
switch (widget) {
case WID_Q_CAPTION:
CopyInDParam(1, this->params, lengthof(this->params));
SetDParam(0, this->caption);
break;
case WID_Q_TEXT:
CopyInDParam(0, this->params, lengthof(this->params));
CopyInDParam(this->params);
break;
}
}
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override
{
if (widget != WID_Q_TEXT) return;
Dimension d = GetStringMultiLineBoundingBox(this->message, *size);
d.width += WidgetDimensions::scaled.frametext.Horizontal();
d.height += WidgetDimensions::scaled.framerect.Vertical();
*size = d;
*size = GetStringMultiLineBoundingBox(this->message, *size);
}
void DrawWidget(const Rect &r, int widget) const override
void DrawWidget(const Rect &r, WidgetID widget) const override
{
if (widget != WID_Q_TEXT) return;
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect),
this->message, TC_FROMSTRING, SA_CENTER);
DrawStringMultiLine(r, this->message, TC_FROMSTRING, SA_CENTER);
}
void OnClick(Point pt, int widget, int click_count) override
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
switch (widget) {
case WID_Q_YES: {
@@ -1211,7 +1171,7 @@ struct QueryWindow : public Window {
}
}
EventState OnKeyPress(WChar key, uint16 keycode) override
EventState OnKeyPress([[maybe_unused]] char32_t key, uint16_t keycode) override
{
/* ESC closes the window, Enter confirms the action */
switch (keycode) {
@@ -1221,7 +1181,7 @@ struct QueryWindow : public Window {
this->proc(this->parent, true);
this->proc = nullptr;
}
FALLTHROUGH;
[[fallthrough]];
case WKC_ESC:
this->Close();
@@ -1231,10 +1191,10 @@ struct QueryWindow : public Window {
}
};
static const NWidgetPart _nested_query_widgets[] = {
static constexpr NWidgetPart _nested_query_widgets[] = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_RED),
NWidget(WWT_CAPTION, COLOUR_RED, WID_Q_CAPTION), SetDataTip(STR_JUST_STRING, STR_NULL),
NWidget(WWT_CAPTION, COLOUR_RED, WID_Q_CAPTION), // The caption's string is set in the constructor
EndContainer(),
NWidget(WWT_PANEL, COLOUR_RED),
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), SetPadding(WidgetDimensions::unscaled.modalpopup),
@@ -1247,25 +1207,26 @@ static const NWidgetPart _nested_query_widgets[] = {
EndContainer(),
};
static WindowDesc _query_desc(
static WindowDesc _query_desc(__FILE__, __LINE__,
WDP_CENTER, nullptr, 0, 0,
WC_CONFIRM_POPUP_QUERY, WC_NONE,
WDF_MODAL,
_nested_query_widgets, lengthof(_nested_query_widgets)
std::begin(_nested_query_widgets), std::end(_nested_query_widgets)
);
/**
* Show a modal confirmation window with standard 'yes' and 'no' buttons
* Show a confirmation window with standard 'yes' and 'no' buttons
* The window is aligned to the centre of its parent.
* @param caption string shown as window caption
* @param message string that will be shown for the window
* @param parent pointer to parent window, if this pointer is nullptr the parent becomes
* the main window WC_MAIN_WINDOW
* @param callback callback function pointer to set in the window descriptor
* @param focus whether the window should be focussed (by default false)
*/
void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallbackProc *callback)
void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallbackProc *callback, bool focus)
{
if (parent == nullptr) parent = FindWindowById(WC_MAIN_WINDOW, 0);
if (parent == nullptr) parent = GetMainWindow();
for (Window *w : Window::Iterate()) {
if (w->window_class != WC_CONFIRM_POPUP_QUERY) continue;
@@ -1277,5 +1238,6 @@ void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallback
break;
}
new QueryWindow(&_query_desc, caption, message, parent, callback);
QueryWindow *q = new QueryWindow(&_query_desc, caption, message, parent, callback);
if (focus) SetFocusedWindow(q);
}