Update to 14.0-beta1
This commit is contained in:
458
src/misc_gui.cpp
458
src/misc_gui.cpp
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user