OpenTTD Source 15.0-beta2
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 <http://www.gnu.org/licenses/>.
6 */
7
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"
37#include "genworld.h"
38#include "fios.h"
39#include "stringfilter_type.h"
40#include "dropdown_func.h"
41#include "town_kdtree.h"
42#include "town_cmd.h"
43#include "timer/timer.h"
45#include "timer/timer_window.h"
46#include "zoom_func.h"
47#include "hotkeys.h"
48
49#include "widgets/town_widget.h"
50
51#include "table/strings.h"
52
53#include "safeguards.h"
54
55TownKdtree _town_local_authority_kdtree{};
56
58
59static constexpr NWidgetPart _nested_town_authority_widgets[] = {
61 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
62 NWidget(WWT_CAPTION, COLOUR_BROWN, WID_TA_CAPTION),
63 NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TA_ZONE_BUTTON), SetMinimalSize(50, 0), SetStringTip(STR_LOCAL_AUTHORITY_ZONE, STR_LOCAL_AUTHORITY_ZONE_TOOLTIP),
64 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
65 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
66 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
68 NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_RATING_INFO), SetMinimalSize(317, 92), SetResize(1, 1), EndContainer(),
69 NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_COMMAND_LIST), SetMinimalSize(317, 52), SetResize(1, 0), SetToolTip(STR_LOCAL_AUTHORITY_ACTIONS_TOOLTIP), EndContainer(),
70 NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_ACTION_INFO), SetMinimalSize(317, 52), SetResize(1, 0), EndContainer(),
72 NWidget(WWT_PUSHTXTBTN, COLOUR_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),
73 NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
75};
76
79private:
80 Town *town = nullptr;
81 TownAction sel_action = TownAction::End;
85 std::array<StringID, to_underlying(TownAction::End)> action_tooltips{};
86
89
98 int GetNthSetBit(int n)
99 {
100 if (n >= 0) {
101 for (uint i : SetBitIterator(this->enabled_actions.base())) {
102 n--;
103 if (n < 0) return i;
104 }
105 }
106 return -1;
107 }
108
115 {
116 TownActions enabled{};
117 enabled.Set();
118
122 if (!_settings_game.economy.bribe) enabled.Reset(TownAction::Bribe);
123
124 return enabled;
125 }
126
127public:
129 {
130 this->town = Town::Get(window_number);
132
134 this->action_tooltips[0] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING;
135 this->action_tooltips[1] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING;
136 this->action_tooltips[2] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING;
137 this->action_tooltips[3] = realtime ? STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION_MINUTES : STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION_MONTHS;
138 this->action_tooltips[4] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY;
139 this->action_tooltips[5] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS;
140 this->action_tooltips[6] = realtime ? STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT_MINUTES : STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT_MONTHS;
141 this->action_tooltips[7] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE;
142
143 this->InitNested(window_number);
144 }
145
146 void OnInit() override
147 {
148 this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
149 this->exclusive_size = GetSpriteSize(SPR_EXCLUSIVE_TRANSPORT);
150 }
151
152 void OnPaint() override
153 {
157
159 this->SetWidgetDisabledState(WID_TA_EXECUTE, (this->sel_action == TownAction::End) || !this->available_actions.Test(this->sel_action));
160
161 this->DrawWidgets();
162 if (!this->IsShaded())
163 {
164 this->DrawRatings();
165 this->DrawActions();
166 }
167 }
168
169 StringID GetRatingString(int rating) const
170 {
171 if (rating > RATING_EXCELLENT) return STR_CARGO_RATING_OUTSTANDING;
172 if (rating > RATING_VERYGOOD) return STR_CARGO_RATING_EXCELLENT;
173 if (rating > RATING_GOOD) return STR_CARGO_RATING_VERY_GOOD;
174 if (rating > RATING_MEDIOCRE) return STR_CARGO_RATING_GOOD;
175 if (rating > RATING_POOR) return STR_CARGO_RATING_MEDIOCRE;
176 if (rating > RATING_VERYPOOR) return STR_CARGO_RATING_POOR;
177 if (rating > RATING_APPALLING) return STR_CARGO_RATING_VERY_POOR;
178 return STR_CARGO_RATING_APPALLING;
179 }
180
183 {
184 Rect r = this->GetWidget<NWidgetBase>(WID_TA_RATING_INFO)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
185
186 int text_y_offset = (this->resize.step_height - GetCharacterHeight(FS_NORMAL)) / 2;
187 int icon_y_offset = (this->resize.step_height - this->icon_size.height) / 2;
188 int exclusive_y_offset = (this->resize.step_height - this->exclusive_size.height) / 2;
189
190 DrawString(r.left, r.right, r.top + text_y_offset, STR_LOCAL_AUTHORITY_COMPANY_RATINGS);
191 r.top += this->resize.step_height;
192
193 bool rtl = _current_text_dir == TD_RTL;
194 Rect icon = r.WithWidth(this->icon_size.width, rtl);
195 Rect exclusive = r.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal, rtl).WithWidth(this->exclusive_size.width, rtl);
196 Rect text = r.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal + this->exclusive_size.width + WidgetDimensions::scaled.hsep_normal, rtl);
197
198 /* Draw list of companies */
199 for (const Company *c : Company::Iterate()) {
200 if ((this->town->have_ratings.Test(c->index) || this->town->exclusivity == c->index)) {
201 DrawCompanyIcon(c->index, icon.left, text.top + icon_y_offset);
202
203 if (this->town->exclusivity == c->index) {
204 DrawSprite(SPR_EXCLUSIVE_TRANSPORT, COMPANY_SPRITE_COLOUR(c->index), exclusive.left, text.top + exclusive_y_offset);
205 }
206
207 int rating = this->town->ratings[c->index];
208 DrawString(text.left, text.right, text.top + text_y_offset, GetString(STR_LOCAL_AUTHORITY_COMPANY_RATING, c->index, c->index, GetRatingString(rating)));
209 text.top += this->resize.step_height;
210 }
211 }
212
213 text.bottom = text.top - 1;
214 if (text.bottom > r.bottom) {
215 /* If the company list is too big to fit, mark ourself dirty and draw again. */
216 ResizeWindow(this, 0, text.bottom - r.bottom, false);
217 }
218 }
219
222 {
223 Rect r = this->GetWidget<NWidgetBase>(WID_TA_COMMAND_LIST)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
224
225 DrawString(r, STR_LOCAL_AUTHORITY_ACTIONS_TITLE);
227
228 /* Draw list of actions */
229 for (TownAction i = {}; i != TownAction::End; ++i) {
230 /* Don't show actions if disabled in settings. */
231 if (!this->enabled_actions.Test(i)) continue;
232
233 /* Set colour of action based on ability to execute and if selected. */
234 TextColour action_colour = TC_GREY | TC_NO_SHADE;
235 if (this->available_actions.Test(i)) action_colour = TC_ORANGE;
236 if (this->sel_action == i) action_colour = TC_WHITE;
237
238 DrawString(r, STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i), action_colour);
240 }
241 }
242
243 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
244 {
245 if (widget == WID_TA_CAPTION) return GetString(STR_LOCAL_AUTHORITY_CAPTION, this->window_number);
246
247 return this->Window::GetWidgetString(widget, stringid);
248 }
249
250 void DrawWidget(const Rect &r, WidgetID widget) const override
251 {
252 switch (widget) {
254 if (this->sel_action != TownAction::End) {
255 Money action_cost = _price[PR_TOWN_ACTION] * GetTownActionCost(this->sel_action) >> 8;
256 bool affordable = Company::IsValidID(_local_company) && action_cost < GetAvailableMoney(_local_company);
257
259 GetString(this->action_tooltips[to_underlying(this->sel_action)], action_cost),
260 affordable ? TC_YELLOW : TC_RED);
261 }
262 break;
263 }
264 }
265
266 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
267 {
268 switch (widget) {
269 case WID_TA_ACTION_INFO: {
270 assert(size.width > padding.width && size.height > padding.height);
271 Dimension d = {0, 0};
272 for (TownAction i = {}; i != TownAction::End; ++i) {
273 Money price = _price[PR_TOWN_ACTION] * GetTownActionCost(i) >> 8;
274 d = maxdim(d, GetStringMultiLineBoundingBox(GetString(this->action_tooltips[to_underlying(i)], price), size));
275 }
276 d.width += padding.width;
277 d.height += padding.height;
278 size = maxdim(size, d);
279 break;
280 }
281
283 size.height = (to_underlying(TownAction::End) + 1) * GetCharacterHeight(FS_NORMAL) + padding.height;
284 size.width = GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTIONS_TITLE).width;
285 for (TownAction i = {}; i != TownAction::End; ++i) {
286 size.width = std::max(size.width, GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i)).width + padding.width);
287 }
288 size.width += padding.width;
289 break;
290
293 size.height = 9 * resize.height + padding.height;
294 break;
295 }
296 }
297
298 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
299 {
300 switch (widget) {
301 case WID_TA_ZONE_BUTTON: {
302 bool new_show_state = !this->town->show_zone;
303 TownID index = this->town->index;
304
305 new_show_state ? _town_local_authority_kdtree.Insert(index) : _town_local_authority_kdtree.Remove(index);
306
307 this->town->show_zone = new_show_state;
308 this->SetWidgetLoweredState(widget, new_show_state);
310 break;
311 }
312
313 case WID_TA_COMMAND_LIST: {
315
316 y = GetNthSetBit(y);
317 if (y >= 0) {
318 this->sel_action = static_cast<TownAction>(y);
319 this->SetDirty();
320 }
321
322 /* When double-clicking, continue */
323 if (click_count == 1 || y < 0 || !this->available_actions.Test(this->sel_action)) break;
324 [[fallthrough]];
325 }
326
327 case WID_TA_EXECUTE:
328 Command<CMD_DO_TOWN_ACTION>::Post(STR_ERROR_CAN_T_DO_THIS, this->town->xy, static_cast<TownID>(this->window_number), this->sel_action);
329 break;
330 }
331 }
332
334 IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
335 this->SetDirty();
336 }};
337
338 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
339 {
340 if (!gui_scope) return;
341
342 this->enabled_actions = this->GetEnabledActions();
343 if (!this->enabled_actions.Test(this->sel_action)) {
344 this->sel_action = TownAction::End;
345 }
346 }
347};
348
349static WindowDesc _town_authority_desc(
350 WDP_AUTO, "view_town_authority", 317, 222,
352 {},
353 _nested_town_authority_widgets
354);
355
356static void ShowTownAuthorityWindow(uint town)
357{
358 AllocateWindowDescFront<TownAuthorityWindow>(_town_authority_desc, town);
359}
360
361
362/* Town view window. */
364private:
365 Town *town = nullptr;
366
367public:
368 static const int WID_TV_HEIGHT_NORMAL = 150;
369
371 {
372 this->CreateNestedTree();
373
374 this->town = Town::Get(window_number);
375 if (this->town->larger_town) this->GetWidget<NWidgetCore>(WID_TV_CAPTION)->SetString(STR_TOWN_VIEW_CITY_CAPTION);
376
377 this->FinishInitNested(window_number);
378
380 NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_TV_VIEWPORT);
381 nvp->InitializeViewport(this, this->town->xy, ScaleZoomGUI(ZOOM_LVL_TOWN));
382
383 /* disable renaming town in network games if you are not the server */
385 }
386
387 void Close([[maybe_unused]] int data = 0) override
388 {
390 this->Window::Close();
391 }
392
393 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
394 {
395 if (widget == WID_TV_CAPTION) return GetString(STR_TOWN_VIEW_TOWN_CAPTION, this->town->index);
396
397 return this->Window::GetWidgetString(widget, stringid);
398 }
399
400 void OnPaint() override
401 {
402 extern const Town *_viewport_highlight_town;
403 this->SetWidgetLoweredState(WID_TV_CATCHMENT, _viewport_highlight_town == this->town);
404
405 this->DrawWidgets();
406 }
407
408 void DrawWidget(const Rect &r, WidgetID widget) const override
409 {
410 if (widget != WID_TV_INFO) return;
411
412 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
413
414 DrawString(tr, GetString(STR_TOWN_VIEW_POPULATION_HOUSES, this->town->cache.population, this->town->cache.num_houses));
415 tr.top += GetCharacterHeight(FS_NORMAL);
416
417 StringID str_last_period = TimerGameEconomy::UsingWallclockUnits() ? STR_TOWN_VIEW_CARGO_LAST_MINUTE_MAX : STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX;
418
419 for (auto tpe : {TPE_PASSENGERS, TPE_MAIL}) {
420 for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) {
421 CargoType cargo_type = cs->Index();
422 DrawString(tr, GetString(str_last_period, 1ULL << cargo_type, this->town->supplied[cargo_type].old_act, this->town->supplied[cargo_type].old_max));
423 tr.top += GetCharacterHeight(FS_NORMAL);
424 }
425 }
426
427 bool first = true;
428 for (int i = TAE_BEGIN; i < TAE_END; i++) {
429 if (this->town->goal[i] == 0) continue;
430 if (this->town->goal[i] == TOWN_GROWTH_WINTER && (TileHeight(this->town->xy) < LowestSnowLine() || this->town->cache.population <= 90)) continue;
431 if (this->town->goal[i] == TOWN_GROWTH_DESERT && (GetTropicZone(this->town->xy) != TROPICZONE_DESERT || this->town->cache.population <= 60)) continue;
432
433 if (first) {
434 DrawString(tr, STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH);
435 tr.top += GetCharacterHeight(FS_NORMAL);
436 first = false;
437 }
438
439 bool rtl = _current_text_dir == TD_RTL;
440
442 assert(cargo != nullptr);
443
444 StringID string;
445
446 if (this->town->goal[i] == TOWN_GROWTH_DESERT || this->town->goal[i] == TOWN_GROWTH_WINTER) {
447 /* For 'original' gameplay, don't show the amount required (you need 1 or more ..) */
448 string = STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED_GENERAL;
449 if (this->town->received[i].old_act == 0) {
450 string = STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL;
451
452 if (this->town->goal[i] == TOWN_GROWTH_WINTER && TileHeight(this->town->xy) < GetSnowLine()) {
453 string = STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER;
454 }
455 }
456
457 DrawString(tr.Indent(20, rtl), GetString(string, cargo->name));
458 } else {
459 string = STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED;
460 if (this->town->received[i].old_act < this->town->goal[i]) {
461 string = STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED;
462 }
463 DrawString(tr.Indent(20, rtl), GetString(string, cargo->Index(), this->town->received[i].old_act, cargo->Index(), this->town->goal[i]));
464 }
465 tr.top += GetCharacterHeight(FS_NORMAL);
466 }
467
468 if (HasBit(this->town->flags, TOWN_IS_GROWING)) {
469 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)));
470 tr.top += GetCharacterHeight(FS_NORMAL);
471 } else {
472 DrawString(tr, STR_TOWN_VIEW_TOWN_GROW_STOPPED);
473 tr.top += GetCharacterHeight(FS_NORMAL);
474 }
475
476 /* only show the town noise, if the noise option is activated. */
478 DrawString(tr, GetString(STR_TOWN_VIEW_NOISE_IN_TOWN, this->town->noise_reached, this->town->MaxTownNoise()));
479 tr.top += GetCharacterHeight(FS_NORMAL);
480 }
481
482 if (!this->town->text.empty()) {
483 tr.top = DrawStringMultiLine(tr, this->town->text.GetDecodedString(), TC_BLACK);
484 }
485 }
486
487 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
488 {
489 switch (widget) {
490 case WID_TV_CENTER_VIEW: // scroll to location
491 if (_ctrl_pressed) {
492 ShowExtraViewportWindow(this->town->xy);
493 } else {
494 ScrollMainWindowToTile(this->town->xy);
495 }
496 break;
497
498 case WID_TV_SHOW_AUTHORITY: // town authority
499 ShowTownAuthorityWindow(this->window_number);
500 break;
501
502 case WID_TV_CHANGE_NAME: // rename
504 break;
505
506 case WID_TV_CATCHMENT:
508 break;
509
510 case WID_TV_EXPAND: { // expand town - only available on Scenario editor
511 Command<CMD_EXPAND_TOWN>::Post(STR_ERROR_CAN_T_EXPAND_TOWN, static_cast<TownID>(this->window_number), 0);
512 break;
513 }
514
515 case WID_TV_DELETE: // delete town - only available on Scenario editor
516 Command<CMD_DELETE_TOWN>::Post(STR_ERROR_TOWN_CAN_T_DELETE, static_cast<TownID>(this->window_number));
517 break;
518 }
519 }
520
521 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
522 {
523 switch (widget) {
524 case WID_TV_INFO:
525 size.height = GetDesiredInfoHeight(size.width) + padding.height;
526 break;
527 }
528 }
529
535 {
537
538 bool first = true;
539 for (int i = TAE_BEGIN; i < TAE_END; i++) {
540 if (this->town->goal[i] == 0) continue;
541 if (this->town->goal[i] == TOWN_GROWTH_WINTER && (TileHeight(this->town->xy) < LowestSnowLine() || this->town->cache.population <= 90)) continue;
542 if (this->town->goal[i] == TOWN_GROWTH_DESERT && (GetTropicZone(this->town->xy) != TROPICZONE_DESERT || this->town->cache.population <= 60)) continue;
543
544 if (first) {
545 aimed_height += GetCharacterHeight(FS_NORMAL);
546 first = false;
547 }
548 aimed_height += GetCharacterHeight(FS_NORMAL);
549 }
550 aimed_height += GetCharacterHeight(FS_NORMAL);
551
553
554 if (!this->town->text.empty()) {
556 }
557
558 return aimed_height;
559 }
560
561 void ResizeWindowAsNeeded()
562 {
563 const NWidgetBase *nwid_info = this->GetWidget<NWidgetBase>(WID_TV_INFO);
564 uint aimed_height = GetDesiredInfoHeight(nwid_info->current_x);
565 if (aimed_height > nwid_info->current_y || (aimed_height < nwid_info->current_y && nwid_info->current_y > nwid_info->smallest_y)) {
566 this->ReInit();
567 }
568 }
569
570 void OnResize() override
571 {
572 if (this->viewport != nullptr) {
573 NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_TV_VIEWPORT);
574 nvp->UpdateViewportCoordinates(this);
575
576 ScrollWindowToTile(this->town->xy, this, true); // Re-center viewport.
577 }
578 }
579
580 void OnMouseWheel(int wheel) override
581 {
583 DoZoomInOutWindow(wheel < 0 ? ZOOM_IN : ZOOM_OUT, this);
584 }
585 }
586
592 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
593 {
594 if (!gui_scope) return;
595 /* Called when setting station noise or required cargoes have changed, in order to resize the window */
596 this->SetDirty(); // refresh display for current size. This will allow to avoid glitches when downgrading
597 this->ResizeWindowAsNeeded();
598 }
599
600 void OnQueryTextFinished(std::optional<std::string> str) override
601 {
602 if (!str.has_value()) return;
603
604 Command<CMD_RENAME_TOWN>::Post(STR_ERROR_CAN_T_RENAME_TOWN, static_cast<TownID>(this->window_number), *str);
605 }
606
607 IntervalTimer<TimerGameCalendar> daily_interval = {{TimerGameCalendar::DAY, TimerGameCalendar::Priority::NONE}, [this](auto) {
608 /* Refresh after possible snowline change */
609 this->SetDirty();
610 }};
611};
612
613static constexpr NWidgetPart _nested_town_game_view_widgets[] = {
615 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
616 NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_TV_CHANGE_NAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME, STR_TOWN_VIEW_RENAME_TOOLTIP),
617 NWidget(WWT_CAPTION, COLOUR_BROWN, WID_TV_CAPTION),
618 NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_TV_CENTER_VIEW), SetAspect(WidgetDimensions::ASPECT_LOCATION), SetSpriteTip(SPR_GOTO_LOCATION, STR_TOWN_VIEW_CENTER_TOOLTIP),
619 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
620 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
621 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
622 EndContainer(),
623 NWidget(WWT_PANEL, COLOUR_BROWN),
624 NWidget(WWT_INSET, COLOUR_BROWN), SetPadding(2, 2, 2, 2),
625 NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_TV_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 0), SetResize(1, 1),
626 EndContainer(),
627 EndContainer(),
628 NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_INFO), SetMinimalSize(260, 32), SetResize(1, 0), SetFill(1, 0), EndContainer(),
630 NWidget(WWT_PUSHTXTBTN, COLOUR_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),
631 NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_CATCHMENT), SetMinimalSize(40, 12), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_BUTTON_CATCHMENT, STR_TOOLTIP_CATCHMENT),
632 NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
633 EndContainer(),
634};
635
636static WindowDesc _town_game_view_desc(
637 WDP_AUTO, "view_town", 260, TownViewWindow::WID_TV_HEIGHT_NORMAL,
639 {},
640 _nested_town_game_view_widgets
641);
642
643static constexpr NWidgetPart _nested_town_editor_view_widgets[] = {
645 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
646 NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_TV_CHANGE_NAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME, STR_TOWN_VIEW_RENAME_TOOLTIP),
647 NWidget(WWT_CAPTION, COLOUR_BROWN, WID_TV_CAPTION), SetStringTip(STR_TOWN_VIEW_TOWN_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
648 NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_TV_CENTER_VIEW), SetAspect(WidgetDimensions::ASPECT_LOCATION), SetSpriteTip(SPR_GOTO_LOCATION, STR_TOWN_VIEW_CENTER_TOOLTIP),
649 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
650 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
651 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
652 EndContainer(),
653 NWidget(WWT_PANEL, COLOUR_BROWN),
654 NWidget(WWT_INSET, COLOUR_BROWN), SetPadding(2, 2, 2, 2),
655 NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_TV_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 1), SetResize(1, 1),
656 EndContainer(),
657 EndContainer(),
658 NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_INFO), SetMinimalSize(260, 32), SetResize(1, 0), SetFill(1, 0), EndContainer(),
660 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TV_EXPAND), SetMinimalSize(80, 12), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_EXPAND_BUTTON, STR_TOWN_VIEW_EXPAND_TOOLTIP),
661 NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TV_DELETE), SetMinimalSize(80, 12), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_DELETE_BUTTON, STR_TOWN_VIEW_DELETE_TOOLTIP),
662 NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_CATCHMENT), SetMinimalSize(40, 12), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_BUTTON_CATCHMENT, STR_TOOLTIP_CATCHMENT),
663 NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
664 EndContainer(),
665};
666
667static WindowDesc _town_editor_view_desc(
668 WDP_AUTO, "view_town_scen", 260, TownViewWindow::WID_TV_HEIGHT_NORMAL,
670 {},
671 _nested_town_editor_view_widgets
672);
673
674void ShowTownViewWindow(TownID town)
675{
676 if (_game_mode == GM_EDITOR) {
677 AllocateWindowDescFront<TownViewWindow>(_town_editor_view_desc, town);
678 } else {
679 AllocateWindowDescFront<TownViewWindow>(_town_game_view_desc, town);
680 }
681}
682
683static constexpr NWidgetPart _nested_town_directory_widgets[] = {
685 NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
686 NWidget(WWT_CAPTION, COLOUR_BROWN, WID_TD_CAPTION),
687 NWidget(WWT_SHADEBOX, COLOUR_BROWN),
688 NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
689 NWidget(WWT_STICKYBOX, COLOUR_BROWN),
690 EndContainer(),
694 NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TD_SORT_ORDER), SetStringTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
695 NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_TD_SORT_CRITERIA), SetToolTip(STR_TOOLTIP_SORT_CRITERIA),
696 NWidget(WWT_EDITBOX, COLOUR_BROWN, WID_TD_FILTER), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
697 EndContainer(),
698 NWidget(WWT_PANEL, COLOUR_BROWN, WID_TD_LIST), SetToolTip(STR_TOWN_DIRECTORY_LIST_TOOLTIP),
700 NWidget(WWT_PANEL, COLOUR_BROWN),
701 NWidget(WWT_TEXT, INVALID_COLOUR, WID_TD_WORLD_POPULATION), SetPadding(2, 0, 2, 2), SetFill(1, 0), SetResize(1, 0),
702 EndContainer(),
703 EndContainer(),
706 NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
707 EndContainer(),
708 EndContainer(),
709};
710
715
718private:
719 /* Runtime saved values */
720 static Listing last_sorting;
721
722 /* Constants for sorting towns */
723 static inline const StringID sorter_names[] = {
724 STR_SORT_BY_NAME,
725 STR_SORT_BY_POPULATION,
726 STR_SORT_BY_RATING,
727 };
728 static const std::initializer_list<GUITownList::SortFunction * const> sorter_funcs;
729
732
733 GUITownList towns{TownDirectoryWindow::last_sorting.order};
734
735 Scrollbar *vscroll = nullptr;
736
737 void BuildSortTownList()
738 {
739 if (this->towns.NeedRebuild()) {
740 this->towns.clear();
741 this->towns.reserve(Town::GetNumItems());
742
743 for (const Town *t : Town::Iterate()) {
744 if (this->string_filter.IsEmpty()) {
745 this->towns.push_back(t);
746 continue;
747 }
749 this->string_filter.AddLine(t->GetCachedName());
750 if (this->string_filter.GetState()) this->towns.push_back(t);
751 }
752
753 this->towns.RebuildDone();
754 this->vscroll->SetCount(this->towns.size()); // Update scrollbar as well.
755 }
756 /* Always sort the towns. */
757 this->towns.Sort();
758 this->SetWidgetDirty(WID_TD_LIST); // Force repaint of the displayed towns.
759 }
760
762 static bool TownNameSorter(const Town * const &a, const Town * const &b, const bool &)
763 {
764 return StrNaturalCompare(a->GetCachedName(), b->GetCachedName()) < 0; // Sort by name (natural sorting).
765 }
766
768 static bool TownPopulationSorter(const Town * const &a, const Town * const &b, const bool &order)
769 {
770 uint32_t a_population = a->cache.population;
771 uint32_t b_population = b->cache.population;
772 if (a_population == b_population) return TownDirectoryWindow::TownNameSorter(a, b, order);
773 return a_population < b_population;
774 }
775
777 static bool TownRatingSorter(const Town * const &a, const Town * const &b, const bool &order)
778 {
779 bool before = !order; // Value to get 'a' before 'b'.
780
781 /* Towns without rating are always after towns with rating. */
784 int16_t a_rating = a->ratings[_local_company];
785 int16_t b_rating = b->ratings[_local_company];
786 if (a_rating == b_rating) return TownDirectoryWindow::TownNameSorter(a, b, order);
787 return a_rating < b_rating;
788 }
789 return before;
790 }
791 if (b->have_ratings.Test(_local_company)) return !before;
792
793 /* Sort unrated towns always on ascending town name. */
794 if (before) return TownDirectoryWindow::TownNameSorter(a, b, order);
795 return TownDirectoryWindow::TownNameSorter(b, a, order);
796 }
797
798public:
800 {
801 this->CreateNestedTree();
802
803 this->vscroll = this->GetScrollbar(WID_TD_SCROLLBAR);
804
805 this->towns.SetListing(this->last_sorting);
807 this->towns.ForceRebuild();
808 this->BuildSortTownList();
809
810 this->FinishInitNested(0);
811
813 this->townname_editbox.cancel_button = QueryString::ACTION_CLEAR;
814 }
815
816 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
817 {
818 switch (widget) {
819 case WID_TD_CAPTION:
820 return GetString(STR_TOWN_DIRECTORY_CAPTION, this->vscroll->GetCount(), Town::GetNumItems());
821
823 return GetString(STR_TOWN_POPULATION, GetWorldPopulation());
824
826 return GetString(TownDirectoryWindow::sorter_names[this->towns.SortType()]);
827
828 default:
829 return this->Window::GetWidgetString(widget, stringid);
830 }
831 }
832
838 static std::string GetTownString(const Town *t, uint64_t population)
839 {
840 return GetString(t->larger_town ? STR_TOWN_DIRECTORY_CITY : STR_TOWN_DIRECTORY_TOWN, t->index, population);
841 }
842
843 void DrawWidget(const Rect &r, WidgetID widget) const override
844 {
845 switch (widget) {
847 this->DrawSortButtonState(widget, this->towns.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
848 break;
849
850 case WID_TD_LIST: {
851 Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
852 if (this->towns.empty()) { // No towns available.
853 DrawString(tr, STR_TOWN_DIRECTORY_NONE);
854 break;
855 }
856
857 /* At least one town available. */
858 bool rtl = _current_text_dir == TD_RTL;
859 Dimension icon_size = GetSpriteSize(SPR_TOWN_RATING_GOOD);
860 int icon_x = tr.WithWidth(icon_size.width, rtl).left;
861 tr = tr.Indent(icon_size.width + WidgetDimensions::scaled.hsep_normal, rtl);
862
863 auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->towns);
864 for (auto it = first; it != last; ++it) {
865 const Town *t = *it;
866 assert(t->xy != INVALID_TILE);
867
868 /* Draw rating icon. */
869 if (_game_mode == GM_EDITOR || !t->have_ratings.Test(_local_company)) {
870 DrawSprite(SPR_TOWN_RATING_NA, PAL_NONE, icon_x, tr.top + (this->resize.step_height - icon_size.height) / 2);
871 } else {
872 SpriteID icon = SPR_TOWN_RATING_APALLING;
873 if (t->ratings[_local_company] > RATING_VERYPOOR) icon = SPR_TOWN_RATING_MEDIOCRE;
874 if (t->ratings[_local_company] > RATING_GOOD) icon = SPR_TOWN_RATING_GOOD;
875 DrawSprite(icon, PAL_NONE, icon_x, tr.top + (this->resize.step_height - icon_size.height) / 2);
876 }
877
878 DrawString(tr.left, tr.right, tr.top + (this->resize.step_height - GetCharacterHeight(FS_NORMAL)) / 2, GetTownString(t, t->cache.population));
879
880 tr.top += this->resize.step_height;
881 }
882 break;
883 }
884 }
885 }
886
887 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
888 {
889 switch (widget) {
890 case WID_TD_SORT_ORDER: {
891 Dimension d = GetStringBoundingBox(this->GetWidget<NWidgetCore>(widget)->GetString());
892 d.width += padding.width + Window::SortButtonWidth() * 2; // Doubled since the string is centred and it also looks better.
893 d.height += padding.height;
894 size = maxdim(size, d);
895 break;
896 }
898 Dimension d = GetStringListBoundingBox(TownDirectoryWindow::sorter_names);
899 d.width += padding.width;
900 d.height += padding.height;
901 size = maxdim(size, d);
902 break;
903 }
904 case WID_TD_LIST: {
905 Dimension d = GetStringBoundingBox(STR_TOWN_DIRECTORY_NONE);
906 uint64_t max_value = GetParamMaxDigits(8);
907 for (uint i = 0; i < this->towns.size(); i++) {
908 const Town *t = this->towns[i];
909
910 assert(t != nullptr);
911
912 d = maxdim(d, GetStringBoundingBox(GetTownString(t, max_value)));
913 }
914 Dimension icon_size = GetSpriteSize(SPR_TOWN_RATING_GOOD);
915 d.width += icon_size.width + 2;
916 d.height = std::max(d.height, icon_size.height);
917 resize.height = d.height;
918 d.height *= 5;
919 d.width += padding.width;
920 d.height += padding.height;
921 size = maxdim(size, d);
922 break;
923 }
925 Dimension d = GetStringBoundingBox(GetString(STR_TOWN_POPULATION, GetParamMaxDigits(10)));
926 d.width += padding.width;
927 d.height += padding.height;
928 size = maxdim(size, d);
929 break;
930 }
931 }
932 }
933
934 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
935 {
936 switch (widget) {
937 case WID_TD_SORT_ORDER: // Click on sort order button
938 if (this->towns.SortType() != 2) { // A different sort than by rating.
939 this->towns.ToggleSortOrder();
940 this->last_sorting = this->towns.GetListing(); // Store new sorting order.
941 } else {
942 /* Some parts are always sorted ascending on name. */
943 this->last_sorting.order = !this->last_sorting.order;
944 this->towns.SetListing(this->last_sorting);
945 this->towns.ForceResort();
946 this->towns.Sort();
947 }
948 this->SetDirty();
949 break;
950
951 case WID_TD_SORT_CRITERIA: // Click on sort criteria dropdown
952 ShowDropDownMenu(this, TownDirectoryWindow::sorter_names, this->towns.SortType(), WID_TD_SORT_CRITERIA, 0, 0);
953 break;
954
955 case WID_TD_LIST: { // Click on Town Matrix
956 auto it = this->vscroll->GetScrolledItemFromWidget(this->towns, pt.y, this, WID_TD_LIST, WidgetDimensions::scaled.framerect.top);
957 if (it == this->towns.end()) return; // click out of town bounds
958
959 const Town *t = *it;
960 assert(t != nullptr);
961 if (_ctrl_pressed) {
963 } else {
965 }
966 break;
967 }
968 }
969 }
970
971 void OnDropdownSelect(WidgetID widget, int index) override
972 {
973 if (widget != WID_TD_SORT_CRITERIA) return;
974
975 if (this->towns.SortType() != index) {
976 this->towns.SetSortType(index);
977 this->last_sorting = this->towns.GetListing(); // Store new sorting order.
978 this->BuildSortTownList();
979 }
980 }
981
982 void OnPaint() override
983 {
984 if (this->towns.NeedRebuild()) this->BuildSortTownList();
985 this->DrawWidgets();
986 }
987
989 IntervalTimer<TimerWindow> rebuild_interval = {std::chrono::seconds(3), [this](auto) {
990 this->BuildSortTownList();
991 this->SetDirty();
992 }};
993
994 void OnResize() override
995 {
996 this->vscroll->SetCapacityFromWidget(this, WID_TD_LIST, WidgetDimensions::scaled.framerect.Vertical());
997 }
998
999 void OnEditboxChanged(WidgetID wid) override
1000 {
1001 if (wid == WID_TD_FILTER) {
1002 this->string_filter.SetFilterTerm(this->townname_editbox.text.GetText());
1003 this->InvalidateData(TDIWD_FORCE_REBUILD);
1004 }
1005 }
1006
1012 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1013 {
1014 switch (data) {
1015 case TDIWD_FORCE_REBUILD:
1016 /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
1017 this->towns.ForceRebuild();
1018 break;
1019
1020 case TDIWD_POPULATION_CHANGE:
1021 if (this->towns.SortType() == 1) this->towns.ForceResort();
1022 break;
1023
1024 default:
1025 this->towns.ForceResort();
1026 }
1027 }
1028
1029 EventState OnHotkey(int hotkey) override
1030 {
1031 switch (hotkey) {
1034 SetFocusedWindow(this); // The user has asked to give focus to the text box, so make sure this window is focused.
1035 break;
1036 default:
1037 return ES_NOT_HANDLED;
1038 }
1039 return ES_HANDLED;
1040 }
1041
1042 static inline HotkeyList hotkeys {"towndirectory", {
1043 Hotkey('F', "focus_filter_box", TDHK_FOCUS_FILTER_BOX),
1044 }};
1045};
1046
1047Listing TownDirectoryWindow::last_sorting = {false, 0};
1048
1050const std::initializer_list<GUITownList::SortFunction * const> TownDirectoryWindow::sorter_funcs = {
1051 &TownNameSorter,
1052 &TownPopulationSorter,
1053 &TownRatingSorter,
1054};
1055
1056static WindowDesc _town_directory_desc(
1057 WDP_AUTO, "list_towns", 208, 202,
1059 {},
1060 _nested_town_directory_widgets,
1061 &TownDirectoryWindow::hotkeys
1062);
1063
1064void ShowTownDirectory()
1065{
1067 new TownDirectoryWindow(_town_directory_desc);
1068}
1069
1070void CcFoundTown(Commands, const CommandCost &result, TileIndex tile)
1071{
1072 if (result.Failed()) return;
1073
1074 if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_CONSTRUCTION_OTHER, tile);
1076}
1077
1078void CcFoundRandomTown(Commands, const CommandCost &result, Money, TownID town_id)
1079{
1080 if (result.Succeeded()) ScrollMainWindowToTile(Town::Get(town_id)->xy);
1081}
1082
1083static constexpr NWidgetPart _nested_found_town_widgets[] = {
1085 NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
1086 NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_FOUND_TOWN_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1087 NWidget(WWT_SHADEBOX, COLOUR_DARK_GREEN),
1088 NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
1089 EndContainer(),
1090 /* Construct new town(s) buttons. */
1091 NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
1093 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_NEW_TOWN), SetStringTip(STR_FOUND_TOWN_NEW_TOWN_BUTTON, STR_FOUND_TOWN_NEW_TOWN_TOOLTIP), SetFill(1, 0),
1096 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_RANDOM_TOWN), SetStringTip(STR_FOUND_TOWN_RANDOM_TOWN_BUTTON, STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP), SetFill(1, 0),
1097 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_MANY_RANDOM_TOWNS), SetStringTip(STR_FOUND_TOWN_MANY_RANDOM_TOWNS, STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP), SetFill(1, 0),
1098 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_LOAD_FROM_FILE), SetStringTip(STR_FOUND_TOWN_LOAD_FROM_FILE, STR_FOUND_TOWN_LOAD_FROM_FILE_TOOLTIP), SetFill(1, 0),
1099 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_EXPAND_ALL_TOWNS), SetStringTip(STR_FOUND_TOWN_EXPAND_ALL_TOWNS, STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP), SetFill(1, 0),
1100 EndContainer(),
1101 EndContainer(),
1102
1103 /* Town name selection. */
1104 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_FOUND_TOWN_NAME_TITLE),
1105 NWidget(WWT_EDITBOX, COLOUR_GREY, WID_TF_TOWN_NAME_EDITBOX), SetStringTip(STR_FOUND_TOWN_NAME_EDITOR_TITLE, STR_FOUND_TOWN_NAME_EDITOR_TOOLTIP), SetFill(1, 0),
1106 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_TOWN_NAME_RANDOM), SetStringTip(STR_FOUND_TOWN_NAME_RANDOM_BUTTON, STR_FOUND_TOWN_NAME_RANDOM_TOOLTIP), SetFill(1, 0),
1107
1108 /* Town size selection. */
1109 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_FOUND_TOWN_INITIAL_SIZE_TITLE),
1112 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_SMALL), SetStringTip(STR_FOUND_TOWN_INITIAL_SIZE_SMALL_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP), SetFill(1, 0),
1113 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_MEDIUM), SetStringTip(STR_FOUND_TOWN_INITIAL_SIZE_MEDIUM_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP), SetFill(1, 0),
1114 EndContainer(),
1116 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_TF_SIZE_SEL),
1117 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_LARGE), SetStringTip(STR_FOUND_TOWN_INITIAL_SIZE_LARGE_BUTTON, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP), SetFill(1, 0),
1118 EndContainer(),
1119 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_SIZE_RANDOM), SetStringTip(STR_FOUND_TOWN_SIZE_RANDOM, STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP), SetFill(1, 0),
1120 EndContainer(),
1121 EndContainer(),
1122 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_CITY), SetStringTip(STR_FOUND_TOWN_CITY, STR_FOUND_TOWN_CITY_TOOLTIP), SetFill(1, 0),
1123
1124 /* Town roads selection. */
1127 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_FOUND_TOWN_ROAD_LAYOUT),
1130 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_ORIGINAL), SetStringTip(STR_FOUND_TOWN_SELECT_LAYOUT_ORIGINAL, STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP), SetFill(1, 0),
1131 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_BETTER), SetStringTip(STR_FOUND_TOWN_SELECT_LAYOUT_BETTER_ROADS, STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP), SetFill(1, 0),
1132 EndContainer(),
1134 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_GRID2), SetStringTip(STR_FOUND_TOWN_SELECT_LAYOUT_2X2_GRID, STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP), SetFill(1, 0),
1135 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_GRID3), SetStringTip(STR_FOUND_TOWN_SELECT_LAYOUT_3X3_GRID, STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP), SetFill(1, 0),
1136 EndContainer(),
1137 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_TF_LAYOUT_RANDOM), SetStringTip(STR_FOUND_TOWN_SELECT_LAYOUT_RANDOM, STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP), SetFill(1, 0),
1138 EndContainer(),
1139 EndContainer(),
1140 EndContainer(),
1141 EndContainer(),
1142 EndContainer(),
1143};
1144
1147private:
1150 bool city = false;
1152 bool townnamevalid = false;
1153 uint32_t townnameparts = 0;
1155
1156public:
1158 Window(desc),
1161 params(_settings_game.game_creation.town_name)
1162 {
1163 this->InitNested(window_number);
1165 this->RandomTownName();
1166 this->UpdateButtons(true);
1167 }
1168
1169 void OnInit() override
1170 {
1171 if (_game_mode == GM_EDITOR) return;
1172
1173 this->GetWidget<NWidgetStacked>(WID_TF_TOWN_ACTION_SEL)->SetDisplayedPlane(SZSP_HORIZONTAL);
1174 this->GetWidget<NWidgetStacked>(WID_TF_SIZE_SEL)->SetDisplayedPlane(SZSP_VERTICAL);
1176 this->GetWidget<NWidgetStacked>(WID_TF_ROAD_LAYOUT_SEL)->SetDisplayedPlane(SZSP_HORIZONTAL);
1177 } else {
1178 this->GetWidget<NWidgetStacked>(WID_TF_ROAD_LAYOUT_SEL)->SetDisplayedPlane(0);
1179 }
1180 }
1181
1182 void RandomTownName()
1183 {
1184 this->townnamevalid = GenerateTownName(_interactive_random, &this->townnameparts);
1185
1186 if (!this->townnamevalid) {
1187 this->townname_editbox.text.DeleteAll();
1188 } else {
1189 this->townname_editbox.text.Assign(GetTownName(&this->params, this->townnameparts));
1190 }
1192
1194 }
1195
1196 void UpdateButtons(bool check_availability)
1197 {
1198 if (check_availability && _game_mode != GM_EDITOR) {
1200 this->ReInit();
1201 }
1202
1203 for (WidgetID i = WID_TF_SIZE_SMALL; i <= WID_TF_SIZE_RANDOM; i++) {
1204 this->SetWidgetLoweredState(i, i == WID_TF_SIZE_SMALL + this->town_size);
1205 }
1206
1207 this->SetWidgetLoweredState(WID_TF_CITY, this->city);
1208
1211 }
1212
1213 this->SetDirty();
1214 }
1215
1216 template <typename Tcallback>
1217 void ExecuteFoundTownCommand(TileIndex tile, bool random, StringID errstr, Tcallback cc)
1218 {
1219 std::string name;
1220
1221 if (!this->townnamevalid) {
1222 name = this->townname_editbox.text.GetText();
1223 } else {
1224 /* If user changed the name, send it */
1225 std::string original_name = GetTownName(&this->params, this->townnameparts);
1226 if (original_name != this->townname_editbox.text.GetText()) name = this->townname_editbox.text.GetText();
1227 }
1228
1229 bool success = Command<CMD_FOUND_TOWN>::Post(errstr, cc,
1230 tile, this->town_size, this->city, this->town_layout, random, townnameparts, name);
1231
1232 /* Rerandomise name, if success and no cost-estimation. */
1233 if (success && !_shift_pressed) this->RandomTownName();
1234 }
1235
1236 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1237 {
1238 switch (widget) {
1239 case WID_TF_NEW_TOWN:
1240 HandlePlacePushButton(this, WID_TF_NEW_TOWN, SPR_CURSOR_TOWN, HT_RECT);
1241 break;
1242
1243 case WID_TF_RANDOM_TOWN:
1244 this->ExecuteFoundTownCommand(TileIndex{}, true, STR_ERROR_CAN_T_GENERATE_TOWN, CcFoundRandomTown);
1245 break;
1246
1248 this->RandomTownName();
1250 break;
1251
1253 Backup<bool> old_generating_world(_generating_world, true);
1255 if (!GenerateTowns(this->town_layout)) {
1256 ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_GENERATE_TOWN), GetEncodedString(STR_ERROR_NO_SPACE_FOR_TOWN), WL_INFO);
1257 }
1259 old_generating_world.Restore();
1260 break;
1261 }
1262
1265 break;
1266
1268 for (Town *t : Town::Iterate()) {
1270 }
1271 break;
1272
1274 this->town_size = (TownSize)(widget - WID_TF_SIZE_SMALL);
1275 this->UpdateButtons(false);
1276 break;
1277
1278 case WID_TF_CITY:
1279 this->city ^= true;
1280 this->SetWidgetLoweredState(WID_TF_CITY, this->city);
1281 this->SetDirty();
1282 break;
1283
1286 this->town_layout = (TownLayout)(widget - WID_TF_LAYOUT_ORIGINAL);
1287
1288 /* If we are in the editor, sync the settings of the current game to the chosen layout,
1289 * so that importing towns from file uses the selected layout. */
1290 if (_game_mode == GM_EDITOR) _settings_game.economy.town_layout = this->town_layout;
1291
1292 this->UpdateButtons(false);
1293 break;
1294 }
1295 }
1296
1297 void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
1298 {
1299 this->ExecuteFoundTownCommand(tile, false, STR_ERROR_CAN_T_FOUND_TOWN_HERE, CcFoundTown);
1300 }
1301
1302 void OnPlaceObjectAbort() override
1303 {
1304 this->RaiseButtons();
1305 this->UpdateButtons(false);
1306 }
1307
1313 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1314 {
1315 if (!gui_scope) return;
1316 this->UpdateButtons(true);
1317 }
1318};
1319
1320static WindowDesc _found_town_desc(
1321 WDP_AUTO, "build_town", 160, 162,
1324 _nested_found_town_widgets
1325);
1326
1327void ShowFoundTownWindow()
1328{
1329 if (_game_mode != GM_EDITOR && !Company::IsValidID(_local_company)) return;
1330 AllocateWindowDescFront<FoundTownWindow>(_found_town_desc, 0);
1331}
1332
1333void InitializeTownGui()
1334{
1335 _town_local_authority_kdtree.Clear();
1336}
1337
1346void DrawNewHouseTileInGUI(int x, int y, const HouseSpec *spec, HouseID house_id, int view)
1347{
1348 HouseResolverObject object(house_id, INVALID_TILE, nullptr, CBID_NO_CALLBACK, 0, 0, true, view);
1349 const SpriteGroup *group = object.Resolve();
1350 if (group == nullptr || group->type != SGT_TILELAYOUT) return;
1351
1352 uint8_t stage = TOWN_HOUSE_COMPLETED;
1353 const DrawTileSprites *dts = reinterpret_cast<const TileLayoutSpriteGroup *>(group)->ProcessRegisters(&stage);
1354
1355 PaletteID palette = GENERAL_SPRITE_COLOUR(spec->random_colour[0]);
1357 uint16_t callback = GetHouseCallback(CBID_HOUSE_COLOUR, 0, 0, house_id, nullptr, INVALID_TILE, true, view);
1358 if (callback != CALLBACK_FAILED) {
1359 /* If bit 14 is set, we should use a 2cc colour map, else use the callback value. */
1360 palette = HasBit(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback;
1361 }
1362 }
1363
1364 SpriteID image = dts->ground.sprite;
1365 PaletteID pal = dts->ground.pal;
1366
1367 if (HasBit(image, SPRITE_MODIFIER_CUSTOM_SPRITE)) image += stage;
1368 if (HasBit(pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) pal += stage;
1369
1370 if (GB(image, 0, SPRITE_WIDTH) != 0) {
1371 DrawSprite(image, GroundSpritePaletteTransform(image, pal, palette), x, y);
1372 }
1373
1374 DrawNewGRFTileSeqInGUI(x, y, dts, stage, palette);
1375}
1376
1384void DrawHouseInGUI(int x, int y, HouseID house_id, int view)
1385{
1386 auto draw = [](int x, int y, HouseID house_id, int view) {
1387 if (house_id >= NEW_HOUSE_OFFSET) {
1388 /* Houses don't necessarily need new graphics. If they don't have a
1389 * spritegroup associated with them, then the sprite for the substitute
1390 * house id is drawn instead. */
1391 const HouseSpec *spec = HouseSpec::Get(house_id);
1392 if (spec->grf_prop.GetSpriteGroup() != nullptr) {
1393 DrawNewHouseTileInGUI(x, y, spec, house_id, view);
1394 return;
1395 } else {
1396 house_id = HouseSpec::Get(house_id)->grf_prop.subst_id;
1397 }
1398 }
1399
1400 /* Retrieve data from the draw town tile struct */
1401 const DrawBuildingsTileStruct &dcts = GetTownDrawTileData()[house_id << 4 | view << 2 | TOWN_HOUSE_COMPLETED];
1402 DrawSprite(dcts.ground.sprite, dcts.ground.pal, x, y);
1403
1404 /* Add a house on top of the ground? */
1405 if (dcts.building.sprite != 0) {
1406 Point pt = RemapCoords(dcts.subtile_x, dcts.subtile_y, 0);
1407 DrawSprite(dcts.building.sprite, dcts.building.pal, x + ScaleSpriteTrad(pt.x), y + ScaleSpriteTrad(pt.y));
1408 }
1409 };
1410
1411 /* Houses can have 1x1, 1x2, 2x1 and 2x2 layouts which are individual HouseIDs. For the GUI we need
1412 * draw all of the tiles with appropriate positions. */
1413 int x_delta = ScaleSpriteTrad(TILE_PIXELS);
1414 int y_delta = ScaleSpriteTrad(TILE_PIXELS / 2);
1415
1416 const HouseSpec *hs = HouseSpec::Get(house_id);
1417 if (hs->building_flags.Test(BuildingFlag::Size2x2)) {
1418 draw(x, y - y_delta - y_delta, house_id, view); // North corner.
1419 draw(x + x_delta, y - y_delta, house_id + 1, view); // West corner.
1420 draw(x - x_delta, y - y_delta, house_id + 2, view); // East corner.
1421 draw(x, y, house_id + 3, view); // South corner.
1422 } else if (hs->building_flags.Test(BuildingFlag::Size2x1)) {
1423 draw(x + x_delta / 2, y - y_delta, house_id, view); // North east tile.
1424 draw(x - x_delta / 2, y, house_id + 1, view); // South west tile.
1425 } else if (hs->building_flags.Test(BuildingFlag::Size1x2)) {
1426 draw(x - x_delta / 2, y - y_delta, house_id, view); // North west tile.
1427 draw(x + x_delta / 2, y, house_id + 1, view); // South east tile.
1428 } else {
1429 draw(x, y, house_id, view);
1430 }
1431}
1432
1439{
1440 uint16_t callback_res = GetHouseCallback(CBID_HOUSE_CUSTOM_NAME, 1, 0, hs->Index(), nullptr, INVALID_TILE, true);
1441 if (callback_res != CALLBACK_FAILED && callback_res != 0x400) {
1442 if (callback_res > 0x400) {
1444 } else {
1445 StringID new_name = GetGRFStringID(hs->grf_prop.grffile->grfid, GRFSTR_MISC_GRF_TEXT + callback_res);
1446 if (new_name != STR_NULL && new_name != STR_UNDEFINED) {
1447 return new_name;
1448 }
1449 }
1450 }
1451
1452 return hs->building_name;
1453}
1454
1456public:
1457 HousePickerCallbacks() : PickerCallbacks("fav_houses") {}
1458
1463 {
1465 case LandscapeType::Temperate: this->climate_mask = HZ_TEMP; break;
1466 case LandscapeType::Arctic: this->climate_mask = HZ_SUBARTC_ABOVE | HZ_SUBARTC_BELOW; break;
1467 case LandscapeType::Tropic: this->climate_mask = HZ_SUBTROPIC; break;
1468 case LandscapeType::Toyland: this->climate_mask = HZ_TOYLND; break;
1469 default: NOT_REACHED();
1470 }
1471
1472 /* In some cases, not all 'classes' (house zones) have distinct houses, so we need to disable those.
1473 * As we need to check all types, and this cannot change with the picker window open, pre-calculate it.
1474 * This loop calls GetTypeName() instead of directly checking properties so that there is no discrepancy. */
1475 this->class_mask = 0;
1476
1477 int num_classes = this->GetClassCount();
1478 for (int cls_id = 0; cls_id < num_classes; ++cls_id) {
1479 int num_types = this->GetTypeCount(cls_id);
1480 for (int id = 0; id < num_types; ++id) {
1481 if (this->GetTypeName(cls_id, id) != INVALID_STRING_ID) {
1482 SetBit(this->class_mask, cls_id);
1483 break;
1484 }
1485 }
1486 }
1487 }
1488
1489 HouseZones climate_mask{};
1490 uint8_t class_mask = 0;
1491
1492 static inline int sel_class;
1493 static inline int sel_type;
1494 static inline int sel_view;
1495
1496 /* Houses do not have classes like NewGRFClass. We'll make up fake classes based on town zone
1497 * availability instead. */
1498 static inline const std::array<StringID, HZB_END> zone_names = {
1499 STR_HOUSE_PICKER_CLASS_ZONE1,
1500 STR_HOUSE_PICKER_CLASS_ZONE2,
1501 STR_HOUSE_PICKER_CLASS_ZONE3,
1502 STR_HOUSE_PICKER_CLASS_ZONE4,
1503 STR_HOUSE_PICKER_CLASS_ZONE5,
1504 };
1505
1506 GrfSpecFeature GetFeature() const override { return GSF_HOUSES; }
1507
1508 StringID GetClassTooltip() const override { return STR_PICKER_HOUSE_CLASS_TOOLTIP; }
1509 StringID GetTypeTooltip() const override { return STR_PICKER_HOUSE_TYPE_TOOLTIP; }
1510 bool IsActive() const override { return true; }
1511
1512 bool HasClassChoice() const override { return true; }
1513 int GetClassCount() const override { return static_cast<int>(zone_names.size()); }
1514
1515 void Close([[maybe_unused]] int data) override { ResetObjectToPlace(); }
1516
1517 int GetSelectedClass() const override { return HousePickerCallbacks::sel_class; }
1518 void SetSelectedClass(int cls_id) const override { HousePickerCallbacks::sel_class = cls_id; }
1519
1520 StringID GetClassName(int id) const override
1521 {
1522 if (id >= GetClassCount()) return INVALID_STRING_ID;
1523 if (!HasBit(this->class_mask, id)) return INVALID_STRING_ID;
1524 return zone_names[id];
1525 }
1526
1527 int GetTypeCount(int cls_id) const override
1528 {
1529 if (cls_id < GetClassCount()) return static_cast<int>(HouseSpec::Specs().size());
1530 return 0;
1531 }
1532
1533 PickerItem GetPickerItem(int cls_id, int id) const override
1534 {
1535 const auto *spec = HouseSpec::Get(id);
1536 if (!spec->grf_prop.HasGrfFile()) return {0, spec->Index(), cls_id, id};
1537 return {spec->grf_prop.grfid, spec->grf_prop.local_id, cls_id, id};
1538 }
1539
1540 int GetSelectedType() const override { return sel_type; }
1541 void SetSelectedType(int id) const override { sel_type = id; }
1542
1543 StringID GetTypeName(int cls_id, int id) const override
1544 {
1545 const HouseSpec *spec = HouseSpec::Get(id);
1546 if (spec == nullptr) return INVALID_STRING_ID;
1547 if (!spec->enabled) return INVALID_STRING_ID;
1548 if ((spec->building_availability & climate_mask) == 0) return INVALID_STRING_ID;
1549 if (!HasBit(spec->building_availability, cls_id)) return INVALID_STRING_ID;
1550 for (int i = 0; i < cls_id; i++) {
1551 /* Don't include if it's already included in an earlier zone. */
1552 if (HasBit(spec->building_availability, i)) return INVALID_STRING_ID;
1553 }
1554
1555 return GetHouseName(spec);
1556 }
1557
1558 std::span<const BadgeID> GetTypeBadges(int cls_id, int id) const override
1559 {
1560 const auto *spec = HouseSpec::Get(id);
1561 if (spec == nullptr) return {};
1562 if (!spec->enabled) return {};
1563 if ((spec->building_availability & climate_mask) == 0) return {};
1564 if (!HasBit(spec->building_availability, cls_id)) return {};
1565 for (int i = 0; i < cls_id; i++) {
1566 /* Don't include if it's already included in an earlier zone. */
1567 if (HasBit(spec->building_availability, i)) return {};
1568 }
1569
1570 return spec->badges;
1571 }
1572
1573 bool IsTypeAvailable(int, int id) const override
1574 {
1575 const HouseSpec *hs = HouseSpec::Get(id);
1576 return hs->enabled;
1577 }
1578
1579 void DrawType(int x, int y, int, int id) const override
1580 {
1582 }
1583
1584 void FillUsedItems(std::set<PickerItem> &items) override
1585 {
1586 auto id_count = GetBuildingHouseIDCounts();
1587 for (auto it = id_count.begin(); it != id_count.end(); ++it) {
1588 if (*it == 0) continue;
1589 HouseID house = static_cast<HouseID>(std::distance(id_count.begin(), it));
1590 const HouseSpec *hs = HouseSpec::Get(house);
1591 int class_index = FindFirstBit(hs->building_availability & HZ_ZONALL);
1592 items.insert({0, house, class_index, house});
1593 }
1594 }
1595
1596 std::set<PickerItem> UpdateSavedItems(const std::set<PickerItem> &src) override
1597 {
1598 if (src.empty()) return src;
1599
1600 const auto &specs = HouseSpec::Specs();
1601 std::set<PickerItem> dst;
1602 for (const auto &item : src) {
1603 if (item.grfid == 0) {
1604 dst.insert(item);
1605 } else {
1606 /* Search for spec by grfid and local index. */
1607 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; });
1608 if (it == specs.end()) {
1609 /* Not preset, hide from UI. */
1610 dst.insert({item.grfid, item.local_id, -1, -1});
1611 } else {
1612 int class_index = FindFirstBit(it->building_availability & HZ_ZONALL);
1613 dst.insert( {item.grfid, item.local_id, class_index, it->Index()});
1614 }
1615 }
1616 }
1617
1618 return dst;
1619 }
1620
1621 static HousePickerCallbacks instance;
1622};
1623/* static */ HousePickerCallbacks HousePickerCallbacks::instance;
1624
1630static CargoTypes GetProducedCargoOfHouse(const HouseSpec *hs)
1631{
1632 CargoTypes produced{};
1634 for (uint i = 0; i < 256; i++) {
1635 uint16_t callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, 0, hs->Index(), nullptr, INVALID_TILE, true);
1636
1637 if (callback == CALLBACK_FAILED || callback == CALLBACK_HOUSEPRODCARGO_END) break;
1638
1639 CargoType cargo = GetCargoTranslation(GB(callback, 8, 7), hs->grf_prop.grffile);
1640 if (!IsValidCargoType(cargo)) continue;
1641
1642 uint amt = GB(callback, 0, 8);
1643 if (amt == 0) continue;
1644
1645 SetBit(produced, cargo);
1646 }
1647 } else {
1648 /* Cargo is not controlled by NewGRF, town production effect is used instead. */
1649 for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_PASSENGERS]) SetBit(produced, cs->Index());
1650 for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_MAIL]) SetBit(produced, cs->Index());
1651 }
1652 return produced;
1653}
1654
1656 std::string house_info{};
1657 bool house_protected = false;
1658
1659 BuildHouseWindow(WindowDesc &desc, Window *parent) : PickerWindow(desc, parent, 0, HousePickerCallbacks::instance)
1660 {
1661 HousePickerCallbacks::instance.SetClimateMask();
1662 this->ConstructWindow();
1663 }
1664
1665 void UpdateSelectSize(const HouseSpec *spec)
1666 {
1667 if (spec == nullptr) {
1668 SetTileSelectSize(1, 1);
1670 } else {
1671 SetObjectToPlaceWnd(SPR_CURSOR_TOWN, PAL_NONE, HT_RECT | HT_DIAGONAL, this);
1672 if (spec->building_flags.Test(BuildingFlag::Size2x2)) {
1673 SetTileSelectSize(2, 2);
1674 } else if (spec->building_flags.Test(BuildingFlag::Size2x1)) {
1675 SetTileSelectSize(2, 1);
1676 } else if (spec->building_flags.Test(BuildingFlag::Size1x2)) {
1677 SetTileSelectSize(1, 2);
1678 } else if (spec->building_flags.Test(BuildingFlag::Size1x1)) {
1679 SetTileSelectSize(1, 1);
1680 }
1681 }
1682 }
1683
1690 static std::string GetHouseYear(TimerGameCalendar::Year min_year, TimerGameCalendar::Year max_year)
1691 {
1692 if (min_year == CalendarTime::MIN_YEAR) {
1693 if (max_year == CalendarTime::MAX_YEAR) {
1694 return GetString(STR_HOUSE_PICKER_YEARS_ANY);
1695 }
1696 return GetString(STR_HOUSE_PICKER_YEARS_UNTIL, max_year);
1697 }
1698 if (max_year == CalendarTime::MAX_YEAR) {
1699 return GetString(STR_HOUSE_PICKER_YEARS_FROM, min_year);
1700 }
1701 return GetString(STR_HOUSE_PICKER_YEARS, min_year, max_year);
1702 }
1703
1709 static std::string GetHouseInformation(const HouseSpec *hs)
1710 {
1711 std::stringstream line;
1712
1713 line << GetString(STR_HOUSE_PICKER_NAME, GetHouseName(hs));
1714 line << "\n";
1715
1716 line << GetString(STR_HOUSE_PICKER_POPULATION, hs->population);
1717 line << "\n";
1718
1719 line << GetHouseYear(hs->min_year, hs->max_year);
1720 line << "\n";
1721
1722 uint8_t size = 0;
1723 if (hs->building_flags.Test(BuildingFlag::Size1x1)) size = 0x11;
1724 if (hs->building_flags.Test(BuildingFlag::Size2x1)) size = 0x21;
1725 if (hs->building_flags.Test(BuildingFlag::Size1x2)) size = 0x12;
1726 if (hs->building_flags.Test(BuildingFlag::Size2x2)) size = 0x22;
1727 line << GetString(STR_HOUSE_PICKER_SIZE, GB(size, 0, 4), GB(size, 4, 4));
1728
1729 auto cargo_string = BuildCargoAcceptanceString(GetAcceptedCargoOfHouse(hs), STR_HOUSE_PICKER_CARGO_ACCEPTED);
1730 if (cargo_string.has_value()) {
1731 line << "\n";
1732 line << *cargo_string;
1733 }
1734
1735 CargoTypes produced = GetProducedCargoOfHouse(hs);
1736 if (produced != 0) {
1737 line << "\n";
1738 line << GetString(STR_HOUSE_PICKER_CARGO_PRODUCED, produced);
1739 }
1740
1741 return line.str();
1742 }
1743
1744 void OnInit() override
1745 {
1746 this->InvalidateData(PickerInvalidation::Position);
1747 this->PickerWindow::OnInit();
1748 }
1749
1750 void DrawWidget(const Rect &r, WidgetID widget) const override
1751 {
1752 if (widget == WID_BH_INFO) {
1753 if (!this->house_info.empty()) DrawStringMultiLine(r, this->house_info);
1754 } else {
1755 this->PickerWindow::DrawWidget(r, widget);
1756 }
1757 }
1758
1759 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1760 {
1761 switch (widget) {
1762 case WID_BH_PROTECT_OFF:
1763 case WID_BH_PROTECT_ON:
1764 this->house_protected = (widget == WID_BH_PROTECT_ON);
1765 this->SetWidgetLoweredState(WID_BH_PROTECT_OFF, !this->house_protected);
1766 this->SetWidgetLoweredState(WID_BH_PROTECT_ON, this->house_protected);
1767
1769 this->SetDirty();
1770 break;
1771
1772 default:
1773 this->PickerWindow::OnClick(pt, widget, click_count);
1774 break;
1775 }
1776 }
1777
1778 void OnInvalidateData(int data = 0, bool gui_scope = true) override
1779 {
1780 this->PickerWindow::OnInvalidateData(data, gui_scope);
1781 if (!gui_scope) return;
1782
1784
1785 PickerInvalidations pi(data);
1787 UpdateSelectSize(spec);
1788 this->house_info = GetHouseInformation(spec);
1789 }
1790
1791 /* If house spec already has the protected flag, handle it automatically and disable the buttons. */
1793 if (hasflag) this->house_protected = true;
1794
1795 this->SetWidgetLoweredState(WID_BH_PROTECT_OFF, !this->house_protected);
1796 this->SetWidgetLoweredState(WID_BH_PROTECT_ON, this->house_protected);
1797
1800 }
1801
1802 void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
1803 {
1805 Command<CMD_PLACE_HOUSE>::Post(STR_ERROR_CAN_T_BUILD_HOUSE, CcPlaySound_CONSTRUCTION_OTHER, tile, spec->Index(), this->house_protected);
1806 }
1807
1808 IntervalTimer<TimerWindow> view_refresh_interval = {std::chrono::milliseconds(2500), [this](auto) {
1809 /* There are four different 'views' that are random based on house tile position. As this is not
1810 * user-controllable, instead we automatically cycle through them. */
1812 this->SetDirty();
1813 }};
1814
1815 static inline HotkeyList hotkeys{"buildhouse", {
1816 Hotkey('F', "focus_filter_box", PCWHK_FOCUS_FILTER_BOX),
1817 }};
1818};
1819
1823 NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
1824 NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_HOUSE_PICKER_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1825 NWidget(WWT_SHADEBOX, COLOUR_DARK_GREEN),
1826 NWidget(WWT_DEFSIZEBOX, COLOUR_DARK_GREEN),
1827 NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
1828 EndContainer(),
1832 NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
1834 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BH_INFO), SetFill(1, 1), SetMinimalTextLines(10, 0),
1835 NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_HOUSE_PICKER_PROTECT_TITLE, STR_NULL), SetFill(1, 0),
1837 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BH_PROTECT_OFF), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_PROTECT_OFF, STR_HOUSE_PICKER_PROTECT_TOOLTIP),
1838 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BH_PROTECT_ON), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_PROTECT_ON, STR_HOUSE_PICKER_PROTECT_TOOLTIP),
1839 EndContainer(),
1840 EndContainer(),
1841 EndContainer(),
1842
1843 EndContainer(),
1845 EndContainer(),
1846};
1847
1848static WindowDesc _build_house_desc(
1849 WDP_AUTO, "build_house", 0, 0,
1853 &BuildHouseWindow::hotkeys
1854);
1855
1856void ShowBuildHousePicker(Window *parent)
1857{
1858 if (BringWindowToFrontById(WC_BUILD_HOUSE, 0)) return;
1859 new BuildHouseWindow(_build_house_desc, parent);
1860}
Class for backupping variables and making sure they are restored later.
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
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.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:23
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:106
std::optional< std::string > BuildCargoAcceptanceString(const CargoArray &acceptance, StringID label)
Build comma-separated cargo acceptance string.
@ TPE_PASSENGERS
Cargo behaves passenger-like for production.
Definition cargotype.h:37
@ TPE_MAIL
Cargo behaves mail-like for production.
Definition cargotype.h:38
TownAcceptanceEffect
Town growth effect when delivering cargo.
Definition cargotype.h:22
@ TAE_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 Tstorage base() const noexcept
Retrieve the raw value behind this bit set.
constexpr Timpl & Set()
Set all bits.
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:217
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.
std::span< const BadgeID > GetTypeBadges(int cls_id, int id) const override
Get the item 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.
std::set< PickerItem > UpdateSavedItems(const std::set< PickerItem > &src) override
Update link between grfid/localidx and class_index/index in saved items.
StringID GetTypeTooltip() const override
Get the tooltip string for the type grid.
void SetSelectedType(int id) const override
Set the selected type.
StringID GetTypeName(int cls_id, int id) const override
Get the item 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?
uint8_t class_mask
Mask of available 'classes'.
int GetTypeCount(int cls_id) const override
Get the number of types in a class.
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
K-dimensional tree, specialised for 2-dimensional space.
Definition kdtree.hpp:35
void Insert(const T &element)
Insert a single element in the tree.
Definition kdtree.hpp:398
void Remove(const T &element)
Remove a single element from the tree, if it exists.
Definition kdtree.hpp:417
void Clear()
Clear the tree.
Definition kdtree.hpp:377
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:2426
void InitializeViewport(Window *w, std::variant< TileIndex, VehicleID > focus, ZoomLevel zoom)
Initialize the viewport of the window.
Definition widget.cpp:2417
Class for PickerClassWindow to collect information and retain state.
Definition picker_gui.h:38
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
@ Position
Update scroll positions.
@ PCWHK_FOCUS_FILTER_BOX
Focus the edit box for editing the filter string.
Definition picker_gui.h:194
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.
void SetCount(size_t num)
Sets the number of elements in the list.
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:2523
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
The absolute minimum year in OTTD.
static constexpr TimerGame< struct Calendar >::Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date,...
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
RectPadding framerect
Standard padding inside many panels.
Definition window_gui.h:40
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:29
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:58
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:94
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:61
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.
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)
Show a dropdown menu window near a widget of the parent window.
Definition dropdown.cpp:444
Functions related to the drop down widget.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23)
Definition enum_type.hpp:17
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.
@ SLO_LOAD
File is being loaded.
Definition fileio_type.h:55
@ FT_TOWN_DATA
town data file
Definition fileio_type.h:21
Declarations for savegames operations.
void ShowSaveLoadDialog(AbstractFileType abstract_filetype, SaveLoadOperation fop)
Launch save/load dialog in the given mode.
Definition fios_gui.cpp:984
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
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:705
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:923
bool _shift_pressed
Is Shift pressed?
Definition gfx.cpp:39
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:852
Dimension GetStringListBoundingBox(std::span< const StringID > list, FontSize fontsize)
Get maximum dimension of a list of strings.
Definition gfx.cpp:890
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:658
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
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:989
Dimension GetStringMultiLineBoundingBox(StringID str, const Dimension &suggestion)
Calculate string bounding box for multi-line strings.
Definition gfx.cpp:741
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:775
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:245
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:296
@ TC_NO_SHADE
Do not add shading to this text colour.
Definition gfx_type.h:320
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 SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
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 SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
constexpr NWidgetPart SetPIPRatio(uint8_t ratio_pre, uint8_t ratio_inter, uint8_t ratio_post)
Widget part function for setting a pre/inter/post ratio.
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:945
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1500
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
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
HouseZones
Definition house.h:68
@ HZ_SUBARTC_BELOW
13 2000 can appear in sub-arctic climate below the snow line
Definition house.h:78
@ HZ_ZONALL
1F This is just to englobe all above types at once
Definition house.h:75
@ HZ_TEMP
12 1000 can appear in temperate climate
Definition house.h:77
@ HZ_TOYLND
15 8000 can appear in toyland climate
Definition house.h:80
@ HZ_SUBTROPIC
14 4000 can appear in subtropical climate
Definition house.h:79
@ HZ_SUBARTC_ABOVE
11 800 can appear in sub-arctic climate above the snow line
Definition house.h:76
uint16_t HouseID
OpenTTD ID of house types.
Definition house_type.h:13
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:79
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:66
bool _network_server
network-server is active
Definition network.cpp:67
Basic functions/variables used all over the place.
GrfSpecFeature
Definition newgrf.h:70
@ CBID_HOUSE_COLOUR
Called to determine the colour of a town building.
@ CBID_NO_CALLBACK
Set when using the callback resolve system, but not to resolve a callback.
@ 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
@ Colour
decide the colour of the building
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.
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.
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:412
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:59
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:58
@ SWS_OFF
Scroll wheel has no effect.
Base types for having sorted lists in GUIs.
Functions related to sound.
@ SND_15_BEEP
19 == 0x13 GUI button click
Definition sound_type.h:66
@ SND_1F_CONSTRUCTION_OTHER
29 == 0x1D Construction: other (non-water, non-rail, non-bridge)
Definition sound_type.h:76
void DrawNewGRFTileSeqInGUI(int x, int y, const DrawTileSprites *dts, uint32_t stage, PaletteID default_palette)
Draw NewGRF object in GUI.
Definition sprite.h:139
PaletteID GroundSpritePaletteTransform(SpriteID image, PaletteID pal, PaletteID default_pal)
Applies PALETTE_MODIFIER_COLOUR to a palette entry of a ground sprite.
Definition sprite.h:174
static constexpr uint8_t SPRITE_MODIFIER_CUSTOM_SPRITE
these masks change the colours of the palette for a sprite.
Definition sprites.h:1549
static constexpr uint8_t SPRITE_WIDTH
number of bits for the sprite number
Definition sprites.h:1539
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:514
Functions related to low-level strings.
@ 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:91
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:57
uint64_t GetParamMaxDigits(uint count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:228
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 later.
void Restore()
Restore the variable.
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 DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
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:74
CargoType Index() const
Determines index of this cargospec.
Definition cargotype.h:108
StringID name
Name of this type of cargo.
Definition cargotype.h:91
static std::array< std::vector< const CargoSpec * >, NUM_TPE > town_production_cargoes
List of cargo specs for each Town Product Effect.
Definition cargotype.h:25
SoundSettings sound
sound effect settings
GUISettings gui
settings related to the GUI
Dimensions (a width and height) of a rectangle in 2D.
This structure is the same for both Industries and Houses.
Definition sprite.h:76
Ground palette sprite of a tile, together with its sprite layout.
Definition sprite.h:46
PalSpriteID ground
Palette and sprite for the ground.
Definition sprite.h:47
bool bribe
enable bribing the local authority
TownFounding found_town
town founding.
bool exclusive_rights
allow buying exclusive rights
TownLayout town_layout
select town layout,
bool station_noise_level
build new airports when the town noise level is still within accepted limits
bool fund_buildings
allow funding new buildings
bool fund_roads
allow funding local road reconstruction
const struct SpriteGroup * GetSpriteGroup(size_t index=0) const
Get the SpriteGroup at the specified index.
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 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.
bool persistent_buildingtools
keep the building tools active after usage
uint8_t scrollwheel_scrolling
scrolling using the scroll wheel?
LandscapeType landscape
the landscape we're currently in
EconomySettings economy
settings to change the economy
GameCreationSettings game_creation
settings used during the creation of a game (map)
List of hotkeys for a window.
Definition hotkeys.h:37
All data for a single hotkey.
Definition hotkeys.h:21
Resolver object to be used for houses (feature 07 spritegroups).
bool enabled
the house is available to build (true by default, but can be disabled by newgrf)
Definition house.h:106
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:104
TimerGameCalendar::Year max_year
last year it can be built
Definition house.h:96
HouseCallbackMasks callback_mask
Bitmask of house callbacks that have to be called.
Definition house.h:110
uint8_t population
population (Zero on other tiles in multi tile house.)
Definition house.h:97
HouseExtraFlags extra_flags
some more flags
Definition house.h:113
TimerGameCalendar::Year min_year
introduction year of the house
Definition house.h:95
HouseID Index() const
Gets the index of this spec.
StringID building_name
building name
Definition house.h:99
GRFFileProps grf_prop
Properties related the the grf file.
Definition house.h:109
Colours random_colour[4]
4 "random" colours
Definition house.h:111
HouseZones building_availability
where can it be built (climates, zones)
Definition house.h:105
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.
Partial widget specification to allow NWidgets to be written nested.
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:23
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition gfx_type.h:24
Coordinates of a point in 2D.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * Get(auto index)
Returns Titem with given index.
static size_t GetNumItems()
Returns number of valid items in the pool.
Tindex index
Index of this pool item.
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
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.
constexpr uint Horizontal() const
Get total horizontal padding of RectPadding.
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.
uint step_height
Step-size of height resize changes.
Definition window_gui.h:213
Iterable ensemble of each set bit in a value.
bool click_beep
Beep on a random selection of buttons.
bool confirm
Play sound effect on successful constructions or other actions.
virtual const SpriteGroup * Resolve(ResolverObject &object) const
Base sprite group resolver.
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.
void ResetState()
Reset the matching state to process a new item.
bool GetState() const
Get the matching state of the current item.
void DeleteAll()
Delete every character in the textbuffer.
Definition textbuf.cpp:112
void Assign(const std::string_view text)
Copy a string into the textbuffer.
Definition textbuf.cpp:420
const char * GetText() const
Get the current text.
Definition textbuf.cpp:284
Action 2 sprite layout for houses, industry tiles, objects and airport tiles.
Town authority window.
Definition town_gui.cpp:78
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition town_gui.cpp:338
void DrawActions()
Draws the contents of the actions panel.
Definition town_gui.cpp:221
Dimension icon_size
Dimensions of company icon.
Definition town_gui.cpp:87
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition town_gui.cpp:146
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition town_gui.cpp:250
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:266
Town * town
Town being displayed.
Definition town_gui.cpp:80
TownActions enabled_actions
Actions that are enabled in settings.
Definition town_gui.cpp:83
TownAction sel_action
Currently selected town action, TownAction::End means no action selected.
Definition town_gui.cpp:81
TownActions available_actions
Actions that are available to execute for the current company.
Definition town_gui.cpp:84
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:298
void DrawRatings()
Draw the contents of the ratings panel.
Definition town_gui.cpp:182
int GetNthSetBit(int n)
Get the position of the Nth set bit.
Definition town_gui.cpp:98
Dimension exclusive_size
Dimensions of exclusive icon.
Definition town_gui.cpp:88
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
Definition town_gui.cpp:243
IntervalTimer< TimerWindow > redraw_interval
Redraw the whole window on a regular interval.
Definition town_gui.cpp:334
static TownActions GetEnabledActions()
Gets all town authority actions enabled in settings.
Definition town_gui.cpp:114
void OnPaint() override
The window must be repainted.
Definition town_gui.cpp:152
TownActions displayed_actions_on_previous_painting
Actions that were available on the previous call to OnPaint()
Definition town_gui.cpp:82
uint32_t population
Current population of people.
Definition town.h:42
Town directory window class.
Definition town_gui.cpp:717
static const std::initializer_list< GUITownList::SortFunction *const > sorter_funcs
Available town directory sorting functions.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition town_gui.cpp:843
static bool TownPopulationSorter(const Town *const &a, const Town *const &b, const bool &order)
Sort by population (default descending, as big towns are of the most interest).
Definition town_gui.cpp:768
IntervalTimer< TimerWindow > rebuild_interval
Redraw the whole window on a regular interval.
Definition town_gui.cpp:989
void OnDropdownSelect(WidgetID widget, int index) override
A dropdown option associated to this window has been selected.
Definition town_gui.cpp:971
QueryString townname_editbox
Filter editbox.
Definition town_gui.cpp:731
void OnEditboxChanged(WidgetID wid) override
The text in an editbox has been edited.
Definition town_gui.cpp:999
static bool TownRatingSorter(const Town *const &a, const Town *const &b, const bool &order)
Sort by town rating.
Definition town_gui.cpp:777
void OnResize() override
Called after the window got resized.
Definition town_gui.cpp:994
StringFilter string_filter
Filter for towns.
Definition town_gui.cpp:730
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
EventState OnHotkey(int hotkey) override
A hotkey has been pressed.
void OnPaint() override
The window must be repainted.
Definition town_gui.cpp:982
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:934
static std::string GetTownString(const Town *t, uint64_t population)
Get the string to draw the town name.
Definition town_gui.cpp:838
static bool TownNameSorter(const Town *const &a, const Town *const &b, const bool &)
Sort by town name.
Definition town_gui.cpp:762
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:887
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
Definition town_gui.cpp:816
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:487
Town * town
Town displayed by the window.
Definition town_gui.cpp:365
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition town_gui.cpp:592
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:521
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition town_gui.cpp:408
uint GetDesiredInfoHeight(int width) const
Gets the desired height for the information panel.
Definition town_gui.cpp:534
void OnMouseWheel(int wheel) override
The mouse wheel has been turned.
Definition town_gui.cpp:580
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
Definition town_gui.cpp:393
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:387
void OnPaint() override
The window must be repainted.
Definition town_gui.cpp:400
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
Definition town_gui.cpp:600
void OnResize() override
Called after the window got resized.
Definition town_gui.cpp:570
Town data structure.
Definition town.h:52
EncodedString text
General text with additional information.
Definition town.h:81
bool larger_town
if this is a larger town and should grow more quickly
Definition town.h:99
ReferenceThroughBaseContainer< std::array< int16_t, MAX_COMPANIES > > ratings
ratings of each company for this town
Definition town.h:75
TileIndex xy
town center tile
Definition town.h:53
uint8_t fund_buildings_months
fund buildings program in action?
Definition town.h:96
uint16_t noise_reached
level of noise that all the airports are generating
Definition town.h:66
uint8_t flags
See TownFlags.
Definition town.h:64
TownCache cache
Container for all cacheable data.
Definition town.h:55
CompanyID exclusivity
which company has exclusivity
Definition town.h:73
std::array< TransportedCargoStat< uint32_t >, NUM_CARGO > supplied
Cargo statistics about supplied cargo.
Definition town.h:77
bool show_zone
NOSAVE: mark town to show the local authority zone in the viewports.
Definition town.h:102
CompanyMask have_ratings
which companies have a rating
Definition town.h:71
uint16_t growth_rate
town growth rate
Definition town.h:94
std::array< TransportedCargoStat< uint16_t >, NUM_TAE > received
Cargo statistics about received cargotypes.
Definition town.h:78
std::array< uint32_t, NUM_TAE > goal
Amount of cargo required for the town to grow.
Definition town.h:79
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:957
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1052
static int SortButtonWidth()
Get width of up/down arrow of sort button state.
Definition widget.cpp:793
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1736
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:744
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3164
Window * parent
Parent window.
Definition window_gui.h:329
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:556
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:504
void DrawSortButtonState(WidgetID widget, SortButtonState state) const
Draw a sort button's up or down arrow symbol.
Definition widget.cpp:776
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:1726
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:485
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:530
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:558
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:212
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1749
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:313
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
AllWindows< false > Iterate
Iterate all windows in whatever order is easiest.
Definition window_gui.h:923
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
@ EnableDefault
enable the 'Default' button ("\0" is returned)
@ LengthIsInChars
the length of the string is counted in characters
TropicZone GetTropicZone(Tile tile)
Get the tropic zone.
Definition tile_map.h:238
static debug_inline uint TileHeight(Tile tile)
Returns the height of a tile.
Definition tile_map.h:29
static const uint TILE_PIXELS
Pixel distance between tile columns/rows in ZOOM_BASE.
Definition tile_type.h:17
@ TROPICZONE_DESERT
Tile is desert.
Definition tile_type.h:78
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
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...
@ 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:31
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:32
@ TOWN_IS_GROWING
Conditions for town growth are met. Grow according to Town::growth_rate.
Definition town.h:194
uint32_t GetWorldPopulation()
Get the total population, the sum of all towns in the world.
Definition town_cmd.cpp:462
CargoArray GetAcceptedCargoOfHouse(const HouseSpec *hs)
Get accepted cargo of a house prototype.
Definition town_cmd.cpp:858
uint8_t GetTownActionCost(TownAction action)
Get cost factors for a TownAction.
TownAction
Town actions of a company.
Definition town.h:210
@ RoadRebuild
Rebuild the roads.
@ Bribe
Try to bribe the council.
@ BuyRights
Buy exclusive transport rights.
@ FundBuildings
Fund new buildings.
bool GenerateTowns(TownLayout layout)
Generate a number of towns with a given layout.
Command definitions related to towns.
TownDirectoryHotkeys
Enum referring to the Hotkeys in the town directory window.
Definition town_gui.cpp:712
@ TDHK_FOCUS_FILTER_BOX
Focus the filter box.
Definition town_gui.cpp:713
static constexpr NWidgetPart _nested_build_house_widgets[]
Nested widget definition for the build NewGRF rail waypoint window.
void DrawHouseInGUI(int x, int y, HouseID house_id, int view)
Draw a house that does not exist.
void DrawNewHouseTileInGUI(int x, int y, const HouseSpec *spec, HouseID house_id, int view)
Draw representation of a house tile for GUI purposes.
static StringID GetHouseName(const HouseSpec *hs)
Get name for a prototype house.
static CargoTypes GetProducedCargoOfHouse(const HouseSpec *hs)
Get the cargo types produced by a house.
Declarations for accessing the k-d tree of towns.
TownLayout
Town Layouts.
Definition town_type.h:81
@ TF_CUSTOM_LAYOUT
Allowed, with custom town layout.
Definition town_type.h:99
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:111
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_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:45
@ 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:69
@ WID_TF_LOAD_FROM_FILE
Load town data from file.
Definition town_widget.h:54
@ WID_TF_SIZE_SEL
Container of town size buttons.
Definition town_widget.h:58
@ WID_TF_SIZE_LARGE
Selection for a large town.
Definition town_widget.h:61
@ WID_TF_NEW_TOWN
Create a new town.
Definition town_widget.h:50
@ WID_TF_EXPAND_ALL_TOWNS
Make all towns grow slightly.
Definition town_widget.h:55
@ WID_TF_MANY_RANDOM_TOWNS
Randomly place many towns.
Definition town_widget.h:53
@ WID_TF_SIZE_SMALL
Selection for a small town.
Definition town_widget.h:59
@ WID_TF_LAYOUT_GRID2
Selection for the 2x2 grid town layout.
Definition town_widget.h:67
@ WID_TF_LAYOUT_ORIGINAL
Selection for the original town layout.
Definition town_widget.h:65
@ WID_TF_SIZE_RANDOM
Selection for a randomly sized town.
Definition town_widget.h:62
@ WID_TF_TOWN_NAME_EDITBOX
Editor for the town name.
Definition town_widget.h:56
@ WID_TF_TOWN_ACTION_SEL
Container of town action buttons.
Definition town_widget.h:51
@ WID_TF_SIZE_MEDIUM
Selection for a medium town.
Definition town_widget.h:60
@ WID_TF_CITY
Selection for the town's city state.
Definition town_widget.h:63
@ WID_TF_RANDOM_TOWN
Randomly place a town.
Definition town_widget.h:52
@ WID_TF_LAYOUT_BETTER
Selection for the better town layout.
Definition town_widget.h:66
@ WID_TF_ROAD_LAYOUT_SEL
Container of town road layout buttons.
Definition town_widget.h:64
@ WID_TF_LAYOUT_GRID3
Selection for the 3x3 grid town layout.
Definition town_widget.h:68
@ WID_TF_TOWN_NAME_RANDOM
Generate a random town name.
Definition town_widget.h:57
@ 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_PROTECT_OFF
Button to protect the next house built.
Definition town_widget.h:75
@ WID_BH_PROTECT_ON
Button to not protect the next house built.
Definition town_widget.h:76
@ WID_BH_INFO
Information panel of selected house.
Definition town_widget.h:74
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.
@ ZOOM_IN
Zoom in (get more detailed view).
@ ZOOM_OUT
Zoom out (get helicopter view).
@ 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:41
@ WWT_PUSHIMGBTN
Normal push-button (no toggle button) with image caption.
@ WWT_LABEL
Centered label.
Definition widget_type.h:47
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:61
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:65
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:45
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:40
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:56
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:54
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:51
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:75
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:67
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:59
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:38
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:58
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:55
@ NWID_VIEWPORT
Nested widget containing a viewport.
Definition widget_type.h:72
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:60
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:48
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:70
@ 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:2025
void SetFocusedWindow(Window *w)
Set the window that has the focus.
Definition window.cpp:421
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1226
Window functions not directly related to making/drawing windows.
@ Construction
This window is used for construction; close it whenever changing company.
@ DisableVpScroll
Window does not do autoscroll,.
@ SBS_DOWN
Sort ascending.
Definition window_gui.h:219
@ SBS_UP
Sort descending.
Definition window_gui.h:220
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:145
int WidgetID
Widget ID.
Definition window_type.h:20
EventState
State of handling an event.
@ ES_HANDLED
The passed event is handled.
@ ES_NOT_HANDLED
The passed event is not handled.
@ 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:75
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
@ 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
@ ZOOM_LVL_TOWN
Default zoom level for the town view.
Definition zoom_type.h:31