OpenTTD Source 20250312-master-gcdcc6b491d
company_gui.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11#include "currency.h"
12#include "error.h"
13#include "gui.h"
14#include "window_gui.h"
15#include "textbuf_gui.h"
16#include "viewport_func.h"
17#include "company_func.h"
18#include "command_func.h"
19#include "network/network.h"
20#include "network/network_gui.h"
22#include "newgrf.h"
24#include "strings_func.h"
26#include "dropdown_type.h"
28#include "tilehighlight_func.h"
29#include "company_base.h"
31#include "object_type.h"
32#include "rail.h"
33#include "road.h"
34#include "engine_base.h"
35#include "window_func.h"
36#include "road_func.h"
37#include "water.h"
38#include "station_func.h"
39#include "zoom_func.h"
40#include "sortlist_type.h"
41#include "company_cmd.h"
42#include "economy_cmd.h"
43#include "group_cmd.h"
44#include "group_gui.h"
45#include "misc_cmd.h"
46#include "object_cmd.h"
47#include "timer/timer.h"
48#include "timer/timer_window.h"
49
51
52#include "safeguards.h"
53
54
56static void DoSelectCompanyManagerFace(Window *parent);
57static void ShowCompanyInfrastructure(CompanyID company);
58
60static const std::initializer_list<ExpensesType> _expenses_list_revenue = {
65};
66
76
78static const std::initializer_list<ExpensesType> _expenses_list_capital_costs = {
82};
83
87 const std::initializer_list<ExpensesType> &items;
88
89 ExpensesList(StringID title, const std::initializer_list<ExpensesType> &list) : title(title), items(list)
90 {
91 }
92
93 uint GetHeight() const
94 {
95 /* Add up the height of all the lines. */
96 return static_cast<uint>(this->items.size()) * GetCharacterHeight(FS_NORMAL);
97 }
98
100 uint GetListWidth() const
101 {
102 uint width = 0;
103 for (const ExpensesType &et : this->items) {
104 width = std::max(width, GetStringBoundingBox(STR_FINANCES_SECTION_CONSTRUCTION + et).width);
105 }
106 return width;
107 }
108};
109
111static const std::initializer_list<ExpensesList> _expenses_list_types = {
112 { STR_FINANCES_REVENUE_TITLE, _expenses_list_revenue },
113 { STR_FINANCES_OPERATING_EXPENSES_TITLE, _expenses_list_operating_costs },
114 { STR_FINANCES_CAPITAL_EXPENSES_TITLE, _expenses_list_capital_costs },
115};
116
122{
123 /* There's an empty line and blockspace on the year row */
125
126 for (const ExpensesList &list : _expenses_list_types) {
127 /* Title + expense list + total line + total + blockspace after category */
129 }
130
131 /* Total income */
133
134 return total_height;
135}
136
142{
143 uint max_width = GetStringBoundingBox(TimerGameEconomy::UsingWallclockUnits() ? STR_FINANCES_PERIOD_CAPTION : STR_FINANCES_YEAR_CAPTION).width;
144
145 /* Loop through categories to check max widths. */
146 for (const ExpensesList &list : _expenses_list_types) {
147 /* Title of category */
148 max_width = std::max(max_width, GetStringBoundingBox(list.title).width);
149 /* Entries in category */
150 max_width = std::max(max_width, list.GetListWidth() + WidgetDimensions::scaled.hsep_indent);
151 }
152
153 return max_width;
154}
155
159static void DrawCategory(const Rect &r, int start_y, const ExpensesList &list)
160{
162
163 tr.top = start_y;
164
165 for (const ExpensesType &et : list.items) {
166 DrawString(tr, STR_FINANCES_SECTION_CONSTRUCTION + et);
167 tr.top += GetCharacterHeight(FS_NORMAL);
168 }
169}
170
176static void DrawCategories(const Rect &r)
177{
178 int y = r.top;
179 /* Draw description of 12-minute economic period. */
180 DrawString(r.left, r.right, y, (TimerGameEconomy::UsingWallclockUnits() ? STR_FINANCES_PERIOD_CAPTION : STR_FINANCES_YEAR_CAPTION), TC_FROMSTRING, SA_LEFT, true);
182
183 for (const ExpensesList &list : _expenses_list_types) {
184 /* Draw category title and advance y */
185 DrawString(r.left, r.right, y, list.title, TC_FROMSTRING, SA_LEFT);
187
188 /* Draw category items and advance y */
189 DrawCategory(r, y, list);
190 y += list.GetHeight();
191
192 /* Advance y by the height of the horizontal line between amounts and subtotal */
194
195 /* Draw category total and advance y */
196 DrawString(r.left, r.right, y, STR_FINANCES_TOTAL_CAPTION, TC_FROMSTRING, SA_RIGHT);
198
199 /* Advance y by a blockspace after this category block */
201 }
202
203 /* Draw total profit/loss */
205 DrawString(r.left, r.right, y, STR_FINANCES_PROFIT, TC_FROMSTRING, SA_LEFT);
206}
207
216static void DrawPrice(Money amount, int left, int right, int top, TextColour colour)
217{
218 StringID str = STR_FINANCES_NEGATIVE_INCOME;
219 if (amount == 0) {
220 str = STR_FINANCES_ZERO_INCOME;
221 } else if (amount < 0) {
222 amount = -amount;
223 str = STR_FINANCES_POSITIVE_INCOME;
224 }
225 DrawString(left, right, top, GetString(str, amount), colour, SA_RIGHT);
226}
227
232static Money DrawYearCategory(const Rect &r, int start_y, const ExpensesList &list, const Expenses &tbl)
233{
234 int y = start_y;
235 Money sum = 0;
236
237 for (const ExpensesType &et : list.items) {
238 Money cost = tbl[et];
239 sum += cost;
240 if (cost != 0) DrawPrice(cost, r.left, r.right, y, TC_BLACK);
242 }
243
244 /* Draw the total at the bottom of the category. */
245 GfxFillRect(r.left, y, r.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
247 if (sum != 0) DrawPrice(sum, r.left, r.right, y, TC_WHITE);
248
249 /* Return the sum for the yearly total. */
250 return sum;
251}
252
253
261static void DrawYearColumn(const Rect &r, TimerGameEconomy::Year year, const Expenses &tbl)
262{
263 int y = r.top;
264 Money sum;
265
266 /* Year header */
267 DrawString(r.left, r.right, y, GetString(STR_FINANCES_YEAR, year), TC_FROMSTRING, SA_RIGHT, true);
269
270 /* Categories */
271 for (const ExpensesList &list : _expenses_list_types) {
273 sum += DrawYearCategory(r, y, list, tbl);
274 /* Expense list + expense category title + expense category total + blockspace after category */
276 }
277
278 /* Total income. */
279 GfxFillRect(r.left, y, r.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
281 DrawPrice(sum, r.left, r.right, y, TC_WHITE);
282}
283
284static constexpr NWidgetPart _nested_company_finances_widgets[] = {
286 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
287 NWidget(WWT_CAPTION, COLOUR_GREY, WID_CF_CAPTION),
288 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_CF_TOGGLE_SIZE), SetSpriteTip(SPR_LARGE_SMALL_WINDOW, STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW), SetAspect(WidgetDimensions::ASPECT_TOGGLE_SIZE),
289 NWidget(WWT_SHADEBOX, COLOUR_GREY),
290 NWidget(WWT_STICKYBOX, COLOUR_GREY),
291 EndContainer(),
292 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_PANEL),
293 NWidget(WWT_PANEL, COLOUR_GREY),
295 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_CATEGORY), SetMinimalSize(120, 0), SetFill(0, 0),
296 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_PRICE1), SetMinimalSize(86, 0), SetFill(0, 0),
297 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_PRICE2), SetMinimalSize(86, 0), SetFill(0, 0),
298 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CF_EXPS_PRICE3), SetMinimalSize(86, 0), SetFill(0, 0),
299 EndContainer(),
300 EndContainer(),
301 EndContainer(),
302 NWidget(WWT_PANEL, COLOUR_GREY),
304 NWidget(NWID_VERTICAL), // Vertical column with 'bank balance', 'loan'
305 NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_FINANCES_OWN_FUNDS_TITLE),
306 NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_FINANCES_LOAN_TITLE),
307 NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_FINANCES_BANK_BALANCE_TITLE), SetPadding(WidgetDimensions::unscaled.vsep_normal, 0, 0, 0),
308 EndContainer(),
309 NWidget(NWID_VERTICAL), // Vertical column with bank balance amount, loan amount, and total.
314 EndContainer(),
315 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_MAXLOAN),
316 NWidget(NWID_VERTICAL), SetPIPRatio(0, 0, 1), // Max loan information
317 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CF_INTEREST_RATE),
318 NWidget(WWT_TEXT, INVALID_COLOUR, WID_CF_MAXLOAN_VALUE),
319 EndContainer(),
320 EndContainer(),
321 EndContainer(),
322 EndContainer(),
323 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_BUTTONS),
325 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_INCREASE_LOAN), SetFill(1, 0), SetToolTip(STR_FINANCES_BORROW_TOOLTIP),
326 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_REPAY_LOAN), SetFill(1, 0), SetToolTip(STR_FINANCES_REPAY_TOOLTIP),
327 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_INFRASTRUCTURE), SetFill(1, 0), SetStringTip(STR_FINANCES_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
328 EndContainer(),
329 EndContainer(),
330};
331
334 static constexpr int NUM_PERIODS = WID_CF_EXPS_PRICE3 - WID_CF_EXPS_PRICE1 + 1;
335
337 bool small = false;
338 uint8_t first_visible = NUM_PERIODS - 1;
339
340 CompanyFinancesWindow(WindowDesc &desc, CompanyID company) : Window(desc)
341 {
342 this->CreateNestedTree();
343 this->SetupWidgets();
344 this->FinishInitNested(company);
345
346 this->owner = this->window_number;
347 this->InvalidateData();
348 }
349
350 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
351 {
352 switch (widget) {
353 case WID_CF_CAPTION:
355
357 const Company *c = Company::Get(this->window_number);
359 }
360
361 case WID_CF_LOAN_VALUE: {
362 const Company *c = Company::Get(this->window_number);
364 }
365
366 case WID_CF_OWN_VALUE: {
367 const Company *c = Company::Get(this->window_number);
369 }
370
373
375 const Company *c = Company::Get(this->window_number);
377 }
378
381
384
385 default:
386 return this->Window::GetWidgetString(widget, stringid);
387 }
388 }
389
391 {
392 switch (widget) {
394 size.width = GetMaxCategoriesWidth();
395 size.height = GetTotalCategoriesHeight();
396 break;
397
401 size.height = GetTotalCategoriesHeight();
402 [[fallthrough]];
403
406 case WID_CF_OWN_VALUE: {
409 size.width += padding.width;
410 break;
411 }
412
414 size.height = GetCharacterHeight(FS_NORMAL);
415 break;
416 }
417 }
418
419 void DrawWidget(const Rect &r, WidgetID widget) const override
420 {
421 switch (widget) {
424 break;
425
428 case WID_CF_EXPS_PRICE3: {
429 int period = widget - WID_CF_EXPS_PRICE1;
431
432 const Company *c = Company::Get(this->window_number);
433 const auto &expenses = c->yearly_expenses[NUM_PERIODS - period - 1];
434 DrawYearColumn(r, TimerGameEconomy::year - (NUM_PERIODS - period - 1), expenses);
435 break;
436 }
437
439 GfxFillRect(r.left, r.top, r.right, r.top + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
440 break;
441 }
442 }
443
449 {
450 int plane = this->small ? SZSP_NONE : 0;
451 this->GetWidget<NWidgetStacked>(WID_CF_SEL_PANEL)->SetDisplayedPlane(plane);
452 this->GetWidget<NWidgetStacked>(WID_CF_SEL_MAXLOAN)->SetDisplayedPlane(plane);
453
454 CompanyID company = this->window_number;
455 plane = (company != _local_company) ? SZSP_NONE : 0;
456 this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->SetDisplayedPlane(plane);
457 }
458
459 void OnPaint() override
460 {
461 if (!this->IsShaded()) {
462 if (!this->small) {
463 /* Check that the expenses panel height matches the height needed for the layout. */
465 this->SetupWidgets();
466 this->ReInit();
467 return;
468 }
469 }
470
471 /* Check that the loan buttons are shown only when the user owns the company. */
472 CompanyID company = this->window_number;
473 int req_plane = (company != _local_company) ? SZSP_NONE : 0;
474 if (req_plane != this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->shown_plane) {
475 this->SetupWidgets();
476 this->ReInit();
477 return;
478 }
479
480 const Company *c = Company::Get(company);
481 this->SetWidgetDisabledState(WID_CF_INCREASE_LOAN, c->current_loan >= c->GetMaxLoan()); // Borrow button only shows when there is any more money to loan.
482 this->SetWidgetDisabledState(WID_CF_REPAY_LOAN, company != _local_company || c->current_loan == 0); // Repay button only shows when there is any more money to repay.
483 }
484
485 this->DrawWidgets();
486 }
487
488 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
489 {
490 switch (widget) {
491 case WID_CF_TOGGLE_SIZE: // toggle size
492 this->small = !this->small;
493 this->SetupWidgets();
494 if (this->IsShaded()) {
495 /* Finances window is not resizable, so size hints given during unshading have no effect
496 * on the changed appearance of the window. */
497 this->SetShaded(false);
498 } else {
499 this->ReInit();
500 }
501 break;
502
503 case WID_CF_INCREASE_LOAN: // increase loan
504 Command<CMD_INCREASE_LOAN>::Post(STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY, _ctrl_pressed ? LoanCommand::Max : LoanCommand::Interval, 0);
505 break;
506
507 case WID_CF_REPAY_LOAN: // repay loan
508 Command<CMD_DECREASE_LOAN>::Post(STR_ERROR_CAN_T_REPAY_LOAN, _ctrl_pressed ? LoanCommand::Max : LoanCommand::Interval, 0);
509 break;
510
511 case WID_CF_INFRASTRUCTURE: // show infrastructure details
513 break;
514 }
515 }
516
517 void RefreshVisibleColumns()
518 {
519 for (uint period = 0; period < this->first_visible; ++period) {
520 const Company *c = Company::Get(this->window_number);
521 const Expenses &expenses = c->yearly_expenses[NUM_PERIODS - period - 1];
522 /* Show expenses column if it has any non-zero value in it. */
523 if (std::ranges::any_of(expenses, [](const Money &value) { return value != 0; })) {
524 this->first_visible = period;
525 break;
526 }
527 }
528 }
529
530 void OnInvalidateData(int, bool) override
531 {
532 this->RefreshVisibleColumns();
533 }
534
539 IntervalTimer<TimerWindow> rescale_interval = {std::chrono::seconds(3), [this](auto) {
540 const Company *c = Company::Get(this->window_number);
543 this->SetupWidgets();
544 this->ReInit();
545 }
546 }};
547};
548
551
552static WindowDesc _company_finances_desc(
553 WDP_AUTO, "company_finances", 0, 0,
555 {},
556 _nested_company_finances_widgets
557);
558
565{
566 if (!Company::IsValidID(company)) return;
567 if (BringWindowToFrontById(WC_FINANCES, company)) return;
568
569 new CompanyFinancesWindow(_company_finances_desc, company);
570}
571
572/* Association of liveries to livery classes */
573static const LiveryClass _livery_class[LS_END] = {
574 LC_OTHER,
575 LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL, LC_RAIL,
576 LC_ROAD, LC_ROAD,
577 LC_SHIP, LC_SHIP,
578 LC_AIRCRAFT, LC_AIRCRAFT, LC_AIRCRAFT,
579 LC_ROAD, LC_ROAD,
580};
581
586template <SpriteID TSprite = SPR_SQUARE>
587class DropDownListColourItem : public DropDownIcon<DropDownString<DropDownListItem>> {
588public:
589 DropDownListColourItem(int colour, bool masked) : DropDownIcon<DropDownString<DropDownListItem>>(TSprite, GENERAL_SPRITE_COLOUR(colour % COLOUR_END), GetString(colour < COLOUR_END ? (STR_COLOUR_DARK_BLUE + colour) : STR_COLOUR_DEFAULT), colour, masked)
590 {
591 }
592};
593
596private:
597 uint32_t sel = 0;
598 LiveryClass livery_class{};
599 Dimension square{};
600 uint rows = 0;
601 uint line_height = 0;
602 GUIGroupList groups{};
603 Scrollbar *vscroll = nullptr;
604
605 void ShowColourDropDownMenu(uint32_t widget)
606 {
608 const Livery *livery, *default_livery = nullptr;
609 bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
611
612 /* Disallow other company colours for the primary colour */
613 if (this->livery_class < LC_GROUP_RAIL && HasBit(this->sel, LS_DEFAULT) && primary) {
614 for (const Company *c : Company::Iterate()) {
616 }
617 }
618
619 const Company *c = Company::Get(this->window_number);
620
621 if (this->livery_class < LC_GROUP_RAIL) {
622 /* Get the first selected livery to use as the default dropdown item */
624 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
625 if (HasBit(this->sel, scheme)) break;
626 }
627 if (scheme == LS_END) scheme = LS_DEFAULT;
628 livery = &c->livery[scheme];
629 if (scheme != LS_DEFAULT) default_livery = &c->livery[LS_DEFAULT];
630 } else {
631 const Group *g = Group::Get(this->sel);
632 livery = &g->livery;
633 if (g->parent == GroupID::Invalid()) {
634 default_livery = &c->livery[LS_DEFAULT];
635 } else {
636 const Group *pg = Group::Get(g->parent);
637 default_livery = &pg->livery;
638 }
639 }
640
641 DropDownList list;
642 if (default_livery != nullptr) {
643 /* Add COLOUR_END to put the colour out of range, but also allow us to show what the default is */
644 default_col = (primary ? default_livery->colour1 : default_livery->colour2) + COLOUR_END;
645 list.push_back(std::make_unique<DropDownListColourItem<>>(default_col, false));
646 }
647 for (Colours colour = COLOUR_BEGIN; colour != COLOUR_END; colour++) {
648 list.push_back(std::make_unique<DropDownListColourItem<>>(colour, HasBit(used_colours, colour)));
649 }
650
651 uint8_t sel;
652 if (default_livery == nullptr || HasBit(livery->in_use, primary ? 0 : 1)) {
653 sel = primary ? livery->colour1 : livery->colour2;
654 } else {
655 sel = default_col;
656 }
657 ShowDropDownList(this, std::move(list), sel, widget);
658 }
659
660 void BuildGroupList(CompanyID owner)
661 {
662 if (!this->groups.NeedRebuild()) return;
663
664 this->groups.clear();
665
666 if (this->livery_class >= LC_GROUP_RAIL) {
667 VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
668 BuildGuiGroupList(this->groups, false, owner, vtype);
669 }
670
671 this->groups.RebuildDone();
672 }
673
674 void SetRows()
675 {
676 if (this->livery_class < LC_GROUP_RAIL) {
677 this->rows = 0;
678 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
679 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
680 this->rows++;
681 }
682 }
683 } else {
684 this->rows = (uint)this->groups.size();
685 }
686
687 this->vscroll->SetCount(this->rows);
688 }
689
690public:
691 SelectCompanyLiveryWindow(WindowDesc &desc, CompanyID company, GroupID group) : Window(desc)
692 {
693 this->CreateNestedTree();
694 this->vscroll = this->GetScrollbar(WID_SCL_MATRIX_SCROLLBAR);
695
696 if (group == GroupID::Invalid()) {
697 this->livery_class = LC_OTHER;
698 this->sel = 1;
700 this->BuildGroupList(company);
701 this->SetRows();
702 } else {
703 this->SetSelectedGroup(company, group);
704 }
705
706 this->FinishInitNested(company);
707 this->owner = company;
708 this->InvalidateData(1);
709 }
710
711 void SetSelectedGroup(CompanyID company, GroupID group)
712 {
713 this->RaiseWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
714 const Group *g = Group::Get(group);
715 switch (g->vehicle_type) {
716 case VEH_TRAIN: this->livery_class = LC_GROUP_RAIL; break;
717 case VEH_ROAD: this->livery_class = LC_GROUP_ROAD; break;
718 case VEH_SHIP: this->livery_class = LC_GROUP_SHIP; break;
719 case VEH_AIRCRAFT: this->livery_class = LC_GROUP_AIRCRAFT; break;
720 default: NOT_REACHED();
721 }
722 this->sel = group.base();
723 this->LowerWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
724
725 this->groups.ForceRebuild();
726 this->BuildGroupList(company);
727 this->SetRows();
728
729 /* Position scrollbar to selected group */
730 for (uint i = 0; i < this->rows; i++) {
731 if (this->groups[i].group->index == sel) {
732 this->vscroll->SetPosition(i - this->vscroll->GetCapacity() / 2);
733 break;
734 }
735 }
736 }
737
739 {
740 switch (widget) {
742 /* The matrix widget below needs enough room to print all the schemes. */
743 Dimension d = {0, 0};
744 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
746 }
747
748 /* And group names */
749 for (const Group *g : Group::Iterate()) {
750 if (g->owner == this->window_number) {
752 }
753 }
754
755 size.width = std::max(size.width, 5 + d.width + padding.width);
756 break;
757 }
758
759 case WID_SCL_MATRIX: {
760 /* 11 items in the default rail class */
761 this->square = GetSpriteSize(SPR_SQUARE);
762 this->line_height = std::max(this->square.height, (uint)GetCharacterHeight(FS_NORMAL)) + padding.height;
763
764 size.height = 5 * this->line_height;
765 resize.width = 1;
766 resize.height = this->line_height;
767 break;
768 }
769
772 size.width = 0;
773 break;
774 }
775 [[fallthrough]];
776
778 this->square = GetSpriteSize(SPR_SQUARE);
779 int string_padding = this->square.width + WidgetDimensions::scaled.hsep_normal + padding.width;
780 for (Colours colour = COLOUR_BEGIN; colour != COLOUR_END; colour++) {
781 size.width = std::max(size.width, GetStringBoundingBox(STR_COLOUR_DARK_BLUE + colour).width + string_padding);
782 }
783 size.width = std::max(size.width, GetStringBoundingBox(STR_COLOUR_DEFAULT).width + string_padding);
784 break;
785 }
786 }
787 }
788
789 void OnPaint() override
790 {
791 bool local = this->window_number == _local_company;
792
793 /* Disable dropdown controls if no scheme is selected */
794 bool disabled = this->livery_class < LC_GROUP_RAIL ? (this->sel == 0) : (this->sel == GroupID::Invalid());
795 this->SetWidgetDisabledState(WID_SCL_PRI_COL_DROPDOWN, !local || disabled);
796 this->SetWidgetDisabledState(WID_SCL_SEC_COL_DROPDOWN, !local || disabled);
797
798 this->BuildGroupList(this->window_number);
799
800 this->DrawWidgets();
801 }
802
803 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
804 {
805 switch (widget) {
806 case WID_SCL_CAPTION:
808
811 const Company *c = Company::Get(this->window_number);
812 bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
814
815 if (this->livery_class < LC_GROUP_RAIL) {
816 if (this->sel != 0) {
817 LiveryScheme scheme = LS_DEFAULT;
818 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
819 if (HasBit(this->sel, scheme)) break;
820 }
821 if (scheme == LS_END) scheme = LS_DEFAULT;
822 const Livery *livery = &c->livery[scheme];
823 if (scheme == LS_DEFAULT || HasBit(livery->in_use, primary ? 0 : 1)) {
824 colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
825 }
826 }
827 } else {
828 if (this->sel != GroupID::Invalid()) {
829 const Group *g = Group::Get(this->sel);
830 const Livery *livery = &g->livery;
831 if (HasBit(livery->in_use, primary ? 0 : 1)) {
832 colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
833 }
834 }
835 }
836 return GetString(colour);
837 }
838
839 default:
840 return this->Window::GetWidgetString(widget, stringid);
841 }
842 }
843
844 void DrawWidget(const Rect &r, WidgetID widget) const override
845 {
846 if (widget != WID_SCL_MATRIX) return;
847
848 bool rtl = _current_text_dir == TD_RTL;
849
850 /* Coordinates of scheme name column. */
852 Rect sch = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
853 /* Coordinates of first dropdown. */
855 Rect pri = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
856 /* Coordinates of second dropdown. */
858 Rect sec = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
859
860 Rect pri_squ = pri.WithWidth(this->square.width, rtl);
861 Rect sec_squ = sec.WithWidth(this->square.width, rtl);
862
863 pri = pri.Indent(this->square.width + WidgetDimensions::scaled.hsep_normal, rtl);
864 sec = sec.Indent(this->square.width + WidgetDimensions::scaled.hsep_normal, rtl);
865
867 int square_offs = (ir.Height() - this->square.height) / 2;
868 int text_offs = (ir.Height() - GetCharacterHeight(FS_NORMAL)) / 2;
869
870 int y = ir.top;
871
872 /* Helper function to draw livery info. */
873 auto draw_livery = [&](std::string_view str, const Livery &livery, bool is_selected, bool is_default_scheme, int indent) {
874 /* Livery Label. */
875 DrawString(sch.left + (rtl ? 0 : indent), sch.right - (rtl ? indent : 0), y + text_offs, str, is_selected ? TC_WHITE : TC_BLACK);
876
877 /* Text below the first dropdown. */
878 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour1), pri_squ.left, y + square_offs);
879 DrawString(pri.left, pri.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 0)) ? STR_COLOUR_DARK_BLUE + livery.colour1 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
880
881 /* Text below the second dropdown. */
882 if (sec.right > sec.left) { // Second dropdown has non-zero size.
883 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour2), sec_squ.left, y + square_offs);
884 DrawString(sec.left, sec.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 1)) ? STR_COLOUR_DARK_BLUE + livery.colour2 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD);
885 }
886
887 y += this->line_height;
888 };
889
890 const Company *c = Company::Get(this->window_number);
891
892 if (livery_class < LC_GROUP_RAIL) {
893 int pos = this->vscroll->GetPosition();
894 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
895 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
896 if (pos-- > 0) continue;
897 draw_livery(GetString(STR_LIVERY_DEFAULT + scheme), c->livery[scheme], HasBit(this->sel, scheme), scheme == LS_DEFAULT, 0);
898 }
899 }
900 } else {
901 auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->groups);
902 for (auto it = first; it != last; ++it) {
903 const Group *g = it->group;
905 }
906
907 if (this->vscroll->GetCount() == 0) {
909 VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
910 DrawString(ir.left, ir.right, y + text_offs, empty_labels[vtype], TC_BLACK);
911 }
912 }
913 }
914
915 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
916 {
917 switch (widget) {
918 /* Livery Class buttons */
928 this->RaiseWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
929 this->livery_class = (LiveryClass)(widget - WID_SCL_CLASS_GENERAL);
930 this->LowerWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
931
932 /* Select the first item in the list */
933 if (this->livery_class < LC_GROUP_RAIL) {
934 this->sel = 0;
935 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
936 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
937 this->sel = 1 << scheme;
938 break;
939 }
940 }
941 } else {
942 this->sel = GroupID::Invalid().base();
943 this->groups.ForceRebuild();
944 this->BuildGroupList(this->window_number);
945
946 if (!this->groups.empty()) {
947 this->sel = this->groups[0].group->index.base();
948 }
949 }
950
951 this->SetRows();
952 this->SetDirty();
953 break;
954
955 case WID_SCL_PRI_COL_DROPDOWN: // First colour dropdown
956 ShowColourDropDownMenu(WID_SCL_PRI_COL_DROPDOWN);
957 break;
958
959 case WID_SCL_SEC_COL_DROPDOWN: // Second colour dropdown
960 ShowColourDropDownMenu(WID_SCL_SEC_COL_DROPDOWN);
961 break;
962
963 case WID_SCL_MATRIX: {
964 if (this->livery_class < LC_GROUP_RAIL) {
965 uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, widget);
966 if (row >= this->rows) return;
967
969
970 for (LiveryScheme scheme = LS_BEGIN; scheme <= j && scheme < LS_END; scheme++) {
971 if (_livery_class[scheme] != this->livery_class || !HasBit(_loaded_newgrf_features.used_liveries, scheme)) j++;
972 }
973 assert(j < LS_END);
974
975 if (_ctrl_pressed) {
976 ToggleBit(this->sel, j);
977 } else {
978 this->sel = 1 << j;
979 }
980 } else {
981 auto it = this->vscroll->GetScrolledItemFromWidget(this->groups, pt.y, this, widget);
982 if (it == std::end(this->groups)) return;
983
984 this->sel = it->group->index.base();
985 }
986 this->SetDirty();
987 break;
988 }
989 }
990 }
991
992 void OnResize() override
993 {
994 this->vscroll->SetCapacityFromWidget(this, WID_SCL_MATRIX);
995 }
996
997 void OnDropdownSelect(WidgetID widget, int index) override
998 {
999 bool local = this->window_number == _local_company;
1000 if (!local) return;
1001
1002 Colours colour = static_cast<Colours>(index);
1003 if (colour >= COLOUR_END) colour = INVALID_COLOUR;
1004
1005 if (this->livery_class < LC_GROUP_RAIL) {
1006 /* Set company colour livery */
1007 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1008 /* Changed colour for the selected scheme, or all visible schemes if CTRL is pressed. */
1009 if (HasBit(this->sel, scheme) || (_ctrl_pressed && _livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme))) {
1011 }
1012 }
1013 } else {
1014 /* Setting group livery */
1015 Command<CMD_SET_GROUP_LIVERY>::Post(static_cast<GroupID>(this->sel), widget == WID_SCL_PRI_COL_DROPDOWN, colour);
1016 }
1017 }
1018
1024 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1025 {
1026 if (!gui_scope) return;
1027
1028 if (data != -1) {
1029 /* data contains a VehicleType, rebuild list if it displayed */
1030 if (this->livery_class == data + LC_GROUP_RAIL) {
1031 this->groups.ForceRebuild();
1032 this->BuildGroupList(this->window_number);
1033 this->SetRows();
1034
1035 if (!Group::IsValidID(this->sel)) {
1036 this->sel = GroupID::Invalid().base();
1037 if (!this->groups.empty()) this->sel = this->groups[0].group->index.base();
1038 }
1039
1040 this->SetDirty();
1041 }
1042 return;
1043 }
1044
1046
1047 bool current_class_valid = this->livery_class == LC_OTHER || this->livery_class >= LC_GROUP_RAIL;
1049 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1051 if (_livery_class[scheme] == this->livery_class) current_class_valid = true;
1052 this->EnableWidget(WID_SCL_CLASS_GENERAL + _livery_class[scheme]);
1053 } else if (this->livery_class < LC_GROUP_RAIL) {
1054 ClrBit(this->sel, scheme);
1055 }
1056 }
1057 }
1058
1059 if (!current_class_valid) {
1060 Point pt = {0, 0};
1061 this->OnClick(pt, WID_SCL_CLASS_GENERAL, 1);
1062 }
1063 }
1064};
1065
1066static constexpr NWidgetPart _nested_select_company_livery_widgets[] = {
1068 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1069 NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCL_CAPTION),
1070 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1071 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1072 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1073 EndContainer(),
1075 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_GENERAL), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_IMG_COMPANY_GENERAL, STR_LIVERY_GENERAL_TOOLTIP),
1076 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_IMG_TRAINLIST, STR_LIVERY_TRAIN_TOOLTIP),
1077 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_IMG_TRUCKLIST, STR_LIVERY_ROAD_VEHICLE_TOOLTIP),
1078 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_IMG_SHIPLIST, STR_LIVERY_SHIP_TOOLTIP),
1079 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_IMG_AIRPLANESLIST, STR_LIVERY_AIRCRAFT_TOOLTIP),
1080 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_TRAIN, STR_LIVERY_TRAIN_GROUP_TOOLTIP),
1081 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_ROADVEH, STR_LIVERY_ROAD_VEHICLE_GROUP_TOOLTIP),
1082 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_SHIP, STR_LIVERY_SHIP_GROUP_TOOLTIP),
1083 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetSpriteTip(SPR_GROUP_LIVERY_AIRCRAFT, STR_LIVERY_AIRCRAFT_GROUP_TOOLTIP),
1084 NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1085 EndContainer(),
1087 NWidget(WWT_MATRIX, COLOUR_GREY, WID_SCL_MATRIX), SetMinimalSize(275, 0), SetResize(1, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_LIVERY_PANEL_TOOLTIP), SetScrollbar(WID_SCL_MATRIX_SCROLLBAR),
1089 EndContainer(),
1092 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetFill(0, 1), SetToolTip(STR_LIVERY_PRIMARY_TOOLTIP),
1093 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetFill(0, 1), SetToolTip(STR_LIVERY_SECONDARY_TOOLTIP),
1094 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1095 EndContainer(),
1096};
1097
1098static WindowDesc _select_company_livery_desc(
1099 WDP_AUTO, "company_color_scheme", 0, 0,
1101 {},
1102 _nested_select_company_livery_widgets
1103);
1104
1105void ShowCompanyLiveryWindow(CompanyID company, GroupID group)
1106{
1108 if (w == nullptr) {
1109 new SelectCompanyLiveryWindow(_select_company_livery_desc, company, group);
1110 } else if (group != GroupID::Invalid()) {
1111 w->SetSelectedGroup(company, group);
1112 }
1113}
1114
1121void DrawCompanyManagerFace(CompanyManagerFace cmf, Colours colour, const Rect &r)
1122{
1124
1125 /* Determine offset from centre of drawing rect. */
1126 Dimension d = GetSpriteSize(SPR_GRADIENT);
1127 int x = CenterBounds(r.left, r.right, d.width);
1128 int y = CenterBounds(r.top, r.bottom, d.height);
1129
1130 bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
1131 bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
1132 bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
1133 PaletteID pal;
1134
1135 /* Modify eye colour palette only if 2 or more valid values exist */
1136 if (_cmf_info[CMFV_EYE_COLOUR].valid_values[ge] < 2) {
1137 pal = PAL_NONE;
1138 } else {
1139 switch (GetCompanyManagerFaceBits(cmf, CMFV_EYE_COLOUR, ge)) {
1140 default: NOT_REACHED();
1141 case 0: pal = PALETTE_TO_BROWN; break;
1142 case 1: pal = PALETTE_TO_BLUE; break;
1143 case 2: pal = PALETTE_TO_GREEN; break;
1144 }
1145 }
1146
1147 /* Draw the gradient (background) */
1148 DrawSprite(SPR_GRADIENT, GENERAL_SPRITE_COLOUR(colour), x, y);
1149
1150 for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
1151 switch (cmfv) {
1152 case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
1153 case CMFV_LIPS:
1154 case CMFV_NOSE: if (has_moustache) continue; break;
1155 case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
1156 case CMFV_GLASSES: if (!has_glasses) continue; break;
1157 default: break;
1158 }
1159 DrawSprite(GetCompanyManagerFaceSprite(cmf, cmfv, ge), (cmfv == CMFV_EYEBROWS) ? pal : PAL_NONE, x, y);
1160 }
1161}
1162
1166 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1167 NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCMF_CAPTION), SetStringTip(STR_FACE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1168 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL), SetSpriteTip(SPR_LARGE_SMALL_WINDOW, STR_FACE_ADVANCED_TOOLTIP), SetAspect(WidgetDimensions::ASPECT_TOGGLE_SIZE),
1169 EndContainer(),
1170 NWidget(WWT_PANEL, COLOUR_GREY, WID_SCMF_SELECT_FACE),
1172 /* Left side */
1175 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
1176 EndContainer(),
1177 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_RANDOM_NEW_FACE), SetFill(1, 0), SetStringTip(STR_FACE_NEW_FACE_BUTTON, STR_FACE_NEW_FACE_TOOLTIP),
1178 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_LOADSAVE), // Load/number/save buttons under the portrait in the advanced view.
1179 NWidget(NWID_VERTICAL), SetPIP(0, 0, 0), SetPIPRatio(1, 0, 1),
1180 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LOAD), SetFill(1, 0), SetStringTip(STR_FACE_LOAD, STR_FACE_LOAD_TOOLTIP),
1181 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_FACECODE), SetFill(1, 0), SetStringTip(STR_FACE_FACECODE, STR_FACE_FACECODE_TOOLTIP),
1182 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_SAVE), SetFill(1, 0), SetStringTip(STR_FACE_SAVE, STR_FACE_SAVE_TOOLTIP),
1183 EndContainer(),
1184 EndContainer(),
1185 EndContainer(),
1186 /* Right side */
1188 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON), SetFill(1, 0), SetStringTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP),
1189 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_MALEFEMALE), // Simple male/female face setting.
1191 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE), SetFill(1, 0), SetStringTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1192 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE), SetFill(1, 0), SetStringTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1193 EndContainer(),
1194 EndContainer(),
1195 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_PARTS), // Advanced face parts setting.
1198 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE2), SetFill(1, 0), SetStringTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1199 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE2), SetFill(1, 0), SetStringTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1200 EndContainer(),
1202 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_EUR), SetFill(1, 0), SetStringTip(STR_FACE_EUROPEAN, STR_FACE_EUROPEAN_TOOLTIP),
1203 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_AFR), SetFill(1, 0), SetStringTip(STR_FACE_AFRICAN, STR_FACE_AFRICAN_TOOLTIP),
1204 EndContainer(),
1208 SetStringTip(STR_FACE_EYECOLOUR), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1209 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_MOUSTACHE_EARRING), SetToolTip(STR_FACE_MOUSTACHE_EARRING_TOOLTIP), SetTextStyle(TC_WHITE),
1210 EndContainer(),
1212 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_HAS_GLASSES_TEXT), SetFill(1, 0),
1213 SetStringTip(STR_FACE_GLASSES), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1214 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_GLASSES), SetToolTip(STR_FACE_GLASSES_TOOLTIP), SetTextStyle(TC_WHITE),
1215 EndContainer(),
1216 EndContainer(),
1219 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_HAIR_TEXT), SetFill(1, 0),
1220 SetStringTip(STR_FACE_HAIR), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1222 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_HAIR_TOOLTIP),
1223 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAIR), SetToolTip(STR_FACE_HAIR_TOOLTIP), SetTextStyle(TC_WHITE),
1224 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_HAIR_TOOLTIP),
1225 EndContainer(),
1226 EndContainer(),
1228 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_EYEBROWS_TEXT), SetFill(1, 0),
1229 SetStringTip(STR_FACE_EYEBROWS), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1231 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_EYEBROWS_TOOLTIP),
1232 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYEBROWS), SetToolTip(STR_FACE_EYEBROWS_TOOLTIP), SetTextStyle(TC_WHITE),
1233 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_EYEBROWS_TOOLTIP),
1234 EndContainer(),
1235 EndContainer(),
1237 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_EYECOLOUR_TEXT), SetFill(1, 0),
1238 SetStringTip(STR_FACE_EYECOLOUR), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1240 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1241 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR), SetToolTip(STR_FACE_EYECOLOUR_TOOLTIP), SetTextStyle(TC_WHITE),
1242 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1243 EndContainer(),
1244 EndContainer(),
1246 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_GLASSES_TEXT), SetFill(1, 0),
1247 SetStringTip(STR_FACE_GLASSES), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1249 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_GLASSES_TOOLTIP_2),
1250 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_GLASSES), SetToolTip(STR_FACE_GLASSES_TOOLTIP_2), SetTextStyle(TC_WHITE),
1251 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_GLASSES_TOOLTIP_2),
1252 EndContainer(),
1253 EndContainer(),
1255 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_NOSE_TEXT), SetFill(1, 0),
1256 SetStringTip(STR_FACE_NOSE), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1258 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_NOSE_TOOLTIP),
1259 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_NOSE), SetToolTip(STR_FACE_NOSE_TOOLTIP), SetTextStyle(TC_WHITE),
1260 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_NOSE_TOOLTIP),
1261 EndContainer(),
1262 EndContainer(),
1264 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_LIPS_MOUSTACHE_TEXT), SetFill(1, 0),
1265 SetStringTip(STR_FACE_MOUSTACHE), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1267 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1268 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE), SetToolTip(STR_FACE_LIPS_MOUSTACHE_TOOLTIP), SetTextStyle(TC_WHITE),
1269 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1270 EndContainer(),
1271 EndContainer(),
1273 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_CHIN_TEXT), SetFill(1, 0),
1274 SetStringTip(STR_FACE_CHIN), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1276 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_CHIN_TOOLTIP),
1277 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CHIN), SetToolTip(STR_FACE_CHIN_TOOLTIP), SetTextStyle(TC_WHITE),
1278 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_CHIN_TOOLTIP),
1279 EndContainer(),
1280 EndContainer(),
1282 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_JACKET_TEXT), SetFill(1, 0),
1283 SetStringTip(STR_FACE_JACKET), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1285 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_JACKET_TOOLTIP),
1286 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_JACKET), SetToolTip(STR_FACE_JACKET_TOOLTIP), SetTextStyle(TC_WHITE),
1287 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_JACKET_TOOLTIP),
1288 EndContainer(),
1289 EndContainer(),
1291 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_COLLAR_TEXT), SetFill(1, 0),
1292 SetStringTip(STR_FACE_COLLAR), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1294 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_COLLAR_TOOLTIP),
1295 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_COLLAR), SetToolTip(STR_FACE_COLLAR_TOOLTIP), SetTextStyle(TC_WHITE),
1296 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_COLLAR_TOOLTIP),
1297 EndContainer(),
1298 EndContainer(),
1300 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_TIE_EARRING_TEXT), SetFill(1, 0),
1301 SetStringTip(STR_FACE_EARRING), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1303 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_L), SetArrowWidgetTypeTip(AWV_DECREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1304 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING), SetToolTip(STR_FACE_TIE_EARRING_TOOLTIP), SetTextStyle(TC_WHITE),
1305 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_R), SetArrowWidgetTypeTip(AWV_INCREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1306 EndContainer(),
1307 EndContainer(),
1308 EndContainer(),
1309 EndContainer(),
1310 EndContainer(),
1311 EndContainer(),
1312 EndContainer(),
1313 EndContainer(),
1315 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CANCEL), SetFill(1, 0), SetStringTip(STR_BUTTON_CANCEL, STR_FACE_CANCEL_TOOLTIP),
1316 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_ACCEPT), SetFill(1, 0), SetStringTip(STR_BUTTON_OK, STR_FACE_OK_TOOLTIP),
1317 EndContainer(),
1318};
1319
1322{
1324 bool advanced = false;
1325
1327 bool is_female = false;
1328 bool is_moust_male = false;
1329
1332
1342 {
1343 const NWidgetCore *nwi_widget = this->GetWidget<NWidgetCore>(widget_index);
1344 if (nwi_widget->IsDisabled()) return {};
1345
1346 /* If it a bool button write yes or no. */
1347 if (is_bool_widget) return GetString((val != 0) ? STR_FACE_YES : STR_FACE_NO);
1348
1349 /* Else write the value + 1. */
1350 return GetString(STR_JUST_INT, val + 1);
1351 }
1352
1353 void UpdateData()
1354 {
1355 this->ge = (GenderEthnicity)GB(this->face, _cmf_info[CMFV_GEN_ETHN].offset, _cmf_info[CMFV_GEN_ETHN].length); // get the gender and ethnicity
1356 this->is_female = HasBit(this->ge, GENDER_FEMALE); // get the gender: 0 == male and 1 == female
1357 this->is_moust_male = !is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge) != 0; // is a male face with moustache
1358
1362 }
1363
1364public:
1366 {
1367 this->CreateNestedTree();
1368 this->SelectDisplayPlanes(this->advanced);
1369 this->FinishInitNested(parent->window_number);
1370 this->parent = parent;
1371 this->owner = this->window_number;
1372 this->face = Company::Get(this->window_number)->face;
1373
1374 this->UpdateData();
1375 }
1376
1382 {
1383 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_LOADSAVE)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1384 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_PARTS)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1385 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_MALEFEMALE)->SetDisplayedPlane(advanced ? SZSP_NONE : 0);
1387
1389 if (advanced) {
1391 } else {
1393 }
1394 }
1395
1396 void OnInit() override
1397 {
1398 /* Size of the boolean yes/no button. */
1402 /* Size of the number button + arrows. */
1403 Dimension number_dim = {0, 0};
1404 for (int val = 1; val <= 12; val++) {
1406 }
1407 uint arrows_width = GetSpriteSize(SPR_ARROW_LEFT).width + GetSpriteSize(SPR_ARROW_RIGHT).width + 2 * (WidgetDimensions::scaled.imgbtn.Horizontal());
1410 /* Compute width of both buttons. */
1411 yesno_dim.width = std::max(yesno_dim.width, number_dim.width);
1412 number_dim.width = yesno_dim.width - arrows_width;
1413
1414 this->yesno_dim = yesno_dim;
1415 this->number_dim = number_dim;
1416 }
1417
1419 {
1420 switch (widget) {
1424 break;
1425
1429 break;
1430
1434 break;
1435
1436 case WID_SCMF_FACE:
1437 size = maxdim(size, GetScaledSpriteSize(SPR_GRADIENT));
1438 break;
1439
1442 size = this->yesno_dim;
1443 break;
1444
1445 case WID_SCMF_EYECOLOUR:
1446 case WID_SCMF_CHIN:
1447 case WID_SCMF_EYEBROWS:
1449 case WID_SCMF_NOSE:
1450 case WID_SCMF_HAIR:
1451 case WID_SCMF_JACKET:
1452 case WID_SCMF_COLLAR:
1454 case WID_SCMF_GLASSES:
1455 size = this->number_dim;
1456 break;
1457 }
1458 }
1459
1460 void OnPaint() override
1461 {
1462 /* lower the non-selected gender button */
1463 this->SetWidgetsLoweredState(!this->is_female, WID_SCMF_MALE, WID_SCMF_MALE2);
1465
1466 /* advanced company manager face selection window */
1467
1468 /* lower the non-selected ethnicity button */
1471
1472
1473 /* Disable dynamically the widgets which CompanyManagerFaceVariable has less than 2 options
1474 * (or in other words you haven't any choice).
1475 * If the widgets depend on a HAS-variable and this is false the widgets will be disabled, too. */
1476
1477 /* Eye colour buttons */
1478 this->SetWidgetsDisabledState(_cmf_info[CMFV_EYE_COLOUR].valid_values[this->ge] < 2,
1480
1481 /* Chin buttons */
1482 this->SetWidgetsDisabledState(_cmf_info[CMFV_CHIN].valid_values[this->ge] < 2,
1484
1485 /* Eyebrows buttons */
1486 this->SetWidgetsDisabledState(_cmf_info[CMFV_EYEBROWS].valid_values[this->ge] < 2,
1488
1489 /* Lips or (if it a male face with a moustache) moustache buttons */
1490 this->SetWidgetsDisabledState(_cmf_info[this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS].valid_values[this->ge] < 2,
1492
1493 /* Nose buttons | male faces with moustache haven't any nose options */
1494 this->SetWidgetsDisabledState(_cmf_info[CMFV_NOSE].valid_values[this->ge] < 2 || this->is_moust_male,
1496
1497 /* Hair buttons */
1498 this->SetWidgetsDisabledState(_cmf_info[CMFV_HAIR].valid_values[this->ge] < 2,
1500
1501 /* Jacket buttons */
1502 this->SetWidgetsDisabledState(_cmf_info[CMFV_JACKET].valid_values[this->ge] < 2,
1504
1505 /* Collar buttons */
1506 this->SetWidgetsDisabledState(_cmf_info[CMFV_COLLAR].valid_values[this->ge] < 2,
1508
1509 /* Tie/earring buttons | female faces without earring haven't any earring options */
1510 this->SetWidgetsDisabledState(_cmf_info[CMFV_TIE_EARRING].valid_values[this->ge] < 2 ||
1511 (this->is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge) == 0),
1513
1514 /* Glasses buttons | faces without glasses haven't any glasses options */
1515 this->SetWidgetsDisabledState(_cmf_info[CMFV_GLASSES].valid_values[this->ge] < 2 || GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge) == 0,
1517
1518 this->DrawWidgets();
1519 }
1520
1521 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
1522 {
1523 switch (widget) {
1525 CompanyManagerFaceVariable facepart = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE;
1526 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, facepart, this->ge), true);
1527 }
1528
1530 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_TIE_EARRING, this->ge), false);
1531
1533 CompanyManagerFaceVariable facepart = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS;
1534 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, facepart, this->ge), false);
1535 }
1536
1538 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge), true );
1539
1540 case WID_SCMF_HAIR:
1541 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_HAIR, this->ge), false);
1542
1543 case WID_SCMF_EYEBROWS:
1544 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_EYEBROWS, this->ge), false);
1545
1546 case WID_SCMF_EYECOLOUR:
1547 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_EYE_COLOUR, this->ge), false);
1548
1549 case WID_SCMF_GLASSES:
1550 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_GLASSES, this->ge), false);
1551
1552 case WID_SCMF_NOSE:
1553 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_NOSE, this->ge), false);
1554
1555 case WID_SCMF_CHIN:
1556 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_CHIN, this->ge), false);
1557
1558 case WID_SCMF_JACKET:
1559 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_JACKET, this->ge), false);
1560
1561 case WID_SCMF_COLLAR:
1562 return this->GetFaceString(widget, GetCompanyManagerFaceBits(this->face, CMFV_COLLAR, this->ge), false);
1563
1564 default:
1565 return this->Window::GetWidgetString(widget, stringid);
1566 }
1567 }
1568
1569 void DrawWidget(const Rect &r, WidgetID widget) const override
1570 {
1571 switch (widget) {
1572 case WID_SCMF_FACE:
1573 DrawCompanyManagerFace(this->face, Company::Get(this->window_number)->colour, r);
1574 break;
1575 }
1576 }
1577
1578 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1579 {
1580 switch (widget) {
1581 /* Toggle size, advanced/simple face selection */
1584 this->advanced = !this->advanced;
1585 this->SelectDisplayPlanes(this->advanced);
1586 this->ReInit();
1587 break;
1588
1589 /* OK button */
1590 case WID_SCMF_ACCEPT:
1592 [[fallthrough]];
1593
1594 /* Cancel button */
1595 case WID_SCMF_CANCEL:
1596 this->Close();
1597 break;
1598
1599 /* Load button */
1600 case WID_SCMF_LOAD:
1604 this->UpdateData();
1605 this->SetDirty();
1606 break;
1607
1608 /* 'Company manager face number' button, view and/or set company manager face number */
1609 case WID_SCMF_FACECODE:
1611 break;
1612
1613 /* Save button */
1614 case WID_SCMF_SAVE:
1617 break;
1618
1619 /* Toggle gender (male/female) button */
1620 case WID_SCMF_MALE:
1621 case WID_SCMF_FEMALE:
1622 case WID_SCMF_MALE2:
1623 case WID_SCMF_FEMALE2:
1624 SetCompanyManagerFaceBits(this->face, CMFV_GENDER, this->ge, (widget == WID_SCMF_FEMALE || widget == WID_SCMF_FEMALE2));
1626 this->UpdateData();
1627 this->SetDirty();
1628 break;
1629
1630 /* Randomize face button */
1632 RandomCompanyManagerFaceBits(this->face, this->ge, this->advanced, _interactive_random);
1633 this->UpdateData();
1634 this->SetDirty();
1635 break;
1636
1637 /* Toggle ethnicity (european/african) button */
1640 SetCompanyManagerFaceBits(this->face, CMFV_ETHNICITY, this->ge, widget - WID_SCMF_ETHNICITY_EUR);
1642 this->UpdateData();
1643 this->SetDirty();
1644 break;
1645
1646 default:
1647 /* Here all buttons from WID_SCMF_HAS_MOUSTACHE_EARRING to WID_SCMF_GLASSES_R are handled.
1648 * First it checks which CompanyManagerFaceVariable is being changed, and then either
1649 * a: invert the value for boolean variables, or
1650 * b: it checks inside of IncreaseCompanyManagerFaceBits() if a left (_L) butten is pressed and then decrease else increase the variable */
1651 if (widget >= WID_SCMF_HAS_MOUSTACHE_EARRING && widget <= WID_SCMF_GLASSES_R) {
1652 CompanyManagerFaceVariable cmfv; // which CompanyManagerFaceVariable shall be edited
1653
1654 if (widget < WID_SCMF_EYECOLOUR_L) { // Bool buttons
1655 switch (widget - WID_SCMF_HAS_MOUSTACHE_EARRING) {
1656 default: NOT_REACHED();
1657 case 0: cmfv = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE; break; // Has earring/moustache button
1658 case 1: cmfv = CMFV_HAS_GLASSES; break; // Has glasses button
1659 }
1660 SetCompanyManagerFaceBits(this->face, cmfv, this->ge, !GetCompanyManagerFaceBits(this->face, cmfv, this->ge));
1662 } else { // Value buttons
1663 switch ((widget - WID_SCMF_EYECOLOUR_L) / 3) {
1664 default: NOT_REACHED();
1665 case 0: cmfv = CMFV_EYE_COLOUR; break; // Eye colour buttons
1666 case 1: cmfv = CMFV_CHIN; break; // Chin buttons
1667 case 2: cmfv = CMFV_EYEBROWS; break; // Eyebrows buttons
1668 case 3: cmfv = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS; break; // Moustache or lips buttons
1669 case 4: cmfv = CMFV_NOSE; break; // Nose buttons
1670 case 5: cmfv = CMFV_HAIR; break; // Hair buttons
1671 case 6: cmfv = CMFV_JACKET; break; // Jacket buttons
1672 case 7: cmfv = CMFV_COLLAR; break; // Collar buttons
1673 case 8: cmfv = CMFV_TIE_EARRING; break; // Tie/earring buttons
1674 case 9: cmfv = CMFV_GLASSES; break; // Glasses buttons
1675 }
1676 /* 0 == left (_L), 1 == middle or 2 == right (_R) - button click */
1677 IncreaseCompanyManagerFaceBits(this->face, cmfv, this->ge, (((widget - WID_SCMF_EYECOLOUR_L) % 3) != 0) ? 1 : -1);
1678 }
1679 this->UpdateData();
1680 this->SetDirty();
1681 }
1682 break;
1683 }
1684 }
1685
1686 void OnQueryTextFinished(std::optional<std::string> str) override
1687 {
1688 if (!str.has_value()) return;
1689 /* Set a new company manager face number */
1690 if (!str->empty()) {
1691 this->face = std::strtoul(str->c_str(), nullptr, 10);
1694 this->UpdateData();
1695 this->SetDirty();
1696 } else {
1698 }
1699 }
1700};
1701
1704 WDP_AUTO, nullptr, 0, 0,
1708);
1709
1722
1723static constexpr NWidgetPart _nested_company_infrastructure_widgets[] = {
1725 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1726 NWidget(WWT_CAPTION, COLOUR_GREY, WID_CI_CAPTION),
1727 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1728 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1729 EndContainer(),
1730 NWidget(WWT_PANEL, COLOUR_GREY),
1733 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_RAIL_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1734 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_RAIL_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1735 EndContainer(),
1737 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_ROAD_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1738 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_ROAD_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1739 EndContainer(),
1741 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_TRAM_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1742 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_TRAM_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1743 EndContainer(),
1745 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_WATER_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1746 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_WATER_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1747 EndContainer(),
1749 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_STATION_DESC), SetMinimalTextLines(3, 0), SetFill(1, 0),
1750 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_STATION_COUNT), SetMinimalTextLines(3, 0), SetFill(0, 1),
1751 EndContainer(),
1753 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_TOTAL_DESC), SetFill(1, 0),
1754 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CI_TOTAL), SetFill(0, 1),
1755 EndContainer(),
1756 EndContainer(),
1757 EndContainer(),
1758};
1759
1764{
1767
1768 uint total_width = 0;
1769
1771 {
1772 this->UpdateRailRoadTypes();
1773
1774 this->InitNested(window_number);
1775 this->owner = this->window_number;
1776 }
1777
1778 void UpdateRailRoadTypes()
1779 {
1780 this->railtypes = RAILTYPES_NONE;
1781 this->roadtypes = ROADTYPES_NONE;
1782
1783 /* Find the used railtypes. */
1784 for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
1785 if (!e->info.climates.Test(_settings_game.game_creation.landscape)) continue;
1786
1787 this->railtypes |= GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes;
1788 }
1789
1790 /* Get the date introduced railtypes as well. */
1792
1793 /* Find the used roadtypes. */
1794 for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
1795 if (!e->info.climates.Test(_settings_game.game_creation.landscape)) continue;
1796
1797 this->roadtypes |= GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes;
1798 }
1799
1800 /* Get the date introduced roadtypes as well. */
1803 }
1804
1807 {
1808 const Company *c = Company::Get(this->window_number);
1809 Money total;
1810
1812 for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
1814 }
1816
1819 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
1820 if (HasBit(this->roadtypes, rt)) total += RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total);
1821 }
1822
1825 total += AirportMaintenanceCost(c->index);
1826
1827 return total;
1828 }
1829
1830 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
1831 {
1832 switch (widget) {
1833 case WID_CI_CAPTION:
1835
1836 default:
1837 return this->Window::GetWidgetString(widget, stringid);
1838 }
1839 }
1840
1842 {
1843 const Company *c = Company::Get(this->window_number);
1844
1845 switch (widget) {
1846 case WID_CI_RAIL_DESC: {
1847 uint lines = 1; // Starts at 1 because a line is also required for the section title
1848
1849 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).width + padding.width);
1850
1851 for (const auto &rt : _sorted_railtypes) {
1852 if (HasBit(this->railtypes, rt)) {
1853 lines++;
1854 size.width = std::max(size.width, GetStringBoundingBox(GetRailTypeInfo(rt)->strings.name).width + padding.width + WidgetDimensions::scaled.hsep_indent);
1855 }
1856 }
1857 if (this->railtypes != RAILTYPES_NONE) {
1858 lines++;
1860 }
1861
1862 size.height = std::max(size.height, lines * GetCharacterHeight(FS_NORMAL));
1863 break;
1864 }
1865
1866 case WID_CI_ROAD_DESC:
1867 case WID_CI_TRAM_DESC: {
1868 uint lines = 1; // Starts at 1 because a line is also required for the section title
1869
1871
1872 for (const auto &rt : _sorted_roadtypes) {
1873 if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
1874 lines++;
1875 size.width = std::max(size.width, GetStringBoundingBox(GetRoadTypeInfo(rt)->strings.name).width + padding.width + WidgetDimensions::scaled.hsep_indent);
1876 }
1877 }
1878
1879 size.height = std::max(size.height, lines * GetCharacterHeight(FS_NORMAL));
1880 break;
1881 }
1882
1883 case WID_CI_WATER_DESC:
1884 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT).width + padding.width);
1886 break;
1887
1889 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT).width + padding.width);
1892 break;
1893
1894 case WID_CI_RAIL_COUNT:
1895 case WID_CI_ROAD_COUNT:
1896 case WID_CI_TRAM_COUNT:
1897 case WID_CI_WATER_COUNT:
1899 case WID_CI_TOTAL: {
1900 /* Find the maximum count that is displayed. */
1901 uint32_t max_val = 1000; // Some random number to reserve enough space.
1902 Money max_cost = 10000; // Some random number to reserve enough space.
1904 for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
1905 max_val = std::max(max_val, c->infrastructure.rail[rt]);
1906 max_cost = std::max(max_cost, RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
1907 }
1908 max_val = std::max(max_val, c->infrastructure.signal);
1909 max_cost = std::max(max_cost, SignalMaintenanceCost(c->infrastructure.signal));
1912 for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
1913 max_val = std::max(max_val, c->infrastructure.road[rt]);
1914 max_cost = std::max(max_cost, RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total));
1915
1916 }
1917 max_val = std::max(max_val, c->infrastructure.water);
1918 max_cost = std::max(max_cost, CanalMaintenanceCost(c->infrastructure.water));
1919 max_val = std::max(max_val, c->infrastructure.station);
1920 max_cost = std::max(max_cost, StationMaintenanceCost(c->infrastructure.station));
1921 max_val = std::max(max_val, c->infrastructure.airport);
1922 max_cost = std::max(max_cost, AirportMaintenanceCost(c->index));
1923
1924 uint count_width = GetStringBoundingBox(GetString(STR_JUST_COMMA, GetParamMaxValue(max_val))).width + WidgetDimensions::scaled.hsep_indent; // Reserve some wiggle room
1925
1928 /* Convert to per year */
1930 size.width = std::max(size.width, this->total_width);
1931
1932 /* Convert to per year */
1933 count_width += std::max(this->total_width, GetStringBoundingBox(GetString(str_total, GetParamMaxValue(max_cost * 12))).width);
1934 }
1935
1936 size.width = std::max(size.width, count_width);
1937
1938 /* Set height of the total line. */
1939 if (widget == WID_CI_TOTAL) {
1941 }
1942 break;
1943 }
1944 }
1945 }
1946
1954 void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
1955 {
1956 DrawString(r.left, r.right, y += GetCharacterHeight(FS_NORMAL), GetString(STR_JUST_COMMA, count), TC_WHITE, SA_RIGHT);
1957
1959 Rect tr = r.WithWidth(this->total_width, _current_text_dir == TD_RTL);
1960 DrawString(tr.left, tr.right, y,
1962 TC_FROMSTRING, SA_RIGHT);
1963 }
1964 }
1965
1966 void DrawWidget(const Rect &r, WidgetID widget) const override
1967 {
1968 const Company *c = Company::Get(this->window_number);
1969
1970 int y = r.top;
1971
1973 switch (widget) {
1974 case WID_CI_RAIL_DESC:
1976
1977 if (this->railtypes != RAILTYPES_NONE) {
1978 /* Draw name of each valid railtype. */
1979 for (const auto &rt : _sorted_railtypes) {
1980 if (HasBit(this->railtypes, rt)) {
1981 DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), GetRailTypeInfo(rt)->strings.name, TC_WHITE);
1982 }
1983 }
1985 } else {
1986 /* No valid railtype. */
1988 }
1989
1990 break;
1991
1992 case WID_CI_RAIL_COUNT: {
1993 /* Draw infrastructure count for each valid railtype. */
1995 for (const auto &rt : _sorted_railtypes) {
1996 if (HasBit(this->railtypes, rt)) {
1998 }
1999 }
2000 if (this->railtypes != RAILTYPES_NONE) {
2002 }
2003 break;
2004 }
2005
2006 case WID_CI_ROAD_DESC:
2007 case WID_CI_TRAM_DESC: {
2009
2010 /* Draw name of each valid roadtype. */
2011 for (const auto &rt : _sorted_roadtypes) {
2012 if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
2013 DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), GetRoadTypeInfo(rt)->strings.name, TC_WHITE);
2014 }
2015 }
2016
2017 break;
2018 }
2019
2020 case WID_CI_ROAD_COUNT:
2021 case WID_CI_TRAM_COUNT: {
2023 for (const auto &rt : _sorted_roadtypes) {
2024 if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_COUNT)) {
2026 }
2027 }
2028 break;
2029 }
2030
2031 case WID_CI_WATER_DESC:
2034 break;
2035
2036 case WID_CI_WATER_COUNT:
2038 break;
2039
2040 case WID_CI_TOTAL:
2042 Rect tr = r.WithWidth(this->total_width, _current_text_dir == TD_RTL);
2043 GfxFillRect(tr.left, y, tr.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_WHITE);
2045 DrawString(tr.left, tr.right, y,
2047 TC_FROMSTRING, SA_RIGHT);
2048 }
2049 break;
2050
2055 break;
2056
2060 break;
2061 }
2062 }
2063
2069 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2070 {
2071 if (!gui_scope) return;
2072
2073 this->UpdateRailRoadTypes();
2074 this->ReInit();
2075 }
2076};
2077
2078static WindowDesc _company_infrastructure_desc(
2079 WDP_AUTO, "company_infrastructure", 0, 0,
2081 {},
2082 _nested_company_infrastructure_widgets
2083);
2084
2090{
2091 if (!Company::IsValidID(company)) return;
2092 AllocateWindowDescFront<CompanyInfrastructureWindow>(_company_infrastructure_desc, company);
2093}
2094
2095static constexpr NWidgetPart _nested_company_widgets[] = {
2097 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2098 NWidget(WWT_CAPTION, COLOUR_GREY, WID_C_CAPTION),
2099 NWidget(WWT_SHADEBOX, COLOUR_GREY),
2100 NWidget(WWT_STICKYBOX, COLOUR_GREY),
2101 EndContainer(),
2102 NWidget(WWT_PANEL, COLOUR_GREY),
2105 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
2106 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE_TITLE), SetFill(1, 1), SetMinimalTextLines(2, 0),
2107 EndContainer(),
2111 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_INAUGURATION), SetFill(1, 0),
2113 NWidget(WWT_LABEL, INVALID_COLOUR, WID_C_DESC_COLOUR_SCHEME), SetStringTip(STR_COMPANY_VIEW_COLOUR_SCHEME_TITLE),
2115 EndContainer(),
2117 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_VEHICLE), SetStringTip(STR_COMPANY_VIEW_VEHICLES_TITLE), SetAlignment(SA_LEFT | SA_TOP),
2119 EndContainer(),
2120 EndContainer(),
2123 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_HQ), SetStringTip(STR_COMPANY_VIEW_VIEW_HQ_BUTTON, STR_COMPANY_VIEW_VIEW_HQ_TOOLTIP),
2124 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_BUILD_HQ), SetStringTip(STR_COMPANY_VIEW_BUILD_HQ_BUTTON, STR_COMPANY_VIEW_BUILD_HQ_TOOLTIP),
2125 EndContainer(),
2127 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_RELOCATE_HQ), SetStringTip(STR_COMPANY_VIEW_RELOCATE_HQ, STR_COMPANY_VIEW_RELOCATE_HQ_TOOLTIP),
2129 EndContainer(),
2130 EndContainer(),
2131 EndContainer(),
2132
2133 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_COMPANY_VALUE), SetFill(1, 0),
2134
2136 NWidget(WWT_TEXT, INVALID_COLOUR, WID_C_DESC_INFRASTRUCTURE), SetStringTip(STR_COMPANY_VIEW_INFRASTRUCTURE), SetAlignment(SA_LEFT | SA_TOP),
2139 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_INFRASTRUCTURE), SetStringTip(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
2140 EndContainer(),
2141 EndContainer(),
2142
2143 /* Multi player buttons. */
2147 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_HOSTILE_TAKEOVER), SetStringTip(STR_COMPANY_VIEW_HOSTILE_TAKEOVER_BUTTON, STR_COMPANY_VIEW_HOSTILE_TAKEOVER_TOOLTIP),
2148 EndContainer(),
2150 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_GIVE_MONEY), SetStringTip(STR_COMPANY_VIEW_GIVE_MONEY_BUTTON, STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP),
2151 EndContainer(),
2153 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_JOIN), SetStringTip(STR_COMPANY_VIEW_JOIN, STR_COMPANY_VIEW_JOIN_TOOLTIP),
2154 EndContainer(),
2155 EndContainer(),
2156 EndContainer(),
2157 EndContainer(),
2158 EndContainer(),
2159 EndContainer(),
2160 /* Button bars at the bottom. */
2163 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_NEW_FACE), SetFill(1, 0), SetStringTip(STR_COMPANY_VIEW_NEW_FACE_BUTTON, STR_COMPANY_VIEW_NEW_FACE_TOOLTIP),
2164 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COLOUR_SCHEME), SetFill(1, 0), SetStringTip(STR_COMPANY_VIEW_COLOUR_SCHEME_BUTTON, STR_COMPANY_VIEW_COLOUR_SCHEME_TOOLTIP),
2165 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_PRESIDENT_NAME), SetFill(1, 0), SetStringTip(STR_COMPANY_VIEW_PRESIDENT_NAME_BUTTON, STR_COMPANY_VIEW_PRESIDENT_NAME_TOOLTIP),
2166 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_NAME), SetFill(1, 0), SetStringTip(STR_COMPANY_VIEW_COMPANY_NAME_BUTTON, STR_COMPANY_VIEW_COMPANY_NAME_TOOLTIP),
2167 EndContainer(),
2168 EndContainer(),
2169};
2170
2173 STR_COMPANY_VIEW_TRAINS, STR_COMPANY_VIEW_ROAD_VEHICLES, STR_COMPANY_VIEW_SHIPS, STR_COMPANY_VIEW_AIRCRAFT
2174};
2175
2180{
2181 CompanyWidgets query_widget{};
2182
2185 /* Display planes of the #WID_C_SELECT_VIEW_BUILD_HQ selection widget. */
2188
2189 /* Display planes of the #WID_C_SELECT_RELOCATE selection widget. */
2192 };
2193
2195 {
2196 this->InitNested(window_number);
2197 this->owner = this->window_number;
2198 this->OnInvalidateData();
2199 }
2200
2201 void OnPaint() override
2202 {
2203 const Company *c = Company::Get(this->window_number);
2204 bool local = this->window_number == _local_company;
2205
2206 if (!this->IsShaded()) {
2207 bool reinit = false;
2208
2209 /* Button bar selection. */
2210 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_BUTTONS)->SetDisplayedPlane(local ? 0 : SZSP_NONE);
2211
2212 /* Build HQ button handling. */
2214
2216
2217 /* Enable/disable 'Relocate HQ' button. */
2219 /* Enable/disable 'Give money' button. */
2221 /* Enable/disable 'Hostile Takeover' button. */
2223
2224 /* Multiplayer buttons. */
2226
2228
2229 if (reinit) {
2230 this->ReInit();
2231 return;
2232 }
2233 }
2234
2235 this->DrawWidgets();
2236 }
2237
2239 {
2240 switch (widget) {
2241 case WID_C_FACE:
2242 size = maxdim(size, GetScaledSpriteSize(SPR_GRADIENT));
2243 break;
2244
2246 Point offset;
2247 Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2248 d.width -= offset.x;
2249 d.height -= offset.y;
2250 size = maxdim(size, d);
2251 break;
2252 }
2253
2255 /* INT64_MAX is arguably the maximum company value */
2257 break;
2258
2260 uint64_t max_value = GetParamMaxValue(5000); // Maximum number of vehicles
2262 size.width = std::max(size.width, GetStringBoundingBox(GetString(count_string, max_value)).width + padding.width);
2263 }
2264 break;
2265 }
2266
2268 uint64_t max_value = GetParamMaxValue(UINT_MAX);
2270 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD, max_value)).width);
2271 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_WATER, max_value)).width);
2272 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_STATION, max_value)).width);
2273 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT, max_value)).width);
2274 size.width = std::max(size.width, GetStringBoundingBox(GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_NONE, max_value)).width);
2275 size.width += padding.width;
2276 break;
2277 }
2278
2279 case WID_C_VIEW_HQ:
2280 case WID_C_BUILD_HQ:
2281 case WID_C_RELOCATE_HQ:
2283 case WID_C_GIVE_MONEY:
2285 case WID_C_COMPANY_JOIN:
2287 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_BUILD_HQ_BUTTON).width);
2288 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_RELOCATE_HQ).width);
2289 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON).width);
2290 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_GIVE_MONEY_BUTTON).width);
2291 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_HOSTILE_TAKEOVER_BUTTON).width);
2292 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_JOIN).width);
2293 size.width += padding.width;
2294 break;
2295 }
2296 }
2297
2298 void DrawVehicleCountsWidget(const Rect &r, const Company *c) const
2299 {
2301
2302 int y = r.top;
2303 for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
2304 uint amount = c->group_all[type].num_vehicle;
2305 if (amount != 0) {
2306 DrawString(r.left, r.right, y, GetString(_company_view_vehicle_count_strings[type], amount));
2308 }
2309 }
2310
2311 if (y == r.top) {
2312 /* No String was emitted before, so there must be no vehicles at all. */
2313 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_VEHICLES_NONE);
2314 }
2315 }
2316
2317 void DrawInfrastructureCountsWidget(const Rect &r, const Company *c) const
2318 {
2319 int y = r.top;
2320
2322 if (rail_pieces != 0) {
2325 }
2326
2327 /* GetRoadTotal() skips tram pieces, but we actually want road and tram here. */
2328 uint road_pieces = std::accumulate(std::begin(c->infrastructure.road), std::end(c->infrastructure.road), 0U);
2329 if (road_pieces != 0) {
2332 }
2333
2334 if (c->infrastructure.water != 0) {
2337 }
2338
2339 if (c->infrastructure.station != 0) {
2342 }
2343
2344 if (c->infrastructure.airport != 0) {
2347 }
2348
2349 if (y == r.top) {
2350 /* No String was emitted before, so there must be no infrastructure at all. */
2352 }
2353 }
2354
2355 void DrawWidget(const Rect &r, WidgetID widget) const override
2356 {
2357 const Company *c = Company::Get(this->window_number);
2358 switch (widget) {
2359 case WID_C_FACE:
2361 break;
2362
2363 case WID_C_FACE_TITLE:
2365 break;
2366
2368 Point offset;
2369 Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2370 d.height -= offset.y;
2371 DrawSprite(SPR_VEH_BUS_SW_VIEW, COMPANY_SPRITE_COLOUR(c->index), r.left - offset.x, CenterBounds(r.top, r.bottom, d.height) - offset.y);
2372 break;
2373 }
2374
2376 DrawVehicleCountsWidget(r, c);
2377 break;
2378
2380 DrawInfrastructureCountsWidget(r, c);
2381 break;
2382 }
2383 }
2384
2385 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
2386 {
2387 switch (widget) {
2388 case WID_C_CAPTION:
2390
2392 const Company &c = *Company::Get(this->window_number);
2395 }
2397 }
2398
2401
2402 default:
2403 return this->Window::GetWidgetString(widget, stringid);
2404 }
2405 }
2406
2407 void OnResize() override
2408 {
2411 if (wid->UpdateVerticalSize(y)) this->ReInit(0, 0);
2412 }
2413
2414 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2415 {
2416 switch (widget) {
2417 case WID_C_NEW_FACE: DoSelectCompanyManagerFace(this); break;
2418
2420 ShowCompanyLiveryWindow(this->window_number, GroupID::Invalid());
2421 break;
2422
2424 this->query_widget = WID_C_PRESIDENT_NAME;
2426 break;
2427
2428 case WID_C_COMPANY_NAME:
2429 this->query_widget = WID_C_COMPANY_NAME;
2431 break;
2432
2433 case WID_C_VIEW_HQ: {
2434 TileIndex tile = Company::Get(this->window_number)->location_of_HQ;
2435 if (_ctrl_pressed) {
2437 } else {
2439 }
2440 break;
2441 }
2442
2443 case WID_C_BUILD_HQ:
2444 if (this->window_number != _local_company) return;
2445 if (this->IsWidgetLowered(WID_C_BUILD_HQ)) {
2447 this->RaiseButtons();
2448 break;
2449 }
2450 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2451 SetTileSelectSize(2, 2);
2454 break;
2455
2456 case WID_C_RELOCATE_HQ:
2459 this->RaiseButtons();
2460 break;
2461 }
2462 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2463 SetTileSelectSize(2, 2);
2466 break;
2467
2470 break;
2471
2472 case WID_C_GIVE_MONEY:
2473 this->query_widget = WID_C_GIVE_MONEY;
2475 break;
2476
2479 break;
2480
2481 case WID_C_COMPANY_JOIN: {
2482 this->query_widget = WID_C_COMPANY_JOIN;
2483 CompanyID company = this->window_number;
2484 if (_network_server) {
2487 } else {
2488 /* just send the join command */
2489 NetworkClientRequestMove(company);
2490 }
2491 break;
2492 }
2493 }
2494 }
2495
2497 IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
2498 this->SetDirty();
2499 }};
2500
2508
2509 void OnPlaceObjectAbort() override
2510 {
2511 this->RaiseButtons();
2512 }
2513
2514 void OnQueryTextFinished(std::optional<std::string> str) override
2515 {
2516 if (!str.has_value()) return;
2517
2518 switch (this->query_widget) {
2519 default: NOT_REACHED();
2520
2521 case WID_C_GIVE_MONEY: {
2522 Money money = std::strtoull(str->c_str(), nullptr, 10) / GetCurrency().rate;
2524 break;
2525 }
2526
2529 break;
2530
2531 case WID_C_COMPANY_NAME:
2533 break;
2534 }
2535 }
2536
2537 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2538 {
2539 if (gui_scope && data == 1) {
2540 /* Manually call OnResize to adjust minimum height of president name widget. */
2541 OnResize();
2542 }
2543 }
2544};
2545
2546static WindowDesc _company_desc(
2547 WDP_AUTO, "company", 0, 0,
2549 {},
2550 _nested_company_widgets
2551);
2552
2558{
2559 if (!Company::IsValidID(company)) return;
2560
2561 AllocateWindowDescFront<CompanyWindow>(_company_desc, company);
2562}
2563
2573
2576 {
2577 this->InitNested(window_number);
2578
2579 const Company *c = Company::Get(this->window_number);
2580 this->company_value = hostile_takeover ? CalculateHostileTakeoverValue(c) : c->bankrupt_value;
2581 }
2582
2584 {
2585 switch (widget) {
2586 case WID_BC_FACE:
2587 size = GetScaledSpriteSize(SPR_GRADIENT);
2588 break;
2589
2590 case WID_BC_QUESTION:
2591 const Company *c = Company::Get(this->window_number);
2592 size.height = GetStringHeight(GetString(this->hostile_takeover ? STR_BUY_COMPANY_HOSTILE_TAKEOVER : STR_BUY_COMPANY_MESSAGE, c->index, this->company_value), size.width);
2593 break;
2594 }
2595 }
2596
2597 std::string GetWidgetString(WidgetID widget, StringID stringid) const override
2598 {
2599 switch (widget) {
2600 case WID_BC_CAPTION:
2601 return GetString(STR_ERROR_MESSAGE_CAPTION_OTHER_COMPANY, Company::Get(this->window_number)->index);
2602
2603 default:
2604 return this->Window::GetWidgetString(widget, stringid);
2605 }
2606 }
2607
2608 void DrawWidget(const Rect &r, WidgetID widget) const override
2609 {
2610 switch (widget) {
2611 case WID_BC_FACE: {
2612 const Company *c = Company::Get(this->window_number);
2614 break;
2615 }
2616
2617 case WID_BC_QUESTION: {
2618 const Company *c = Company::Get(this->window_number);
2620 break;
2621 }
2622 }
2623 }
2624
2625 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2626 {
2627 switch (widget) {
2628 case WID_BC_NO:
2629 this->Close();
2630 break;
2631
2632 case WID_BC_YES:
2633 Command<CMD_BUY_COMPANY>::Post(STR_ERROR_CAN_T_BUY_COMPANY, this->window_number, this->hostile_takeover);
2634 break;
2635 }
2636 }
2637
2641 IntervalTimer<TimerWindow> rescale_interval = {std::chrono::seconds(3), [this](auto) {
2642 /* Value can't change when in bankruptcy. */
2643 if (!this->hostile_takeover) return;
2644
2645 const Company *c = Company::Get(this->window_number);
2647 if (new_value != this->company_value) {
2648 this->company_value = new_value;
2649 this->ReInit();
2650 }
2651 }};
2652
2653private:
2654 bool hostile_takeover = false;
2656};
2657
2658static constexpr NWidgetPart _nested_buy_company_widgets[] = {
2660 NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
2661 NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE, WID_BC_CAPTION),
2662 EndContainer(),
2663 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
2666 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_FACE), SetFill(0, 1),
2667 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_QUESTION), SetMinimalSize(240, 0), SetFill(1, 1),
2668 EndContainer(),
2670 NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_NO), SetMinimalSize(60, 12), SetStringTip(STR_QUIT_NO), SetFill(1, 0),
2671 NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_YES), SetMinimalSize(60, 12), SetStringTip(STR_QUIT_YES), SetFill(1, 0),
2672 EndContainer(),
2673 EndContainer(),
2674 EndContainer(),
2675};
2676
2677static WindowDesc _buy_company_desc(
2678 WDP_AUTO, nullptr, 0, 0,
2681 _nested_buy_company_widgets
2682);
2683
2689void ShowBuyCompanyDialog(CompanyID company, bool hostile_takeover)
2690{
2691 auto window = BringWindowToFrontById(WC_BUY_COMPANY, company);
2692 if (window == nullptr) {
2693 new BuyCompanyWindow(_buy_company_desc, company, hostile_takeover);
2694 }
2695}
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr T ToggleBit(T &x, const uint8_t y)
Toggles a bit in a variable.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Drop down icon component.
Colour selection list item, with icon and string components.
bool masked
Masked and unselectable item.
void RebuildDone()
Notify the sortlist that the rebuild is done.
bool NeedRebuild() const
Check if a rebuild is needed.
void ForceRebuild()
Force that a rebuild is needed.
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).
Base class for a 'real' widget.
Base class for a resizable nested widget.
RailTypes introduces_railtypes
Bitmask of which other railtypes are introduced when this railtype is introduced.
Definition rail.h:257
StringID name
Name of this rail type.
Definition rail.h:167
RoadTypes introduces_roadtypes
Bitmask of which other roadtypes are introduced when this roadtype is introduced.
Definition road.h:168
StringID name
Name of this rail type.
Definition road.h:94
Scrollbar data structure.
size_type GetCapacity() const
Gets the number of visible elements of the scrollbar.
void SetCount(size_t num)
Sets the number of elements in the list.
auto GetScrolledItemFromWidget(Tcontainer &container, int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Return an iterator pointing to the element of a scrolled widget that a user clicked in.
size_type GetScrolledRowFromWidget(int clickpos, const Window *const w, WidgetID widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition widget.cpp:2447
bool SetPosition(size_type position)
Sets the position of the first visible element.
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:2521
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.
size_type GetPosition() const
Gets the position of the first visible element in the list.
Management class for customizing the face of the company manager.
std::string GetFaceString(WidgetID widget_index, uint8_t val, bool is_bool_widget) const
Get the string for the value of face control buttons.
void SelectDisplayPlanes(bool advanced)
Select planes to display to the user with the NWID_SELECTION widgets WID_SCMF_SEL_LOADSAVE,...
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
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.
bool advanced
advanced company manager face selection window
bool is_moust_male
Male face with a moustache.
GenderEthnicity ge
Gender and ethnicity.
Dimension yesno_dim
Dimension of a yes/no button of a part in the advanced face window.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
CompanyManagerFace face
company manager face bits
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 OnInit() override
Notification that the nested widget tree gets initialized.
void OnPaint() override
The window must be repainted.
Dimension number_dim
Dimension of a number widget of a part in the advanced face window.
static constexpr TimerGame< struct Calendar >::Date MAX_DATE
The date of the last day of the max year.
static Year year
Current year, starting at 0.
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
RectPadding framerect
Standard padding inside many panels.
Definition window_gui.h:40
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:29
RectPadding imgbtn
Padding around image button image.
Definition window_gui.h:34
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:58
int vsep_wide
Wide vertical spacing.
Definition window_gui.h:60
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:94
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:61
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:38
int hsep_indent
Width of indentation for tree layouts.
Definition window_gui.h:63
Functions related to commands.
Definition of stuff that is very close to a company, like the company struct itself.
Money CalculateHostileTakeoverValue(const Company *c)
Calculate what you have to pay to take over a company.
Definition economy.cpp:177
Money CalculateCompanyValue(const Company *c, bool including_loan=true)
Calculate the value of the company.
Definition economy.cpp:150
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
CompanyManagerFace _company_manager_face
for company manager face storage in openttd.cfg
Command definitions related to companies.
Functions related to companies.
void ShowCompanyFinances(CompanyID company)
Open the finances window of a company.
static Money DrawYearCategory(const Rect &r, int start_y, const ExpensesList &list, const Expenses &tbl)
Draw a category of expenses/revenues in the year column.
static uint GetMaxCategoriesWidth()
Get the required width of the "categories" column, equal to the widest element.
static void DrawYearColumn(const Rect &r, TimerGameEconomy::Year year, const Expenses &tbl)
Draw a column with prices.
static const std::initializer_list< ExpensesType > _expenses_list_capital_costs
List of capital expenses.
void ShowBuyCompanyDialog(CompanyID company, bool hostile_takeover)
Show the query to buy another company.
static const StringID _company_view_vehicle_count_strings[]
Strings for the company vehicle counts.
static const std::initializer_list< ExpensesList > _expenses_list_types
Types of expense lists.
static void DrawPrice(Money amount, int left, int right, int top, TextColour colour)
Draw an amount of money.
static void ShowCompanyInfrastructure(CompanyID company)
Open the infrastructure window of a company.
static void DrawCategories(const Rect &r)
Draw the expenses categories.
static void DoSelectCompanyManagerFace(Window *parent)
Company GUI constants.
void ShowCompany(CompanyID company)
Show the window with the overview of the company.
static constexpr NWidgetPart _nested_select_company_manager_face_widgets[]
Nested widget description for the company manager face selection dialog.
static WindowDesc _select_company_manager_face_desc(WDP_AUTO, nullptr, 0, 0, WC_COMPANY_MANAGER_FACE, WC_NONE, WindowDefaultFlag::Construction, _nested_select_company_manager_face_widgets)
Company manager face selection window description.
static const std::initializer_list< ExpensesType > _expenses_list_operating_costs
List of operating expenses.
static uint GetTotalCategoriesHeight()
Get the total height of the "categories" column.
static const std::initializer_list< ExpensesType > _expenses_list_revenue
List of revenues.
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
void DrawCompanyManagerFace(CompanyManagerFace cmf, Colours colour, const Rect &r)
Draws the face of a company manager's face.
static void DrawCategory(const Rect &r, int start_y, const ExpensesList &list)
Draw a category of expenses (revenue, operating expenses, capital expenses).
Functionality related to the company manager's face.
uint GetCompanyManagerFaceBits(CompanyManagerFace cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge)
Make sure the table's size is right.
void SetCompanyManagerFaceBits(CompanyManagerFace &cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge, uint val)
Sets the company manager's face bits for the given company manager's face variable.
GenderEthnicity
The gender/race combinations that we have faces for.
@ GE_WM
A male of Caucasian origin (white)
@ ETHNICITY_BLACK
This bit set means black, otherwise white.
@ GENDER_FEMALE
This bit set means a female, otherwise male.
void RandomCompanyManagerFaceBits(CompanyManagerFace &cmf, GenderEthnicity ge, bool adv, Randomizer &randomizer)
Make a random new face.
void ScaleAllCompanyManagerFaceBits(CompanyManagerFace &cmf)
Scales all company manager's face bits to the correct scope.
CompanyManagerFaceVariable
Bitgroups of the CompanyManagerFace variable.
static const CompanyManagerFaceBitsInfo _cmf_info[]
Lookup table for indices into the CompanyManagerFace, valid ranges and sprites.
void IncreaseCompanyManagerFaceBits(CompanyManagerFace &cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge, int8_t amount)
Increase/Decrease the company manager's face variable by the given amount.
SpriteID GetCompanyManagerFaceSprite(CompanyManagerFace cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge)
Gets the sprite to draw for the given company manager's face variable.
static const uint MAX_LENGTH_PRESIDENT_NAME_CHARS
The maximum length of a president name in characters including '\0'.
static const uint MAX_LENGTH_COMPANY_NAME_CHARS
The maximum length of a company name in characters including '\0'.
static constexpr CompanyID COMPANY_SPECTATOR
The client is spectating.
uint32_t CompanyManagerFace
Company manager face bits, info see in company_manager_face.h.
Types related to the company widgets.
@ WID_CF_CAPTION
Caption of the window.
@ WID_CF_SEL_BUTTONS
Selection of buttons.
@ WID_CF_SEL_PANEL
Select panel or nothing.
@ WID_CF_EXPS_CATEGORY
Column for expenses category strings.
@ WID_CF_EXPS_PRICE1
Column for year Y-2 expenses.
@ WID_CF_INFRASTRUCTURE
View company infrastructure.
@ WID_CF_TOGGLE_SIZE
Toggle windows size.
@ WID_CF_EXPS_PRICE2
Column for year Y-1 expenses.
@ WID_CF_OWN_VALUE
Own funds, not including loan.
@ WID_CF_LOAN_VALUE
Loan.
@ WID_CF_INCREASE_LOAN
Increase loan.
@ WID_CF_INTEREST_RATE
Loan interest rate.
@ WID_CF_BALANCE_VALUE
Bank balance value.
@ WID_CF_EXPS_PRICE3
Column for year Y expenses.
@ WID_CF_BALANCE_LINE
Available cash.
@ WID_CF_REPAY_LOAN
Decrease loan..
@ WID_CF_SEL_MAXLOAN
Selection of maxloan column.
@ WID_CF_MAXLOAN_VALUE
Max loan widget.
@ WID_BC_NO
No button.
@ WID_BC_YES
Yes button.
@ WID_BC_QUESTION
Question text.
@ WID_BC_CAPTION
Caption of window.
@ WID_BC_FACE
Face button.
@ WID_SCMF_NOSE_L
Nose left.
@ WID_SCMF_COLLAR_TEXT
Text about collar.
@ WID_SCMF_HAIR
Hair.
@ WID_SCMF_EYECOLOUR_L
Eyecolour left.
@ WID_SCMF_CAPTION
Caption of window.
@ WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON
Toggle for large or small.
@ WID_SCMF_ETHNICITY_EUR
Text about ethnicity european.
@ WID_SCMF_CHIN_R
Chin right.
@ WID_SCMF_EYEBROWS
Eyebrows.
@ WID_SCMF_COLLAR
Collar.
@ WID_SCMF_GLASSES_R
Glasses right.
@ WID_SCMF_JACKET_L
Jacket left.
@ WID_SCMF_CHIN
Chin.
@ WID_SCMF_LIPS_MOUSTACHE_TEXT
Text about lips and moustache.
@ WID_SCMF_SELECT_FACE
Select face.
@ WID_SCMF_LIPS_MOUSTACHE
Lips / Moustache.
@ WID_SCMF_RANDOM_NEW_FACE
Create random new face.
@ WID_SCMF_GLASSES_TEXT
Text about glasses.
@ WID_SCMF_EYEBROWS_L
Eyebrows left.
@ WID_SCMF_GLASSES
Glasses.
@ WID_SCMF_LIPS_MOUSTACHE_L
Lips / Moustache left.
@ WID_SCMF_EYEBROWS_R
Eyebrows right.
@ WID_SCMF_SEL_PARTS
Selection to display the buttons for setting each part of the face in the advanced view.
@ WID_SCMF_CHIN_L
Chin left.
@ WID_SCMF_GLASSES_L
Glasses left.
@ WID_SCMF_FEMALE2
Female button in the advanced view.
@ WID_SCMF_NOSE
Nose.
@ WID_SCMF_TIE_EARRING_R
Tie / Earring right.
@ WID_SCMF_CANCEL
Cancel.
@ WID_SCMF_HAIR_TEXT
Text about hair.
@ WID_SCMF_EYECOLOUR_R
Eyecolour right.
@ WID_SCMF_NOSE_R
Nose right.
@ WID_SCMF_CHIN_TEXT
Text about chin.
@ WID_SCMF_TIE_EARRING
Tie / Earring.
@ WID_SCMF_SAVE
Save face.
@ WID_SCMF_NOSE_TEXT
Text about nose.
@ WID_SCMF_MALE
Male button in the simple view.
@ WID_SCMF_SEL_LOADSAVE
Selection to display the load/save/number buttons in the advanced view.
@ WID_SCMF_ETHNICITY_AFR
Text about ethnicity african.
@ WID_SCMF_FACE
Current face.
@ WID_SCMF_JACKET_R
Jacket right.
@ WID_SCMF_TIE_EARRING_L
Tie / Earring left.
@ WID_SCMF_LOAD
Load face.
@ WID_SCMF_ACCEPT
Accept.
@ WID_SCMF_MALE2
Male button in the advanced view.
@ WID_SCMF_EYECOLOUR_TEXT
Text about eyecolour.
@ WID_SCMF_COLLAR_L
Collar left.
@ WID_SCMF_HAS_GLASSES_TEXT
Text about glasses.
@ WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT
Text about moustache and earring.
@ WID_SCMF_JACKET
Jacket.
@ WID_SCMF_SEL_MALEFEMALE
Selection to display the male/female buttons in the simple view.
@ WID_SCMF_JACKET_TEXT
Text about jacket.
@ WID_SCMF_TOGGLE_LARGE_SMALL
Toggle for large or small.
@ WID_SCMF_FACECODE
Get the face code.
@ WID_SCMF_EYECOLOUR
Eyecolour.
@ WID_SCMF_EYEBROWS_TEXT
Text about eyebrows.
@ WID_SCMF_HAIR_L
Hair left.
@ WID_SCMF_LIPS_MOUSTACHE_R
Lips / Moustache right.
@ WID_SCMF_TIE_EARRING_TEXT
Text about tie and earring.
@ WID_SCMF_FEMALE
Female button in the simple view.
@ WID_SCMF_HAS_GLASSES
Has glasses.
@ WID_SCMF_COLLAR_R
Collar right.
@ WID_SCMF_HAS_MOUSTACHE_EARRING
Has moustache or earring.
@ WID_SCMF_HAIR_R
Hair right.
@ WID_SCL_CLASS_AIRCRAFT
Class aircraft.
@ WID_SCL_MATRIX_SCROLLBAR
Matrix scrollbar.
@ WID_SCL_CLASS_SHIP
Class ship.
@ WID_SCL_GROUPS_SHIP
Ship groups.
@ WID_SCL_GROUPS_ROAD
Road groups.
@ WID_SCL_CLASS_ROAD
Class road.
@ WID_SCL_GROUPS_AIRCRAFT
Aircraft groups.
@ WID_SCL_SEC_COL_DROPDOWN
Dropdown for secondary colour.
@ WID_SCL_SPACER_DROPDOWN
Spacer for dropdown.
@ WID_SCL_GROUPS_RAIL
Rail groups.
@ WID_SCL_PRI_COL_DROPDOWN
Dropdown for primary colour.
@ WID_SCL_CLASS_RAIL
Class rail.
@ WID_SCL_MATRIX
Matrix.
@ WID_SCL_CAPTION
Caption of window.
@ WID_SCL_CLASS_GENERAL
Class general.
@ WID_CI_RAIL_COUNT
Count of rail.
@ WID_CI_WATER_DESC
Description of water.
@ WID_CI_TRAM_COUNT
Count of tram.
@ WID_CI_ROAD_DESC
Description of road.
@ WID_CI_CAPTION
Caption of window.
@ WID_CI_STATION_DESC
Description of station.
@ WID_CI_WATER_COUNT
Count of water.
@ WID_CI_TOTAL_DESC
Description of total.
@ WID_CI_TOTAL
Count of total.
@ WID_CI_STATION_COUNT
Count of station.
@ WID_CI_TRAM_DESC
Description of tram.
@ WID_CI_RAIL_DESC
Description of rail.
@ WID_CI_ROAD_COUNT
Count of road.
CompanyWidgets
Widgets of the CompanyWindow class.
@ WID_C_SELECT_VIEW_BUILD_HQ
Panel about HQ.
@ WID_C_DESC_INFRASTRUCTURE_COUNTS
Infrastructure count.
@ WID_C_DESC_VEHICLE
Vehicles.
@ WID_C_COLOUR_SCHEME
Button to change colour scheme.
@ WID_C_CAPTION
Caption of the window.
@ WID_C_VIEW_HQ
Button to view the HQ.
@ WID_C_SELECT_RELOCATE
Panel about 'Relocate HQ'.
@ WID_C_SELECT_BUTTONS
Selection widget for the button bar.
@ WID_C_VIEW_INFRASTRUCTURE
Panel about infrastructure.
@ WID_C_SELECT_HOSTILE_TAKEOVER
Selection widget for the hostile takeover button.
@ WID_C_SELECT_GIVE_MONEY
Selection widget for the give money button.
@ WID_C_DESC_COLOUR_SCHEME
Colour scheme.
@ WID_C_GIVE_MONEY
Button to give money.
@ WID_C_SELECT_MULTIPLAYER
Multiplayer selection panel.
@ WID_C_DESC_INAUGURATION
Inauguration.
@ WID_C_DESC_COLOUR_SCHEME_EXAMPLE
Colour scheme example.
@ WID_C_BUILD_HQ
Button to build the HQ.
@ WID_C_HOSTILE_TAKEOVER
Button to hostile takeover another company.
@ WID_C_DESC_INFRASTRUCTURE
Infrastructure.
@ WID_C_FACE_TITLE
Title for the face.
@ WID_C_DESC_COMPANY_VALUE
Company value.
@ WID_C_COMPANY_JOIN
Button to join company.
@ WID_C_PRESIDENT_NAME
Button to change president name.
@ WID_C_DESC_VEHICLE_COUNTS
Vehicle count.
@ WID_C_NEW_FACE
Button to make new face.
@ WID_C_FACE
View of the face.
@ WID_C_RELOCATE_HQ
Button to relocate the HQ.
@ WID_C_COMPANY_NAME
Button to change company name.
Functions to handle different currencies.
const CurrencySpec & GetCurrency()
Get the currently selected currency.
Definition currency.h:118
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, bool instant_close, bool persist)
Show a drop down list.
Definition dropdown.cpp:404
Common drop down list components.
Types related to the drop down widget.
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
Command definitions related to the economy.
std::array< Money, EXPENSES_END > Expenses
Data type for storage of Money for each ExpensesType category.
ExpensesType
Types of expenses.
@ EXPENSES_ROADVEH_RUN
Running costs road vehicles.
@ EXPENSES_TRAIN_RUN
Running costs trains.
@ EXPENSES_AIRCRAFT_REVENUE
Revenue from aircraft.
@ EXPENSES_CONSTRUCTION
Construction costs.
@ EXPENSES_AIRCRAFT_RUN
Running costs aircraft.
@ EXPENSES_ROADVEH_REVENUE
Revenue from road vehicles.
@ EXPENSES_PROPERTY
Property costs.
@ EXPENSES_OTHER
Other expenses.
@ EXPENSES_SHIP_REVENUE
Revenue from ships.
@ EXPENSES_LOAN_INTEREST
Interest payments over the loan.
@ EXPENSES_TRAIN_REVENUE
Revenue from trains.
@ EXPENSES_SHIP_RUN
Running costs ships.
@ EXPENSES_NEW_VEHICLES
New vehicles.
static const int LOAN_INTERVAL
The "steps" in loan size, in British Pounds!
Base class for engines.
Functions related to errors.
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, const CommandCost &cc)
Display an error message in a window.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:77
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Geometry functions.
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition gfx.cpp:705
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:923
bool _shift_pressed
Is Shift pressed?
Definition gfx.cpp:39
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition gfx.cpp:852
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:658
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:115
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:989
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition gfx.cpp:775
Dimension GetScaledSpriteSize(SpriteID sprid)
Scale sprite size for GUI.
Definition widget.cpp:67
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition gfx_func.h:166
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:243
@ SA_TOP
Top align the text.
Definition gfx_type.h:380
@ SA_LEFT
Left align the text.
Definition gfx_type.h:375
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:377
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:376
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:385
@ SA_VERT_CENTER
Vertically center the text.
Definition gfx_type.h:381
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:294
constexpr NWidgetPart SetMatrixDataTip(uint32_t cols, uint32_t rows, StringID tip={})
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
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 SetTextStyle(TextColour colour, FontSize size=FS_NORMAL)
Widget part function for setting the text style.
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=-1)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetToolTip(StringID tip)
Widget part function for setting tooltip and clearing the widget data.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart SetArrowWidgetTypeTip(ArrowWidgetValues widget_type, StringID tip={})
Widget part function for setting the arrow widget type and tooltip.
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
constexpr NWidgetPart SetAlignment(StringAlignment align)
Widget part function for setting the alignment of text/images.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
constexpr NWidgetPart SetPIPRatio(uint8_t ratio_pre, uint8_t ratio_inter, uint8_t ratio_post)
Widget part function for setting a pre/inter/post ratio.
Command definitions related to engine groups.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition window.cpp:943
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1500
void BuildGuiGroupList(GUIGroupList &dst, bool fold, Owner owner, VehicleType veh_type)
Build GUI group list, a sorted hierarchical list of groups for owner and vehicle type.
Functions/definitions that have something to do with groups.
GUI functions that shouldn't be here.
void ShowExtraViewportWindow(TileIndex tile=INVALID_TILE)
Show a new Extra Viewport window.
static const uint8_t LIT_ALL
Show the liveries of all companies.
Definition livery.h:18
LiveryScheme
List of different livery schemes.
Definition livery.h:21
static const uint8_t LIT_COMPANY
Show the liveries of your own company.
Definition livery.h:17
LiveryClass
List of different livery classes, used only by the livery GUI.
Definition livery.h:63
Miscellaneous command definitions.
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:65
bool _network_server
network-server is active
Definition network.cpp:66
bool NetworkCanJoinCompany(CompanyID company_id)
Returns whether the given company can be joined by this client.
Definition network.cpp:141
Basic functions/variables used all over the place.
void NetworkClientRequestMove(CompanyID company_id)
Notify the server of this client wanting to be moved to another company.
Network functions used by other parts of OpenTTD.
void NetworkServerDoMove(ClientID client_id, CompanyID company_id)
Handle the tid-bits of moving a client from one company to another.
GUIs related to networking.
@ CLIENT_ID_SERVER
Servers always have this ID.
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition newgrf.cpp:87
Base for the NewGRF implementation.
Command definitions related to objects.
Types related to object tiles.
static const ObjectType OBJECT_HQ
HeadQuarter of a player.
Definition object_type.h:22
static const uint8_t PC_WHITE
White palette colour.
static const uint8_t PC_BLACK
Black palette colour.
RailTypes AddDateIntroducedRailTypes(RailTypes current, TimerGameCalendar::Date date)
Add the rail types that are to be introduced at the given date.
Definition rail.cpp:218
Rail specific functions.
Money RailMaintenanceCost(RailType railtype, uint32_t num, uint32_t total_num)
Calculates the maintenance cost of a number of track bits.
Definition rail.h:423
Money SignalMaintenanceCost(uint32_t num)
Calculates the maintenance cost of a number of signals.
Definition rail.h:434
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:300
RailTypes
Allow incrementing of Track variables.
Definition rail_type.h:44
@ RAILTYPES_NONE
No rail types.
Definition rail_type.h:45
RailType
Enumeration for all possible railtypes.
Definition rail_type.h:27
@ RAILTYPE_BEGIN
Used for iterations.
Definition rail_type.h:28
@ RAILTYPE_END
Used for iterations.
Definition rail_type.h:33
Randomizer _interactive_random
Random used everywhere else, where it does not (directly) influence the game state.
RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, TimerGameCalendar::Date date)
Add the road types that are to be introduced at the given date.
Definition road.cpp:166
Road specific functions.
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:220
Functions related to roads.
Money RoadMaintenanceCost(RoadType roadtype, uint32_t num, uint32_t total_num)
Calculates the maintenance cost of a number of road bits.
Definition road_func.h:125
RoadTypes
The different roadtypes we support, but then a bitmask of them.
Definition road_type.h:38
@ ROADTYPES_NONE
No roadtypes.
Definition road_type.h:39
RoadType
The different roadtypes we support.
Definition road_type.h:25
@ ROADTYPE_END
Used for iterations.
Definition road_type.h:29
@ ROADTYPE_BEGIN
Used for iterations.
Definition road_type.h:26
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:58
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:57
Base types for having sorted lists in GUIs.
Money AirportMaintenanceCost(Owner owner)
Calculates the maintenance cost of all airports of a company.
Definition station.cpp:712
Functions related to stations.
Money StationMaintenanceCost(uint32_t num)
Calculates the maintenance cost of a number of station tiles.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:277
@ 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
uint64_t GetParamMaxValue(uint64_t max_value, uint min_count, FontSize size)
Get some number that is suitable for string size computations.
Definition strings.cpp:248
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:426
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ TD_RTL
Text is written right-to-left by default.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Money company_value
The value of the company for which the user can buy it.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
IntervalTimer< TimerWindow > rescale_interval
Check on a regular interval if the company value has changed.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
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.
bool hostile_takeover
Whether the window is showing a hostile takeover.
GUISettings gui
settings related to the GUI
Window class displaying the company finances.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
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.
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, bool) override
Some data on this window has become invalid.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
bool small
Window is toggled to 'small'.
static Money max_money
The maximum amount of money a company has had this 'run'.
uint8_t first_visible
First visible expenses column. The last column (current) is always visible.
void SetupWidgets()
Setup the widgets in the nested tree, such that the finances window is displayed properly.
IntervalTimer< TimerWindow > rescale_interval
Check on a regular interval if the maximum amount of money has changed.
void OnPaint() override
The window must be repainted.
Window with detailed information about the company's infrastructure.
Money GetTotalMaintenanceCost() const
Get total infrastructure maintenance cost.
void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
Helper for drawing the counts line.
RoadTypes roadtypes
Valid roadtypes.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
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.
uint total_width
String width of the total cost line.
RailTypes railtypes
Valid railtypes.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
std::array< uint32_t, ROADTYPE_END > road
Count of company owned track bits for each road type.
uint32_t GetRailTotal() const
Get total sum of all owned track bits.
uint32_t GetRoadTotal() const
Get total sum of all owned road bits.
uint32_t station
Count of company owned station tiles.
uint32_t signal
Count of company owned signals.
std::array< uint32_t, RAILTYPE_END > rail
Count of company owned track bits for each rail type.
uint32_t GetTramTotal() const
Get total sum of all owned tram bits.
uint32_t airport
Count of company owned airports.
uint32_t water
Count of company owned track bits for canals.
uint8_t valid_values[GE_END]
The number of valid values per gender/ethnicity.
TileIndex location_of_HQ
Northern tile of HQ; INVALID_TILE when there is none.
bool is_ai
If true, the company is (also) controlled by the computer (a NoAI program).
Money current_loan
Amount of money borrowed from the bank.
TimerGameCalendar::Year inaugurated_year_calendar
Calendar year of starting the company. Used to display proper Inauguration year while in wallclock mo...
TimerGameEconomy::Year inaugurated_year
Economy year of starting the company.
Colours colour
Company colour.
CompanyManagerFace face
Face description of the president.
std::array< Expenses, 3 > yearly_expenses
Expenses of the company for the last three years.
Money money
Money owned by the company.
Window with general information about a company.
void OnResize() override
Called after the window got resized.
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.
IntervalTimer< TimerWindow > redraw_interval
Redraw the window on a regular interval.
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.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void OnPlaceObject(Point pt, TileIndex tile) override
The user clicked some place on the map when a tile highlight mode has been set.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
CompanyWindowPlanes
Display planes in the company window.
@ CWP_RELOCATE_SHOW
Show the relocate HQ button.
@ CWP_RELOCATE_HIDE
Hide the relocate HQ button.
@ CWP_VB_BUILD
Display the build button.
@ CWP_VB_VIEW
Display the view button.
void OnPaint() override
The window must be repainted.
Money GetMaxLoan() const
Calculate the max allowed loan for this company.
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
std::array< GroupStatistics, VEH_COMPANY_END > group_all
NOSAVE: Statistics for the ALL_GROUP group.
uint16_t rate
The conversion rate compared to the base currency.
Definition currency.h:77
uint8_t initial_interest
amount of interest (to pay over the loan)
Dimensions (a width and height) of a rectangle in 2D.
bool infrastructure_maintenance
enable monthly maintenance fee for owner infrastructure
bool give_money
allow giving other companies money
Expense list container.
uint GetListWidth() const
Compute width of the expenses categories in pixels.
const std::initializer_list< ExpensesType > & items
List of expenses types.
const StringID title
StringID of list title.
bool has_2CC
Set if any vehicle is loaded which uses 2cc (two company colours).
Definition newgrf.h:182
uint64_t used_liveries
Bitmask of LiveryScheme used by the defined engines.
Definition newgrf.h:183
uint8_t liveries
options for displaying company liveries, 0=none, 1=self, 2=all
LandscapeType landscape
the landscape we're currently in
EconomySettings economy
settings to change the economy
DifficultySettings difficulty
settings related to the difficulty
GameCreationSettings game_creation
settings used during the creation of a game (map)
Group data.
Definition group.h:72
Livery livery
Custom colour scheme for vehicles in this group.
Definition group.h:78
GroupID parent
Parent group.
Definition group.h:83
VehicleType vehicle_type
Vehicle type of the group.
Definition group.h:75
Information about a particular livery.
Definition livery.h:78
Colours colour2
Second colour, for vehicles with 2CC support.
Definition livery.h:81
Colours colour1
First colour, for all vehicles.
Definition livery.h:80
uint8_t in_use
Bit 0 set if this livery should override the default livery first colour, Bit 1 for the second colour...
Definition livery.h:79
Partial widget specification to allow NWidgets to be written nested.
Coordinates of a point in 2D.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
constexpr uint Horizontal() const
Get total horizontal padding of RectPadding.
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Specification of a rectangle with absolute coordinates of all edges.
Rect WithWidth(int width, bool end) const
Copy Rect and set its width.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Rect WithHeight(int height, bool end=false) const
Copy Rect and set its height.
Rect Indent(int indent, bool end) const
Copy Rect and indent it from its position.
uint step_height
Step-size of height resize changes.
Definition window_gui.h:213
Company livery colour scheme window.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
void OnDropdownSelect(WidgetID widget, int index) override
A dropdown option associated to this window has been selected.
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.
void OnPaint() override
The window must be repainted.
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
void OnResize() override
Called after the window got resized.
High level window description.
Definition window_gui.h:168
Number to differentiate different windows of the same class.
Data structure for an opened window.
Definition window_gui.h:274
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:955
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1050
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1736
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:744
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3164
Window * parent
Parent window.
Definition window_gui.h:329
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition window_gui.h:470
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:554
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:502
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void SetShaded(bool make_shaded)
Set the shaded state of the window to make_shaded.
Definition window.cpp:998
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:516
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1726
bool IsWidgetLowered(WidgetID widget_index) const
Gets the lowered state of a widget.
Definition window_gui.h:492
void RaiseButtons(bool autoraise=false)
Raise the buttons of the window.
Definition window.cpp:528
void SetWidgetsLoweredState(bool lowered_stat, Args... widgets)
Sets the lowered/raised status of a list of widgets.
Definition window_gui.h:527
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition window_gui.h:317
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:442
void EnableWidget(WidgetID widget_index)
Sets a widget to Enabled.
Definition window_gui.h:401
bool IsShaded() const
Is window shaded currently?
Definition window_gui.h:558
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:973
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition window_gui.h:461
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1749
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:311
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:312
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
Stuff related to the text buffer GUI.
@ EnableDefault
enable the 'Default' button ("\0" is returned)
@ LengthIsInChars
the length of the string is counted in characters
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
Functions related to tile highlights.
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows).
void SetObjectToPlaceWnd(CursorID icon, PaletteID pal, HighLightStyle mode, Window *w)
Change the cursor and mouse click/drag handling to a mode for performing special operations like tile...
@ HT_RECT
rectangle (stations, depots, ...)
Definition of Interval and OneShot timers.
Definition of the game-economy-timer.
Definition of the Window system.
VehicleType
Available vehicle types.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
@ VEH_COMPANY_END
Last company-ownable type.
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.
Functions related to (drawing on) viewports.
Functions related to water (management)
Money CanalMaintenanceCost(uint32_t num)
Calculates the maintenance cost of a number of canal tiles.
Definition water.h:51
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_IMGBTN
(Toggle) Button with image
Definition widget_type.h:42
@ WWT_PUSHARROWBTN
Normal push-button (no toggle button) with arrow caption.
@ WWT_LABEL
Centered label.
Definition widget_type.h:47
@ NWID_SPACER
Invisible widget that takes some space.
Definition widget_type.h:69
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:65
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:45
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:40
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:56
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:49
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:54
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:51
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:75
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:67
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:59
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:38
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:58
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:55
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:60
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:48
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:70
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
@ EqualSize
Containers should keep all their (resizing) children equally large.
@ AWV_DECREASE
Arrow to the left or in case of RTL to the right.
Definition widget_type.h:21
@ AWV_INCREASE
Arrow to the right or in case of RTL to the left.
Definition widget_type.h:22
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1226
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3106
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
@ Construction
This window is used for construction; close it whenever changing company.
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:145
int WidgetID
Widget ID.
Definition window_type.h:20
@ WC_BUY_COMPANY
Buyout company (merger); Window numbers:
@ WC_COMPANY_INFRASTRUCTURE
Company infrastructure overview; Window numbers:
@ WC_COMPANY_COLOUR
Company colour selection; Window numbers:
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:47
@ WC_FINANCES
Finances of a company; Window numbers:
@ WC_COMPANY_MANAGER_FACE
Alter company face window; Window numbers:
@ WC_COMPANY
Company view; Window numbers:
Functions related to zooming.