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