OpenTTD Source 20260512-master-g20b387b91f
town_gui.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "stdafx.h"
11#include "town.h"
12#include "viewport_func.h"
13#include "error.h"
14#include "gui.h"
15#include "house.h"
16#include "newgrf_cargo.h"
17#include "newgrf_house.h"
18#include "newgrf_text.h"
19#include "picker_gui.h"
20#include "command_func.h"
21#include "company_func.h"
22#include "company_base.h"
23#include "company_gui.h"
24#include "network/network.h"
25#include "string_func.h"
26#include "strings_func.h"
27#include "sound_func.h"
28#include "tilehighlight_func.h"
29#include "sortlist_type.h"
30#include "road_cmd.h"
31#include "landscape.h"
32#include "querystring_gui.h"
33#include "window_func.h"
34#include "townname_func.h"
35#include "core/backup_type.hpp"
38#include "genworld.h"
39#include "fios.h"
40#include "stringfilter_type.h"
41#include "dropdown_func.h"
42#include "town_kdtree.h"
43#include "town_cmd.h"
44#include "timer/timer.h"
46#include "timer/timer_window.h"
47#include "zoom_func.h"
48#include "hotkeys.h"
49#include "graph_gui.h"
50
51#include "widgets/town_widget.h"
52
53#include "table/strings.h"
54
55#include "safeguards.h"
56
57TownKdtree _town_local_authority_kdtree{};
58
59typedef GUIList<const Town*, const bool &> GUITownList;
60
61static constexpr std::initializer_list<NWidgetPart> _nested_town_authority_widgets = {
65 NWidget(WWT_TEXTBTN, Colours::Brown, WID_TA_ZONE_BUTTON), SetMinimalSize(50, 0), SetStringTip(STR_LOCAL_AUTHORITY_ZONE, STR_LOCAL_AUTHORITY_ZONE_TOOLTIP),
71 NWidget(WWT_PANEL, Colours::Brown, WID_TA_COMMAND_LIST), SetMinimalSize(317, 52), SetResize(1, 0), SetToolTip(STR_LOCAL_AUTHORITY_ACTIONS_TOOLTIP), EndContainer(),
74 NWidget(WWT_PUSHTXTBTN, Colours::Brown, WID_TA_EXECUTE), SetMinimalSize(317, 12), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_LOCAL_AUTHORITY_DO_IT_BUTTON, STR_LOCAL_AUTHORITY_DO_IT_TOOLTIP),
77};
78
80struct TownAuthorityWindow : Window {
81private:
82 Town *town = nullptr;
85 TownActions enabled_actions{};
86 TownActions available_actions{};
87 std::array<StringID, to_underlying(TownAction::End)> action_tooltips{};
88
91
97 static TownActions GetEnabledActions()
98 {
99 TownActions enabled{};
100 enabled.Set();
101
102 if (!_settings_game.economy.fund_roads) enabled.Reset(TownAction::RoadRebuild);
103 if (!_settings_game.economy.fund_buildings) enabled.Reset(TownAction::FundBuildings);
104 if (!_settings_game.economy.exclusive_rights) enabled.Reset(TownAction::BuyRights);
105 if (!_settings_game.economy.bribe) enabled.Reset(TownAction::Bribe);
106
107 return enabled;
108 }
109
110public:
112 {
113 this->town = Town::Get(window_number);
114 this->enabled_actions = GetEnabledActions();
115
117 this->action_tooltips[0] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING;
118 this->action_tooltips[1] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING;
119 this->action_tooltips[2] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING;
120 this->action_tooltips[3] = realtime ? STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION_MINUTES : STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION_MONTHS;
121 this->action_tooltips[4] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY;
122 this->action_tooltips[5] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS;
123 this->action_tooltips[6] = realtime ? STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT_MINUTES : STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT_MONTHS;
124 this->action_tooltips[7] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE;
125
126 this->InitNested(window_number);
127 }
128
129 void OnInit() override
130 {
131 this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
132 this->exclusive_size = GetSpriteSize(SPR_EXCLUSIVE_TRANSPORT);
133 }
134
135 void OnPaint() override
136 {
137 this->available_actions = GetMaskOfTownActions(_local_company, this->town);
138 if (this->available_actions != displayed_actions_on_previous_painting) this->SetDirty();
139 displayed_actions_on_previous_painting = this->available_actions;
140
142 this->SetWidgetDisabledState(WID_TA_EXECUTE, (this->sel_action == TownAction::End) || !this->available_actions.Test(this->sel_action));
143
144 this->DrawWidgets();
145 if (!this->IsShaded())
146 {
147 this->DrawRatings();
148 this->DrawActions();
149 }
150 }
151
152 StringID GetRatingString(int rating) const
153 {
154 if (rating > RATING_EXCELLENT) return STR_CARGO_RATING_OUTSTANDING;
155 if (rating > RATING_VERYGOOD) return STR_CARGO_RATING_EXCELLENT;
156 if (rating > RATING_GOOD) return STR_CARGO_RATING_VERY_GOOD;
157 if (rating > RATING_MEDIOCRE) return STR_CARGO_RATING_GOOD;
158 if (rating > RATING_POOR) return STR_CARGO_RATING_MEDIOCRE;
159 if (rating > RATING_VERYPOOR) return STR_CARGO_RATING_POOR;
160 if (rating > RATING_APPALLING) return STR_CARGO_RATING_VERY_POOR;
161 return STR_CARGO_RATING_APPALLING;
162 }
163
166 {
167 Rect r = this->GetWidget<NWidgetBase>(WID_TA_RATING_INFO)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
168
169 int text_y_offset = (this->resize.step_height - GetCharacterHeight(FontSize::Normal)) / 2;
170 int icon_y_offset = (this->resize.step_height - this->icon_size.height) / 2;
171 int exclusive_y_offset = (this->resize.step_height - this->exclusive_size.height) / 2;
172
173 DrawString(r.left, r.right, r.top + text_y_offset, STR_LOCAL_AUTHORITY_COMPANY_RATINGS);
174 r.top += this->resize.step_height;
175
176 bool rtl = _current_text_dir == TD_RTL;
177 Rect icon = r.WithWidth(this->icon_size.width, rtl);
178 Rect exclusive = r.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal, rtl).WithWidth(this->exclusive_size.width, rtl);
179 Rect text = r.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal + this->exclusive_size.width + WidgetDimensions::scaled.hsep_normal, rtl);
180
181 /* Draw list of companies */
182 for (const Company *c : Company::Iterate()) {
183 if ((this->town->have_ratings.Test(c->index) || this->town->exclusivity == c->index)) {
184 DrawCompanyIcon(c->index, icon.left, text.top + icon_y_offset);
185
186 if (this->town->exclusivity == c->index) {
187 DrawSprite(SPR_EXCLUSIVE_TRANSPORT, GetCompanyPalette(c->index), exclusive.left, text.top + exclusive_y_offset);
188 }
189
190 int rating = this->town->ratings[c->index];
191 DrawString(text.left, text.right, text.top + text_y_offset, GetString(STR_LOCAL_AUTHORITY_COMPANY_RATING, c->index, c->index, GetRatingString(rating)));
192 text.top += this->resize.step_height;
193 }
194 }
195
196 text.bottom = text.top - 1;
197 if (text.bottom > r.bottom) {
198 /* If the company list is too big to fit, mark ourself dirty and draw again. */
199 ResizeWindow(this, 0, text.bottom - r.bottom, false);
200 }
201 }
202
205 {
206 Rect r = this->GetWidget<NWidgetBase>(WID_TA_COMMAND_LIST)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
207
208 DrawString(r, STR_LOCAL_AUTHORITY_ACTIONS_TITLE);
210
211 /* Draw list of actions */
212 for (TownAction i = {}; i != TownAction::End; ++i) {
213 /* Don't show actions if disabled in settings. */
214 if (!this->enabled_actions.Test(i)) continue;
215
216 /* Set colour of action based on ability to execute and if selected. */
217 TextColour action_colour = TC_GREY | TC_NO_SHADE;
218 if (this->available_actions.Test(i)) action_colour = TC_ORANGE;
219 if (this->sel_action == i) action_colour = TC_WHITE;
220
221 DrawString(r, STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i), action_colour);
223 }
224 }
225
226 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
227 {
228 if (widget == WID_TA_CAPTION) return GetString(STR_LOCAL_AUTHORITY_CAPTION, this->window_number);
229
230 return this->Window::GetWidgetString(widget, stringid);
231 }
232
233 void DrawWidget(const Rect &r, WidgetID widget) const override
234 {
235 switch (widget) {
237 if (this->sel_action != TownAction::End) {
238 Money action_cost = _price[Price::TownAction] * GetTownActionCost(this->sel_action) >> 8;
239 bool affordable = Company::IsValidID(_local_company) && action_cost < GetAvailableMoney(_local_company);
240
242 GetString(this->action_tooltips[to_underlying(this->sel_action)], action_cost),
243 affordable ? TC_YELLOW : TC_RED);
244 }
245 break;
246 }
247 }
248
249 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
250 {
251 switch (widget) {
252 case WID_TA_ACTION_INFO: {
253 assert(size.width > padding.width && size.height > padding.height);
254 Dimension d = {0, 0};
255 for (TownAction i = {}; i != TownAction::End; ++i) {
256 Money price = _price[Price::TownAction] * GetTownActionCost(i) >> 8;
257 d = maxdim(d, GetStringMultiLineBoundingBox(GetString(this->action_tooltips[to_underlying(i)], price), size));
258 }
259 d.width += padding.width;
260 d.height += padding.height;
261 size = maxdim(size, d);
262 break;
263 }
264
266 size.height = (to_underlying(TownAction::End) + 1) * GetCharacterHeight(FontSize::Normal) + padding.height;
267 size.width = GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTIONS_TITLE).width;
268 for (TownAction i = {}; i != TownAction::End; ++i) {
269 size.width = std::max(size.width, GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i)).width + padding.width);
270 }
271 size.width += padding.width;
272 break;
273
275 fill.height = resize.height = std::max({this->icon_size.height + WidgetDimensions::scaled.vsep_normal, this->exclusive_size.height + WidgetDimensions::scaled.vsep_normal, (uint)GetCharacterHeight(FontSize::Normal)});
276 size.height = 9 * resize.height + padding.height;
277 break;
278 }
279 }
280
281 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
282 {
283 switch (widget) {
284 case WID_TA_ZONE_BUTTON: {
285 bool new_show_state = !this->town->show_zone;
286 TownID index = this->town->index;
287
288 new_show_state ? _town_local_authority_kdtree.Insert(index) : _town_local_authority_kdtree.Remove(index);
289
290 this->town->show_zone = new_show_state;
291 this->SetWidgetLoweredState(widget, new_show_state);
292 SndClickBeep();
294 break;
295 }
296
297 case WID_TA_COMMAND_LIST: {
299
300 auto action = this->enabled_actions.GetNthSetBit(y);
301 if (!action.has_value()) break;
302
303 this->sel_action = *action;
304 this->SetDirty();
305
306 /* When double-clicking, continue */
307 if (click_count == 1 || !this->available_actions.Test(this->sel_action)) break;
308 [[fallthrough]];
309 }
310
311 case WID_TA_EXECUTE:
312 Command<Commands::TownAction>::Post(STR_ERROR_CAN_T_DO_THIS, this->town->xy, static_cast<TownID>(this->window_number), this->sel_action);
313 break;
314 }
315 }
316
318 const IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
319 this->SetDirty();
320 }};
321
322 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
323 {
324 if (!gui_scope) return;
325
326 this->enabled_actions = this->GetEnabledActions();
327 if (!this->enabled_actions.Test(this->sel_action)) {
328 this->sel_action = TownAction::End;
329 }
330 }
331};
332
335 WindowPosition::Automatic, "view_town_authority", 317, 222,
337 {},
338 _nested_town_authority_widgets
339);
340
341static void ShowTownAuthorityWindow(uint town)
342{
344}
345
346
348struct TownViewWindow : Window {
349private:
350 Town *town = nullptr;
351
352public:
353 static const int WID_TV_HEIGHT_NORMAL = 150;
354
355 TownViewWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
356 {
357 this->CreateNestedTree();
358
359 this->town = Town::Get(window_number);
360
361 this->FinishInitNested(window_number);
362
365 nvp->InitializeViewport(this, this->town->xy, ScaleZoomGUI(ZoomLevel::Town));
366
367 /* disable renaming town in network games if you are not the server */
369 }
370
371 void Close([[maybe_unused]] int data = 0) override
372 {
374 this->Window::Close();
375 }
376
377 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
378 {
379 if (widget == WID_TV_CAPTION) return GetString(this->town->larger_town ? STR_TOWN_VIEW_CITY_CAPTION : STR_TOWN_VIEW_TOWN_CAPTION, this->town->index);
380
381 return this->Window::GetWidgetString(widget, stringid);
382 }
383
384 void OnPaint() override
385 {
386 extern const Town *_viewport_highlight_town;
388
389 this->DrawWidgets();
390 }
391
392 void DrawWidget(const Rect &r, WidgetID widget) const override
393 {
394 if (widget != WID_TV_INFO) return;
395
396 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
397
398 DrawString(tr, GetString(STR_TOWN_VIEW_POPULATION_HOUSES, this->town->cache.population, this->town->cache.num_houses));
400
401 StringID str_last_period = TimerGameEconomy::UsingWallclockUnits() ? STR_TOWN_VIEW_CARGO_LAST_MINUTE_MAX : STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX;
402
404 for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) {
405 CargoType cargo_type = cs->Index();
406 auto it = this->town->GetCargoSupplied(cargo_type);
407 if (it == std::end(this->town->supplied)) {
408 DrawString(tr, GetString(str_last_period, 1ULL << cargo_type, 0, 0));
409 } else {
410 DrawString(tr, GetString(str_last_period, 1ULL << cargo_type, it->history[LAST_MONTH].transported, it->history[LAST_MONTH].production));
411 }
413 }
414 }
415
416 bool first = true;
418 if (this->town->goal[i] == 0) continue;
419 if (this->town->goal[i] == TOWN_GROWTH_WINTER && (TileHeight(this->town->xy) < LowestSnowLine() || this->town->cache.population <= 90)) continue;
420 if (this->town->goal[i] == TOWN_GROWTH_DESERT && (GetTropicZone(this->town->xy) != TropicZone::Desert || this->town->cache.population <= 60)) continue;
421
422 if (first) {
423 DrawString(tr, STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH);
425 first = false;
426 }
427
428 bool rtl = _current_text_dir == TD_RTL;
429
431 assert(cargo != nullptr);
432
433 StringID string;
434
435 if (this->town->goal[i] == TOWN_GROWTH_DESERT || this->town->goal[i] == TOWN_GROWTH_WINTER) {
436 /* For 'original' gameplay, don't show the amount required (you need 1 or more ..) */
437 string = STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED_GENERAL;
438 if (this->town->received[i].old_act == 0) {
439 string = STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL;
440
441 if (this->town->goal[i] == TOWN_GROWTH_WINTER && TileHeight(this->town->xy) < GetSnowLine()) {
442 string = STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER;
443 }
444 }
445
446 DrawString(tr.Indent(20, rtl), GetString(string, cargo->name));
447 } else {
448 string = STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED;
449 if (this->town->received[i].old_act < this->town->goal[i]) {
450 string = STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED;
451 }
452 DrawString(tr.Indent(20, rtl), GetString(string, cargo->Index(), this->town->received[i].old_act, cargo->Index(), this->town->goal[i]));
453 }
455 }
456
457 if (this->town->flags.Test(TownFlag::IsGrowing)) {
458 DrawString(tr, GetString(this->town->fund_buildings_months == 0 ? STR_TOWN_VIEW_TOWN_GROWS_EVERY : STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED, RoundDivSU(this->town->growth_rate + 1, Ticks::DAY_TICKS)));
460 } else {
461 DrawString(tr, STR_TOWN_VIEW_TOWN_GROW_STOPPED);
463 }
464
465 /* only show the town noise, if the noise option is activated. */
466 if (_settings_game.economy.station_noise_level) {
467 DrawString(tr, GetString(STR_TOWN_VIEW_NOISE_IN_TOWN, this->town->noise_reached, this->town->MaxTownNoise()));
469 }
470
471 if (!this->town->text.empty()) {
472 tr.top = DrawStringMultiLine(tr, this->town->text.GetDecodedString(), TC_BLACK);
473 }
474 }
475
476 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
477 {
478 switch (widget) {
479 case WID_TV_CENTER_VIEW: // scroll to location
480 if (_ctrl_pressed) {
481 ShowExtraViewportWindow(this->town->xy);
482 } else {
483 ScrollMainWindowToTile(this->town->xy);
484 }
485 break;
486
487 case WID_TV_SHOW_AUTHORITY: // town authority
488 ShowTownAuthorityWindow(this->window_number);
489 break;
490
491 case WID_TV_CHANGE_NAME: // rename
493 break;
494
495 case WID_TV_CATCHMENT:
497 break;
498
499 case WID_TV_EXPAND: // expand town - only available on Scenario editor
500 Command<Commands::ExpandTown>::Post(STR_ERROR_CAN_T_EXPAND_TOWN, static_cast<TownID>(this->window_number), 0, {TownExpandMode::Buildings, TownExpandMode::Roads});
501 break;
502
503 case WID_TV_EXPAND_BUILDINGS: // expand buildings of town - only available on Scenario editor
504 Command<Commands::ExpandTown>::Post(STR_ERROR_CAN_T_EXPAND_TOWN, static_cast<TownID>(this->window_number), 0, {TownExpandMode::Buildings});
505 break;
506
507 case WID_TV_EXPAND_ROADS: // expand roads of town - only available on Scenario editor
508 Command<Commands::ExpandTown>::Post(STR_ERROR_CAN_T_EXPAND_TOWN, static_cast<TownID>(this->window_number), 0, {TownExpandMode::Roads});
509 break;
510
511 case WID_TV_DELETE: // delete town - only available on Scenario editor
512 Command<Commands::DeleteTown>::Post(STR_ERROR_TOWN_CAN_T_DELETE, static_cast<TownID>(this->window_number));
513 break;
514
515 case WID_TV_GRAPH: {
516 ShowTownCargoGraph(this->window_number);
517 break;
518 }
519 }
520 }
521
522 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
523 {
524 switch (widget) {
525 case WID_TV_INFO:
526 size.height = GetDesiredInfoHeight(size.width) + padding.height;
527 break;
528 }
529 }
530
537 {
539
540 bool first = true;
542 if (this->town->goal[i] == 0) continue;
543 if (this->town->goal[i] == TOWN_GROWTH_WINTER && (TileHeight(this->town->xy) < LowestSnowLine() || this->town->cache.population <= 90)) continue;
544 if (this->town->goal[i] == TOWN_GROWTH_DESERT && (GetTropicZone(this->town->xy) != TropicZone::Desert || this->town->cache.population <= 60)) continue;
545
546 if (first) {
547 aimed_height += GetCharacterHeight(FontSize::Normal);
548 first = false;
549 }
550 aimed_height += GetCharacterHeight(FontSize::Normal);
551 }
552 aimed_height += GetCharacterHeight(FontSize::Normal);
553
554 if (_settings_game.economy.station_noise_level) aimed_height += GetCharacterHeight(FontSize::Normal);
555
556 if (!this->town->text.empty()) {
557 aimed_height += GetStringHeight(this->town->text.GetDecodedString(), width - WidgetDimensions::scaled.framerect.Horizontal());
558 }
559
560 return aimed_height;
561 }
562
563 void ResizeWindowAsNeeded()
564 {
565 const NWidgetBase *nwid_info = this->GetWidget<NWidgetBase>(WID_TV_INFO);
566 uint aimed_height = GetDesiredInfoHeight(nwid_info->current_x);
567 if (aimed_height > nwid_info->current_y || (aimed_height < nwid_info->current_y && nwid_info->current_y > nwid_info->smallest_y)) {
568 this->ReInit();
569 }
570 }
571
572 void OnResize() override
573 {
574 if (this->viewport != nullptr) {
576 nvp->UpdateViewportCoordinates(this);
577
578 ScrollWindowToTile(this->town->xy, this, true); // Re-center viewport.
579 }
580 }
581
582 void OnMouseWheel(int wheel, WidgetID widget) override
583 {
584 if (widget != WID_TV_VIEWPORT) return;
585 if (_settings_client.gui.scrollwheel_scrolling != ScrollWheelScrolling::Off) {
586 DoZoomInOutWindow(wheel < 0 ? ZOOM_IN : ZOOM_OUT, this);
587 }
588 }
589
595 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
596 {
597 if (!gui_scope) return;
598 /* Called when setting station noise or required cargoes have changed, in order to resize the window */
599 this->SetDirty(); // refresh display for current size. This will allow to avoid glitches when downgrading
600 this->ResizeWindowAsNeeded();
601 }
602
603 void OnQueryTextFinished(std::optional<std::string> str) override
604 {
605 if (!str.has_value()) return;
606
607 Command<Commands::RenameTown>::Post(STR_ERROR_CAN_T_RENAME_TOWN, static_cast<TownID>(this->window_number), *str);
608 }
609
610 const IntervalTimer<TimerGameCalendar> daily_interval = {{TimerGameCalendar::Trigger::Day, TimerGameCalendar::Priority::None}, [this](auto) {
611 /* Refresh after possible snowline change */
612 this->SetDirty();
613 }};
614};
615
616static constexpr std::initializer_list<NWidgetPart> _nested_town_game_view_widgets = {
619 NWidget(WWT_PUSHIMGBTN, Colours::Brown, WID_TV_CHANGE_NAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME, STR_TOWN_VIEW_RENAME_TOOLTIP),
621 NWidget(WWT_PUSHIMGBTN, Colours::Brown, WID_TV_CENTER_VIEW), SetAspect(WidgetDimensions::ASPECT_LOCATION), SetSpriteTip(SPR_GOTO_LOCATION, STR_TOWN_VIEW_CENTER_TOOLTIP),
625 EndContainer(),
629 EndContainer(),
630 EndContainer(),
633 NWidget(WWT_PUSHTXTBTN, Colours::Brown, WID_TV_SHOW_AUTHORITY), SetMinimalSize(80, 12), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON, STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP),
634 NWidget(WWT_TEXTBTN, Colours::Brown, WID_TV_CATCHMENT), SetMinimalSize(40, 12), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_BUTTON_CATCHMENT, STR_TOOLTIP_CATCHMENT),
635 NWidget(WWT_PUSHTXTBTN, Colours::Brown, WID_TV_GRAPH), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_CARGO_GRAPH, STR_TOWN_VIEW_CARGO_GRAPH_TOOLTIP),
637 EndContainer(),
638};
639
642 WindowPosition::Automatic, "view_town", 260, TownViewWindow::WID_TV_HEIGHT_NORMAL,
644 {},
645 _nested_town_game_view_widgets
646);
647
648static constexpr std::initializer_list<NWidgetPart> _nested_town_editor_view_widgets = {
651 NWidget(WWT_PUSHIMGBTN, Colours::Brown, WID_TV_CHANGE_NAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME, STR_TOWN_VIEW_RENAME_TOOLTIP),
652 NWidget(WWT_CAPTION, Colours::Brown, WID_TV_CAPTION), SetToolTip(STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
653 NWidget(WWT_PUSHIMGBTN, Colours::Brown, WID_TV_CENTER_VIEW), SetAspect(WidgetDimensions::ASPECT_LOCATION), SetSpriteTip(SPR_GOTO_LOCATION, STR_TOWN_VIEW_CENTER_TOOLTIP),
657 EndContainer(),
661 EndContainer(),
662 EndContainer(),
665 NWidget(WWT_PUSHTXTBTN, Colours::Brown, WID_TV_EXPAND), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_EXPAND_BUTTON, STR_TOWN_VIEW_EXPAND_TOOLTIP),
666 NWidget(WWT_PUSHTXTBTN, Colours::Brown, WID_TV_EXPAND_BUILDINGS), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_EXPAND_BUILDINGS_BUTTON, STR_TOWN_VIEW_EXPAND_BUILDINGS_TOOLTIP),
667 NWidget(WWT_PUSHTXTBTN, Colours::Brown, WID_TV_EXPAND_ROADS), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_EXPAND_ROADS_BUTTON, STR_TOWN_VIEW_EXPAND_ROADS_TOOLTIP),
668 EndContainer(),
670 NWidget(WWT_PUSHTXTBTN, Colours::Brown, WID_TV_DELETE), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_DELETE_BUTTON, STR_TOWN_VIEW_DELETE_TOOLTIP),
671 NWidget(WWT_TEXTBTN, Colours::Brown, WID_TV_CATCHMENT), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_BUTTON_CATCHMENT, STR_TOOLTIP_CATCHMENT),
673 EndContainer(),
674};
675
678 WindowPosition::Automatic, "view_town_scen", 260, TownViewWindow::WID_TV_HEIGHT_NORMAL,
680 {},
681 _nested_town_editor_view_widgets
682);
683
684void ShowTownViewWindow(TownID town)
685{
686 if (_game_mode == GM_EDITOR) {
688 } else {
690 }
691}
692
693static constexpr std::initializer_list<NWidgetPart> _nested_town_directory_widgets = {
700 EndContainer(),
704 NWidget(WWT_TEXTBTN, Colours::Brown, WID_TD_SORT_ORDER), SetStringTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
706 NWidget(WWT_EDITBOX, Colours::Brown, WID_TD_FILTER), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
707 EndContainer(),
708 NWidget(WWT_PANEL, Colours::Brown, WID_TD_LIST), SetToolTip(STR_TOWN_DIRECTORY_LIST_TOOLTIP),
712 EndContainer(),
713 EndContainer(),
717 EndContainer(),
718 EndContainer(),
719};
720
722struct TownDirectoryWindow : public Window {
723private:
725 static Listing last_sorting;
726
728 static inline const StringID sorter_names[] = {
729 STR_SORT_BY_NAME,
730 STR_SORT_BY_POPULATION,
731 STR_SORT_BY_RATING,
732 };
733 static const std::initializer_list<GUITownList::SortFunction * const> sorter_funcs;
734
737
738 GUITownList towns{TownDirectoryWindow::last_sorting.order};
739
740 Scrollbar *vscroll = nullptr;
741
742 void BuildSortTownList()
743 {
744 if (this->towns.NeedRebuild()) {
745 this->towns.clear();
746 this->towns.reserve(Town::GetNumItems());
747
748 for (const Town *t : Town::Iterate()) {
749 if (this->string_filter.IsEmpty()) {
750 this->towns.push_back(t);
751 continue;
752 }
753 this->string_filter.ResetState();
754 this->string_filter.AddLine(t->GetCachedName());
755 if (this->string_filter.GetState()) this->towns.push_back(t);
756 }
757
758 this->towns.RebuildDone();
759 this->vscroll->SetCount(this->towns.size()); // Update scrollbar as well.
760 }
761 /* Always sort the towns. */
762 this->towns.Sort();
763 this->SetWidgetDirty(WID_TD_LIST); // Force repaint of the displayed towns.
764 }
765
767 static bool TownNameSorter(const Town * const &a, const Town * const &b, [[maybe_unused]] const bool &filter)
768 {
769 return StrNaturalCompare(a->GetCachedName(), b->GetCachedName()) < 0; // Sort by name (natural sorting).
770 }
771
773 static bool TownPopulationSorter(const Town * const &a, const Town * const &b, const bool &filter)
774 {
775 uint32_t a_population = a->cache.population;
776 uint32_t b_population = b->cache.population;
777 if (a_population == b_population) return TownDirectoryWindow::TownNameSorter(a, b, filter);
778 return a_population < b_population;
779 }
780
782 static bool TownRatingSorter(const Town * const &a, const Town * const &b, const bool &filter)
783 {
784 bool before = !filter; // Value to get 'a' before 'b'.
785
786 /* Towns without rating are always after towns with rating. */
789 int16_t a_rating = a->ratings[_local_company];
790 int16_t b_rating = b->ratings[_local_company];
791 if (a_rating == b_rating) return TownDirectoryWindow::TownNameSorter(a, b, filter);
792 return a_rating < b_rating;
793 }
794 return before;
795 }
796 if (b->have_ratings.Test(_local_company)) return !before;
797
798 /* Sort unrated towns always on ascending town name. */
799 if (before) return TownDirectoryWindow::TownNameSorter(a, b, filter);
800 return TownDirectoryWindow::TownNameSorter(b, a, filter);
801 }
802
803public:
805 {
806 this->CreateNestedTree();
807
808 this->vscroll = this->GetScrollbar(WID_TD_SCROLLBAR);
809
810 this->towns.SetListing(this->last_sorting);
812 this->towns.ForceRebuild();
813 this->BuildSortTownList();
814
815 this->FinishInitNested(0);
816
817 this->querystrings[WID_TD_FILTER] = &this->townname_editbox;
818 this->townname_editbox.cancel_button = QueryString::ACTION_CLEAR;
819 }
820
821 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
822 {
823 switch (widget) {
824 case WID_TD_CAPTION:
825 return GetString(STR_TOWN_DIRECTORY_CAPTION, this->vscroll->GetCount(), Town::GetNumItems());
826
828 return GetString(STR_TOWN_POPULATION, GetWorldPopulation());
829
832
833 default:
834 return this->Window::GetWidgetString(widget, stringid);
835 }
836 }
837
844 static std::string GetTownString(const Town *t, uint64_t population)
845 {
846 return GetString(t->larger_town ? STR_TOWN_DIRECTORY_CITY : STR_TOWN_DIRECTORY_TOWN, t->index, population);
847 }
848
849 void DrawWidget(const Rect &r, WidgetID widget) const override
850 {
851 switch (widget) {
853 this->DrawSortButtonState(widget, this->towns.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
854 break;
855
856 case WID_TD_LIST: {
857 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
858 if (this->towns.empty()) { // No towns available.
859 DrawString(tr, STR_TOWN_DIRECTORY_NONE);
860 break;
861 }
862
863 /* At least one town available. */
864 bool rtl = _current_text_dir == TD_RTL;
865 Dimension icon_size = GetSpriteSize(SPR_TOWN_RATING_GOOD);
866 int icon_x = tr.WithWidth(icon_size.width, rtl).left;
867 tr = tr.Indent(icon_size.width + WidgetDimensions::scaled.hsep_normal, rtl);
868
869 auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->towns);
870 for (auto it = first; it != last; ++it) {
871 const Town *t = *it;
872 assert(t->xy != INVALID_TILE);
873
874 /* Draw rating icon. */
875 if (_game_mode == GM_EDITOR || !t->have_ratings.Test(_local_company)) {
876 DrawSprite(SPR_TOWN_RATING_NA, PAL_NONE, icon_x, tr.top + (this->resize.step_height - icon_size.height) / 2);
877 } else {
878 SpriteID icon = SPR_TOWN_RATING_APPALLING;
879 if (t->ratings[_local_company] > RATING_VERYPOOR) icon = SPR_TOWN_RATING_MEDIOCRE;
880 if (t->ratings[_local_company] > RATING_GOOD) icon = SPR_TOWN_RATING_GOOD;
881 DrawSprite(icon, PAL_NONE, icon_x, tr.top + (this->resize.step_height - icon_size.height) / 2);
882 }
883
884 DrawString(tr.left, tr.right, tr.top + (this->resize.step_height - GetCharacterHeight(FontSize::Normal)) / 2, GetTownString(t, t->cache.population));
885
886 tr.top += this->resize.step_height;
887 }
888 break;
889 }
890 }
891 }
892
893 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
894 {
895 switch (widget) {
896 case WID_TD_SORT_ORDER: {
898 d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
899 d.height += padding.height;
900 size = maxdim(size, d);
901 break;
902 }
905 d.width += padding.width;
906 d.height += padding.height;
907 size = maxdim(size, d);
908 break;
909 }
910 case WID_TD_LIST: {
911 Dimension d = GetStringBoundingBox(STR_TOWN_DIRECTORY_NONE);
912 uint64_t max_value = GetParamMaxDigits(8);
913 for (uint i = 0; i < this->towns.size(); i++) {
914 const Town *t = this->towns[i];
915
916 assert(t != nullptr);
917
918 d = maxdim(d, GetStringBoundingBox(GetTownString(t, max_value)));
919 }
920 Dimension icon_size = GetSpriteSize(SPR_TOWN_RATING_GOOD);
921 d.width += icon_size.width + 2;
922 d.height = std::max(d.height, icon_size.height);
923 fill.height = resize.height = d.height;
924 d.height *= 5;
925 d.width += padding.width;
926 d.height += padding.height;
927 size = maxdim(size, d);
928 break;
929 }
931 Dimension d = GetStringBoundingBox(GetString(STR_TOWN_POPULATION, GetParamMaxDigits(10)));
932 d.width += padding.width;
933 d.height += padding.height;
934 size = maxdim(size, d);
935 break;
936 }
937 }
938 }
939
940 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
941 {
942 switch (widget) {
943 case WID_TD_SORT_ORDER: // Click on sort order button
944 if (this->towns.SortType() != 2) { // A different sort than by rating.
945 this->towns.ToggleSortOrder();
946 this->last_sorting = this->towns.GetListing(); // Store new sorting order.
947 } else {
948 /* Some parts are always sorted ascending on name. */
949 this->last_sorting.order = !this->last_sorting.order;
950 this->towns.SetListing(this->last_sorting);
951 this->towns.ForceResort();
952 this->towns.Sort();
953 }
954 this->SetDirty();
955 break;
956
957 case WID_TD_SORT_CRITERIA: // Click on sort criteria dropdown
959 break;
960
961 case WID_TD_LIST: { // Click on Town Matrix
962 auto it = this->vscroll->GetScrolledItemFromWidget(this->towns, pt.y, this, WID_TD_LIST, WidgetDimensions::scaled.framerect.top);
963 if (it == this->towns.end()) return; // click out of town bounds
964
965 const Town *t = *it;
966 assert(t != nullptr);
967 if (_ctrl_pressed) {
969 } else {
971 }
972 break;
973 }
974 }
975 }
976
977 void OnDropdownSelect(WidgetID widget, int index, int) override
978 {
979 if (widget != WID_TD_SORT_CRITERIA) return;
980
981 if (this->towns.SortType() != index) {
982 this->towns.SetSortType(index);
983 this->last_sorting = this->towns.GetListing(); // Store new sorting order.
984 this->BuildSortTownList();
985 }
986 }
987
988 void OnPaint() override
989 {
990 if (this->towns.NeedRebuild()) this->BuildSortTownList();
991 this->DrawWidgets();
992 }
993
995 const IntervalTimer<TimerWindow> rebuild_interval = {std::chrono::seconds(3), [this](auto) {
996 this->BuildSortTownList();
997 this->SetDirty();
998 }};
999
1000 void OnResize() override
1001 {
1002 this->vscroll->SetCapacityFromWidget(this, WID_TD_LIST, WidgetDimensions::scaled.framerect.Vertical());
1003 }
1004
1005 void OnEditboxChanged(WidgetID wid) override
1006 {
1007 if (wid == WID_TD_FILTER) {
1008 this->string_filter.SetFilterTerm(this->townname_editbox.text.GetText());
1009 this->InvalidateData(TDIWD_FORCE_REBUILD);
1010 }
1011 }
1012
1018 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1019 {
1020 switch (data) {
1021 case TDIWD_FORCE_REBUILD:
1022 /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
1023 this->towns.ForceRebuild();
1024 break;
1025
1026 case TDIWD_POPULATION_CHANGE:
1027 if (this->towns.SortType() == 1) this->towns.ForceResort();
1028 break;
1029
1030 default:
1031 this->towns.ForceResort();
1032 }
1033 }
1034
1035 static inline HotkeyList hotkeys {"towndirectory", {
1036 Hotkey('F', "focus_filter_box", WID_TD_FILTER),
1037 }};
1038};
1039
1041
1043const std::initializer_list<GUITownList::SortFunction * const> TownDirectoryWindow::sorter_funcs = {
1047};
1048
1051 WindowPosition::Automatic, "list_towns", 208, 202,
1053 {},
1054 _nested_town_directory_widgets,
1055 &TownDirectoryWindow::hotkeys
1056);
1057
1058void ShowTownDirectory()
1059{
1062}
1063
1064void CcFoundTown(Commands, const CommandCost &result, TileIndex tile)
1065{
1066 if (result.Failed()) return;
1067
1068 if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
1069 if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
1070}
1071
1072void CcFoundRandomTown(Commands, const CommandCost &result, Money, TownID town_id)
1073{
1074 if (result.Succeeded()) ScrollMainWindowToTile(Town::Get(town_id)->xy);
1075}
1076
1077static constexpr std::initializer_list<NWidgetPart> _nested_found_town_widgets = {
1080 NWidget(WWT_CAPTION, Colours::DarkGreen), SetStringTip(STR_FOUND_TOWN_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1083 EndContainer(),
1084 /* Construct new town(s) buttons. */
1087 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_NEW_TOWN), SetStringTip(STR_FOUND_TOWN_NEW_TOWN_BUTTON, STR_FOUND_TOWN_NEW_TOWN_TOOLTIP), SetFill(1, 0),
1090 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_TF_RANDOM_TOWN), SetStringTip(STR_FOUND_TOWN_RANDOM_TOWN_BUTTON, STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP), SetFill(1, 0),
1091 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_TF_MANY_RANDOM_TOWNS), SetStringTip(STR_FOUND_TOWN_MANY_RANDOM_TOWNS, STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP), SetFill(1, 0),
1092 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_TF_LOAD_FROM_FILE), SetStringTip(STR_FOUND_TOWN_LOAD_FROM_FILE, STR_FOUND_TOWN_LOAD_FROM_FILE_TOOLTIP), SetFill(1, 0),
1093 EndContainer(),
1094 EndContainer(),
1095
1096 /* Town name selection. */
1097 NWidget(WWT_LABEL, Colours::Invalid), SetStringTip(STR_FOUND_TOWN_NAME_TITLE),
1098 NWidget(WWT_EDITBOX, Colours::Grey, WID_TF_TOWN_NAME_EDITBOX), SetStringTip(STR_FOUND_TOWN_NAME_EDITOR_TITLE, STR_FOUND_TOWN_NAME_EDITOR_TOOLTIP), SetFill(1, 0),
1099 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_TF_TOWN_NAME_RANDOM), SetStringTip(STR_FOUND_TOWN_NAME_RANDOM_BUTTON, STR_FOUND_TOWN_NAME_RANDOM_TOOLTIP), SetFill(1, 0),
1100
1101 /* Town size selection. */
1102 NWidget(WWT_LABEL, Colours::Invalid), SetStringTip(STR_FOUND_TOWN_INITIAL_SIZE_TITLE),
1105 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_SIZE_SMALL), SetStringTip(STR_FOUND_TOWN_INITIAL_SIZE_SMALL_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP), SetFill(1, 0),
1106 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_SIZE_MEDIUM), SetStringTip(STR_FOUND_TOWN_INITIAL_SIZE_MEDIUM_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP), SetFill(1, 0),
1107 EndContainer(),
1110 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_SIZE_LARGE), SetStringTip(STR_FOUND_TOWN_INITIAL_SIZE_LARGE_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP), SetFill(1, 0),
1111 EndContainer(),
1112 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_SIZE_RANDOM), SetStringTip(STR_FOUND_TOWN_SIZE_RANDOM, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP), SetFill(1, 0),
1113 EndContainer(),
1114 EndContainer(),
1115 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_CITY), SetStringTip(STR_FOUND_TOWN_CITY, STR_FOUND_TOWN_CITY_TOOLTIP), SetFill(1, 0),
1116
1117 /* Town roads selection. */
1120 NWidget(WWT_LABEL, Colours::Invalid), SetStringTip(STR_FOUND_TOWN_ROAD_LAYOUT),
1123 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_LAYOUT_ORIGINAL), SetStringTip(STR_FOUND_TOWN_SELECT_LAYOUT_ORIGINAL, STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP), SetFill(1, 0),
1124 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_LAYOUT_BETTER), SetStringTip(STR_FOUND_TOWN_SELECT_LAYOUT_BETTER_ROADS, STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP), SetFill(1, 0),
1125 EndContainer(),
1127 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_LAYOUT_GRID2), SetStringTip(STR_FOUND_TOWN_SELECT_LAYOUT_2X2_GRID, STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP), SetFill(1, 0),
1128 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_LAYOUT_GRID3), SetStringTip(STR_FOUND_TOWN_SELECT_LAYOUT_3X3_GRID, STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP), SetFill(1, 0),
1129 EndContainer(),
1130 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_LAYOUT_RANDOM), SetStringTip(STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM, STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP), SetFill(1, 0),
1131 EndContainer(),
1132 EndContainer(),
1133 EndContainer(),
1134
1135 /* Town expansion selection. */
1138 NWidget(WWT_LABEL, Colours::Invalid), SetStringTip(STR_FOUND_TOWN_EXPAND_MODE),
1139 NWidget(WWT_PUSHTXTBTN, Colours::Grey, WID_TF_EXPAND_ALL_TOWNS), SetStringTip(STR_FOUND_TOWN_EXPAND_ALL_TOWNS, STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP), SetFill(1, 0),
1141 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_EXPAND_BUILDINGS), SetStringTip(STR_FOUND_TOWN_EXPAND_BUILDINGS, STR_FOUND_TOWN_EXPAND_BUILDINGS_TOOLTIP), SetFill(1, 0),
1142 NWidget(WWT_TEXTBTN, Colours::Grey, WID_TF_EXPAND_ROADS), SetStringTip(STR_FOUND_TOWN_EXPAND_ROADS, STR_FOUND_TOWN_EXPAND_ROADS_TOOLTIP), SetFill(1, 0),
1143 EndContainer(),
1144 EndContainer(),
1145 EndContainer(),
1146 EndContainer(),
1147 EndContainer(),
1148};
1149
1151struct FoundTownWindow : Window {
1152private:
1155 bool city = false;
1157 bool townnamevalid = false;
1158 uint32_t townnameparts = 0;
1160 static inline TownExpandModes expand_modes{TownExpandMode::Buildings, TownExpandMode::Roads};
1161
1162public:
1164 Window(desc),
1167 params(_settings_game.game_creation.town_name)
1168 {
1169 this->InitNested(window_number);
1170 this->querystrings[WID_TF_TOWN_NAME_EDITBOX] = &this->townname_editbox;
1171 this->RandomTownName();
1172 this->UpdateButtons(true);
1173 }
1174
1175 void OnInit() override
1176 {
1177 if (_game_mode == GM_EDITOR) return;
1178
1181 this->GetWidget<NWidgetStacked>(WID_TF_SIZE_SEL)->SetDisplayedPlane(SZSP_VERTICAL);
1182 if (_settings_game.economy.found_town != TF_CUSTOM_LAYOUT) {
1184 } else {
1185 this->GetWidget<NWidgetStacked>(WID_TF_ROAD_LAYOUT_SEL)->SetDisplayedPlane(0);
1186 }
1187 }
1188
1189 void RandomTownName()
1190 {
1191 this->townnamevalid = GenerateTownName(_interactive_random, &this->townnameparts);
1192
1193 if (!this->townnamevalid) {
1194 this->townname_editbox.text.DeleteAll();
1195 } else {
1196 this->townname_editbox.text.Assign(GetTownName(&this->params, this->townnameparts));
1197 }
1199
1201 }
1202
1203 void UpdateButtons(bool check_availability)
1204 {
1205 if (check_availability && _game_mode != GM_EDITOR) {
1207 this->ReInit();
1208 }
1209
1210 for (WidgetID i = WID_TF_SIZE_SMALL; i <= WID_TF_SIZE_RANDOM; i++) {
1211 this->SetWidgetLoweredState(i, i == WID_TF_SIZE_SMALL + this->town_size);
1212 }
1213
1215
1218 }
1219
1220 this->SetWidgetLoweredState(WID_TF_EXPAND_BUILDINGS, FoundTownWindow::expand_modes.Test(TownExpandMode::Buildings));
1221 this->SetWidgetLoweredState(WID_TF_EXPAND_ROADS, FoundTownWindow::expand_modes.Test(TownExpandMode::Roads));
1222
1223 this->SetDirty();
1224 }
1225
1226 template <typename Tcallback>
1227 void ExecuteFoundTownCommand(TileIndex tile, bool random, StringID errstr, Tcallback cc)
1228 {
1229 std::string name;
1230
1231 if (!this->townnamevalid) {
1232 name = this->townname_editbox.text.GetText();
1233 } else {
1234 /* If user changed the name, send it */
1235 std::string original_name = GetTownName(&this->params, this->townnameparts);
1236 if (original_name != this->townname_editbox.text.GetText()) name = this->townname_editbox.text.GetText();
1237 }
1238
1239 bool success = Command<Commands::FoundTown>::Post(errstr, cc,
1240 tile, this->town_size, this->city, this->town_layout, random, townnameparts, name);
1241
1242 /* Rerandomise name, if success and no cost-estimation. */
1243 if (success && !_shift_pressed) this->RandomTownName();
1244 }
1245
1246 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1247 {
1248 switch (widget) {
1249 case WID_TF_NEW_TOWN:
1250 HandlePlacePushButton(this, WID_TF_NEW_TOWN, SPR_CURSOR_TOWN, HT_RECT);
1251 break;
1252
1253 case WID_TF_RANDOM_TOWN:
1254 this->ExecuteFoundTownCommand(TileIndex{}, true, STR_ERROR_CAN_T_GENERATE_TOWN, CcFoundRandomTown);
1255 break;
1256
1258 this->RandomTownName();
1260 break;
1261
1263 std::string default_town_number = fmt::format("{}", GetDefaultTownsForMapSize());
1264 ShowQueryString(default_town_number, STR_MAPGEN_NUMBER_OF_TOWNS, 5, this, CS_NUMERAL, {QueryStringFlag::AcceptUnchanged});
1265 break;
1266 }
1269 break;
1270
1272 for (Town *t : Town::Iterate()) {
1273 Command<Commands::ExpandTown>::Do(DoCommandFlag::Execute, t->index, 0, FoundTownWindow::expand_modes);
1274 }
1275 break;
1276
1278 this->town_size = (TownSize)(widget - WID_TF_SIZE_SMALL);
1279 this->UpdateButtons(false);
1280 break;
1281
1282 case WID_TF_CITY:
1283 this->city ^= true;
1284 this->SetWidgetLoweredState(WID_TF_CITY, this->city);
1285 this->SetDirty();
1286 break;
1287
1289 FoundTownWindow::expand_modes.Flip(TownExpandMode::Buildings);
1290 this->UpdateButtons(false);
1291 break;
1292
1294 FoundTownWindow::expand_modes.Flip(TownExpandMode::Roads);
1295 this->UpdateButtons(false);
1296 break;
1297
1300 this->town_layout = (TownLayout)(widget - WID_TF_LAYOUT_ORIGINAL);
1301
1302 /* If we are in the editor, sync the settings of the current game to the chosen layout,
1303 * so that importing towns from file uses the selected layout. */
1304 if (_game_mode == GM_EDITOR) _settings_game.economy.town_layout = this->town_layout;
1305
1306 this->UpdateButtons(false);
1307 break;
1308 }
1309 }
1310
1311 void OnQueryTextFinished(std::optional<std::string> str) override
1312 {
1313 /* Was 'cancel' pressed? */
1314 if (!str.has_value()) return;
1315
1316 auto value = ParseInteger(*str, 10, true);
1317 if (!value.has_value()) return;
1318
1319 AutoRestoreBackup old_generating_world(_generating_world, true);
1321 if (!GenerateTowns(this->town_layout, value)) {
1322 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_GENERATE_TOWN), GetEncodedString(STR_ERROR_NO_SPACE_FOR_TOWN), WL_INFO);
1323 }
1325 }
1326
1327 void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
1328 {
1329 this->ExecuteFoundTownCommand(tile, false, STR_ERROR_CAN_T_FOUND_TOWN_HERE, CcFoundTown);
1330 }
1331
1332 void OnPlaceObjectAbort() override
1333 {
1334 this->RaiseButtons();
1335 this->UpdateButtons(false);
1336 }
1337
1343 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1344 {
1345 if (!gui_scope) return;
1346 this->UpdateButtons(true);
1347 }
1348};
1349
1352 WindowPosition::Automatic, "build_town", 160, 162,
1355 _nested_found_town_widgets
1356);
1357
1358void ShowFoundTownWindow()
1359{
1360 if (_game_mode != GM_EDITOR && !Company::IsValidID(_local_company)) return;
1362}
1363
1364void InitializeTownGui()
1365{
1366 _town_local_authority_kdtree.Clear();
1367}
1368
1376void DrawHouseInGUI(int x, int y, HouseID house_id, int view)
1377{
1378 auto draw = [](int x, int y, HouseID house_id, int view) {
1379 if (house_id >= NEW_HOUSE_OFFSET) {
1380 /* Houses don't necessarily need new graphics. If they don't have a
1381 * spritegroup associated with them, then the sprite for the substitute
1382 * house id is drawn instead. */
1383 const HouseSpec *spec = HouseSpec::Get(house_id);
1384 if (spec->grf_prop.HasSpriteGroups()) {
1385 DrawNewHouseTileInGUI(x, y, spec, house_id, view);
1386 return;
1387 } else {
1388 house_id = HouseSpec::Get(house_id)->grf_prop.subst_id;
1389 }
1390 }
1391
1392 /* Retrieve data from the draw town tile struct */
1393 const DrawBuildingsTileStruct &dcts = GetTownDrawTileData()[house_id << 4 | view << 2 | TOWN_HOUSE_COMPLETED];
1394 DrawSprite(dcts.ground.sprite, dcts.ground.pal, x, y);
1395
1396 /* Add a house on top of the ground? */
1397 if (dcts.building.sprite != 0) {
1398 Point pt = RemapCoords(dcts.origin.x, dcts.origin.y, dcts.origin.z);
1399 DrawSprite(dcts.building.sprite, dcts.building.pal, x + UnScaleGUI(pt.x), y + UnScaleGUI(pt.y));
1400 }
1401 };
1402
1403 /* Houses can have 1x1, 1x2, 2x1 and 2x2 layouts which are individual HouseIDs. For the GUI we need
1404 * draw all of the tiles with appropriate positions. */
1405 int x_delta = ScaleSpriteTrad(TILE_PIXELS);
1406 int y_delta = ScaleSpriteTrad(TILE_PIXELS / 2);
1407
1408 const HouseSpec *hs = HouseSpec::Get(house_id);
1410 draw(x, y - y_delta - y_delta, house_id, view); // North corner.
1411 draw(x + x_delta, y - y_delta, house_id + 1, view); // West corner.
1412 draw(x - x_delta, y - y_delta, house_id + 2, view); // East corner.
1413 draw(x, y, house_id + 3, view); // South corner.
1414 } else if (hs->building_flags.Test(BuildingFlag::Size2x1)) {
1415 draw(x + x_delta / 2, y - y_delta, house_id, view); // North east tile.
1416 draw(x - x_delta / 2, y, house_id + 1, view); // South west tile.
1417 } else if (hs->building_flags.Test(BuildingFlag::Size1x2)) {
1418 draw(x - x_delta / 2, y - y_delta, house_id, view); // North west tile.
1419 draw(x + x_delta / 2, y, house_id + 1, view); // South east tile.
1420 } else {
1421 draw(x, y, house_id, view);
1422 }
1423}
1424
1431{
1432 std::array<int32_t, 1> regs100;
1433 uint16_t callback_res = GetHouseCallback(CBID_HOUSE_CUSTOM_NAME, 1, 0, hs->Index(), nullptr, INVALID_TILE, regs100, true);
1434 if (callback_res != CALLBACK_FAILED && callback_res != 0x400) {
1435 StringID new_name = STR_NULL;
1436 if (callback_res == 0x40F) {
1437 new_name = GetGRFStringID(hs->grf_prop.grffile->grfid, static_cast<GRFStringID>(regs100[0]));
1438 } else if (callback_res > 0x400) {
1440 } else {
1441 new_name = GetGRFStringID(hs->grf_prop.grffile->grfid, GRFSTR_MISC_GRF_TEXT + callback_res);
1442 }
1443 if (new_name != STR_NULL && new_name != STR_UNDEFINED) {
1444 return new_name;
1445 }
1446 }
1447
1448 return hs->building_name;
1449}
1450
1451class HousePickerCallbacks : public PickerCallbacks {
1452public:
1453 HousePickerCallbacks() : PickerCallbacks("fav_houses") {}
1454
1459 {
1460 this->climate_mask = GetClimateMaskForLandscape();
1461
1462 /* In some cases, not all 'classes' (house zones) have distinct houses, so we need to disable those.
1463 * As we need to check all types, and this cannot change with the picker window open, pre-calculate it.
1464 * This loop calls GetTypeName() instead of directly checking properties so that there is no discrepancy. */
1465 this->class_mask = 0;
1466
1467 int num_classes = this->GetClassCount();
1468 for (int cls_id = 0; cls_id < num_classes; ++cls_id) {
1469 int num_types = this->GetTypeCount(cls_id);
1470 for (int id = 0; id < num_types; ++id) {
1471 if (this->GetTypeName(cls_id, id) != INVALID_STRING_ID) {
1472 SetBit(this->class_mask, cls_id);
1473 break;
1474 }
1475 }
1476 }
1477 }
1478
1479 HouseZones climate_mask{};
1480 uint8_t class_mask = 0;
1481
1482 static inline int sel_class;
1483 static inline int sel_type;
1484 static inline int sel_view;
1485
1487 static inline const std::array<StringID, NUM_HOUSE_ZONES> zone_names = {
1488 STR_HOUSE_PICKER_CLASS_ZONE1,
1489 STR_HOUSE_PICKER_CLASS_ZONE2,
1490 STR_HOUSE_PICKER_CLASS_ZONE3,
1491 STR_HOUSE_PICKER_CLASS_ZONE4,
1492 STR_HOUSE_PICKER_CLASS_ZONE5,
1493 };
1494
1496
1497 StringID GetClassTooltip() const override { return STR_PICKER_HOUSE_CLASS_TOOLTIP; }
1498 StringID GetTypeTooltip() const override { return STR_PICKER_HOUSE_TYPE_TOOLTIP; }
1499 StringID GetCollectionTooltip() const override { return STR_PICKER_HOUSE_COLLECTION_TOOLTIP; }
1500 bool IsActive() const override { return true; }
1501
1502 bool HasClassChoice() const override { return true; }
1503 int GetClassCount() const override { return static_cast<int>(zone_names.size()); }
1504
1505 void Close([[maybe_unused]] int data) override { ResetObjectToPlace(); }
1506
1507 int GetSelectedClass() const override { return HousePickerCallbacks::sel_class; }
1508 void SetSelectedClass(int cls_id) const override { HousePickerCallbacks::sel_class = cls_id; }
1509
1510 StringID GetClassName(int id) const override
1511 {
1512 if (id >= GetClassCount()) return INVALID_STRING_ID;
1513 if (!HasBit(this->class_mask, id)) return INVALID_STRING_ID;
1514 return zone_names[id];
1515 }
1516
1517 int GetTypeCount(int cls_id) const override
1518 {
1519 if (cls_id < GetClassCount()) return static_cast<int>(HouseSpec::Specs().size());
1520 return 0;
1521 }
1522
1523 PickerItem GetPickerItem(int cls_id, int id) const override
1524 {
1525 const auto *spec = HouseSpec::Get(id);
1526 if (!spec->grf_prop.HasGrfFile()) return {0, spec->Index(), cls_id, id};
1527 return {spec->grf_prop.grfid, spec->grf_prop.local_id, cls_id, id};
1528 }
1529
1530 int GetSelectedType() const override { return sel_type; }
1531 void SetSelectedType(int id) const override { sel_type = id; }
1532
1533 static HouseZone GetHouseZoneFromClassId(int cls_id) { return static_cast<HouseZone>(to_underlying(HouseZone::TownEdge) + cls_id); }
1534 static int GetClassIdFromHouseZone(HouseZones zones) { return FindFirstBit((zones & HZ_ZONE_ALL).base()) - to_underlying(HouseZone::TownEdge); }
1535
1536 StringID GetTypeName(int cls_id, int id) const override
1537 {
1538 const HouseSpec *spec = HouseSpec::Get(id);
1539 if (spec == nullptr) return INVALID_STRING_ID;
1540 if (!spec->enabled) return INVALID_STRING_ID;
1541 if (!spec->building_availability.Any(climate_mask)) return INVALID_STRING_ID;
1542 if (!spec->building_availability.Test(GetHouseZoneFromClassId(cls_id))) return INVALID_STRING_ID;
1543 for (int i = 0; i < cls_id; i++) {
1544 /* Don't include if it's already included in an earlier zone. */
1545 if (spec->building_availability.Test(GetHouseZoneFromClassId(i))) return INVALID_STRING_ID;
1546 }
1547
1548 return GetHouseName(spec);
1549 }
1550
1551 std::span<const BadgeID> GetTypeBadges(int cls_id, int id) const override
1552 {
1553 const auto *spec = HouseSpec::Get(id);
1554 if (spec == nullptr) return {};
1555 if (!spec->enabled) return {};
1556 if (!spec->building_availability.Any(climate_mask)) return {};
1557 if (!spec->building_availability.Test(GetHouseZoneFromClassId(cls_id))) return {};
1558 for (int i = 0; i < cls_id; i++) {
1559 /* Don't include if it's already included in an earlier zone. */
1560 if (spec->building_availability.Test(GetHouseZoneFromClassId(i))) return {};
1561 }
1562
1563 return spec->badges;
1564 }
1565
1566 bool IsTypeAvailable(int, int id) const override
1567 {
1568 const HouseSpec *hs = HouseSpec::Get(id);
1569 return hs->enabled;
1570 }
1571
1572 void DrawType(int x, int y, int, int id) const override
1573 {
1575 }
1576
1577 void FillUsedItems(std::set<PickerItem> &items) override
1578 {
1579 auto id_count = GetBuildingHouseIDCounts();
1580 for (auto it = id_count.begin(); it != id_count.end(); ++it) {
1581 if (*it == 0) continue;
1582 HouseID house = static_cast<HouseID>(std::distance(id_count.begin(), it));
1583 const HouseSpec *hs = HouseSpec::Get(house);
1584 int class_index = GetClassIdFromHouseZone(hs->building_availability);
1585 items.insert({0, house, class_index, house});
1586 }
1587 }
1588
1589 std::map<std::string, std::set<PickerItem>> UpdateSavedItems(const std::map<std::string, std::set<PickerItem>> &src) override
1590 {
1591 if (src.empty()) return src;
1592
1593 const auto &specs = HouseSpec::Specs();
1594 std::map<std::string, std::set<PickerItem>> dst;
1595 for (auto group_it = src.begin(); group_it != src.end(); group_it++) {
1596 if (group_it->second.empty() || (group_it->second.size() == 1 && group_it->second.contains({}))) {
1597 dst[group_it->first];
1598 continue;
1599 }
1600
1601 for (const auto &item : group_it->second) {
1602 if (item.grfid == 0) {
1603 const HouseSpec *hs = HouseSpec::Get(item.local_id);
1604 if (hs == nullptr) continue;
1605 int class_index = GetClassIdFromHouseZone(hs->building_availability);
1606 dst[group_it->first].emplace(item.grfid, item.local_id, class_index, item.local_id);
1607 } else {
1608 /* Search for spec by grfid and local index. */
1609 auto it = std::ranges::find_if(specs, [&item](const HouseSpec &spec) { return spec.grf_prop.grfid == item.grfid && spec.grf_prop.local_id == item.local_id; });
1610 if (it == specs.end()) {
1611 /* Not preset, hide from UI. */
1612 dst[group_it->first].emplace(item.grfid, item.local_id, -1, -1);
1613 } else {
1614 int class_index = GetClassIdFromHouseZone(it->building_availability);
1615 dst[group_it->first].emplace(item.grfid, item.local_id, class_index, it->Index());
1616 }
1617 }
1618 }
1619 }
1620
1621 return dst;
1622 }
1623
1624 static HousePickerCallbacks instance;
1625};
1626/* static */ HousePickerCallbacks HousePickerCallbacks::instance;
1627
1633static CargoTypes GetProducedCargoOfHouse(const HouseSpec *hs)
1634{
1635 CargoTypes produced{};
1637 for (uint i = 0; i < 256; i++) {
1638 uint16_t callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, 0, hs->Index(), nullptr, INVALID_TILE, {}, true);
1639
1640 if (callback == CALLBACK_FAILED || callback == CALLBACK_HOUSEPRODCARGO_END) break;
1641
1642 CargoType cargo = GetCargoTranslation(GB(callback, 8, 7), hs->grf_prop.grffile);
1643 if (!IsValidCargoType(cargo)) continue;
1644
1645 uint amt = GB(callback, 0, 8);
1646 if (amt == 0) continue;
1647
1648 produced.Set(cargo);
1649 }
1650 } else {
1651 /* Cargo is not controlled by NewGRF, town production effect is used instead. */
1653 for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TownProductionEffect::Mail]) produced.Set(cs->Index());
1654 }
1655 return produced;
1656}
1657
1658struct BuildHouseWindow : public PickerWindow {
1659 std::string house_info{};
1660 static inline bool house_protected;
1661 static inline bool replace;
1662
1663 BuildHouseWindow(WindowDesc &desc, Window *parent) : PickerWindow(desc, parent, 0, HousePickerCallbacks::instance)
1664 {
1665 HousePickerCallbacks::instance.SetClimateMask();
1666 this->ConstructWindow();
1667 }
1668
1669 void UpdateSelectSize(const HouseSpec *spec)
1670 {
1671 if (spec == nullptr) {
1672 SetTileSelectSize(1, 1);
1674 } else {
1675 SetObjectToPlaceWnd(SPR_CURSOR_TOWN, PAL_NONE, HT_RECT | HT_DIAGONAL, this);
1677 SetTileSelectSize(2, 2);
1678 } else if (spec->building_flags.Test(BuildingFlag::Size2x1)) {
1679 SetTileSelectSize(2, 1);
1680 } else if (spec->building_flags.Test(BuildingFlag::Size1x2)) {
1681 SetTileSelectSize(1, 2);
1682 } else if (spec->building_flags.Test(BuildingFlag::Size1x1)) {
1683 SetTileSelectSize(1, 1);
1684 }
1685 }
1686 }
1687
1694 static std::string GetHouseYear(TimerGameCalendar::Year min_year, TimerGameCalendar::Year max_year)
1695 {
1696 if (min_year == CalendarTime::MIN_YEAR) {
1697 if (max_year == CalendarTime::MAX_YEAR) {
1698 return GetString(STR_HOUSE_PICKER_YEARS_ANY);
1699 }
1700 return GetString(STR_HOUSE_PICKER_YEARS_UNTIL, max_year);
1701 }
1702 if (max_year == CalendarTime::MAX_YEAR) {
1703 return GetString(STR_HOUSE_PICKER_YEARS_FROM, min_year);
1704 }
1705 return GetString(STR_HOUSE_PICKER_YEARS, min_year, max_year);
1706 }
1707
1713 static std::string GetHouseInformation(const HouseSpec *hs)
1714 {
1715 std::stringstream line;
1716
1717 line << GetString(STR_HOUSE_PICKER_NAME, GetHouseName(hs));
1718 line << "\n";
1719
1720 line << GetString(STR_HOUSE_PICKER_POPULATION, hs->population);
1721 line << "\n";
1722
1723 line << GetHouseYear(hs->min_year, hs->max_year);
1724 line << "\n";
1725
1726 uint8_t size = 0;
1727 if (hs->building_flags.Test(BuildingFlag::Size1x1)) size = 0x11;
1728 if (hs->building_flags.Test(BuildingFlag::Size2x1)) size = 0x21;
1729 if (hs->building_flags.Test(BuildingFlag::Size1x2)) size = 0x12;
1730 if (hs->building_flags.Test(BuildingFlag::Size2x2)) size = 0x22;
1731 line << GetString(STR_HOUSE_PICKER_SIZE, GB(size, 0, 4), GB(size, 4, 4));
1732
1733 auto cargo_string = BuildCargoAcceptanceString(GetAcceptedCargoOfHouse(hs), STR_HOUSE_PICKER_CARGO_ACCEPTED);
1734 if (cargo_string.has_value()) {
1735 line << "\n";
1736 line << *cargo_string;
1737 }
1738
1739 CargoTypes produced = GetProducedCargoOfHouse(hs);
1740 if (produced.Any()) {
1741 line << "\n";
1742 line << GetString(STR_HOUSE_PICKER_CARGO_PRODUCED, produced);
1743 }
1744
1745 return line.str();
1746 }
1747
1748 void OnInit() override
1749 {
1750 this->InvalidateData(PICKER_INVALIDATION_ALL);
1751 this->PickerWindow::OnInit();
1752 }
1753
1754 void DrawWidget(const Rect &r, WidgetID widget) const override
1755 {
1756 if (widget == WID_BH_INFO) {
1757 if (!this->house_info.empty()) DrawStringMultiLine(r, this->house_info);
1758 } else {
1759 this->PickerWindow::DrawWidget(r, widget);
1760 }
1761 }
1762
1763 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1764 {
1765 switch (widget) {
1767 BuildHouseWindow::house_protected = !BuildHouseWindow::house_protected;
1768 this->SetWidgetLoweredState(WID_BH_PROTECT_TOGGLE, BuildHouseWindow::house_protected);
1769
1770 SndClickBeep();
1771 this->SetDirty();
1772 break;
1773
1775 BuildHouseWindow::replace = !BuildHouseWindow::replace;
1776 this->SetWidgetLoweredState(WID_BH_REPLACE_TOGGLE, BuildHouseWindow::replace);
1777
1778 SndClickBeep();
1779 this->SetDirty();
1780 break;
1781
1782 default:
1783 this->PickerWindow::OnClick(pt, widget, click_count);
1784 break;
1785 }
1786 }
1787
1788 void OnInvalidateData(int data = 0, bool gui_scope = true) override
1789 {
1790 this->PickerWindow::OnInvalidateData(data, gui_scope);
1791 if (!gui_scope) return;
1792
1794
1795 PickerInvalidations pi(data);
1797 UpdateSelectSize(spec);
1798 this->house_info = spec->enabled ? GetHouseInformation(spec) : "";
1799 }
1800
1801 /* If house spec already has the protected flag, handle it automatically and disable the buttons. */
1803 if (hasflag) BuildHouseWindow::house_protected = true;
1804
1805 this->SetWidgetLoweredState(WID_BH_PROTECT_TOGGLE, BuildHouseWindow::house_protected);
1806 this->SetWidgetLoweredState(WID_BH_REPLACE_TOGGLE, BuildHouseWindow::replace);
1807
1809 }
1810
1811 void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
1812 {
1814
1817 } else {
1818 Command<Commands::PlaceHouse>::Post(STR_ERROR_CAN_T_BUILD_HOUSE, CcPlaySound_CONSTRUCTION_OTHER, tile, spec->Index(), BuildHouseWindow::house_protected, BuildHouseWindow::replace);
1819 }
1820 }
1821
1822 void OnPlaceDrag(ViewportPlaceMethod select_method, [[maybe_unused]] ViewportDragDropSelectionProcess select_proc, [[maybe_unused]] Point pt) override
1823 {
1824 VpSelectTilesWithMethod(pt.x, pt.y, select_method);
1825 }
1826
1827 void OnPlaceMouseUp([[maybe_unused]] ViewportPlaceMethod select_method, [[maybe_unused]] ViewportDragDropSelectionProcess select_proc, [[maybe_unused]] Point pt, TileIndex start_tile, TileIndex end_tile) override
1828 {
1829 if (pt.x == -1) return;
1830
1831 assert(select_proc == DDSP_PLACE_HOUSE);
1832
1834 Command<Commands::PlaceHouseArea>::Post(STR_ERROR_CAN_T_BUILD_HOUSE, CcPlaySound_CONSTRUCTION_OTHER,
1835 end_tile, start_tile, spec->Index(), BuildHouseWindow::house_protected, BuildHouseWindow::replace, _ctrl_pressed);
1836 }
1837
1838 const IntervalTimer<TimerWindow> view_refresh_interval = {std::chrono::milliseconds(2500), [this](auto) {
1839 /* There are four different 'views' that are random based on house tile position. As this is not
1840 * user-controllable, instead we automatically cycle through them. */
1842 this->SetDirty();
1843 }};
1844
1845 static inline HotkeyList hotkeys{"buildhouse", {
1846 Hotkey('F', "focus_filter_box", PCWHK_FOCUS_FILTER_BOX),
1847 }};
1848};
1849
1851static constexpr std::initializer_list<NWidgetPart> _nested_build_house_widgets = {
1854 NWidget(WWT_CAPTION, Colours::DarkGreen), SetStringTip(STR_HOUSE_PICKER_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1858 EndContainer(),
1865 NWidget(WWT_TEXTBTN, Colours::Grey, WID_BH_PROTECT_TOGGLE), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_PROTECT, STR_HOUSE_PICKER_PROTECT_TOOLTIP),
1866 NWidget(WWT_TEXTBTN, Colours::Grey, WID_BH_REPLACE_TOGGLE), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_REPLACE, STR_HOUSE_PICKER_REPLACE_TOOLTIP),
1867 EndContainer(),
1868 EndContainer(),
1869 EndContainer(),
1871 EndContainer(),
1872};
1873
1876 WindowPosition::Automatic, "build_house", 0, 0,
1880 &BuildHouseWindow::hotkeys
1881);
1882
1883void ShowBuildHousePicker(Window *parent)
1884{
1885 if (BringWindowToFrontById(WC_BUILD_HOUSE, 0)) return;
1887}
Class for backupping variables and making sure they are restored later.
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:110
CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:22
std::optional< std::string > BuildCargoAcceptanceString(const CargoArray &acceptance, StringID label)
Build comma-separated cargo acceptance string.
@ Mail
Cargo behaves mail-like for production.
Definition cargotype.h:39
@ Passengers
Cargo behaves passenger-like for production.
Definition cargotype.h:38
TownAcceptanceEffect
Town growth effect when delivering cargo.
Definition cargotype.h:22
@ Begin
Used for iteration.
Definition cargotype.h:23
@ End
End of town effects.
Definition cargotype.h:30
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Reset()
Reset all bits.
constexpr Timpl & Set()
Set all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
std::optional< Tvalue_type > GetNthSetBit(uint n) const
Get the value of the Nth set bit.
Common return value for all commands.
bool Succeeded() const
Did this command succeed?
bool Failed() const
Did this command fail?
std::string GetDecodedString() const
Decode the encoded string.
Definition strings.cpp:207
List template of 'things' T to sort in a GUI.
void RebuildDone()
Notify the sortlist that the rebuild is done.
void SetListing(Listing l)
Import sort conditions.
bool IsDescSortOrder() const
Check if the sort order is descending.
void ToggleSortOrder()
Toggle the sort order Since that is the worst condition for the sort function reverse the list here.
bool NeedRebuild() const
Check if a rebuild is needed.
void ForceRebuild()
Force that a rebuild is needed.
bool Sort(Comp compare)
Sort the list.
void ForceResort()
Force a resort next Sort call Reset the resort timer if used too.
uint8_t SortType() const
Get the sorttype of the list.
Listing GetListing() const
Export current sort conditions.
void SetSortFuncs(std::span< SortFunction *const > n_funcs)
Hand the sort function pointers to the GUIList.
void SetSortType(uint8_t n_type)
Set the sorttype of the list.
PickerItem GetPickerItem(int cls_id, int id) const override
Get data about an item.
bool IsActive() const override
Should picker class/type selection be enabled?
void SetClimateMask()
Set climate mask for filtering buildings from current landscape.
void SetSelectedClass(int cls_id) const override
Set the selected class.
StringID GetClassTooltip() const override
Get the tooltip string for the class list.
GrfSpecFeature GetFeature() const override
NewGRF feature this picker is for.
std::span< const BadgeID > GetTypeBadges(int cls_id, int id) const override
Get the item's badges of a type.
void DrawType(int x, int y, int, int id) const override
Draw preview image of an item.
static int sel_view
Currently selected 'view'. This is not controllable as its based on random data.
int GetClassCount() const override
Get the number of classes.
void FillUsedItems(std::set< PickerItem > &items) override
Fill a set with all items that are used by the current player.
static int sel_type
Currently selected HouseID.
int GetSelectedClass() const override
Get the index of the selected class.
StringID GetTypeTooltip() const override
Get the tooltip string for the type grid.
void SetSelectedType(int id) const override
Set the selected type.
StringID GetCollectionTooltip() const override
Get the tooltip string for the collection list.
StringID GetTypeName(int cls_id, int id) const override
Get the item name of a type.
int GetSelectedType() const override
Get the selected type.
bool IsTypeAvailable(int, int id) const override
Test if an item is currently buildable.
bool HasClassChoice() const override
Are there multiple classes to chose from?
std::map< std::string, std::set< PickerItem > > UpdateSavedItems(const std::map< std::string, std::set< PickerItem > > &src) override
Update link between grfid/localidx and class_index/index in saved items.
uint8_t class_mask
Mask of available 'classes'.
static const std::array< StringID, NUM_HOUSE_ZONES > zone_names
Houses do not have classes like NewGRFClass.
int GetTypeCount(int cls_id) const override
Get the number of types in a class.
void Close(int data) override
Hide the window and all its child windows, and mark them for a later deletion.
StringID GetClassName(int id) const override
Get the name of a class.
static int sel_class
Currently selected 'class'.
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
Baseclass for nested widgets.
uint current_x
Current horizontal size (after resizing).
uint smallest_y
Smallest vertical size of the widget in a filled window.
uint current_y
Current vertical size (after resizing).
Nested widget to display a viewport in a window.
void UpdateViewportCoordinates(Window *w)
Update the position and size of the viewport (after eg a resize).
Definition widget.cpp:2435
void InitializeViewport(Window *w, std::variant< TileIndex, VehicleID > focus, ZoomLevel zoom)
Initialize the viewport of the window.
Definition widget.cpp:2426
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
@ Position
Update scroll positions.
Definition picker_gui.h:325
@ PCWHK_FOCUS_FILTER_BOX
Focus the edit box for editing the filter string.
Definition picker_gui.h:367
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
void OnInit() override
Notification that the nested widget tree gets initialized.
Scrollbar data structure.
auto GetScrolledItemFromWidget(Tcontainer &container, int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Return an iterator pointing to the element of a scrolled widget that a user clicked in.
void SetCapacityFromWidget(Window *w, WidgetID widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget.
Definition widget.cpp:2532
size_type GetCount() const
Gets the number of elements in the list.
auto GetVisibleRangeIterators(Tcontainer &container) const
Get a pair of iterators for the range of visible elements in a container.
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
static constexpr TimerGame< struct Calendar >::Year MIN_YEAR
static constexpr TimerGame< struct Calendar >::Year MAX_YEAR
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
StrongType::Typedef< int32_t, struct YearTag< struct Calendar >, StrongType::Compare, StrongType::Integer > Year
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:93
Functions related to commands.
@ Execute
execute the given command
Commands
List of commands.
Definition of stuff that is very close to a company, like the company struct itself.
void DrawCompanyIcon(CompanyID c, int x, int y)
Draw the icon of a company.
PaletteID GetCompanyPalette(CompanyID company)
Get the palette for recolouring with a company colour.
Money GetAvailableMoney(CompanyID company)
Get the amount of money that a company has available, or INT64_MAX if there is no such valid company.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
GUI Functions related to companies.
void ShowDropDownMenu(Window *w, std::span< const StringID > strings, int selected, WidgetID button, uint32_t disabled_mask, uint32_t hidden_mask, uint width, DropDownOptions options, std::string *const persistent_filter_text)
Show a dropdown menu window near a widget of the parent window.
Definition dropdown.cpp:629
Functions related to the drop down widget.
Prices _price
Prices and also the fractional part.
Definition economy.cpp:106
@ TownAction
Price for interaction with local authorities.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
Functions related to errors.
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
@ Load
File is being loaded.
Definition fileio_type.h:54
@ TownData
town data file
Definition fileio_type.h:22
Declarations for savegames operations.
void ShowSaveLoadDialog(AbstractFileType abstract_filetype, SaveLoadOperation fop)
Launch save/load dialog in the given mode.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:88
bool _generating_world
Whether we are generating the map or not.
Definition genworld.cpp:74
Functions related to world/map generation.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Geometry functions.
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition gfx.cpp:717
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:972
bool _shift_pressed
Is Shift pressed?
Definition gfx.cpp:40
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:900
Dimension GetStringListBoundingBox(std::span< const StringID > list, FontSize fontsize)
Get maximum dimension of a list of strings.
Definition gfx.cpp:939
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:669
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:39
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:1038
Dimension GetStringMultiLineBoundingBox(StringID str, const Dimension &suggestion)
Calculate string bounding box for multi-line strings.
Definition gfx.cpp:753
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:788
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ Normal
Index of the normal font in the font tables.
Definition gfx_type.h:249
@ Invalid
Invalid marker.
Definition gfx_type.h:302
@ Grey
Grey.
Definition gfx_type.h:299
@ Brown
Brown.
Definition gfx_type.h:298
@ DarkGreen
Dark green.
Definition gfx_type.h:292
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:307
@ TC_NO_SHADE
Do not add shading to this text colour.
Definition gfx_type.h:331
Graph GUI functions.
constexpr NWidgetPart NWidgetFunction(NWidgetFunctionType *func_ptr)
Obtain a nested widget (sub)tree from an external source.
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetSpriteTip(SpriteID sprite, StringID tip={})
Widget part function for setting the sprite and tooltip.
constexpr NWidgetPart SetPIP(uint8_t pre, uint8_t inter, uint8_t post)
Widget part function for setting a pre/inter/post spaces.
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
Widget part function for setting additional space around a widget.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlag::ResizeX)
Widget part function for setting the aspect ratio.
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FontSize::Normal)
Widget part function for setting the minimal text lines.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
constexpr NWidgetPart SetToolTip(StringID tip)
Widget part function for setting tooltip and clearing the widget data.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=INVALID_WIDGET)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
uint8_t LowestSnowLine()
Get the lowest possible snow line height, either variable or static.
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
void SetDirty() const
Mark entire window as dirty (in need of re-paint).
Definition window.cpp:980
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1554
GUI functions that shouldn't be here.
void ShowExtraViewportWindow(TileIndex tile=INVALID_TILE)
Show a new Extra Viewport window.
Hotkey related functions.
Definition of HouseSpec and accessors.
@ BuildingIsProtected
towns and AI will not remove this house, while human players will be able to
Definition house.h:94
HouseZones GetClimateMaskForLandscape()
Get the HouseZones climate mask for the current landscape type.
@ Size1x1
The building is a single tile.
Definition house.h:39
@ Size2x2
The building is 2x2 tiles.
Definition house.h:43
@ Size2x1
The building is 2x1 tiles, i.e. wider on the X-axis.
Definition house.h:41
@ Size1x2
The building is 1x2 tiles, i.e. wider on the Y-axis.
Definition house.h:42
static const HouseID NEW_HOUSE_OFFSET
Offset for new houses.
Definition house.h:28
static const uint8_t TOWN_HOUSE_COMPLETED
Simple value that indicates the house has reached the final stage of construction.
Definition house.h:25
HouseZone
Concentric rings of zoning around the centre of a town.
Definition house.h:57
@ TownEdge
Edge of the town; roads without pavement.
Definition house.h:58
uint16_t HouseID
OpenTTD ID of house types.
Definition house_type.h:15
Functions related to OTTD's landscape.
Point RemapCoords(int x, int y, int z)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap.
Definition landscape.h:81
#define Point
Macro that prevents name conflicts between included headers.
bool DoZoomInOutWindow(ZoomStateChange how, Window *w)
Zooms a viewport in a window in or out.
Definition main_gui.cpp:93
bool HandlePlacePushButton(Window *w, WidgetID widget, CursorID cursor, HighLightStyle mode)
This code is shared for the majority of the pushbuttons.
Definition main_gui.cpp:63
constexpr int RoundDivSU(int a, uint b)
Computes round(a / b) for signed a and unsigned b.
void ShowQueryString(std::string_view str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
bool _networking
are we in networking mode?
Definition network.cpp:67
bool _network_server
network-server is active
Definition network.cpp:68
Basic functions/variables used all over the place.
GrfSpecFeature
Definition newgrf.h:72
@ Houses
Houses feature.
Definition newgrf.h:80
@ CBID_HOUSE_CUSTOM_NAME
Called on the Get Tile Description for an house tile.
@ CBID_HOUSE_PRODUCE_CARGO
Called to determine how much cargo a town building produces.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
@ ProduceCargo
custom cargo production
static const uint CALLBACK_HOUSEPRODCARGO_END
Sentinel indicating that the loop for CBID_HOUSE_PRODUCE_CARGO has ended.
CargoType GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoType.
Cargo support for NewGRFs.
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
std::span< const uint > GetBuildingHouseIDCounts()
Get read-only span of total HouseID building counts.
void DrawNewHouseTileInGUI(int x, int y, const HouseSpec *spec, HouseID house_id, int view)
Draw representation of a house tile for GUI purposes.
uint16_t GetHouseCallback(CallbackID callback, uint32_t param1, uint32_t param2, HouseID house_id, Town *town, TileIndex tile, std::span< int32_t > regs100, bool not_yet_constructed, uint8_t initial_random_bits, CargoTypes watched_cargo_triggers, int view)
Get the result of a house callback.
Functions related to NewGRF houses.
StringID GetGRFStringID(uint32_t grfid, GRFStringID stringid)
Returns the index for this stringid associated with its grfID.
Header of Action 04 "universal holder" structure and functions.
StrongType::Typedef< uint32_t, struct GRFStringIDTag, StrongType::Compare, StrongType::Integer > GRFStringID
Type for GRF-internal string IDs.
static constexpr GRFStringID GRFSTR_MISC_GRF_TEXT
Miscellaneous GRF text range.
void UpdateOSKOriginalText(const Window *parent, WidgetID button)
Updates the original text of the OSK so when the 'parent' changes the original and you press on cance...
Definition osk_gui.cpp:407
std::unique_ptr< NWidgetBase > MakePickerClassWidgets()
Create nested widgets for the class picker widgets.
std::unique_ptr< NWidgetBase > MakePickerTypeWidgets()
Create nested widgets for the type picker widgets.
Functions/types etc.
Base for the GUIs that have an edit box in them.
Randomizer _interactive_random
Random used everywhere else, where it does not (directly) influence the game state.
void UpdateNearestTownForRoadTiles(bool invalidate)
Updates cached nearest town for all road tiles.
Road related functions.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
@ Off
Scroll wheel has no effect.
Base types for having sorted lists in GUIs.
void SndClickBeep()
Play a beep sound for a click event if enabled in settings.
Definition sound.cpp:253
Functions related to sound.
@ SND_1F_CONSTRUCTION_OTHER
29 == 0x1D Construction: other (non-water, non-rail, non-bridge)
Definition sound_type.h:77
Definition of base types and functions in a cross-platform compatible way.
int StrNaturalCompare(std::string_view s1, std::string_view s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Definition string.cpp:429
Parse strings.
static std::optional< T > ParseInteger(std::string_view arg, int base=10, bool clamp=false)
Change a string into its number representation.
Functions related to low-level strings.
@ CS_NUMERAL
Only numeric ones.
Definition string_type.h:26
@ CS_ALPHANUMERAL
Both numeric and alphabetic and spaces and stuff.
Definition string_type.h:25
Searching and filtering using a stringterm.
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
uint64_t GetParamMaxDigits(uint count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:218
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames).
@ TD_RTL
Text is written right-to-left by default.
static const int MAX_CHAR_LENGTH
Max. length of UTF-8 encoded unicode character.
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
static std::string GetHouseYear(TimerGameCalendar::Year min_year, TimerGameCalendar::Year max_year)
Get a date range string for house availability year.
void OnPlaceObject(Point pt, TileIndex tile) override
The user clicked some place on the map when a tile highlight mode has been set.
void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt) override
The user is dragging over the map when the tile highlight mode has been set.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) override
The user has dragged over the map when the tile highlight mode has been set.
static std::string GetHouseInformation(const HouseSpec *hs)
Get information string for a house.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnInit() override
Notification that the nested widget tree gets initialized.
Specification of a cargo type.
Definition cargotype.h:75
static EnumIndexArray< std::vector< const CargoSpec * >, TownProductionEffect, TownProductionEffect::End > town_production_cargoes
List of cargo specs for each Town Product Effect.
Definition cargotype.h:195
CargoType Index() const
Determines index of this cargospec.
Definition cargotype.h:109
StringID name
Name of this type of cargo.
Definition cargotype.h:92
T y
Y coordinate.
T x
X coordinate.
T x
X coordinate.
T y
Y coordinate.
T z
Z coordinate.
Dimensions (a width and height) of a rectangle in 2D.
This structure is the same for both Industries and Houses.
Definition sprite.h:90
TownFounding found_town
town founding.
TownLayout town_layout
select town layout,
Found a town window class.
uint32_t townnameparts
Generated town name.
TownLayout town_layout
Selected town layout.
void OnPlaceObject(Point pt, TileIndex tile) override
The user clicked some place on the map when a tile highlight mode has been set.
QueryString townname_editbox
Townname editbox.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
void OnInit() override
Notification that the nested widget tree gets initialized.
TownSize town_size
Selected town size.
bool townnamevalid
Is generated town name valid?
TownNameParams params
Town name parameters.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnPlaceObjectAbort() override
The user cancelled a tile highlight mode that has been set.
bool city
Are we building a city?
const struct GRFFile * grffile
grf file that introduced this entity
uint16_t local_id
id defined by the grf file for this entity
uint32_t grfid
grfid that introduced this entity.
EconomySettings economy
settings to change the economy
List of hotkeys for a window.
Definition hotkeys.h:46
All data for a single hotkey.
Definition hotkeys.h:22
SubstituteGRFFileProps grf_prop
Properties related the the grf file.
Definition house.h:116
bool enabled
the house is available to build (true by default, but can be disabled by newgrf)
Definition house.h:113
static HouseSpec * Get(size_t house_id)
Get the spec for a house ID.
BuildingFlags building_flags
some flags that describe the house (size, stadium etc...)
Definition house.h:111
TimerGameCalendar::Year max_year
last year it can be built
Definition house.h:103
HouseCallbackMasks callback_mask
Bitmask of house callbacks that have to be called.
Definition house.h:117
uint8_t population
population (Zero on other tiles in multi tile house.)
Definition house.h:104
HouseExtraFlags extra_flags
some more flags
Definition house.h:120
TimerGameCalendar::Year min_year
introduction year of the house
Definition house.h:102
HouseID Index() const
Gets the index of this spec.
StringID building_name
building name
Definition house.h:106
HouseZones building_availability
where can it be built (climates, zones)
Definition house.h:112
static std::vector< HouseSpec > & Specs()
Get a reference to all HouseSpecs.
Data structure describing how to show the list (what sort direction and criteria).
bool order
Ascending/descending.
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:23
PaletteID pal
The palette (use PAL_NONE) if not needed).
Definition gfx_type.h:24
static Pool::IterateWrapper< Company > Iterate(size_t from=0)
static Town * Get(auto index)
Data stored about a string that can be modified in the GUI.
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
static const int ACTION_CLEAR
Clear editbox.
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
Coord3D< int8_t > origin
Position of northern corner within tile.
Definition sprite.h:19
bool HasSpriteGroups() const
Check whether the entity has sprite groups.
String filter and state.
bool IsEmpty() const
Check whether any filter words were entered.
void SetFilterTerm(std::string_view str)
Set the term to filter on.
uint16_t subst_id
The id of the entity to replace.
void DeleteAll()
Delete every character in the textbuffer.
Definition textbuf.cpp:112
std::string_view GetText() const
Get the current text.
Definition textbuf.cpp:284
Town authority window.
Definition town_gui.cpp:80
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition town_gui.cpp:322
void DrawActions()
Draws the contents of the actions panel.
Definition town_gui.cpp:204
Dimension icon_size
Dimensions of company icon.
Definition town_gui.cpp:89
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition town_gui.cpp:129
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition town_gui.cpp:233
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
Definition town_gui.cpp:249
Town * town
Town being displayed.
Definition town_gui.cpp:82
TownActions enabled_actions
Actions that are enabled in settings.
Definition town_gui.cpp:85
TownAction sel_action
Currently selected town action, TownAction::End means no action selected.
Definition town_gui.cpp:83
TownActions available_actions
Actions that are available to execute for the current company.
Definition town_gui.cpp:86
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition town_gui.cpp:281
void DrawRatings()
Draw the contents of the ratings panel.
Definition town_gui.cpp:165
const IntervalTimer< TimerWindow > redraw_interval
Redraw the whole window on a regular interval.
Definition town_gui.cpp:318
Dimension exclusive_size
Dimensions of exclusive icon.
Definition town_gui.cpp:90
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
Definition town_gui.cpp:226
static TownActions GetEnabledActions()
Gets all town authority actions enabled in settings.
Definition town_gui.cpp:97
void OnPaint() override
The window must be repainted.
Definition town_gui.cpp:135
TownActions displayed_actions_on_previous_painting
Actions that were available on the previous call to OnPaint().
Definition town_gui.cpp:84
uint32_t population
Current population of people.
Definition town.h:53
Town directory window class.
Definition town_gui.cpp:722
static bool TownPopulationSorter(const Town *const &a, const Town *const &b, const bool &filter)
Sort by population (default descending, as big towns are of the most interest).
Definition town_gui.cpp:773
static const std::initializer_list< GUITownList::SortFunction *const > sorter_funcs
Functions to sort towns.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition town_gui.cpp:849
static Listing last_sorting
Retains sorting setting when closing the window.
QueryString townname_editbox
Filter editbox.
Definition town_gui.cpp:736
static bool TownRatingSorter(const Town *const &a, const Town *const &b, const bool &filter)
Sort by town rating.
Definition town_gui.cpp:782
void OnEditboxChanged(WidgetID wid) override
The text in an editbox has been edited.
void OnResize() override
Called after the window got resized.
StringFilter string_filter
Filter for towns.
Definition town_gui.cpp:735
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
const IntervalTimer< TimerWindow > rebuild_interval
Redraw the whole window on a regular interval.
Definition town_gui.cpp:995
static bool TownNameSorter(const Town *const &a, const Town *const &b, const bool &filter)
Sort by town name.
Definition town_gui.cpp:767
void OnPaint() override
The window must be repainted.
Definition town_gui.cpp:988
void OnDropdownSelect(WidgetID widget, int index, int) override
A dropdown option associated to this window has been selected.
Definition town_gui.cpp:977
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition town_gui.cpp:940
static std::string GetTownString(const Town *t, uint64_t population)
Get the string to draw the town name.
Definition town_gui.cpp:844
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
Definition town_gui.cpp:893
static const StringID sorter_names[]
Strings describing how towns are sorted.
Definition town_gui.cpp:728
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
Definition town_gui.cpp:821
Struct holding parameters used to generate town name.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition town_gui.cpp:476
Town * town
Town displayed by the window.
Definition town_gui.cpp:350
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition town_gui.cpp:595
void OnMouseWheel(int wheel, WidgetID widget) override
The mouse wheel has been turned.
Definition town_gui.cpp:582
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
Definition town_gui.cpp:522
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition town_gui.cpp:392
uint GetDesiredInfoHeight(int width) const
Gets the desired height for the information panel.
Definition town_gui.cpp:536
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
Definition town_gui.cpp:377
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
Definition town_gui.cpp:371
void OnPaint() override
The window must be repainted.
Definition town_gui.cpp:384
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
Definition town_gui.cpp:603
void OnResize() override
Called after the window got resized.
Definition town_gui.cpp:572
Town data structure.
Definition town.h:63
EncodedString text
General text with additional information.
Definition town.h:136
bool larger_town
if this is a larger town and should grow more quickly
Definition town.h:198
TileIndex xy
town center tile
Definition town.h:64
uint8_t fund_buildings_months
fund buildings program in action?
Definition town.h:195
uint16_t noise_reached
level of noise that all the airports are generating
Definition town.h:79
SuppliedCargoes supplied
Cargo statistics about supplied cargo.
Definition town.h:130
TownFlags flags
See TownFlags.
Definition town.h:77
TownCache cache
Container for all cacheable data.
Definition town.h:66
CompanyID exclusivity
which company has exclusivity
Definition town.h:86
bool show_zone
NOSAVE: mark town to show the local authority zone in the viewports.
Definition town.h:201
EnumIndexArray< TransportedCargoStat< uint16_t >, TownAcceptanceEffect, TownAcceptanceEffect::End > received
Cargo statistics about received cargotypes.
Definition town.h:132
CompanyMask have_ratings
which companies have a rating
Definition town.h:84
TypedIndexContainer< std::array< int16_t, MAX_COMPANIES >, CompanyID > ratings
ratings of each company for this town
Definition town.h:88
uint16_t growth_rate
town growth rate
Definition town.h:193
EnumIndexArray< uint32_t, TownAcceptanceEffect, TownAcceptanceEffect::End > goal
Amount of cargo required for the town to grow.
Definition town.h:133
High level window description.
Definition window_gui.h:168
Number to differentiate different windows of the same class.
Data structure for an opened window.
Definition window_gui.h:274
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:992
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1117
static int SortButtonWidth()
Get width of up/down arrow of sort button state.
Definition widget.cpp:835
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1822
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:321
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:786
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing).
Definition window.cpp:3262
Window * parent
Parent window.
Definition window_gui.h:329
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:570
std::unique_ptr< ViewportData > viewport
Pointer to viewport data, if present.
Definition window_gui.h:319
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:518
void DrawSortButtonState(WidgetID widget, SortButtonState state) const
Draw a sort button's up or down arrow symbol.
Definition widget.cpp:818
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1812
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:499
bool IsWidgetLowered(WidgetID widget_index) const
Gets the lowered state of a widget.
Definition window_gui.h:492
void RaiseButtons(bool autoraise=false)
Raise the buttons of the window.
Definition window.cpp:544
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:442
bool IsShaded() const
Is window shaded currently?
Definition window_gui.h:563
Window(WindowDesc &desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition window.cpp:1846
int GetRowFromWidget(int clickpos, WidgetID widget, int padding, int line_height=-1) const
Compute the row of a widget that a user clicked in.
Definition window.cpp:223
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:990
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1836
WindowFlags flags
Window flags.
Definition window_gui.h:301
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:327
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:312
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
@ AcceptUnchanged
return success even when the text didn't change
Definition textbuf_gui.h:19
@ EnableDefault
enable the 'Default' button ("\0" is returned)
Definition textbuf_gui.h:20
@ LengthIsInChars
the length of the string is counted in characters
Definition textbuf_gui.h:21
static uint TileHeight(Tile tile)
Returns the height of a tile.
Definition tile_map.h:29
TropicZone GetTropicZone(Tile tile)
Get the tropic zone.
Definition tile_map.h:238
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
@ Desert
Tile is desert.
Definition tile_type.h:83
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
static constexpr uint TILE_PIXELS
Pixel distance between tile columns/rows in ZOOM_BASE.
Definition tile_type.h:17
Functions related to tile highlights.
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows).
void SetObjectToPlaceWnd(CursorID icon, PaletteID pal, HighLightStyle mode, Window *w)
Change the cursor and mouse click/drag handling to a mode for performing special operations like tile...
void VpSelectTilesWithMethod(int x, int y, ViewportPlaceMethod method)
Selects tiles while dragging.
void VpStartPlaceSizing(TileIndex tile, ViewportPlaceMethod method, ViewportDragDropSelectionProcess process)
Prepare state for highlighting tiles while dragging with the mouse.
@ HT_DIAGONAL
Also allow 'diagonal rectangles'. Only usable in combination with HT_RECT or HT_POINT.
@ HT_RECT
rectangle (stations, depots, ...)
Definition of Interval and OneShot timers.
Definition of the game-calendar-timer.
Definition of the Window system.
Base of the town class.
static const uint TOWN_GROWTH_WINTER
The town only needs this cargo in the winter (any amount).
Definition town.h:32
uint GetDefaultTownsForMapSize()
Calculate the number of towns which should be on the map according to the current "town density" newg...
TownActions GetMaskOfTownActions(CompanyID cid, const Town *t)
Get a list of available town authority actions.
const CargoSpec * FindFirstCargoWithTownAcceptanceEffect(TownAcceptanceEffect effect)
Determines the first cargo with a certain town effect.
static const uint TOWN_GROWTH_DESERT
The town needs the cargo for growth when on desert (any amount).
Definition town.h:33
bool GenerateTowns(TownLayout layout, std::optional< uint > number=std::nullopt)
Generate a number of towns with a given layout.
uint32_t GetWorldPopulation()
Get the total population, the sum of all towns in the world.
Definition town_cmd.cpp:446
CargoArray GetAcceptedCargoOfHouse(const HouseSpec *hs)
Get accepted cargo of a house prototype.
Definition town_cmd.cpp:837
uint8_t GetTownActionCost(TownAction action)
Get cost factors for a TownAction.
TownAction
Town actions of a company.
Definition town.h:296
@ RoadRebuild
Rebuild the roads.
Definition town.h:300
@ Bribe
Try to bribe the council.
Definition town.h:304
@ End
End marker.
Definition town.h:305
@ BuyRights
Buy exclusive transport rights.
Definition town.h:303
@ FundBuildings
Fund new buildings.
Definition town.h:302
@ IsGrowing
Conditions for town growth are met. Grow according to Town::growth_rate.
Definition town.h:42
Command definitions related to towns.
void DrawHouseInGUI(int x, int y, HouseID house_id, int view)
Draw a house that does not exist.
static WindowDesc _town_game_view_desc(WindowPosition::Automatic, "view_town", 260, TownViewWindow::WID_TV_HEIGHT_NORMAL, WC_TOWN_VIEW, WC_NONE, {}, _nested_town_game_view_widgets)
Window definition for the town view window.
static WindowDesc _town_editor_view_desc(WindowPosition::Automatic, "view_town_scen", 260, TownViewWindow::WID_TV_HEIGHT_NORMAL, WC_TOWN_VIEW, WC_NONE, {}, _nested_town_editor_view_widgets)
Window definition for the town view window of the scenario edtior.
static WindowDesc _found_town_desc(WindowPosition::Automatic, "build_town", 160, 162, WC_FOUND_TOWN, WC_NONE, WindowDefaultFlag::Construction, _nested_found_town_widgets)
Window definition for the town funding window.
static StringID GetHouseName(const HouseSpec *hs)
Get name for a prototype house.
static WindowDesc _build_house_desc(WindowPosition::Automatic, "build_house", 0, 0, WC_BUILD_HOUSE, WC_BUILD_TOOLBAR, WindowDefaultFlag::Construction, _nested_build_house_widgets, &BuildHouseWindow::hotkeys)
Window definition for the house building window.
static CargoTypes GetProducedCargoOfHouse(const HouseSpec *hs)
Get the cargo types produced by a house.
static constexpr std::initializer_list< NWidgetPart > _nested_build_house_widgets
Nested widget definition for the build NewGRF rail waypoint window.
static WindowDesc _town_authority_desc(WindowPosition::Automatic, "view_town_authority", 317, 222, WC_TOWN_AUTHORITY, WC_NONE, {}, _nested_town_authority_widgets)
Window definition for the town authority window.
static WindowDesc _town_directory_desc(WindowPosition::Automatic, "list_towns", 208, 202, WC_TOWN_DIRECTORY, WC_NONE, {}, _nested_town_directory_widgets, &TownDirectoryWindow::hotkeys)
Window definition for the town directory window.
Declarations for accessing the k-d tree of towns.
TownLayout
Town Layouts.
Definition town_type.h:84
@ TF_CUSTOM_LAYOUT
Allowed, with custom town layout.
Definition town_type.h:110
TownSize
Supported initial town sizes.
Definition town_type.h:21
@ TSZ_MEDIUM
Medium town.
Definition town_type.h:23
static const uint MAX_LENGTH_TOWN_NAME_CHARS
The maximum length of a town name in characters including '\0'.
Definition town_type.h:122
@ Roads
Allow town to place roads.
Definition town_type.h:100
@ Buildings
Allow town to place buildings.
Definition town_type.h:99
Types related to the town widgets.
@ WID_TA_EXECUTE
Do-it button.
Definition town_widget.h:32
@ WID_TA_ACTION_INFO
Additional information about the action.
Definition town_widget.h:31
@ WID_TA_RATING_INFO
Overview with ratings for each company.
Definition town_widget.h:28
@ WID_TA_CAPTION
Caption of window.
Definition town_widget.h:26
@ WID_TA_ZONE_BUTTON
Turn on/off showing local authority zone.
Definition town_widget.h:27
@ WID_TA_COMMAND_LIST
List of commands for the player.
Definition town_widget.h:29
@ WID_TV_VIEWPORT
View of the center of the town.
Definition town_widget.h:38
@ WID_TV_EXPAND_BUILDINGS
Expand number of buildings this town (scenario editor only).
Definition town_widget.h:45
@ WID_TV_INFO
General information about the town.
Definition town_widget.h:39
@ WID_TV_EXPAND
Expand this town (scenario editor only).
Definition town_widget.h:44
@ WID_TV_CATCHMENT
Toggle catchment area highlight.
Definition town_widget.h:43
@ WID_TV_SHOW_AUTHORITY
Show the town authority window.
Definition town_widget.h:41
@ WID_TV_CHANGE_NAME
Change the name of this town.
Definition town_widget.h:42
@ WID_TV_CENTER_VIEW
Center the main view on this town.
Definition town_widget.h:40
@ WID_TV_DELETE
Delete this town (scenario editor only).
Definition town_widget.h:47
@ WID_TV_EXPAND_ROADS
Expand roads of this town (scenario editor only).
Definition town_widget.h:46
@ WID_TV_CAPTION
Caption of window.
Definition town_widget.h:37
@ WID_TF_LAYOUT_RANDOM
Selection for a randomly chosen town layout.
Definition town_widget.h:72
@ WID_TF_LOAD_FROM_FILE
Load town data from file.
Definition town_widget.h:57
@ WID_TF_SIZE_SEL
Container of town size buttons.
Definition town_widget.h:61
@ WID_TF_SIZE_LARGE
Selection for a large town.
Definition town_widget.h:64
@ WID_TF_NEW_TOWN
Create a new town.
Definition town_widget.h:53
@ WID_TF_EXPAND_ALL_TOWNS
Make all towns grow slightly.
Definition town_widget.h:58
@ WID_TF_MANY_RANDOM_TOWNS
Randomly place many towns.
Definition town_widget.h:56
@ WID_TF_SIZE_SMALL
Selection for a small town.
Definition town_widget.h:62
@ WID_TF_EXPAND_BUILDINGS
Expand buildings toggle.
Definition town_widget.h:74
@ WID_TF_LAYOUT_GRID2
Selection for the 2x2 grid town layout.
Definition town_widget.h:70
@ WID_TF_LAYOUT_ORIGINAL
Selection for the original town layout.
Definition town_widget.h:68
@ WID_TF_SIZE_RANDOM
Selection for a randomly sized town.
Definition town_widget.h:65
@ WID_TF_TOWN_NAME_EDITBOX
Editor for the town name.
Definition town_widget.h:59
@ WID_TF_TOWN_ACTION_SEL
Container of town action buttons.
Definition town_widget.h:54
@ WID_TF_SIZE_MEDIUM
Selection for a medium town.
Definition town_widget.h:63
@ WID_TF_TOWN_EXPAND_SEL
Container of town expansion buttons.
Definition town_widget.h:73
@ WID_TF_EXPAND_ROADS
Expand roads toggle.
Definition town_widget.h:75
@ WID_TF_CITY
Selection for the town's city state.
Definition town_widget.h:66
@ WID_TF_RANDOM_TOWN
Randomly place a town.
Definition town_widget.h:55
@ WID_TF_LAYOUT_BETTER
Selection for the better town layout.
Definition town_widget.h:69
@ WID_TF_ROAD_LAYOUT_SEL
Container of town road layout buttons.
Definition town_widget.h:67
@ WID_TF_LAYOUT_GRID3
Selection for the 3x3 grid town layout.
Definition town_widget.h:71
@ WID_TF_TOWN_NAME_RANDOM
Generate a random town name.
Definition town_widget.h:60
@ WID_TD_LIST
List of towns.
Definition town_widget.h:19
@ WID_TD_CAPTION
Caption of the window.
Definition town_widget.h:15
@ WID_TD_FILTER
Filter of name.
Definition town_widget.h:18
@ WID_TD_SORT_ORDER
Direction of sort dropdown.
Definition town_widget.h:16
@ WID_TD_WORLD_POPULATION
The world's population.
Definition town_widget.h:21
@ WID_TD_SCROLLBAR
Scrollbar for the town list.
Definition town_widget.h:20
@ WID_TD_SORT_CRITERIA
Criteria of sort dropdown.
Definition town_widget.h:17
@ WID_BH_REPLACE_TOGGLE
Button to toggle replacing existing houses.
Definition town_widget.h:82
@ WID_BH_PROTECT_TOGGLE
Button to toggle protecting the next house built.
Definition town_widget.h:81
@ WID_BH_INFO
Information panel of selected house.
Definition town_widget.h:80
bool GenerateTownName(Randomizer &randomizer, uint32_t *townnameparts, TownNames *town_names)
Generates valid town name.
Definition townname.cpp:136
Town name generator stuff.
bool ScrollWindowToTile(TileIndex tile, Window *w, bool instant)
Scrolls the viewport in a window to a given location.
void SetTileSelectSize(int w, int h)
Highlight w by h tiles at the cursor.
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
void SetViewportCatchmentTown(const Town *t, bool sel)
Select or deselect town for coverage area highlight.
const Town * _viewport_highlight_town
Currently selected town for coverage area highlight.
Functions related to (drawing on) viewports.
ViewportPlaceMethod
Viewport place method (type of highlighted area and placed objects).
@ VPM_X_AND_Y
area of land in X and Y directions
@ ZOOM_IN
Zoom in (get more detailed view).
@ ZOOM_OUT
Zoom out (get helicopter view).
ViewportDragDropSelectionProcess
Drag and drop selection process, or, what to do with an area of land when you've selected it.
@ DDSP_PLACE_HOUSE
Place a house.
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_INSET
Pressed (inset) panel, most commonly used as combo box text area.
Definition widget_type.h:40
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
@ WWT_LABEL
Centered label.
Definition widget_type.h:48
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:62
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:66
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:44
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:39
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX).
Definition widget_type.h:57
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX).
Definition widget_type.h:55
@ WWT_CAPTION
Window caption (window title between closebox and stickybox).
Definition widget_type.h:52
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:76
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:68
@ WWT_CLOSEBOX
Close box (at top-left of a window).
Definition widget_type.h:60
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:37
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window).
Definition widget_type.h:59
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX).
Definition widget_type.h:56
@ NWID_VIEWPORT
Nested widget containing a viewport.
Definition widget_type.h:73
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:61
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:49
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:71
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
@ SZSP_VERTICAL
Display plane with zero size horizontally, and filling and resizing vertically.
@ EqualSize
Containers should keep all their (resizing) children equally large.
void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen, bool schedule_resize)
Resize the window.
Definition window.cpp:2113
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1293
Window functions not directly related to making/drawing windows.
@ Construction
This window is used for construction; close it whenever changing company.
Definition window_gui.h:153
Twindow * AllocateWindowDescFront(WindowDesc &desc, WindowNumber window_number, Targs... extra_arguments)
Open a new window.
@ DisableVpScroll
Window does not do autoscroll,.
Definition window_gui.h:234
@ SBS_DOWN
Sort ascending.
Definition window_gui.h:219
@ SBS_UP
Sort descending.
Definition window_gui.h:220
@ Automatic
Find a place automatically.
Definition window_gui.h:144
int WidgetID
Widget ID.
Definition window_type.h:21
@ WC_TOWN_AUTHORITY
Town authority; Window numbers:
@ WC_FOUND_TOWN
Found a town; Window numbers:
@ WC_BUILD_HOUSE
Build house; Window numbers:
@ WC_BUILD_TOOLBAR
Build toolbar; Window numbers:
Definition window_type.h:79
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:51
@ WC_TOWN_VIEW
Town view; Window numbers:
@ WC_TOWN_DIRECTORY
Town directory; Window numbers:
Functions related to zooming.
int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
Definition zoom_func.h:107
ZoomLevel ScaleZoomGUI(ZoomLevel value)
Scale zoom level relative to GUI zoom.
Definition zoom_func.h:87
int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition zoom_func.h:77
@ Town
Default zoom level for the town view.
Definition zoom_type.h:37