OpenTTD Source 20241222-master-gc72542431a
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 SetDParam(0, amount);
226 DrawString(left, right, top, str, colour, SA_RIGHT);
227}
228
233static Money DrawYearCategory(const Rect &r, int start_y, const ExpensesList &list, const Expenses &tbl)
234{
235 int y = start_y;
236 Money sum = 0;
237
238 for (const ExpensesType &et : list.items) {
239 Money cost = tbl[et];
240 sum += cost;
241 if (cost != 0) DrawPrice(cost, r.left, r.right, y, TC_BLACK);
243 }
244
245 /* Draw the total at the bottom of the category. */
246 GfxFillRect(r.left, y, r.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
248 if (sum != 0) DrawPrice(sum, r.left, r.right, y, TC_WHITE);
249
250 /* Return the sum for the yearly total. */
251 return sum;
252}
253
254
262static void DrawYearColumn(const Rect &r, TimerGameEconomy::Year year, const Expenses &tbl)
263{
264 int y = r.top;
265 Money sum;
266
267 /* Year header */
268 SetDParam(0, year);
269 DrawString(r.left, r.right, y, STR_FINANCES_YEAR, TC_FROMSTRING, SA_RIGHT, true);
271
272 /* Categories */
273 for (const ExpensesList &list : _expenses_list_types) {
275 sum += DrawYearCategory(r, y, list, tbl);
276 /* Expense list + expense category title + expense category total + blockspace after category */
278 }
279
280 /* Total income. */
281 GfxFillRect(r.left, y, r.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
283 DrawPrice(sum, r.left, r.right, y, TC_WHITE);
284}
285
286static constexpr NWidgetPart _nested_company_finances_widgets[] = {
288 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
289 NWidget(WWT_CAPTION, COLOUR_GREY, WID_CF_CAPTION), SetDataTip(STR_FINANCES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
290 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_CF_TOGGLE_SIZE), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW), SetAspect(WidgetDimensions::ASPECT_TOGGLE_SIZE),
291 NWidget(WWT_SHADEBOX, COLOUR_GREY),
292 NWidget(WWT_STICKYBOX, COLOUR_GREY),
293 EndContainer(),
294 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_PANEL),
295 NWidget(WWT_PANEL, COLOUR_GREY),
297 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CF_EXPS_CATEGORY), SetMinimalSize(120, 0), SetFill(0, 0),
298 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CF_EXPS_PRICE1), SetMinimalSize(86, 0), SetFill(0, 0),
299 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CF_EXPS_PRICE2), SetMinimalSize(86, 0), SetFill(0, 0),
300 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CF_EXPS_PRICE3), SetMinimalSize(86, 0), SetFill(0, 0),
301 EndContainer(),
302 EndContainer(),
303 EndContainer(),
304 NWidget(WWT_PANEL, COLOUR_GREY),
306 NWidget(NWID_VERTICAL), // Vertical column with 'bank balance', 'loan'
307 NWidget(WWT_TEXT, COLOUR_GREY), SetDataTip(STR_FINANCES_OWN_FUNDS_TITLE, STR_NULL),
308 NWidget(WWT_TEXT, COLOUR_GREY), SetDataTip(STR_FINANCES_LOAN_TITLE, STR_NULL),
309 NWidget(WWT_TEXT, COLOUR_GREY), SetDataTip(STR_FINANCES_BANK_BALANCE_TITLE, STR_NULL), SetPadding(WidgetDimensions::unscaled.vsep_normal, 0, 0, 0),
310 EndContainer(),
311 NWidget(NWID_VERTICAL), // Vertical column with bank balance amount, loan amount, and total.
312 NWidget(WWT_TEXT, COLOUR_GREY, WID_CF_OWN_VALUE), SetDataTip(STR_FINANCES_TOTAL_CURRENCY, STR_NULL), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
313 NWidget(WWT_TEXT, COLOUR_GREY, WID_CF_LOAN_VALUE), SetDataTip(STR_FINANCES_TOTAL_CURRENCY, STR_NULL), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
315 NWidget(WWT_TEXT, COLOUR_GREY, WID_CF_BALANCE_VALUE), SetDataTip(STR_FINANCES_BANK_BALANCE, STR_NULL), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
316 EndContainer(),
317 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_MAXLOAN),
318 NWidget(NWID_VERTICAL), SetPIPRatio(0, 0, 1), // Max loan information
319 NWidget(WWT_TEXT, COLOUR_GREY, WID_CF_INTEREST_RATE), SetDataTip(STR_FINANCES_INTEREST_RATE, STR_NULL),
320 NWidget(WWT_TEXT, COLOUR_GREY, WID_CF_MAXLOAN_VALUE), SetDataTip(STR_FINANCES_MAX_LOAN, STR_NULL),
321 EndContainer(),
322 EndContainer(),
323 EndContainer(),
324 EndContainer(),
325 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_CF_SEL_BUTTONS),
327 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_INCREASE_LOAN), SetFill(1, 0), SetDataTip(STR_FINANCES_BORROW_BUTTON, STR_FINANCES_BORROW_TOOLTIP),
328 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_REPAY_LOAN), SetFill(1, 0), SetDataTip(STR_FINANCES_REPAY_BUTTON, STR_FINANCES_REPAY_TOOLTIP),
329 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CF_INFRASTRUCTURE), SetFill(1, 0), SetDataTip(STR_FINANCES_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
330 EndContainer(),
331 EndContainer(),
332};
333
336 static constexpr int NUM_PERIODS = WID_CF_EXPS_PRICE3 - WID_CF_EXPS_PRICE1 + 1;
337
339 bool small;
340 uint8_t first_visible = NUM_PERIODS - 1;
341
342 CompanyFinancesWindow(WindowDesc &desc, CompanyID company) : Window(desc)
343 {
344 this->small = false;
345 this->CreateNestedTree();
346 this->SetupWidgets();
347 this->FinishInitNested(company);
348
349 this->owner = (Owner)this->window_number;
350 this->InvalidateData();
351 }
352
353 void SetStringParameters(WidgetID widget) const override
354 {
355 switch (widget) {
356 case WID_CF_CAPTION:
358 SetDParam(1, (CompanyID)this->window_number);
359 break;
360
362 const Company *c = Company::Get((CompanyID)this->window_number);
363 SetDParam(0, c->money);
364 break;
365 }
366
367 case WID_CF_LOAN_VALUE: {
368 const Company *c = Company::Get((CompanyID)this->window_number);
369 SetDParam(0, c->current_loan);
370 break;
371 }
372
373 case WID_CF_OWN_VALUE: {
374 const Company *c = Company::Get((CompanyID)this->window_number);
375 SetDParam(0, c->money - c->current_loan);
376 break;
377 }
378
381 break;
382
384 const Company *c = Company::Get((CompanyID)this->window_number);
385 SetDParam(0, c->GetMaxLoan());
386 break;
387 }
388
392 break;
393 }
394 }
395
397 {
398 switch (widget) {
400 size.width = GetMaxCategoriesWidth();
401 size.height = GetTotalCategoriesHeight();
402 break;
403
407 size.height = GetTotalCategoriesHeight();
408 [[fallthrough]];
409
412 case WID_CF_OWN_VALUE:
415 break;
416
418 size.height = GetCharacterHeight(FS_NORMAL);
419 break;
420 }
421 }
422
423 void DrawWidget(const Rect &r, WidgetID widget) const override
424 {
425 switch (widget) {
428 break;
429
432 case WID_CF_EXPS_PRICE3: {
433 int period = widget - WID_CF_EXPS_PRICE1;
435
436 const Company *c = Company::Get((CompanyID)this->window_number);
437 const auto &expenses = c->yearly_expenses[NUM_PERIODS - period - 1];
438 DrawYearColumn(r, TimerGameEconomy::year - (NUM_PERIODS - period - 1), expenses);
439 break;
440 }
441
443 GfxFillRect(r.left, r.top, r.right, r.top + WidgetDimensions::scaled.bevel.top - 1, PC_BLACK);
444 break;
445 }
446 }
447
453 {
454 int plane = this->small ? SZSP_NONE : 0;
455 this->GetWidget<NWidgetStacked>(WID_CF_SEL_PANEL)->SetDisplayedPlane(plane);
456 this->GetWidget<NWidgetStacked>(WID_CF_SEL_MAXLOAN)->SetDisplayedPlane(plane);
457
458 CompanyID company = (CompanyID)this->window_number;
459 plane = (company != _local_company) ? SZSP_NONE : 0;
460 this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->SetDisplayedPlane(plane);
461 }
462
463 void OnPaint() override
464 {
465 if (!this->IsShaded()) {
466 if (!this->small) {
467 /* Check that the expenses panel height matches the height needed for the layout. */
469 this->SetupWidgets();
470 this->ReInit();
471 return;
472 }
473 }
474
475 /* Check that the loan buttons are shown only when the user owns the company. */
476 CompanyID company = (CompanyID)this->window_number;
477 int req_plane = (company != _local_company) ? SZSP_NONE : 0;
478 if (req_plane != this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->shown_plane) {
479 this->SetupWidgets();
480 this->ReInit();
481 return;
482 }
483
484 const Company *c = Company::Get(company);
485 this->SetWidgetDisabledState(WID_CF_INCREASE_LOAN, c->current_loan >= c->GetMaxLoan()); // Borrow button only shows when there is any more money to loan.
486 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.
487 }
488
489 this->DrawWidgets();
490 }
491
492 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
493 {
494 switch (widget) {
495 case WID_CF_TOGGLE_SIZE: // toggle size
496 this->small = !this->small;
497 this->SetupWidgets();
498 if (this->IsShaded()) {
499 /* Finances window is not resizable, so size hints given during unshading have no effect
500 * on the changed appearance of the window. */
501 this->SetShaded(false);
502 } else {
503 this->ReInit();
504 }
505 break;
506
507 case WID_CF_INCREASE_LOAN: // increase loan
508 Command<CMD_INCREASE_LOAN>::Post(STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY, _ctrl_pressed ? LoanCommand::Max : LoanCommand::Interval, 0);
509 break;
510
511 case WID_CF_REPAY_LOAN: // repay loan
512 Command<CMD_DECREASE_LOAN>::Post(STR_ERROR_CAN_T_REPAY_LOAN, _ctrl_pressed ? LoanCommand::Max : LoanCommand::Interval, 0);
513 break;
514
515 case WID_CF_INFRASTRUCTURE: // show infrastructure details
517 break;
518 }
519 }
520
521 void RefreshVisibleColumns()
522 {
523 for (uint period = 0; period < this->first_visible; ++period) {
524 const Company *c = Company::Get((CompanyID)this->window_number);
525 const Expenses &expenses = c->yearly_expenses[NUM_PERIODS - period - 1];
526 /* Show expenses column if it has any non-zero value in it. */
527 if (std::ranges::any_of(expenses, [](const Money &value) { return value != 0; })) {
528 this->first_visible = period;
529 break;
530 }
531 }
532 }
533
534 void OnInvalidateData(int, bool) override
535 {
536 this->RefreshVisibleColumns();
537 }
538
543 IntervalTimer<TimerWindow> rescale_interval = {std::chrono::seconds(3), [this](auto) {
544 const Company *c = Company::Get((CompanyID)this->window_number);
547 this->SetupWidgets();
548 this->ReInit();
549 }
550 }};
551};
552
555
556static WindowDesc _company_finances_desc(
557 WDP_AUTO, "company_finances", 0, 0,
559 0,
560 _nested_company_finances_widgets
561);
562
569{
570 if (!Company::IsValidID(company)) return;
571 if (BringWindowToFrontById(WC_FINANCES, company)) return;
572
573 new CompanyFinancesWindow(_company_finances_desc, company);
574}
575
576/* Association of liveries to livery classes */
577static const LiveryClass _livery_class[LS_END] = {
578 LC_OTHER,
579 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,
580 LC_ROAD, LC_ROAD,
581 LC_SHIP, LC_SHIP,
582 LC_AIRCRAFT, LC_AIRCRAFT, LC_AIRCRAFT,
583 LC_ROAD, LC_ROAD,
584};
585
590template <SpriteID TSprite = SPR_SQUARE>
591class DropDownListColourItem : public DropDownIcon<DropDownString<DropDownListItem>> {
592public:
593 DropDownListColourItem(int colour, bool masked) : DropDownIcon<DropDownString<DropDownListItem>>(TSprite, GENERAL_SPRITE_COLOUR(colour % COLOUR_END), colour < COLOUR_END ? (STR_COLOUR_DARK_BLUE + colour) : STR_COLOUR_DEFAULT, colour, masked)
594 {
595 }
596};
597
600private:
601 uint32_t sel;
602 LiveryClass livery_class;
603 Dimension square;
604 uint rows;
605 uint line_height;
606 GUIGroupList groups;
607 Scrollbar *vscroll;
608
609 void ShowColourDropDownMenu(uint32_t widget)
610 {
612 const Livery *livery, *default_livery = nullptr;
613 bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
615
616 /* Disallow other company colours for the primary colour */
617 if (this->livery_class < LC_GROUP_RAIL && HasBit(this->sel, LS_DEFAULT) && primary) {
618 for (const Company *c : Company::Iterate()) {
620 }
621 }
622
623 const Company *c = Company::Get((CompanyID)this->window_number);
624
625 if (this->livery_class < LC_GROUP_RAIL) {
626 /* Get the first selected livery to use as the default dropdown item */
628 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
629 if (HasBit(this->sel, scheme)) break;
630 }
631 if (scheme == LS_END) scheme = LS_DEFAULT;
632 livery = &c->livery[scheme];
633 if (scheme != LS_DEFAULT) default_livery = &c->livery[LS_DEFAULT];
634 } else {
635 const Group *g = Group::Get(this->sel);
636 livery = &g->livery;
637 if (g->parent == INVALID_GROUP) {
638 default_livery = &c->livery[LS_DEFAULT];
639 } else {
640 const Group *pg = Group::Get(g->parent);
641 default_livery = &pg->livery;
642 }
643 }
644
645 DropDownList list;
646 if (default_livery != nullptr) {
647 /* Add COLOUR_END to put the colour out of range, but also allow us to show what the default is */
648 default_col = (primary ? default_livery->colour1 : default_livery->colour2) + COLOUR_END;
649 list.push_back(std::make_unique<DropDownListColourItem<>>(default_col, false));
650 }
651 for (Colours colour = COLOUR_BEGIN; colour != COLOUR_END; colour++) {
652 list.push_back(std::make_unique<DropDownListColourItem<>>(colour, HasBit(used_colours, colour)));
653 }
654
655 uint8_t sel;
656 if (default_livery == nullptr || HasBit(livery->in_use, primary ? 0 : 1)) {
657 sel = primary ? livery->colour1 : livery->colour2;
658 } else {
659 sel = default_col;
660 }
661 ShowDropDownList(this, std::move(list), sel, widget);
662 }
663
664 void BuildGroupList(CompanyID owner)
665 {
666 if (!this->groups.NeedRebuild()) return;
667
668 this->groups.clear();
669
670 if (this->livery_class >= LC_GROUP_RAIL) {
671 VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
672 BuildGuiGroupList(this->groups, false, owner, vtype);
673 }
674
675 this->groups.RebuildDone();
676 }
677
678 void SetRows()
679 {
680 if (this->livery_class < LC_GROUP_RAIL) {
681 this->rows = 0;
682 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
683 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
684 this->rows++;
685 }
686 }
687 } else {
688 this->rows = (uint)this->groups.size();
689 }
690
691 this->vscroll->SetCount(this->rows);
692 }
693
694public:
695 SelectCompanyLiveryWindow(WindowDesc &desc, CompanyID company, GroupID group) : Window(desc)
696 {
697 this->CreateNestedTree();
698 this->vscroll = this->GetScrollbar(WID_SCL_MATRIX_SCROLLBAR);
699
700 if (group == INVALID_GROUP) {
701 this->livery_class = LC_OTHER;
702 this->sel = 1;
704 this->BuildGroupList(company);
705 this->SetRows();
706 } else {
707 this->SetSelectedGroup(company, group);
708 }
709
710 this->FinishInitNested(company);
711 this->owner = company;
712 this->InvalidateData(1);
713 }
714
715 void SetSelectedGroup(CompanyID company, GroupID group)
716 {
717 this->RaiseWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
718 const Group *g = Group::Get(group);
719 switch (g->vehicle_type) {
720 case VEH_TRAIN: this->livery_class = LC_GROUP_RAIL; break;
721 case VEH_ROAD: this->livery_class = LC_GROUP_ROAD; break;
722 case VEH_SHIP: this->livery_class = LC_GROUP_SHIP; break;
723 case VEH_AIRCRAFT: this->livery_class = LC_GROUP_AIRCRAFT; break;
724 default: NOT_REACHED();
725 }
726 this->sel = group;
727 this->LowerWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
728
729 this->groups.ForceRebuild();
730 this->BuildGroupList(company);
731 this->SetRows();
732
733 /* Position scrollbar to selected group */
734 for (uint i = 0; i < this->rows; i++) {
735 if (this->groups[i].group->index == sel) {
736 this->vscroll->SetPosition(i - this->vscroll->GetCapacity() / 2);
737 break;
738 }
739 }
740 }
741
743 {
744 switch (widget) {
746 /* The matrix widget below needs enough room to print all the schemes. */
747 Dimension d = {0, 0};
748 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
750 }
751
752 /* And group names */
753 for (const Group *g : Group::Iterate()) {
754 if (g->owner == (CompanyID)this->window_number) {
755 SetDParam(0, g->index);
757 }
758 }
759
760 size.width = std::max(size.width, 5 + d.width + padding.width);
761 break;
762 }
763
764 case WID_SCL_MATRIX: {
765 /* 11 items in the default rail class */
766 this->square = GetSpriteSize(SPR_SQUARE);
767 this->line_height = std::max(this->square.height, (uint)GetCharacterHeight(FS_NORMAL)) + padding.height;
768
769 size.height = 5 * this->line_height;
770 resize.width = 1;
771 resize.height = this->line_height;
772 break;
773 }
774
777 size.width = 0;
778 break;
779 }
780 [[fallthrough]];
781
783 this->square = GetSpriteSize(SPR_SQUARE);
784 int string_padding = this->square.width + WidgetDimensions::scaled.hsep_normal + padding.width;
785 for (Colours colour = COLOUR_BEGIN; colour != COLOUR_END; colour++) {
786 size.width = std::max(size.width, GetStringBoundingBox(STR_COLOUR_DARK_BLUE + colour).width + string_padding);
787 }
788 size.width = std::max(size.width, GetStringBoundingBox(STR_COLOUR_DEFAULT).width + string_padding);
789 break;
790 }
791 }
792 }
793
794 void OnPaint() override
795 {
797
798 /* Disable dropdown controls if no scheme is selected */
799 bool disabled = this->livery_class < LC_GROUP_RAIL ? (this->sel == 0) : (this->sel == INVALID_GROUP);
800 this->SetWidgetDisabledState(WID_SCL_PRI_COL_DROPDOWN, !local || disabled);
801 this->SetWidgetDisabledState(WID_SCL_SEC_COL_DROPDOWN, !local || disabled);
802
803 this->BuildGroupList((CompanyID)this->window_number);
804
805 this->DrawWidgets();
806 }
807
808 void SetStringParameters(WidgetID widget) const override
809 {
810 switch (widget) {
811 case WID_SCL_CAPTION:
813 break;
814
817 const Company *c = Company::Get((CompanyID)this->window_number);
818 bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
820
821 if (this->livery_class < LC_GROUP_RAIL) {
822 if (this->sel != 0) {
823 LiveryScheme scheme = LS_DEFAULT;
824 for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
825 if (HasBit(this->sel, scheme)) break;
826 }
827 if (scheme == LS_END) scheme = LS_DEFAULT;
828 const Livery *livery = &c->livery[scheme];
829 if (scheme == LS_DEFAULT || HasBit(livery->in_use, primary ? 0 : 1)) {
830 colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
831 }
832 }
833 } else {
834 if (this->sel != INVALID_GROUP) {
835 const Group *g = Group::Get(this->sel);
836 const Livery *livery = &g->livery;
837 if (HasBit(livery->in_use, primary ? 0 : 1)) {
838 colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
839 }
840 }
841 }
842 SetDParam(0, colour);
843 break;
844 }
845 }
846 }
847
848 void DrawWidget(const Rect &r, WidgetID widget) const override
849 {
850 if (widget != WID_SCL_MATRIX) return;
851
852 bool rtl = _current_text_dir == TD_RTL;
853
854 /* Coordinates of scheme name column. */
856 Rect sch = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
857 /* Coordinates of first dropdown. */
859 Rect pri = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
860 /* Coordinates of second dropdown. */
862 Rect sec = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
863
864 Rect pri_squ = pri.WithWidth(this->square.width, rtl);
865 Rect sec_squ = sec.WithWidth(this->square.width, rtl);
866
867 pri = pri.Indent(this->square.width + WidgetDimensions::scaled.hsep_normal, rtl);
868 sec = sec.Indent(this->square.width + WidgetDimensions::scaled.hsep_normal, rtl);
869
871 int square_offs = (ir.Height() - this->square.height) / 2;
872 int text_offs = (ir.Height() - GetCharacterHeight(FS_NORMAL)) / 2;
873
874 int y = ir.top;
875
876 /* Helper function to draw livery info. */
877 auto draw_livery = [&](StringID str, const Livery &livery, bool is_selected, bool is_default_scheme, int indent) {
878 /* Livery Label. */
879 DrawString(sch.left + (rtl ? 0 : indent), sch.right - (rtl ? indent : 0), y + text_offs, str, is_selected ? TC_WHITE : TC_BLACK);
880
881 /* Text below the first dropdown. */
882 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour1), pri_squ.left, y + square_offs);
883 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);
884
885 /* Text below the second dropdown. */
886 if (sec.right > sec.left) { // Second dropdown has non-zero size.
887 DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour2), sec_squ.left, y + square_offs);
888 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);
889 }
890
891 y += this->line_height;
892 };
893
894 const Company *c = Company::Get((CompanyID)this->window_number);
895
896 if (livery_class < LC_GROUP_RAIL) {
897 int pos = this->vscroll->GetPosition();
898 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
899 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
900 if (pos-- > 0) continue;
901 draw_livery(STR_LIVERY_DEFAULT + scheme, c->livery[scheme], HasBit(this->sel, scheme), scheme == LS_DEFAULT, 0);
902 }
903 }
904 } else {
905 auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->groups);
906 for (auto it = first; it != last; ++it) {
907 const Group *g = it->group;
908 SetDParam(0, g->index);
909 draw_livery(STR_GROUP_NAME, g->livery, this->sel == g->index, false, it->indent * WidgetDimensions::scaled.hsep_indent);
910 }
911
912 if (this->vscroll->GetCount() == 0) {
914 VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
915 DrawString(ir.left, ir.right, y + text_offs, empty_labels[vtype], TC_BLACK);
916 }
917 }
918 }
919
920 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
921 {
922 switch (widget) {
923 /* Livery Class buttons */
933 this->RaiseWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
934 this->livery_class = (LiveryClass)(widget - WID_SCL_CLASS_GENERAL);
935 this->LowerWidget(WID_SCL_CLASS_GENERAL + this->livery_class);
936
937 /* Select the first item in the list */
938 if (this->livery_class < LC_GROUP_RAIL) {
939 this->sel = 0;
940 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
941 if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
942 this->sel = 1 << scheme;
943 break;
944 }
945 }
946 } else {
947 this->sel = INVALID_GROUP;
948 this->groups.ForceRebuild();
949 this->BuildGroupList((CompanyID)this->window_number);
950
951 if (!this->groups.empty()) {
952 this->sel = this->groups[0].group->index;
953 }
954 }
955
956 this->SetRows();
957 this->SetDirty();
958 break;
959
960 case WID_SCL_PRI_COL_DROPDOWN: // First colour dropdown
961 ShowColourDropDownMenu(WID_SCL_PRI_COL_DROPDOWN);
962 break;
963
964 case WID_SCL_SEC_COL_DROPDOWN: // Second colour dropdown
965 ShowColourDropDownMenu(WID_SCL_SEC_COL_DROPDOWN);
966 break;
967
968 case WID_SCL_MATRIX: {
969 if (this->livery_class < LC_GROUP_RAIL) {
970 uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, widget);
971 if (row >= this->rows) return;
972
974
975 for (LiveryScheme scheme = LS_BEGIN; scheme <= j && scheme < LS_END; scheme++) {
976 if (_livery_class[scheme] != this->livery_class || !HasBit(_loaded_newgrf_features.used_liveries, scheme)) j++;
977 }
978 assert(j < LS_END);
979
980 if (_ctrl_pressed) {
981 ToggleBit(this->sel, j);
982 } else {
983 this->sel = 1 << j;
984 }
985 } else {
986 auto it = this->vscroll->GetScrolledItemFromWidget(this->groups, pt.y, this, widget);
987 if (it == std::end(this->groups)) return;
988
989 this->sel = it->group->index;
990 }
991 this->SetDirty();
992 break;
993 }
994 }
995 }
996
997 void OnResize() override
998 {
999 this->vscroll->SetCapacityFromWidget(this, WID_SCL_MATRIX);
1000 }
1001
1002 void OnDropdownSelect(WidgetID widget, int index) override
1003 {
1005 if (!local) return;
1006
1007 Colours colour = static_cast<Colours>(index);
1008 if (colour >= COLOUR_END) colour = INVALID_COLOUR;
1009
1010 if (this->livery_class < LC_GROUP_RAIL) {
1011 /* Set company colour livery */
1012 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1013 /* Changed colour for the selected scheme, or all visible schemes if CTRL is pressed. */
1014 if (HasBit(this->sel, scheme) || (_ctrl_pressed && _livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme))) {
1016 }
1017 }
1018 } else {
1019 /* Setting group livery */
1021 }
1022 }
1023
1029 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
1030 {
1031 if (!gui_scope) return;
1032
1033 if (data != -1) {
1034 /* data contains a VehicleType, rebuild list if it displayed */
1035 if (this->livery_class == data + LC_GROUP_RAIL) {
1036 this->groups.ForceRebuild();
1037 this->BuildGroupList((CompanyID)this->window_number);
1038 this->SetRows();
1039
1040 if (!Group::IsValidID(this->sel)) {
1041 this->sel = INVALID_GROUP;
1042 if (!this->groups.empty()) this->sel = this->groups[0].group->index;
1043 }
1044
1045 this->SetDirty();
1046 }
1047 return;
1048 }
1049
1051
1052 bool current_class_valid = this->livery_class == LC_OTHER || this->livery_class >= LC_GROUP_RAIL;
1054 for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1056 if (_livery_class[scheme] == this->livery_class) current_class_valid = true;
1057 this->EnableWidget(WID_SCL_CLASS_GENERAL + _livery_class[scheme]);
1058 } else if (this->livery_class < LC_GROUP_RAIL) {
1059 ClrBit(this->sel, scheme);
1060 }
1061 }
1062 }
1063
1064 if (!current_class_valid) {
1065 Point pt = {0, 0};
1066 this->OnClick(pt, WID_SCL_CLASS_GENERAL, 1);
1067 }
1068 }
1069};
1070
1071static constexpr NWidgetPart _nested_select_company_livery_widgets[] = {
1073 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1074 NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCL_CAPTION), SetDataTip(STR_LIVERY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1075 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1076 NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
1077 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1078 EndContainer(),
1080 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_GENERAL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_LIVERY_GENERAL_TOOLTIP),
1081 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRAINLIST, STR_LIVERY_TRAIN_TOOLTIP),
1082 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRUCKLIST, STR_LIVERY_ROAD_VEHICLE_TOOLTIP),
1083 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_SHIPLIST, STR_LIVERY_SHIP_TOOLTIP),
1084 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_AIRPLANESLIST, STR_LIVERY_AIRCRAFT_TOOLTIP),
1085 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_TRAIN, STR_LIVERY_TRAIN_GROUP_TOOLTIP),
1086 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_ROADVEH, STR_LIVERY_ROAD_VEHICLE_GROUP_TOOLTIP),
1087 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_SHIP, STR_LIVERY_SHIP_GROUP_TOOLTIP),
1088 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_AIRCRAFT, STR_LIVERY_AIRCRAFT_GROUP_TOOLTIP),
1089 NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(),
1090 EndContainer(),
1092 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),
1094 EndContainer(),
1097 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetFill(0, 1), SetDataTip(STR_JUST_STRING, STR_LIVERY_PRIMARY_TOOLTIP),
1098 NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetFill(0, 1), SetDataTip(STR_JUST_STRING, STR_LIVERY_SECONDARY_TOOLTIP),
1099 NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1100 EndContainer(),
1101};
1102
1103static WindowDesc _select_company_livery_desc(
1104 WDP_AUTO, "company_color_scheme", 0, 0,
1106 0,
1107 _nested_select_company_livery_widgets
1108);
1109
1110void ShowCompanyLiveryWindow(CompanyID company, GroupID group)
1111{
1113 if (w == nullptr) {
1114 new SelectCompanyLiveryWindow(_select_company_livery_desc, company, group);
1115 } else if (group != INVALID_GROUP) {
1116 w->SetSelectedGroup(company, group);
1117 }
1118}
1119
1126void DrawCompanyManagerFace(CompanyManagerFace cmf, Colours colour, const Rect &r)
1127{
1129
1130 /* Determine offset from centre of drawing rect. */
1131 Dimension d = GetSpriteSize(SPR_GRADIENT);
1132 int x = CenterBounds(r.left, r.right, d.width);
1133 int y = CenterBounds(r.top, r.bottom, d.height);
1134
1135 bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
1136 bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
1137 bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
1138 PaletteID pal;
1139
1140 /* Modify eye colour palette only if 2 or more valid values exist */
1141 if (_cmf_info[CMFV_EYE_COLOUR].valid_values[ge] < 2) {
1142 pal = PAL_NONE;
1143 } else {
1144 switch (GetCompanyManagerFaceBits(cmf, CMFV_EYE_COLOUR, ge)) {
1145 default: NOT_REACHED();
1146 case 0: pal = PALETTE_TO_BROWN; break;
1147 case 1: pal = PALETTE_TO_BLUE; break;
1148 case 2: pal = PALETTE_TO_GREEN; break;
1149 }
1150 }
1151
1152 /* Draw the gradient (background) */
1153 DrawSprite(SPR_GRADIENT, GENERAL_SPRITE_COLOUR(colour), x, y);
1154
1155 for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
1156 switch (cmfv) {
1157 case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
1158 case CMFV_LIPS:
1159 case CMFV_NOSE: if (has_moustache) continue; break;
1160 case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
1161 case CMFV_GLASSES: if (!has_glasses) continue; break;
1162 default: break;
1163 }
1164 DrawSprite(GetCompanyManagerFaceSprite(cmf, cmfv, ge), (cmfv == CMFV_EYEBROWS) ? pal : PAL_NONE, x, y);
1165 }
1166}
1167
1171 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1172 NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCMF_CAPTION), SetDataTip(STR_FACE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1173 NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_FACE_ADVANCED_TOOLTIP), SetAspect(WidgetDimensions::ASPECT_TOGGLE_SIZE),
1174 EndContainer(),
1175 NWidget(WWT_PANEL, COLOUR_GREY, WID_SCMF_SELECT_FACE),
1177 /* Left side */
1180 NWidget(WWT_EMPTY, COLOUR_GREY, WID_SCMF_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
1181 EndContainer(),
1182 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_RANDOM_NEW_FACE), SetFill(1, 0), SetDataTip(STR_FACE_NEW_FACE_BUTTON, STR_FACE_NEW_FACE_TOOLTIP),
1183 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_LOADSAVE), // Load/number/save buttons under the portrait in the advanced view.
1184 NWidget(NWID_VERTICAL), SetPIP(0, 0, 0), SetPIPRatio(1, 0, 1),
1185 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LOAD), SetFill(1, 0), SetDataTip(STR_FACE_LOAD, STR_FACE_LOAD_TOOLTIP),
1186 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_FACECODE), SetFill(1, 0), SetDataTip(STR_FACE_FACECODE, STR_FACE_FACECODE_TOOLTIP),
1187 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_SAVE), SetFill(1, 0), SetDataTip(STR_FACE_SAVE, STR_FACE_SAVE_TOOLTIP),
1188 EndContainer(),
1189 EndContainer(),
1190 EndContainer(),
1191 /* Right side */
1193 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON), SetFill(1, 0), SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP),
1194 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_MALEFEMALE), // Simple male/female face setting.
1196 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1197 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1198 EndContainer(),
1199 EndContainer(),
1200 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_PARTS), // Advanced face parts setting.
1203 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE2), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1204 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE2), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1205 EndContainer(),
1207 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_EUR), SetFill(1, 0), SetDataTip(STR_FACE_EUROPEAN, STR_FACE_SELECT_EUROPEAN),
1208 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_AFR), SetFill(1, 0), SetDataTip(STR_FACE_AFRICAN, STR_FACE_SELECT_AFRICAN),
1209 EndContainer(),
1213 SetDataTip(STR_FACE_EYECOLOUR, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1214 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_MOUSTACHE_EARRING), SetDataTip(STR_JUST_STRING1, STR_FACE_MOUSTACHE_EARRING_TOOLTIP), SetTextStyle(TC_WHITE),
1215 EndContainer(),
1217 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_HAS_GLASSES_TEXT), SetFill(1, 0),
1218 SetDataTip(STR_FACE_GLASSES, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1219 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_GLASSES), SetDataTip(STR_JUST_STRING1, STR_FACE_GLASSES_TOOLTIP), SetTextStyle(TC_WHITE),
1220 EndContainer(),
1221 EndContainer(),
1224 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_HAIR_TEXT), SetFill(1, 0),
1225 SetDataTip(STR_FACE_HAIR, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1227 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_L), SetDataTip(AWV_DECREASE, STR_FACE_HAIR_TOOLTIP),
1228 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAIR), SetDataTip(STR_JUST_STRING1, STR_FACE_HAIR_TOOLTIP), SetTextStyle(TC_WHITE),
1229 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_R), SetDataTip(AWV_INCREASE, STR_FACE_HAIR_TOOLTIP),
1230 EndContainer(),
1231 EndContainer(),
1233 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_EYEBROWS_TEXT), SetFill(1, 0),
1234 SetDataTip(STR_FACE_EYEBROWS, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1236 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_L), SetDataTip(AWV_DECREASE, STR_FACE_EYEBROWS_TOOLTIP),
1237 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYEBROWS), SetDataTip(STR_JUST_STRING1, STR_FACE_EYEBROWS_TOOLTIP), SetTextStyle(TC_WHITE),
1238 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_R), SetDataTip(AWV_INCREASE, STR_FACE_EYEBROWS_TOOLTIP),
1239 EndContainer(),
1240 EndContainer(),
1242 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_EYECOLOUR_TEXT), SetFill(1, 0),
1243 SetDataTip(STR_FACE_EYECOLOUR, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1245 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_L), SetDataTip(AWV_DECREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1246 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR), SetDataTip(STR_JUST_STRING1, STR_FACE_EYECOLOUR_TOOLTIP), SetTextStyle(TC_WHITE),
1247 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_R), SetDataTip(AWV_INCREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1248 EndContainer(),
1249 EndContainer(),
1251 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_GLASSES_TEXT), SetFill(1, 0),
1252 SetDataTip(STR_FACE_GLASSES, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1254 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_L), SetDataTip(AWV_DECREASE, STR_FACE_GLASSES_TOOLTIP_2),
1255 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_GLASSES), SetDataTip(STR_JUST_STRING1, STR_FACE_GLASSES_TOOLTIP_2), SetTextStyle(TC_WHITE),
1256 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_R), SetDataTip(AWV_INCREASE, STR_FACE_GLASSES_TOOLTIP_2),
1257 EndContainer(),
1258 EndContainer(),
1260 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_NOSE_TEXT), SetFill(1, 0),
1261 SetDataTip(STR_FACE_NOSE, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1263 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_L), SetDataTip(AWV_DECREASE, STR_FACE_NOSE_TOOLTIP),
1264 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_NOSE), SetDataTip(STR_JUST_STRING1, STR_FACE_NOSE_TOOLTIP), SetTextStyle(TC_WHITE),
1265 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_R), SetDataTip(AWV_INCREASE, STR_FACE_NOSE_TOOLTIP),
1266 EndContainer(),
1267 EndContainer(),
1269 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_LIPS_MOUSTACHE_TEXT), SetFill(1, 0),
1270 SetDataTip(STR_FACE_MOUSTACHE, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1272 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_L), SetDataTip(AWV_DECREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1273 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE), SetDataTip(STR_JUST_STRING1, STR_FACE_LIPS_MOUSTACHE_TOOLTIP), SetTextStyle(TC_WHITE),
1274 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_R), SetDataTip(AWV_INCREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1275 EndContainer(),
1276 EndContainer(),
1278 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_CHIN_TEXT), SetFill(1, 0),
1279 SetDataTip(STR_FACE_CHIN, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1281 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_L), SetDataTip(AWV_DECREASE, STR_FACE_CHIN_TOOLTIP),
1282 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CHIN), SetDataTip(STR_JUST_STRING1, STR_FACE_CHIN_TOOLTIP), SetTextStyle(TC_WHITE),
1283 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_R), SetDataTip(AWV_INCREASE, STR_FACE_CHIN_TOOLTIP),
1284 EndContainer(),
1285 EndContainer(),
1287 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_JACKET_TEXT), SetFill(1, 0),
1288 SetDataTip(STR_FACE_JACKET, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1290 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_L), SetDataTip(AWV_DECREASE, STR_FACE_JACKET_TOOLTIP),
1291 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_JACKET), SetDataTip(STR_JUST_STRING1, STR_FACE_JACKET_TOOLTIP), SetTextStyle(TC_WHITE),
1292 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_R), SetDataTip(AWV_INCREASE, STR_FACE_JACKET_TOOLTIP),
1293 EndContainer(),
1294 EndContainer(),
1296 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_COLLAR_TEXT), SetFill(1, 0),
1297 SetDataTip(STR_FACE_COLLAR, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1299 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_L), SetDataTip(AWV_DECREASE, STR_FACE_COLLAR_TOOLTIP),
1300 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_COLLAR), SetDataTip(STR_JUST_STRING1, STR_FACE_COLLAR_TOOLTIP), SetTextStyle(TC_WHITE),
1301 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_R), SetDataTip(AWV_INCREASE, STR_FACE_COLLAR_TOOLTIP),
1302 EndContainer(),
1303 EndContainer(),
1305 NWidget(WWT_TEXT, INVALID_COLOUR, WID_SCMF_TIE_EARRING_TEXT), SetFill(1, 0),
1306 SetDataTip(STR_FACE_EARRING, STR_NULL), SetTextStyle(TC_GOLD), SetAlignment(SA_VERT_CENTER | SA_RIGHT),
1308 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_L), SetDataTip(AWV_DECREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1309 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING), SetDataTip(STR_JUST_STRING1, STR_FACE_TIE_EARRING_TOOLTIP), SetTextStyle(TC_WHITE),
1310 NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_R), SetDataTip(AWV_INCREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1311 EndContainer(),
1312 EndContainer(),
1313 EndContainer(),
1314 EndContainer(),
1315 EndContainer(),
1316 EndContainer(),
1317 EndContainer(),
1318 EndContainer(),
1320 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CANCEL), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_FACE_CANCEL_TOOLTIP),
1321 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_ACCEPT), SetFill(1, 0), SetDataTip(STR_BUTTON_OK, STR_FACE_OK_TOOLTIP),
1322 EndContainer(),
1323};
1324
1327{
1330
1334
1337
1346 {
1347 const NWidgetCore *nwi_widget = this->GetWidget<NWidgetCore>(widget_index);
1348 if (nwi_widget->IsDisabled()) {
1349 SetDParam(0, STR_EMPTY);
1350 } else {
1351 if (is_bool_widget) {
1352 /* if it a bool button write yes or no */
1353 SetDParam(0, (val != 0) ? STR_FACE_YES : STR_FACE_NO);
1354 } else {
1355 /* else write the value + 1 */
1357 SetDParam(1, val + 1);
1358 }
1359 }
1360 }
1361
1362 void UpdateData()
1363 {
1364 this->ge = (GenderEthnicity)GB(this->face, _cmf_info[CMFV_GEN_ETHN].offset, _cmf_info[CMFV_GEN_ETHN].length); // get the gender and ethnicity
1365 this->is_female = HasBit(this->ge, GENDER_FEMALE); // get the gender: 0 == male and 1 == female
1366 this->is_moust_male = !is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge) != 0; // is a male face with moustache
1367
1369 this->GetWidget<NWidgetCore>(WID_SCMF_TIE_EARRING_TEXT)->widget_data = this->is_female ? STR_FACE_EARRING : STR_FACE_TIE;
1370 this->GetWidget<NWidgetCore>(WID_SCMF_LIPS_MOUSTACHE_TEXT)->widget_data = this->is_moust_male ? STR_FACE_MOUSTACHE : STR_FACE_LIPS;
1371 }
1372
1373public:
1375 {
1376 this->advanced = false;
1377 this->CreateNestedTree();
1378 this->SelectDisplayPlanes(this->advanced);
1379 this->FinishInitNested(parent->window_number);
1380 this->parent = parent;
1381 this->owner = (Owner)this->window_number;
1382 this->face = Company::Get((CompanyID)this->window_number)->face;
1383
1384 this->UpdateData();
1385 }
1386
1392 {
1393 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_LOADSAVE)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1394 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_PARTS)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1395 this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_MALEFEMALE)->SetDisplayedPlane(advanced ? SZSP_NONE : 0);
1397
1399 if (advanced) {
1401 } else {
1403 }
1404 }
1405
1406 void OnInit() override
1407 {
1408 /* Size of the boolean yes/no button. */
1412 /* Size of the number button + arrows. */
1413 Dimension number_dim = {0, 0};
1414 for (int val = 1; val <= 12; val++) {
1415 SetDParam(0, val);
1417 }
1418 uint arrows_width = GetSpriteSize(SPR_ARROW_LEFT).width + GetSpriteSize(SPR_ARROW_RIGHT).width + 2 * (WidgetDimensions::scaled.imgbtn.Horizontal());
1421 /* Compute width of both buttons. */
1422 yesno_dim.width = std::max(yesno_dim.width, number_dim.width);
1423 number_dim.width = yesno_dim.width - arrows_width;
1424
1425 this->yesno_dim = yesno_dim;
1426 this->number_dim = number_dim;
1427 }
1428
1430 {
1431 switch (widget) {
1435 break;
1436
1440 break;
1441
1445 break;
1446
1447 case WID_SCMF_FACE:
1448 size = maxdim(size, GetScaledSpriteSize(SPR_GRADIENT));
1449 break;
1450
1453 size = this->yesno_dim;
1454 break;
1455
1456 case WID_SCMF_EYECOLOUR:
1457 case WID_SCMF_CHIN:
1458 case WID_SCMF_EYEBROWS:
1460 case WID_SCMF_NOSE:
1461 case WID_SCMF_HAIR:
1462 case WID_SCMF_JACKET:
1463 case WID_SCMF_COLLAR:
1465 case WID_SCMF_GLASSES:
1466 size = this->number_dim;
1467 break;
1468 }
1469 }
1470
1471 void OnPaint() override
1472 {
1473 /* lower the non-selected gender button */
1474 this->SetWidgetsLoweredState(!this->is_female, WID_SCMF_MALE, WID_SCMF_MALE2);
1476
1477 /* advanced company manager face selection window */
1478
1479 /* lower the non-selected ethnicity button */
1482
1483
1484 /* Disable dynamically the widgets which CompanyManagerFaceVariable has less than 2 options
1485 * (or in other words you haven't any choice).
1486 * If the widgets depend on a HAS-variable and this is false the widgets will be disabled, too. */
1487
1488 /* Eye colour buttons */
1489 this->SetWidgetsDisabledState(_cmf_info[CMFV_EYE_COLOUR].valid_values[this->ge] < 2,
1491
1492 /* Chin buttons */
1493 this->SetWidgetsDisabledState(_cmf_info[CMFV_CHIN].valid_values[this->ge] < 2,
1495
1496 /* Eyebrows buttons */
1497 this->SetWidgetsDisabledState(_cmf_info[CMFV_EYEBROWS].valid_values[this->ge] < 2,
1499
1500 /* Lips or (if it a male face with a moustache) moustache buttons */
1501 this->SetWidgetsDisabledState(_cmf_info[this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS].valid_values[this->ge] < 2,
1503
1504 /* Nose buttons | male faces with moustache haven't any nose options */
1505 this->SetWidgetsDisabledState(_cmf_info[CMFV_NOSE].valid_values[this->ge] < 2 || this->is_moust_male,
1507
1508 /* Hair buttons */
1509 this->SetWidgetsDisabledState(_cmf_info[CMFV_HAIR].valid_values[this->ge] < 2,
1511
1512 /* Jacket buttons */
1513 this->SetWidgetsDisabledState(_cmf_info[CMFV_JACKET].valid_values[this->ge] < 2,
1515
1516 /* Collar buttons */
1517 this->SetWidgetsDisabledState(_cmf_info[CMFV_COLLAR].valid_values[this->ge] < 2,
1519
1520 /* Tie/earring buttons | female faces without earring haven't any earring options */
1521 this->SetWidgetsDisabledState(_cmf_info[CMFV_TIE_EARRING].valid_values[this->ge] < 2 ||
1522 (this->is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge) == 0),
1524
1525 /* Glasses buttons | faces without glasses haven't any glasses options */
1526 this->SetWidgetsDisabledState(_cmf_info[CMFV_GLASSES].valid_values[this->ge] < 2 || GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge) == 0,
1528
1529 this->DrawWidgets();
1530 }
1531
1532 void SetStringParameters(WidgetID widget) const override
1533 {
1534 switch (widget) {
1536 if (this->is_female) { // Only for female faces
1537 this->SetFaceStringParameters(WID_SCMF_HAS_MOUSTACHE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge), true);
1538 } else { // Only for male faces
1539 this->SetFaceStringParameters(WID_SCMF_HAS_MOUSTACHE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge), true);
1540 }
1541 break;
1542
1544 this->SetFaceStringParameters(WID_SCMF_TIE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_TIE_EARRING, this->ge), false);
1545 break;
1546
1548 if (this->is_moust_male) { // Only for male faces with moustache
1549 this->SetFaceStringParameters(WID_SCMF_LIPS_MOUSTACHE, GetCompanyManagerFaceBits(this->face, CMFV_MOUSTACHE, this->ge), false);
1550 } else { // Only for female faces or male faces without moustache
1551 this->SetFaceStringParameters(WID_SCMF_LIPS_MOUSTACHE, GetCompanyManagerFaceBits(this->face, CMFV_LIPS, this->ge), false);
1552 }
1553 break;
1554
1556 this->SetFaceStringParameters(WID_SCMF_HAS_GLASSES, GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge), true );
1557 break;
1558
1559 case WID_SCMF_HAIR:
1560 this->SetFaceStringParameters(WID_SCMF_HAIR, GetCompanyManagerFaceBits(this->face, CMFV_HAIR, this->ge), false);
1561 break;
1562
1563 case WID_SCMF_EYEBROWS:
1564 this->SetFaceStringParameters(WID_SCMF_EYEBROWS, GetCompanyManagerFaceBits(this->face, CMFV_EYEBROWS, this->ge), false);
1565 break;
1566
1567 case WID_SCMF_EYECOLOUR:
1568 this->SetFaceStringParameters(WID_SCMF_EYECOLOUR, GetCompanyManagerFaceBits(this->face, CMFV_EYE_COLOUR, this->ge), false);
1569 break;
1570
1571 case WID_SCMF_GLASSES:
1572 this->SetFaceStringParameters(WID_SCMF_GLASSES, GetCompanyManagerFaceBits(this->face, CMFV_GLASSES, this->ge), false);
1573 break;
1574
1575 case WID_SCMF_NOSE:
1576 this->SetFaceStringParameters(WID_SCMF_NOSE, GetCompanyManagerFaceBits(this->face, CMFV_NOSE, this->ge), false);
1577 break;
1578
1579 case WID_SCMF_CHIN:
1580 this->SetFaceStringParameters(WID_SCMF_CHIN, GetCompanyManagerFaceBits(this->face, CMFV_CHIN, this->ge), false);
1581 break;
1582
1583 case WID_SCMF_JACKET:
1584 this->SetFaceStringParameters(WID_SCMF_JACKET, GetCompanyManagerFaceBits(this->face, CMFV_JACKET, this->ge), false);
1585 break;
1586
1587 case WID_SCMF_COLLAR:
1588 this->SetFaceStringParameters(WID_SCMF_COLLAR, GetCompanyManagerFaceBits(this->face, CMFV_COLLAR, this->ge), false);
1589 break;
1590 }
1591 }
1592
1593 void DrawWidget(const Rect &r, WidgetID widget) const override
1594 {
1595 switch (widget) {
1596 case WID_SCMF_FACE:
1597 DrawCompanyManagerFace(this->face, Company::Get((CompanyID)this->window_number)->colour, r);
1598 break;
1599 }
1600 }
1601
1602 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
1603 {
1604 switch (widget) {
1605 /* Toggle size, advanced/simple face selection */
1608 this->advanced = !this->advanced;
1609 this->SelectDisplayPlanes(this->advanced);
1610 this->ReInit();
1611 break;
1612
1613 /* OK button */
1614 case WID_SCMF_ACCEPT:
1616 [[fallthrough]];
1617
1618 /* Cancel button */
1619 case WID_SCMF_CANCEL:
1620 this->Close();
1621 break;
1622
1623 /* Load button */
1624 case WID_SCMF_LOAD:
1625 this->face = _company_manager_face;
1628 this->UpdateData();
1629 this->SetDirty();
1630 break;
1631
1632 /* 'Company manager face number' button, view and/or set company manager face number */
1633 case WID_SCMF_FACECODE:
1634 SetDParam(0, this->face);
1636 break;
1637
1638 /* Save button */
1639 case WID_SCMF_SAVE:
1642 break;
1643
1644 /* Toggle gender (male/female) button */
1645 case WID_SCMF_MALE:
1646 case WID_SCMF_FEMALE:
1647 case WID_SCMF_MALE2:
1648 case WID_SCMF_FEMALE2:
1649 SetCompanyManagerFaceBits(this->face, CMFV_GENDER, this->ge, (widget == WID_SCMF_FEMALE || widget == WID_SCMF_FEMALE2));
1651 this->UpdateData();
1652 this->SetDirty();
1653 break;
1654
1655 /* Randomize face button */
1657 RandomCompanyManagerFaceBits(this->face, this->ge, this->advanced, _interactive_random);
1658 this->UpdateData();
1659 this->SetDirty();
1660 break;
1661
1662 /* Toggle ethnicity (european/african) button */
1665 SetCompanyManagerFaceBits(this->face, CMFV_ETHNICITY, this->ge, widget - WID_SCMF_ETHNICITY_EUR);
1667 this->UpdateData();
1668 this->SetDirty();
1669 break;
1670
1671 default:
1672 /* Here all buttons from WID_SCMF_HAS_MOUSTACHE_EARRING to WID_SCMF_GLASSES_R are handled.
1673 * First it checks which CompanyManagerFaceVariable is being changed, and then either
1674 * a: invert the value for boolean variables, or
1675 * b: it checks inside of IncreaseCompanyManagerFaceBits() if a left (_L) butten is pressed and then decrease else increase the variable */
1676 if (widget >= WID_SCMF_HAS_MOUSTACHE_EARRING && widget <= WID_SCMF_GLASSES_R) {
1677 CompanyManagerFaceVariable cmfv; // which CompanyManagerFaceVariable shall be edited
1678
1679 if (widget < WID_SCMF_EYECOLOUR_L) { // Bool buttons
1680 switch (widget - WID_SCMF_HAS_MOUSTACHE_EARRING) {
1681 default: NOT_REACHED();
1682 case 0: cmfv = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE; break; // Has earring/moustache button
1683 case 1: cmfv = CMFV_HAS_GLASSES; break; // Has glasses button
1684 }
1685 SetCompanyManagerFaceBits(this->face, cmfv, this->ge, !GetCompanyManagerFaceBits(this->face, cmfv, this->ge));
1687 } else { // Value buttons
1688 switch ((widget - WID_SCMF_EYECOLOUR_L) / 3) {
1689 default: NOT_REACHED();
1690 case 0: cmfv = CMFV_EYE_COLOUR; break; // Eye colour buttons
1691 case 1: cmfv = CMFV_CHIN; break; // Chin buttons
1692 case 2: cmfv = CMFV_EYEBROWS; break; // Eyebrows buttons
1693 case 3: cmfv = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS; break; // Moustache or lips buttons
1694 case 4: cmfv = CMFV_NOSE; break; // Nose buttons
1695 case 5: cmfv = CMFV_HAIR; break; // Hair buttons
1696 case 6: cmfv = CMFV_JACKET; break; // Jacket buttons
1697 case 7: cmfv = CMFV_COLLAR; break; // Collar buttons
1698 case 8: cmfv = CMFV_TIE_EARRING; break; // Tie/earring buttons
1699 case 9: cmfv = CMFV_GLASSES; break; // Glasses buttons
1700 }
1701 /* 0 == left (_L), 1 == middle or 2 == right (_R) - button click */
1702 IncreaseCompanyManagerFaceBits(this->face, cmfv, this->ge, (((widget - WID_SCMF_EYECOLOUR_L) % 3) != 0) ? 1 : -1);
1703 }
1704 this->UpdateData();
1705 this->SetDirty();
1706 }
1707 break;
1708 }
1709 }
1710
1711 void OnQueryTextFinished(std::optional<std::string> str) override
1712 {
1713 if (!str.has_value()) return;
1714 /* Set a new company manager face number */
1715 if (!str->empty()) {
1716 this->face = std::strtoul(str->c_str(), nullptr, 10);
1719 this->UpdateData();
1720 this->SetDirty();
1721 } else {
1723 }
1724 }
1725};
1726
1729 WDP_AUTO, nullptr, 0, 0,
1733);
1734
1747
1748static constexpr NWidgetPart _nested_company_infrastructure_widgets[] = {
1750 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1751 NWidget(WWT_CAPTION, COLOUR_GREY, WID_CI_CAPTION), SetDataTip(STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1752 NWidget(WWT_SHADEBOX, COLOUR_GREY),
1753 NWidget(WWT_STICKYBOX, COLOUR_GREY),
1754 EndContainer(),
1755 NWidget(WWT_PANEL, COLOUR_GREY),
1758 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1759 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1760 EndContainer(),
1762 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1763 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1764 EndContainer(),
1766 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TRAM_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1767 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TRAM_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1768 EndContainer(),
1770 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1771 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1772 EndContainer(),
1776 EndContainer(),
1778 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL_DESC), SetFill(1, 0),
1779 NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL), SetFill(0, 1),
1780 EndContainer(),
1781 EndContainer(),
1782 EndContainer(),
1783};
1784
1789{
1792
1794
1796 {
1797 this->UpdateRailRoadTypes();
1798
1799 this->InitNested(window_number);
1800 this->owner = (Owner)this->window_number;
1801 }
1802
1803 void UpdateRailRoadTypes()
1804 {
1805 this->railtypes = RAILTYPES_NONE;
1806 this->roadtypes = ROADTYPES_NONE;
1807
1808 /* Find the used railtypes. */
1809 for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
1810 if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
1811
1812 this->railtypes |= GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes;
1813 }
1814
1815 /* Get the date introduced railtypes as well. */
1816 this->railtypes = AddDateIntroducedRailTypes(this->railtypes, CalendarTime::MAX_DATE);
1817
1818 /* Find the used roadtypes. */
1819 for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
1820 if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
1821
1822 this->roadtypes |= GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes;
1823 }
1824
1825 /* Get the date introduced roadtypes as well. */
1826 this->roadtypes = AddDateIntroducedRoadTypes(this->roadtypes, CalendarTime::MAX_DATE);
1827 this->roadtypes &= ~_roadtypes_hidden_mask;
1828 }
1829
1832 {
1833 const Company *c = Company::Get((CompanyID)this->window_number);
1834 Money total;
1835
1837 for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
1838 if (HasBit(this->railtypes, rt)) total += RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total);
1839 }
1841
1844 for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
1845 if (HasBit(this->roadtypes, rt)) total += RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total);
1846 }
1847
1850 total += AirportMaintenanceCost(c->index);
1851
1852 return total;
1853 }
1854
1855 void SetStringParameters(WidgetID widget) const override
1856 {
1857 switch (widget) {
1858 case WID_CI_CAPTION:
1860 break;
1861 }
1862 }
1863
1865 {
1866 const Company *c = Company::Get((CompanyID)this->window_number);
1867
1868 switch (widget) {
1869 case WID_CI_RAIL_DESC: {
1870 uint lines = 1; // Starts at 1 because a line is also required for the section title
1871
1872 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).width + padding.width);
1873
1874 for (const auto &rt : _sorted_railtypes) {
1875 if (HasBit(this->railtypes, rt)) {
1876 lines++;
1877 size.width = std::max(size.width, GetStringBoundingBox(GetRailTypeInfo(rt)->strings.name).width + padding.width + WidgetDimensions::scaled.hsep_indent);
1878 }
1879 }
1880 if (this->railtypes != RAILTYPES_NONE) {
1881 lines++;
1883 }
1884
1885 size.height = std::max(size.height, lines * GetCharacterHeight(FS_NORMAL));
1886 break;
1887 }
1888
1889 case WID_CI_ROAD_DESC:
1890 case WID_CI_TRAM_DESC: {
1891 uint lines = 1; // Starts at 1 because a line is also required for the section title
1892
1894
1895 for (const auto &rt : _sorted_roadtypes) {
1896 if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
1897 lines++;
1898 size.width = std::max(size.width, GetStringBoundingBox(GetRoadTypeInfo(rt)->strings.name).width + padding.width + WidgetDimensions::scaled.hsep_indent);
1899 }
1900 }
1901
1902 size.height = std::max(size.height, lines * GetCharacterHeight(FS_NORMAL));
1903 break;
1904 }
1905
1906 case WID_CI_WATER_DESC:
1907 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT).width + padding.width);
1909 break;
1910
1912 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT).width + padding.width);
1915 break;
1916
1917 case WID_CI_RAIL_COUNT:
1918 case WID_CI_ROAD_COUNT:
1919 case WID_CI_TRAM_COUNT:
1920 case WID_CI_WATER_COUNT:
1922 case WID_CI_TOTAL: {
1923 /* Find the maximum count that is displayed. */
1924 uint32_t max_val = 1000; // Some random number to reserve enough space.
1925 Money max_cost = 10000; // Some random number to reserve enough space.
1927 for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
1928 max_val = std::max(max_val, c->infrastructure.rail[rt]);
1929 max_cost = std::max(max_cost, RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
1930 }
1931 max_val = std::max(max_val, c->infrastructure.signal);
1932 max_cost = std::max(max_cost, SignalMaintenanceCost(c->infrastructure.signal));
1935 for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
1936 max_val = std::max(max_val, c->infrastructure.road[rt]);
1937 max_cost = std::max(max_cost, RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total));
1938
1939 }
1940 max_val = std::max(max_val, c->infrastructure.water);
1941 max_cost = std::max(max_cost, CanalMaintenanceCost(c->infrastructure.water));
1942 max_val = std::max(max_val, c->infrastructure.station);
1943 max_cost = std::max(max_cost, StationMaintenanceCost(c->infrastructure.station));
1944 max_val = std::max(max_val, c->infrastructure.airport);
1945 max_cost = std::max(max_cost, AirportMaintenanceCost(c->index));
1946
1948 uint count_width = GetStringBoundingBox(STR_JUST_COMMA).width + WidgetDimensions::scaled.hsep_indent; // Reserve some wiggle room
1949
1952 SetDParamMaxValue(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
1953 this->total_width = GetStringBoundingBox(str_total).width + WidgetDimensions::scaled.hsep_indent * 2;
1954 size.width = std::max(size.width, this->total_width);
1955
1956 SetDParamMaxValue(0, max_cost * 12); // Convert to per year
1957 count_width += std::max(this->total_width, GetStringBoundingBox(str_total).width);
1958 }
1959
1960 size.width = std::max(size.width, count_width);
1961
1962 /* Set height of the total line. */
1963 if (widget == WID_CI_TOTAL) {
1965 }
1966 break;
1967 }
1968 }
1969 }
1970
1978 void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
1979 {
1980 SetDParam(0, count);
1981 DrawString(r.left, r.right, y += GetCharacterHeight(FS_NORMAL), STR_JUST_COMMA, TC_WHITE, SA_RIGHT);
1982
1984 SetDParam(0, monthly_cost * 12); // Convert to per year
1985 Rect tr = r.WithWidth(this->total_width, _current_text_dir == TD_RTL);
1986 DrawString(tr.left, tr.right, y,
1988 TC_FROMSTRING, SA_RIGHT);
1989 }
1990 }
1991
1992 void DrawWidget(const Rect &r, WidgetID widget) const override
1993 {
1994 const Company *c = Company::Get((CompanyID)this->window_number);
1995
1996 int y = r.top;
1997
1999 switch (widget) {
2000 case WID_CI_RAIL_DESC:
2002
2003 if (this->railtypes != RAILTYPES_NONE) {
2004 /* Draw name of each valid railtype. */
2005 for (const auto &rt : _sorted_railtypes) {
2006 if (HasBit(this->railtypes, rt)) {
2007 DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), GetRailTypeInfo(rt)->strings.name, TC_WHITE);
2008 }
2009 }
2011 } else {
2012 /* No valid railtype. */
2014 }
2015
2016 break;
2017
2018 case WID_CI_RAIL_COUNT: {
2019 /* Draw infrastructure count for each valid railtype. */
2021 for (const auto &rt : _sorted_railtypes) {
2022 if (HasBit(this->railtypes, rt)) {
2024 }
2025 }
2026 if (this->railtypes != RAILTYPES_NONE) {
2028 }
2029 break;
2030 }
2031
2032 case WID_CI_ROAD_DESC:
2033 case WID_CI_TRAM_DESC: {
2035
2036 /* Draw name of each valid roadtype. */
2037 for (const auto &rt : _sorted_roadtypes) {
2038 if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
2039 DrawString(ir.left, ir.right, y += GetCharacterHeight(FS_NORMAL), GetRoadTypeInfo(rt)->strings.name, TC_WHITE);
2040 }
2041 }
2042
2043 break;
2044 }
2045
2046 case WID_CI_ROAD_COUNT:
2047 case WID_CI_TRAM_COUNT: {
2049 for (const auto &rt : _sorted_roadtypes) {
2050 if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_COUNT)) {
2052 }
2053 }
2054 break;
2055 }
2056
2057 case WID_CI_WATER_DESC:
2060 break;
2061
2062 case WID_CI_WATER_COUNT:
2064 break;
2065
2066 case WID_CI_TOTAL:
2068 Rect tr = r.WithWidth(this->total_width, _current_text_dir == TD_RTL);
2069 GfxFillRect(tr.left, y, tr.right, y + WidgetDimensions::scaled.bevel.top - 1, PC_WHITE);
2071 SetDParam(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
2072 DrawString(tr.left, tr.right, y,
2074 TC_FROMSTRING, SA_RIGHT);
2075 }
2076 break;
2077
2082 break;
2083
2087 break;
2088 }
2089 }
2090
2096 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2097 {
2098 if (!gui_scope) return;
2099
2100 this->UpdateRailRoadTypes();
2101 this->ReInit();
2102 }
2103};
2104
2105static WindowDesc _company_infrastructure_desc(
2106 WDP_AUTO, "company_infrastructure", 0, 0,
2108 0,
2109 _nested_company_infrastructure_widgets
2110);
2111
2117{
2118 if (!Company::IsValidID(company)) return;
2119 AllocateWindowDescFront<CompanyInfrastructureWindow>(_company_infrastructure_desc, company);
2120}
2121
2122static constexpr NWidgetPart _nested_company_widgets[] = {
2124 NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2125 NWidget(WWT_CAPTION, COLOUR_GREY, WID_C_CAPTION), SetDataTip(STR_COMPANY_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2126 NWidget(WWT_SHADEBOX, COLOUR_GREY),
2127 NWidget(WWT_STICKYBOX, COLOUR_GREY),
2128 EndContainer(),
2129 NWidget(WWT_PANEL, COLOUR_GREY),
2132 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
2133 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE_TITLE), SetFill(1, 1), SetMinimalTextLines(2, 0),
2134 EndContainer(),
2138 NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_INAUGURATION), SetDataTip(STR_JUST_STRING2, STR_NULL), SetFill(1, 0),
2140 NWidget(WWT_LABEL, COLOUR_GREY, WID_C_DESC_COLOUR_SCHEME), SetDataTip(STR_COMPANY_VIEW_COLOUR_SCHEME_TITLE, STR_NULL),
2142 EndContainer(),
2144 NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_VEHICLE), SetDataTip(STR_COMPANY_VIEW_VEHICLES_TITLE, STR_NULL), SetAlignment(SA_LEFT | SA_TOP),
2146 EndContainer(),
2147 EndContainer(),
2150 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_HQ), SetDataTip(STR_COMPANY_VIEW_VIEW_HQ_BUTTON, STR_COMPANY_VIEW_VIEW_HQ_TOOLTIP),
2151 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_BUILD_HQ), SetDataTip(STR_COMPANY_VIEW_BUILD_HQ_BUTTON, STR_COMPANY_VIEW_BUILD_HQ_TOOLTIP),
2152 EndContainer(),
2154 NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_RELOCATE_HQ), SetDataTip(STR_COMPANY_VIEW_RELOCATE_HQ, STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS),
2156 EndContainer(),
2157 EndContainer(),
2158 EndContainer(),
2159
2160 NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_COMPANY_VALUE), SetDataTip(STR_COMPANY_VIEW_COMPANY_VALUE, STR_NULL), SetFill(1, 0),
2161
2163 NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_INFRASTRUCTURE), SetDataTip(STR_COMPANY_VIEW_INFRASTRUCTURE, STR_NULL), SetAlignment(SA_LEFT | SA_TOP),
2166 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_INFRASTRUCTURE), SetDataTip(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
2167 EndContainer(),
2168 EndContainer(),
2169
2170 /* Multi player buttons. */
2174 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_HOSTILE_TAKEOVER), SetDataTip(STR_COMPANY_VIEW_HOSTILE_TAKEOVER_BUTTON, STR_COMPANY_VIEW_HOSTILE_TAKEOVER_TOOLTIP),
2175 EndContainer(),
2177 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_GIVE_MONEY), SetDataTip(STR_COMPANY_VIEW_GIVE_MONEY_BUTTON, STR_COMPANY_VIEW_GIVE_MONEY_TOOLTIP),
2178 EndContainer(),
2180 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_JOIN), SetDataTip(STR_COMPANY_VIEW_JOIN, STR_COMPANY_VIEW_JOIN_TOOLTIP),
2181 EndContainer(),
2182 EndContainer(),
2183 EndContainer(),
2184 EndContainer(),
2185 EndContainer(),
2186 EndContainer(),
2187 /* Button bars at the bottom. */
2190 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_NEW_FACE), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_NEW_FACE_BUTTON, STR_COMPANY_VIEW_NEW_FACE_TOOLTIP),
2191 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COLOUR_SCHEME), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_COLOUR_SCHEME_BUTTON, STR_COMPANY_VIEW_COLOUR_SCHEME_TOOLTIP),
2192 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_PRESIDENT_NAME), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_PRESIDENT_NAME_BUTTON, STR_COMPANY_VIEW_PRESIDENT_NAME_TOOLTIP),
2193 NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_NAME), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_COMPANY_NAME_BUTTON, STR_COMPANY_VIEW_COMPANY_NAME_TOOLTIP),
2194 EndContainer(),
2195 EndContainer(),
2196};
2197
2200 STR_COMPANY_VIEW_TRAINS, STR_COMPANY_VIEW_ROAD_VEHICLES, STR_COMPANY_VIEW_SHIPS, STR_COMPANY_VIEW_AIRCRAFT
2201};
2202
2207{
2208 CompanyWidgets query_widget;
2209
2212 /* Display planes of the #WID_C_SELECT_VIEW_BUILD_HQ selection widget. */
2215
2216 /* Display planes of the #WID_C_SELECT_RELOCATE selection widget. */
2219 };
2220
2222 {
2223 this->InitNested(window_number);
2224 this->owner = (Owner)this->window_number;
2225 this->OnInvalidateData();
2226 }
2227
2228 void OnPaint() override
2229 {
2230 const Company *c = Company::Get((CompanyID)this->window_number);
2231 bool local = this->window_number == _local_company;
2232
2233 if (!this->IsShaded()) {
2234 bool reinit = false;
2235
2236 /* Button bar selection. */
2237 reinit |= this->GetWidget<NWidgetStacked>(WID_C_SELECT_BUTTONS)->SetDisplayedPlane(local ? 0 : SZSP_NONE);
2238
2239 /* Build HQ button handling. */
2241
2243
2244 /* Enable/disable 'Relocate HQ' button. */
2246 /* Enable/disable 'Give money' button. */
2248 /* Enable/disable 'Hostile Takeover' button. */
2250
2251 /* Multiplayer buttons. */
2253
2255
2256 if (reinit) {
2257 this->ReInit();
2258 return;
2259 }
2260 }
2261
2262 this->DrawWidgets();
2263 }
2264
2266 {
2267 switch (widget) {
2268 case WID_C_FACE:
2269 size = maxdim(size, GetScaledSpriteSize(SPR_GRADIENT));
2270 break;
2271
2273 Point offset;
2274 Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2275 d.width -= offset.x;
2276 d.height -= offset.y;
2277 size = maxdim(size, d);
2278 break;
2279 }
2280
2282 SetDParam(0, INT64_MAX); // Arguably the maximum company value
2284 break;
2285
2287 SetDParamMaxValue(0, 5000); // Maximum number of vehicles
2289 size.width = std::max(size.width, GetStringBoundingBox(count_string).width + padding.width);
2290 }
2291 break;
2292
2296 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD).width);
2297 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_WATER).width);
2298 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_STATION).width);
2299 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT).width);
2300 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_NONE).width);
2301 size.width += padding.width;
2302 break;
2303
2304 case WID_C_VIEW_HQ:
2305 case WID_C_BUILD_HQ:
2306 case WID_C_RELOCATE_HQ:
2308 case WID_C_GIVE_MONEY:
2310 case WID_C_COMPANY_JOIN:
2312 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_BUILD_HQ_BUTTON).width);
2313 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_RELOCATE_HQ).width);
2314 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON).width);
2315 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_GIVE_MONEY_BUTTON).width);
2316 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_HOSTILE_TAKEOVER_BUTTON).width);
2317 size.width = std::max(size.width, GetStringBoundingBox(STR_COMPANY_VIEW_JOIN).width);
2318 size.width += padding.width;
2319 break;
2320 }
2321 }
2322
2323 void DrawVehicleCountsWidget(const Rect &r, const Company *c) const
2324 {
2326
2327 int y = r.top;
2328 for (VehicleType type = VEH_BEGIN; type < VEH_COMPANY_END; type++) {
2329 uint amount = c->group_all[type].num_vehicle;
2330 if (amount != 0) {
2331 SetDParam(0, amount);
2332 DrawString(r.left, r.right, y, _company_view_vehicle_count_strings[type]);
2334 }
2335 }
2336
2337 if (y == r.top) {
2338 /* No String was emited before, so there must be no vehicles at all. */
2339 DrawString(r.left, r.right, y, STR_COMPANY_VIEW_VEHICLES_NONE);
2340 }
2341 }
2342
2343 void DrawInfrastructureCountsWidget(const Rect &r, const Company *c) const
2344 {
2345 int y = r.top;
2346
2348 if (rail_pieces != 0) {
2352 }
2353
2354 /* GetRoadTotal() skips tram pieces, but we actually want road and tram here. */
2355 uint road_pieces = std::accumulate(std::begin(c->infrastructure.road), std::end(c->infrastructure.road), 0U);
2356 if (road_pieces != 0) {
2360 }
2361
2362 if (c->infrastructure.water != 0) {
2366 }
2367
2368 if (c->infrastructure.station != 0) {
2372 }
2373
2374 if (c->infrastructure.airport != 0) {
2378 }
2379
2380 if (y == r.top) {
2381 /* No String was emited before, so there must be no infrastructure at all. */
2383 }
2384 }
2385
2386 void DrawWidget(const Rect &r, WidgetID widget) const override
2387 {
2388 const Company *c = Company::Get((CompanyID)this->window_number);
2389 switch (widget) {
2390 case WID_C_FACE:
2392 break;
2393
2394 case WID_C_FACE_TITLE:
2395 SetDParam(0, c->index);
2396 DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE, TC_FROMSTRING, SA_HOR_CENTER);
2397 break;
2398
2400 Point offset;
2401 Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2402 d.height -= offset.y;
2403 DrawSprite(SPR_VEH_BUS_SW_VIEW, COMPANY_SPRITE_COLOUR(c->index), r.left - offset.x, CenterBounds(r.top, r.bottom, d.height) - offset.y);
2404 break;
2405 }
2406
2408 DrawVehicleCountsWidget(r, c);
2409 break;
2410
2412 DrawInfrastructureCountsWidget(r, c);
2413 break;
2414 }
2415 }
2416
2417 void SetStringParameters(WidgetID widget) const override
2418 {
2419 switch (widget) {
2420 case WID_C_CAPTION:
2422 SetDParam(1, (CompanyID)this->window_number);
2423 break;
2424
2428 SetDParam(1, Company::Get(static_cast<CompanyID>(this->window_number))->inaugurated_year_calendar);
2429 SetDParam(2, Company::Get(static_cast<CompanyID>(this->window_number))->inaugurated_year);
2430 } else {
2432 SetDParam(1, Company::Get(static_cast<CompanyID>(this->window_number))->inaugurated_year);
2433 }
2434 break;
2435
2437 SetDParam(0, CalculateCompanyValue(Company::Get((CompanyID)this->window_number)));
2438 break;
2439 }
2440 }
2441
2442 void OnResize() override
2443 {
2445 SetDParam(0, this->owner);
2447 if (wid->UpdateVerticalSize(y)) this->ReInit(0, 0);
2448 }
2449
2450 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2451 {
2452 switch (widget) {
2453 case WID_C_NEW_FACE: DoSelectCompanyManagerFace(this); break;
2454
2456 ShowCompanyLiveryWindow((CompanyID)this->window_number, INVALID_GROUP);
2457 break;
2458
2460 this->query_widget = WID_C_PRESIDENT_NAME;
2461 SetDParam(0, this->window_number);
2463 break;
2464
2465 case WID_C_COMPANY_NAME:
2466 this->query_widget = WID_C_COMPANY_NAME;
2467 SetDParam(0, this->window_number);
2469 break;
2470
2471 case WID_C_VIEW_HQ: {
2472 TileIndex tile = Company::Get((CompanyID)this->window_number)->location_of_HQ;
2473 if (_ctrl_pressed) {
2475 } else {
2477 }
2478 break;
2479 }
2480
2481 case WID_C_BUILD_HQ:
2482 if ((uint8_t)this->window_number != _local_company) return;
2483 if (this->IsWidgetLowered(WID_C_BUILD_HQ)) {
2485 this->RaiseButtons();
2486 break;
2487 }
2488 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2489 SetTileSelectSize(2, 2);
2492 break;
2493
2494 case WID_C_RELOCATE_HQ:
2497 this->RaiseButtons();
2498 break;
2499 }
2500 SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2501 SetTileSelectSize(2, 2);
2504 break;
2505
2507 ShowCompanyInfrastructure((CompanyID)this->window_number);
2508 break;
2509
2510 case WID_C_GIVE_MONEY:
2511 this->query_widget = WID_C_GIVE_MONEY;
2513 break;
2514
2516 ShowBuyCompanyDialog((CompanyID)this->window_number, true);
2517 break;
2518
2519 case WID_C_COMPANY_JOIN: {
2520 this->query_widget = WID_C_COMPANY_JOIN;
2521 CompanyID company = (CompanyID)this->window_number;
2522 if (_network_server) {
2525 } else {
2526 /* just send the join command */
2527 NetworkClientRequestMove(company);
2528 }
2529 break;
2530 }
2531 }
2532 }
2533
2535 IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
2536 this->SetDirty();
2537 }};
2538
2546
2547 void OnPlaceObjectAbort() override
2548 {
2549 this->RaiseButtons();
2550 }
2551
2552 void OnQueryTextFinished(std::optional<std::string> str) override
2553 {
2554 if (!str.has_value()) return;
2555
2556 switch (this->query_widget) {
2557 default: NOT_REACHED();
2558
2559 case WID_C_GIVE_MONEY: {
2560 Money money = std::strtoull(str->c_str(), nullptr, 10) / GetCurrency().rate;
2562 break;
2563 }
2564
2567 break;
2568
2569 case WID_C_COMPANY_NAME:
2571 break;
2572 }
2573 }
2574
2575 void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
2576 {
2577 if (gui_scope && data == 1) {
2578 /* Manually call OnResize to adjust minimum height of president name widget. */
2579 OnResize();
2580 }
2581 }
2582};
2583
2584static WindowDesc _company_desc(
2585 WDP_AUTO, "company", 0, 0,
2587 0,
2588 _nested_company_widgets
2589);
2590
2596{
2597 if (!Company::IsValidID(company)) return;
2598
2599 AllocateWindowDescFront<CompanyWindow>(_company_desc, company);
2600}
2601
2611
2614 {
2615 this->InitNested(window_number);
2616
2617 const Company *c = Company::Get((CompanyID)this->window_number);
2618 this->company_value = hostile_takeover ? CalculateHostileTakeoverValue(c) : c->bankrupt_value;
2619 }
2620
2622 {
2623 switch (widget) {
2624 case WID_BC_FACE:
2625 size = GetScaledSpriteSize(SPR_GRADIENT);
2626 break;
2627
2628 case WID_BC_QUESTION:
2629 const Company *c = Company::Get((CompanyID)this->window_number);
2630 SetDParam(0, c->index);
2631 SetDParam(1, this->company_value);
2632 size.height = GetStringHeight(this->hostile_takeover ? STR_BUY_COMPANY_HOSTILE_TAKEOVER : STR_BUY_COMPANY_MESSAGE, size.width);
2633 break;
2634 }
2635 }
2636
2637 void SetStringParameters(WidgetID widget) const override
2638 {
2639 switch (widget) {
2640 case WID_BC_CAPTION:
2642 SetDParam(1, Company::Get((CompanyID)this->window_number)->index);
2643 break;
2644 }
2645 }
2646
2647 void DrawWidget(const Rect &r, WidgetID widget) const override
2648 {
2649 switch (widget) {
2650 case WID_BC_FACE: {
2651 const Company *c = Company::Get((CompanyID)this->window_number);
2653 break;
2654 }
2655
2656 case WID_BC_QUESTION: {
2657 const Company *c = Company::Get((CompanyID)this->window_number);
2658 SetDParam(0, c->index);
2659 SetDParam(1, this->company_value);
2660 DrawStringMultiLine(r.left, r.right, r.top, r.bottom, this->hostile_takeover ? STR_BUY_COMPANY_HOSTILE_TAKEOVER : STR_BUY_COMPANY_MESSAGE, TC_FROMSTRING, SA_CENTER);
2661 break;
2662 }
2663 }
2664 }
2665
2666 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
2667 {
2668 switch (widget) {
2669 case WID_BC_NO:
2670 this->Close();
2671 break;
2672
2673 case WID_BC_YES:
2674 Command<CMD_BUY_COMPANY>::Post(STR_ERROR_CAN_T_BUY_COMPANY, (CompanyID)this->window_number, this->hostile_takeover);
2675 break;
2676 }
2677 }
2678
2682 IntervalTimer<TimerWindow> rescale_interval = {std::chrono::seconds(3), [this](auto) {
2683 /* Value can't change when in bankruptcy. */
2684 if (!this->hostile_takeover) return;
2685
2686 const Company *c = Company::Get((CompanyID)this->window_number);
2688 if (new_value != this->company_value) {
2689 this->company_value = new_value;
2690 this->ReInit();
2691 }
2692 }};
2693
2694private:
2697};
2698
2699static constexpr NWidgetPart _nested_buy_company_widgets[] = {
2701 NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
2702 NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE, WID_BC_CAPTION), SetDataTip(STR_ERROR_MESSAGE_CAPTION_OTHER_COMPANY, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2703 EndContainer(),
2704 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
2707 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_FACE), SetFill(0, 1),
2708 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_QUESTION), SetMinimalSize(240, 0), SetFill(1, 1),
2709 EndContainer(),
2711 NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_NO), SetMinimalSize(60, 12), SetDataTip(STR_QUIT_NO, STR_NULL), SetFill(1, 0),
2712 NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_YES), SetMinimalSize(60, 12), SetDataTip(STR_QUIT_YES, STR_NULL), SetFill(1, 0),
2713 EndContainer(),
2714 EndContainer(),
2715 EndContainer(),
2716};
2717
2718static WindowDesc _buy_company_desc(
2719 WDP_AUTO, nullptr, 0, 0,
2722 _nested_buy_company_widgets
2723);
2724
2730void ShowBuyCompanyDialog(CompanyID company, bool hostile_takeover)
2731{
2732 auto window = BringWindowToFrontById(WC_BUY_COMPANY, company);
2733 if (window == nullptr) {
2734 new BuyCompanyWindow(_buy_company_desc, company, hostile_takeover);
2735 }
2736}
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.
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:266
StringID name
Name of this rail type.
Definition rail.h:176
RoadTypes introduces_roadtypes
Bitmask of which other roadtypes are introduced when this roadtype is introduced.
Definition road.h:177
StringID name
Name of this rail type.
Definition road.h:103
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:2377
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:2451
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.
void SelectDisplayPlanes(bool advanced)
Select planes to display to the user with the NWID_SELECTION widgets WID_SCMF_SEL_LOADSAVE,...
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.
void SetFaceStringParameters(WidgetID widget_index, uint8_t val, bool is_bool_widget) const
Set parameters for value of face control buttons.
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 SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
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:42
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:28
RectPadding imgbtn
Padding around image button image.
Definition window_gui.h:36
int vsep_normal
Normal vertical spacing.
Definition window_gui.h:60
int vsep_wide
Wide vertical spacing.
Definition window_gui.h:62
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:96
int hsep_normal
Normal horizontal spacing.
Definition window_gui.h:63
RectPadding bevel
Bevel thickness, affected by "scaled bevels" game option.
Definition window_gui.h:40
int hsep_indent
Width of identation for tree layouts.
Definition window_gui.h:65
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:176
Money CalculateCompanyValue(const Company *c, bool including_loan=true)
Calculate the value of the company.
Definition economy.cpp:149
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 WindowDesc _select_company_manager_face_desc(WDP_AUTO, nullptr, 0, 0, WC_COMPANY_MANAGER_FACE, WC_NONE, WDF_CONSTRUCTION, _nested_select_company_manager_face_widgets)
Company manager face selection window description.
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 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.
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 SetCompanyManagerFaceBits(CompanyManagerFace &cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge, uint val)
Sets the company manager's face bits for the given company manager's face variable.
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.
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.
CompanyManagerFaceVariable
Bitgroups of the CompanyManagerFace variable.
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'.
uint32_t CompanyManagerFace
Company manager face bits, info see in company_manager_face.h.
Owner
Enum for all companies/owners.
@ COMPANY_SPECTATOR
The client is spectating.
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:117
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.
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
@ WL_INFO
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition error.h:24
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:704
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:922
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:851
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:657
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:114
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:988
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:774
Dimension GetScaledSpriteSize(SpriteID sprid)
Scale sprite size for GUI.
Definition widget.cpp:54
int CenterBounds(int min, int max, int size)
Determine where to draw a centred object inside a widget.
Definition gfx_func.h:166
@ SA_TOP
Top align the text.
Definition gfx_type.h:348
@ SA_LEFT
Left align the text.
Definition gfx_type.h:343
@ SA_RIGHT
Right align the text (must be a single bit).
Definition gfx_type.h:345
@ SA_HOR_CENTER
Horizontally center the text.
Definition gfx_type.h:344
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:353
@ SA_VERT_CENTER
Vertically center the text.
Definition gfx_type.h:349
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:209
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:19
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:260
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
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 SetDataTip(uint32_t data, StringID tip)
Widget part function for setting the data and tooltip.
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 SetMatrixDataTip(uint8_t cols, uint8_t rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
constexpr NWidgetPart SetAlignment(StringAlignment align)
Widget part function for setting the alignment of text/images.
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlags::ResizeX)
Widget part function for setting the aspect ratio.
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:940
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition gfx.cpp:1529
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.
uint16_t GroupID
Type for all group identifiers.
Definition group_type.h:13
static const GroupID INVALID_GROUP
Sentinel for invalid groups.
Definition group_type.h:18
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(StringID 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:84
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:20
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:430
Money SignalMaintenanceCost(uint32_t num)
Calculates the maintenance cost of a number of signals.
Definition rail.h:441
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:307
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:227
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:57
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:56
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:709
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:280
@ 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
void SetDParamMaxValue(size_t n, uint64_t max_value, uint min_count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
Definition strings.cpp:127
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition strings.cpp:104
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
Functions related to OTTD's strings.
@ TD_RTL
Text is written right-to-left by default.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
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.
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.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
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.
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.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
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.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters 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.
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.
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 OnPlaceObjectAbort() override
The user cancelled a tile highlight mode that has been set.
void OnPlaceObject(Point pt, TileIndex tile) override
The user clicked some place on the map when a tile highlight mode has been set.
void SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
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.
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.
GroupStatistics group_all[VEH_COMPANY_END]
NOSAVE: Statistics for the ALL_GROUP group.
uint16_t rate
The conversion rate compared to the base currency.
Definition currency.h:76
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:176
uint64_t used_liveries
Bitmask of LiveryScheme used by the defined engines.
Definition newgrf.h:177
uint8_t liveries
options for displaying company liveries, 0=none, 1=self, 2=all
uint8_t 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)
uint16_t num_vehicle
Number of vehicles.
Definition group.h:28
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.
Tindex index
Index of this pool item.
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * Get(size_t index)
Returns Titem with given index.
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:214
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 SetStringParameters(WidgetID widget) const override
Initialize string parameters for a widget.
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnResize() override
Called after the window got resized.
High level window description.
Definition window_gui.h:159
Data structure for an opened window.
Definition window_gui.h:273
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:952
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1047
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1733
void DrawWidgets() const
Paint all widgets of a window.
Definition widget.cpp:732
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
Definition window.cpp:3159
Window * parent
Parent window.
Definition window_gui.h:328
void RaiseWidget(WidgetID widget_index)
Marks a widget as raised.
Definition window_gui.h:475
void SetWidgetDirty(WidgetID widget_index) const
Invalidate a widget, i.e.
Definition window.cpp:551
ResizeInfo resize
Resize information.
Definition window_gui.h:314
void SetShaded(bool make_shaded)
Set the shaded state of the window to make_shaded.
Definition window.cpp:995
void SetWidgetsDisabledState(bool disab_stat, Args... widgets)
Sets the enabled/disabled status of a list of widgets.
Definition window_gui.h:521
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1723
bool IsWidgetLowered(WidgetID widget_index) const
Gets the lowered state of a widget.
Definition window_gui.h:497
void RaiseButtons(bool autoraise=false)
Raise the buttons of the window.
Definition window.cpp:525
void SetWidgetsLoweredState(bool lowered_stat, Args... widgets)
Sets the lowered/raised status of a list of widgets.
Definition window_gui.h:532
Owner owner
The owner of the content shown in this window. Company colour is acquired from this variable.
Definition window_gui.h:316
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:447
void EnableWidget(WidgetID widget_index)
Sets a widget to Enabled.
Definition window_gui.h:406
bool IsShaded() const
Is window shaded currently?
Definition window_gui.h:563
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:977
void LowerWidget(WidgetID widget_index)
Marks a widget as lowered.
Definition window_gui.h:466
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition window.cpp:1746
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:314
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:387
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:311
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:302
Stuff related to the text buffer GUI.
@ QSF_ENABLE_DEFAULT
enable the 'Default' button ("\0" is returned)
Definition textbuf_gui.h:21
@ QSF_LEN_IN_CHARS
the length of the string is counted in characters
Definition textbuf_gui.h:22
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
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
@ AWV_DECREASE
Arrow to the left or in case of RTL to the right.
Definition widget_type.h:31
@ AWV_INCREASE
Arrow to the right or in case of RTL to the left.
Definition widget_type.h:32
@ NC_EQUALSIZE
Value of the NCB_EQUALSIZE flag.
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
@ WWT_IMGBTN
(Toggle) Button with image
Definition widget_type.h:52
@ WWT_PUSHARROWBTN
Normal push-button (no toggle button) with arrow caption.
@ WWT_LABEL
Centered label.
Definition widget_type.h:57
@ NWID_SPACER
Invisible widget that takes some space.
Definition widget_type.h:79
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:75
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:55
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:50
@ WWT_STICKYBOX
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition widget_type.h:66
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:59
@ WWT_SHADEBOX
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition widget_type.h:64
@ WWT_CAPTION
Window caption (window title between closebox and stickybox)
Definition widget_type.h:61
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:85
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:77
@ WWT_CLOSEBOX
Close box (at top-left of a window)
Definition widget_type.h:69
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:48
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:68
@ WWT_DEFSIZEBOX
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX)
Definition widget_type.h:65
@ WWT_DROPDOWN
Drop down list.
Definition widget_type.h:70
@ WWT_TEXT
Pure simple text.
Definition widget_type.h:58
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:80
Window * BringWindowToFrontById(WindowClass cls, WindowNumber number)
Find a window and make it the relative top-window on the screen.
Definition window.cpp:1223
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3101
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
@ WDF_CONSTRUCTION
This window is used for construction; close it whenever changing company.
Definition window_gui.h:203
@ WDP_AUTO
Find a place automatically.
Definition window_gui.h:147
int WidgetID
Widget ID.
Definition window_type.h:18
int32_t WindowNumber
Number to differentiate different windows of the same class.
@ 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:45
@ 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.