OpenRCT2/src/openrct2-ui/windows/Finances.cpp

1056 lines
39 KiB
C++
Raw Normal View History

/*****************************************************************************
* Copyright (c) 2014-2023 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <algorithm>
2018-06-22 23:21:44 +02:00
#include <openrct2-ui/interface/Dropdown.h>
#include <openrct2-ui/interface/Graph.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
#include <openrct2/Context.h>
#include <openrct2/Game.h>
#include <openrct2/GameState.h>
Split actions hpp files into separate h and cpp files (#13548) * Split up SmallSceneryPlace/Remove Added undo function for Remove Scenery * Refactor: Balloon and Banner actions hpp=>h/cpp * Refactor: rename all action *.hpp files to *.cpp This is preparation for separation in later commits. Note that without the complete set of commits in this branch, the code will not build. * Refactor Clear, Climate, Custom, and Footpath actions hpp=>h/cpp * VSCode: add src subdirectories to includePath * Refactor Guest actions hpp=>h/cpp * Refactor Land actions hpp=>h/cpp * Refactor LargeScenery actions hpp=>h/cpp * Refactor Load, Maze, Network actions hpp=>h/cpp * Refactor Park actions hpp=>h/cpp * Refactor/style: move private function declarations in actions *.h Previous action .h files included private function declarations with private member variables, before public function declarations. This commit re-orders the header files to the following order: - public member variables - private member variables - public functions - private functions * Refactor Pause action hpp=>h/cpp * Refactor Peep, Place, Player actions hpp=>h/cpp * Refactor Ride actions hpp=>h/cpp * Refactor Scenario, Set*, Sign* actions hpp=>h/cpp * Refactor SmallScenerySetColourAction hpp=>h/cpp * Refactor Staff actions hpp=>h/cpp * Refactor Surface, Tile, Track* actions hpp=>h/cpp * Refactor Wall and Water actions hpp=>h/cpp * Fix various includes and other compile errors Update includes for tests. Move static function declarations to .h files Add explicit includes to various files that were previously implicit (the required header was a nested include in an action hpp file, and the action .h file does not include that header) Move RideSetStatus string enum to the cpp file to avoid unused imports * Xcode: modify project file for actions refactor * Cleanup whitespace and end-of-file newlines Co-authored-by: duncanspumpkin <duncans_pumpkin@hotmail.co.uk>
2020-12-10 07:39:10 +01:00
#include <openrct2/actions/ParkSetLoanAction.h>
#include <openrct2/actions/ParkSetResearchFundingAction.h>
2017-09-05 20:55:18 +02:00
#include <openrct2/config/Config.h>
2018-01-06 18:32:25 +01:00
#include <openrct2/localisation/Date.h>
2021-12-12 00:06:06 +01:00
#include <openrct2/localisation/Formatter.h>
2018-01-06 18:32:25 +01:00
#include <openrct2/localisation/Localisation.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/management/Finance.h>
2018-01-10 00:00:09 +01:00
#include <openrct2/ride/RideData.h>
#include <openrct2/ride/ShopItem.h>
2018-03-19 23:28:40 +01:00
#include <openrct2/scenario/Scenario.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/sprites.h>
2018-03-19 23:28:40 +01:00
#include <openrct2/world/Park.h>
2018-01-04 04:43:34 +01:00
enum
{
WINDOW_FINANCES_PAGE_SUMMARY,
WINDOW_FINANCES_PAGE_FINANCIAL_GRAPH,
WINDOW_FINANCES_PAGE_VALUE_GRAPH,
WINDOW_FINANCES_PAGE_PROFIT_GRAPH,
WINDOW_FINANCES_PAGE_MARKETING,
WINDOW_FINANCES_PAGE_RESEARCH,
WINDOW_FINANCES_PAGE_COUNT
2014-05-26 01:55:46 +02:00
};
2018-01-04 04:43:34 +01:00
enum
{
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_PAGE_BACKGROUND,
WIDX_TAB_1,
WIDX_TAB_2,
WIDX_TAB_3,
WIDX_TAB_4,
WIDX_TAB_5,
WIDX_TAB_6,
WIDX_TAB_CONTENT,
WIDX_SUMMARY_SCROLL = WIDX_TAB_CONTENT,
WIDX_LOAN,
WIDX_LOAN_INCREASE,
WIDX_LOAN_DECREASE,
WIDX_ACTIVE_CAMPAIGNS_GROUP = WIDX_TAB_CONTENT,
WIDX_CAMPAIGNS_AVAILABLE_GROUP,
WIDX_CAMPAIGN_1,
WIDX_CAMPAIGN_2,
WIDX_CAMPAIGN_3,
WIDX_CAMPAIGN_4,
WIDX_CAMPAIGN_5,
WIDX_CAMPAIGN_6,
WIDX_RESEARCH_FUNDING_GROUP = WIDX_TAB_CONTENT,
WIDX_RESEARCH_FUNDING,
WIDX_RESEARCH_FUNDING_DROPDOWN_BUTTON,
WIDX_RESEARCH_PRIORITIES_GROUP,
WIDX_TRANSPORT_RIDES,
WIDX_GENTLE_RIDES,
WIDX_ROLLER_COASTERS,
WIDX_THRILL_RIDES,
WIDX_WATER_RIDES,
WIDX_SHOPS_AND_STALLS,
WIDX_SCENERY_AND_THEMING,
2014-05-26 01:55:46 +02:00
};
#pragma region Measurements
2014-05-26 01:55:46 +02:00
static constexpr const int32_t WH_SUMMARY = 309;
static constexpr const int32_t WH_RESEARCH = 207;
static constexpr const int32_t WH_OTHER_TABS = 257;
static constexpr const int32_t WW_RESEARCH = 320;
static constexpr const int32_t WW_OTHER_TABS = 530;
static constexpr const int32_t RSH_SUMMARY = 266;
static constexpr const int32_t RSH_RESEARCH = 164;
static constexpr const int32_t RSH_OTHER_TABS = 214;
static constexpr const int32_t RSW_RESEARCH = WW_RESEARCH;
static constexpr const int32_t RSW_OTHER_TABS = WW_OTHER_TABS;
#pragma endregion
#pragma region Widgets
// clang-format off
#define MAIN_FINANCES_WIDGETS(TITLE, RSW, RSH, WW, WH) \
WINDOW_SHIM(TITLE, WW, WH), \
MakeWidget({0, 43}, {RSW, RSH}, WindowWidgetType::Resize, WindowColour::Secondary), \
MakeTab({ 3, 17}, STR_FINANCES_SHOW_SUMMARY_TAB_TIP ), \
MakeTab({ 34, 17}, STR_FINANCES_SHOW_CASH_TAB_TIP ), \
MakeTab({ 65, 17}, STR_FINANCES_SHOW_PARK_VALUE_TAB_TIP ), \
MakeTab({ 96, 17}, STR_FINANCES_SHOW_WEEKLY_PROFIT_TAB_TIP), \
MakeTab({127, 17}, STR_FINANCES_SHOW_MARKETING_TAB_TIP ), \
MakeTab({158, 17}, STR_FINANCES_RESEARCH_TIP )
2022-12-24 16:50:29 +01:00
static Widget _windowFinancesSummaryWidgets[] =
2018-01-04 04:43:34 +01:00
{
MAIN_FINANCES_WIDGETS(STR_FINANCIAL_SUMMARY, RSW_OTHER_TABS, RSH_SUMMARY, WW_OTHER_TABS, WH_SUMMARY),
MakeWidget ({130, 50}, {391, 211}, WindowWidgetType::Scroll, WindowColour::Secondary, SCROLL_HORIZONTAL ),
MakeSpinnerWidgets({ 64, 279}, { 97, 14}, WindowWidgetType::Spinner, WindowColour::Secondary, STR_FINANCES_SUMMARY_LOAN_VALUE), // NB: 3 widgets.
2021-09-26 11:11:42 +02:00
WIDGETS_END,
2014-05-26 01:55:46 +02:00
};
2022-12-24 16:50:29 +01:00
static Widget _windowFinancesCashWidgets[] =
2018-01-04 04:43:34 +01:00
{
MAIN_FINANCES_WIDGETS(STR_FINANCIAL_GRAPH, RSW_OTHER_TABS, RSH_OTHER_TABS, WW_OTHER_TABS, WH_OTHER_TABS),
2021-09-26 11:11:42 +02:00
WIDGETS_END,
2014-05-26 01:55:46 +02:00
};
2022-12-24 16:50:29 +01:00
static Widget _windowFinancesParkValueWidgets[] =
2018-01-04 04:43:34 +01:00
{
MAIN_FINANCES_WIDGETS(STR_PARK_VALUE_GRAPH, RSW_OTHER_TABS, RSH_OTHER_TABS, WW_OTHER_TABS, WH_OTHER_TABS),
2021-09-26 11:11:42 +02:00
WIDGETS_END,
2014-05-26 01:55:46 +02:00
};
2022-12-24 16:50:29 +01:00
static Widget _windowFinancesProfitWidgets[] =
2018-01-04 04:43:34 +01:00
{
MAIN_FINANCES_WIDGETS(STR_PROFIT_GRAPH, RSW_OTHER_TABS, RSH_OTHER_TABS, WW_OTHER_TABS, WH_OTHER_TABS),
2021-09-26 11:11:42 +02:00
WIDGETS_END,
2014-05-26 01:55:46 +02:00
};
2022-12-24 16:50:29 +01:00
static Widget _windowFinancesMarketingWidgets[] =
2018-01-04 04:43:34 +01:00
{
MAIN_FINANCES_WIDGETS(STR_MARKETING, RSW_OTHER_TABS, RSH_OTHER_TABS, WW_OTHER_TABS, WH_OTHER_TABS),
MakeWidget({3, 47}, { WW_OTHER_TABS - 6, 45}, WindowWidgetType::Groupbox, WindowColour::Tertiary , STR_MARKETING_CAMPAIGNS_IN_OPERATION ),
MakeWidget({3, 47}, { WW_OTHER_TABS - 6, 206}, WindowWidgetType::Groupbox, WindowColour::Tertiary , STR_MARKETING_CAMPAIGNS_AVAILABLE ),
MakeWidget({8, 0}, {WW_OTHER_TABS - 16, 14}, WindowWidgetType::ImgBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN),
MakeWidget({8, 0}, {WW_OTHER_TABS - 16, 14}, WindowWidgetType::ImgBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN),
MakeWidget({8, 0}, {WW_OTHER_TABS - 16, 14}, WindowWidgetType::ImgBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN),
MakeWidget({8, 0}, {WW_OTHER_TABS - 16, 14}, WindowWidgetType::ImgBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN),
MakeWidget({8, 0}, {WW_OTHER_TABS - 16, 14}, WindowWidgetType::ImgBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN),
MakeWidget({8, 0}, {WW_OTHER_TABS - 16, 14}, WindowWidgetType::ImgBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN),
2021-09-26 11:11:42 +02:00
WIDGETS_END,
2014-05-26 01:55:46 +02:00
};
2022-12-24 16:50:29 +01:00
static Widget _windowFinancesResearchWidgets[] =
2018-01-04 04:43:34 +01:00
{
MAIN_FINANCES_WIDGETS(STR_RESEARCH_FUNDING, RSW_RESEARCH, RSH_RESEARCH, WW_RESEARCH, WH_RESEARCH),
MakeWidget({ 3, 47}, { WW_RESEARCH - 6, 45}, WindowWidgetType::Groupbox, WindowColour::Tertiary, STR_RESEARCH_FUNDING_ ),
MakeWidget({ 8, 59}, { 160, 14}, WindowWidgetType::DropdownMenu, WindowColour::Tertiary, 0xFFFFFFFF, STR_SELECT_LEVEL_OF_RESEARCH_AND_DEVELOPMENT),
MakeWidget({156, 60}, { 11, 12}, WindowWidgetType::Button, WindowColour::Tertiary, STR_DROPDOWN_GLYPH, STR_SELECT_LEVEL_OF_RESEARCH_AND_DEVELOPMENT),
MakeWidget({ 3, 96}, { WW_RESEARCH - 6, 107}, WindowWidgetType::Groupbox, WindowColour::Tertiary, STR_RESEARCH_PRIORITIES ),
MakeWidget({ 8, 108}, {WW_RESEARCH - 14, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary, STR_RESEARCH_NEW_TRANSPORT_RIDES, STR_RESEARCH_NEW_TRANSPORT_RIDES_TIP ),
MakeWidget({ 8, 121}, {WW_RESEARCH - 14, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary, STR_RESEARCH_NEW_GENTLE_RIDES, STR_RESEARCH_NEW_GENTLE_RIDES_TIP ),
MakeWidget({ 8, 134}, {WW_RESEARCH - 14, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary, STR_RESEARCH_NEW_ROLLER_COASTERS, STR_RESEARCH_NEW_ROLLER_COASTERS_TIP ),
MakeWidget({ 8, 147}, {WW_RESEARCH - 14, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary, STR_RESEARCH_NEW_THRILL_RIDES, STR_RESEARCH_NEW_THRILL_RIDES_TIP ),
MakeWidget({ 8, 160}, {WW_RESEARCH - 14, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary, STR_RESEARCH_NEW_WATER_RIDES, STR_RESEARCH_NEW_WATER_RIDES_TIP ),
MakeWidget({ 8, 173}, {WW_RESEARCH - 14, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary, STR_RESEARCH_NEW_SHOPS_AND_STALLS, STR_RESEARCH_NEW_SHOPS_AND_STALLS_TIP ),
MakeWidget({ 8, 186}, {WW_RESEARCH - 14, 12}, WindowWidgetType::Checkbox, WindowColour::Tertiary, STR_RESEARCH_NEW_SCENERY_AND_THEMING, STR_RESEARCH_NEW_SCENERY_AND_THEMING_TIP ),
2021-09-26 11:11:42 +02:00
WIDGETS_END,
2014-05-26 01:55:46 +02:00
};
// clang-format on
2014-05-26 01:55:46 +02:00
2022-12-24 16:50:29 +01:00
static Widget* _windowFinancesPageWidgets[] = {
_windowFinancesSummaryWidgets, // WINDOW_FINANCES_PAGE_SUMMARY
_windowFinancesCashWidgets, // WINDOW_FINANCES_PAGE_FINANCIAL_GRAPH
_windowFinancesParkValueWidgets, // WINDOW_FINANCES_PAGE_VALUE_GRAPH
_windowFinancesProfitWidgets, // WINDOW_FINANCES_PAGE_PROFIT_GRAPH
_windowFinancesMarketingWidgets, // WINDOW_FINANCES_PAGE_MARKETING
_windowFinancesResearchWidgets, // WINDOW_FINANCES_PAGE_RESEARCH
2014-05-26 01:55:46 +02:00
};
static_assert(std::size(_windowFinancesPageWidgets) == WINDOW_FINANCES_PAGE_COUNT);
2014-05-26 01:55:46 +02:00
#pragma endregion
2022-07-31 14:22:58 +02:00
static constexpr const StringId _windowFinancesSummaryRowLabels[static_cast<int32_t>(ExpenditureType::Count)] = {
STR_FINANCES_SUMMARY_RIDE_CONSTRUCTION,
STR_FINANCES_SUMMARY_RIDE_RUNNING_COSTS,
STR_FINANCES_SUMMARY_LAND_PURCHASE,
STR_FINANCES_SUMMARY_LANDSCAPING,
STR_FINANCES_SUMMARY_PARK_ENTRANCE_TICKETS,
STR_FINANCES_SUMMARY_RIDE_TICKETS,
STR_FINANCES_SUMMARY_SHOP_SALES,
STR_FINANCES_SUMMARY_SHOP_STOCK,
STR_FINANCES_SUMMARY_FOOD_DRINK_SALES,
STR_FINANCES_SUMMARY_FOOD_DRINK_STOCK,
STR_FINANCES_SUMMARY_STAFF_WAGES,
STR_FINANCES_SUMMARY_MARKETING,
STR_FINANCES_SUMMARY_RESEARCH,
STR_FINANCES_SUMMARY_LOAN_INTEREST,
};
2014-05-26 02:29:59 +02:00
static constexpr const int32_t _windowFinancesTabAnimationFrames[] = {
8, // WINDOW_FINANCES_PAGE_SUMMARY
16, // WINDOW_FINANCES_PAGE_FINANCIAL_GRAPH
16, // WINDOW_FINANCES_PAGE_VALUE_GRAPH
16, // WINDOW_FINANCES_PAGE_PROFIT_GRAPH
19, // WINDOW_FINANCES_PAGE_MARKETING
8, // WINDOW_FINANCES_PAGE_RESEARCH
};
static_assert(std::size(_windowFinancesTabAnimationFrames) == WINDOW_FINANCES_PAGE_COUNT);
static constexpr const int32_t EXPENDITURE_COLUMN_WIDTH = 80;
static constexpr const uint32_t _windowFinancesPageHoldDownWidgets[] = {
2022-10-17 19:21:18 +02:00
(1uLL << WIDX_LOAN_INCREASE) | (1uLL << WIDX_LOAN_DECREASE), // WINDOW_FINANCES_PAGE_SUMMARY
0, // WINDOW_FINANCES_PAGE_FINANCIAL_GRAPH
0, // WINDOW_FINANCES_PAGE_VALUE_GRAPH
0, // WINDOW_FINANCES_PAGE_PROFIT_GRAPH
0, // WINDOW_FINANCES_PAGE_MARKETING
0, // WINDOW_FINANCES_PAGE_RESEARCH
};
static_assert(std::size(_windowFinancesPageHoldDownWidgets) == WINDOW_FINANCES_PAGE_COUNT);
2017-09-05 20:55:18 +02:00
#pragma endregion
class FinancesWindow final : public Window
{
private:
int32_t _lastPaintedMonth;
public:
void OnOpen() override
{
SetPage(WINDOW_FINANCES_PAGE_SUMMARY);
_lastPaintedMonth = std::numeric_limits<int32_t>::max();
ResearchUpdateUncompletedTypes();
}
2014-05-26 02:29:59 +02:00
void OnUpdate() override
{
frame_no++;
InvalidateWidget(WIDX_TAB_1 + page);
}
2014-05-26 02:29:59 +02:00
2022-08-21 18:49:23 +02:00
void OnMouseDown(WidgetIndex widgetIndex) override
{
switch (page)
{
case WINDOW_FINANCES_PAGE_SUMMARY:
OnMouseDownSummary(widgetIndex);
break;
case WINDOW_FINANCES_PAGE_RESEARCH:
OnMouseDownResearch(widgetIndex);
break;
}
}
2022-08-21 18:49:23 +02:00
void OnMouseUp(WidgetIndex widgetIndex) override
2018-06-22 23:21:44 +02:00
{
switch (widgetIndex)
{
case WIDX_CLOSE:
Close();
break;
case WIDX_TAB_1:
case WIDX_TAB_2:
case WIDX_TAB_3:
case WIDX_TAB_4:
case WIDX_TAB_5:
case WIDX_TAB_6:
SetPage(widgetIndex - WIDX_TAB_1);
break;
default:
switch (page)
{
case WINDOW_FINANCES_PAGE_MARKETING:
OnMouseUpMarketing(widgetIndex);
break;
case WINDOW_FINANCES_PAGE_RESEARCH:
OnMouseUpResearch(widgetIndex);
}
break;
}
}
2014-05-26 02:29:59 +02:00
2022-08-21 18:49:23 +02:00
void OnDropdown(WidgetIndex widgetIndex, int32_t selectedIndex) override
{
if (page == WINDOW_FINANCES_PAGE_RESEARCH)
{
OnDropdownResearch(widgetIndex, selectedIndex);
}
}
2014-05-26 02:29:59 +02:00
void OnPrepareDraw() override
{
auto* targetWidgets = _windowFinancesPageWidgets[page];
if (widgets != targetWidgets)
{
widgets = targetWidgets;
WindowInitScrollWidgets(*this);
}
disabled_widgets = 0;
for (auto i = 0; i < WINDOW_FINANCES_PAGE_COUNT; i++)
SetWidgetPressed(WIDX_TAB_1 + i, false);
SetWidgetPressed(WIDX_TAB_1 + page, true);
switch (page)
{
case WINDOW_FINANCES_PAGE_SUMMARY:
OnPrepareDrawSummary();
break;
case WINDOW_FINANCES_PAGE_MARKETING:
OnPrepareDrawMarketing();
break;
case WINDOW_FINANCES_PAGE_RESEARCH:
OnPrepareDrawResearch();
break;
}
}
void OnDraw(DrawPixelInfo& dpi) override
{
DrawWidgets(dpi);
DrawTabImages(dpi);
switch (page)
{
case WINDOW_FINANCES_PAGE_SUMMARY:
OnDrawSummary(dpi);
break;
case WINDOW_FINANCES_PAGE_FINANCIAL_GRAPH:
OnDrawFinancialGraph(dpi);
break;
case WINDOW_FINANCES_PAGE_VALUE_GRAPH:
OnDrawParkValueGraph(dpi);
break;
case WINDOW_FINANCES_PAGE_PROFIT_GRAPH:
OnDrawProfitGraph(dpi);
break;
case WINDOW_FINANCES_PAGE_MARKETING:
OnDrawMarketing(dpi);
break;
case WINDOW_FINANCES_PAGE_RESEARCH:
OnDrawResearch(dpi);
break;
}
}
ScreenSize OnScrollGetSize(int32_t scrollIndex) override
2018-06-22 23:21:44 +02:00
{
if (page == WINDOW_FINANCES_PAGE_SUMMARY)
{
return { EXPENDITURE_COLUMN_WIDTH * (SummaryMaxAvailableMonth() + 1), 0 };
}
return {};
}
void OnScrollDraw(int32_t scrollIndex, DrawPixelInfo& dpi) override
{
if (page != WINDOW_FINANCES_PAGE_SUMMARY)
return;
auto screenCoords = ScreenCoordsXY{ 0, TABLE_CELL_HEIGHT + 2 };
2022-12-24 16:50:29 +01:00
Widget self = widgets[WIDX_SUMMARY_SCROLL];
int32_t row_width = std::max<uint16_t>(scrolls[0].h_right, self.width());
// Expenditure / Income row labels
for (int32_t i = 0; i < static_cast<int32_t>(ExpenditureType::Count); i++)
{
// Darken every even row
if (i % 2 == 0)
GfxFillRect(
&dpi,
{ screenCoords - ScreenCoordsXY{ 0, 1 },
screenCoords + ScreenCoordsXY{ row_width, (TABLE_CELL_HEIGHT - 2) } },
ColourMapA[colours[1]].lighter | 0x1000000);
screenCoords.y += TABLE_CELL_HEIGHT;
}
// Expenditure / Income values for each month
uint16_t currentMonthYear = static_cast<uint16_t>(gDateMonthsElapsed);
for (int32_t i = SummaryMaxAvailableMonth(); i >= 0; i--)
{
screenCoords.y = 0;
uint16_t monthyear = currentMonthYear - i;
// Month heading
auto ft = Formatter();
2022-07-31 14:22:58 +02:00
ft.Add<StringId>(STR_FINANCES_SUMMARY_MONTH_HEADING);
ft.Add<uint16_t>(monthyear);
DrawTextBasic(
2023-02-24 22:05:07 +01:00
dpi, screenCoords + ScreenCoordsXY{ EXPENDITURE_COLUMN_WIDTH, 0 },
monthyear == currentMonthYear ? STR_WINDOW_COLOUR_2_STRINGID : STR_BLACK_STRING, ft,
{ TextUnderline::On, TextAlignment::RIGHT });
screenCoords.y += 14;
// Month expenditures
money64 profit = 0;
for (int32_t j = 0; j < static_cast<int32_t>(ExpenditureType::Count); j++)
{
auto expenditure = gExpenditureTable[i][j];
if (expenditure != 0)
{
profit += expenditure;
2022-07-31 14:22:58 +02:00
const StringId format = expenditure >= 0 ? STR_FINANCES_SUMMARY_INCOME_VALUE
: STR_FINANCES_SUMMARY_EXPENDITURE_VALUE;
ft = Formatter();
ft.Add<money64>(expenditure);
DrawTextBasic(
2023-02-24 22:05:07 +01:00
dpi, screenCoords + ScreenCoordsXY{ EXPENDITURE_COLUMN_WIDTH, 0 }, format, ft,
{ TextAlignment::RIGHT });
}
screenCoords.y += TABLE_CELL_HEIGHT;
}
screenCoords.y += 4;
// Month profit
2022-07-31 14:22:58 +02:00
const StringId format = profit >= 0 ? STR_FINANCES_SUMMARY_INCOME_VALUE : STR_FINANCES_SUMMARY_LOSS_VALUE;
ft = Formatter();
ft.Add<money64>(profit);
DrawTextBasic(
2023-02-24 22:05:07 +01:00
dpi, screenCoords + ScreenCoordsXY{ EXPENDITURE_COLUMN_WIDTH, 0 }, format, ft, { TextAlignment::RIGHT });
GfxFillRect(
&dpi,
{ screenCoords + ScreenCoordsXY{ 10, -2 }, screenCoords + ScreenCoordsXY{ EXPENDITURE_COLUMN_WIDTH, -2 } },
PALETTE_INDEX_10);
screenCoords.x += EXPENDITURE_COLUMN_WIDTH;
}
_lastPaintedMonth = currentMonthYear;
}
void SetPage(int32_t p)
{
page = p;
frame_no = 0;
2014-08-09 15:47:58 +02:00
hold_down_widgets = _windowFinancesPageHoldDownWidgets[p];
pressed_widgets = 0;
widgets = _windowFinancesPageWidgets[p];
2014-05-26 02:29:59 +02:00
Invalidate();
if (p == WINDOW_FINANCES_PAGE_RESEARCH)
{
width = WW_RESEARCH;
height = WH_RESEARCH;
}
else if (p == WINDOW_FINANCES_PAGE_SUMMARY)
{
width = WW_OTHER_TABS;
height = WH_SUMMARY;
}
else
{
width = WW_OTHER_TABS;
height = WH_OTHER_TABS;
}
WindowEventResizeCall(this);
WindowEventInvalidateCall(this);
WindowInitScrollWidgets(*this);
// Scroll summary all the way to the right, initially.
if (p == WINDOW_FINANCES_PAGE_SUMMARY)
InitialiseScrollPosition(WIDX_SUMMARY_SCROLL, 0);
Invalidate();
}
#pragma region Summary Events
2022-08-21 18:49:23 +02:00
void OnMouseDownSummary(WidgetIndex widgetIndex)
2018-06-22 23:21:44 +02:00
{
switch (widgetIndex)
2018-06-22 23:21:44 +02:00
{
case WIDX_LOAN_INCREASE:
{
// If loan can be increased, do so.
// If not, action shows error message.
auto newLoan = gBankLoan + 1000.00_GBP;
if (gBankLoan < gMaxBankLoan)
{
newLoan = std::min(gMaxBankLoan, newLoan);
}
auto gameAction = ParkSetLoanAction(newLoan);
GameActions::Execute(&gameAction);
break;
}
case WIDX_LOAN_DECREASE:
{
// If loan is positive, decrease it.
// If loan is negative, action shows error message.
// If loan is exactly 0, prevent error message.
if (gBankLoan != 0)
{
auto newLoan = gBankLoan - 1000.00_GBP;
if (gBankLoan > 0)
{
newLoan = std::max(static_cast<money64>(0LL), newLoan);
}
auto gameAction = ParkSetLoanAction(newLoan);
GameActions::Execute(&gameAction);
}
break;
}
}
}
void OnPrepareDrawSummary()
2018-06-22 23:21:44 +02:00
{
// Setting loan widget's format arguments here.
// Nothing else should use the global formatter until
// drawing has completed.
auto ft = Formatter::Common();
ft.Increment(6);
ft.Add<money64>(gBankLoan);
// Keep up with new months being added in the first two years.
if (gDateMonthsElapsed != _lastPaintedMonth)
InitialiseScrollPosition(WIDX_SUMMARY_SCROLL, 0);
}
void OnDrawSummary(DrawPixelInfo& dpi)
{
auto screenCoords = windowPos + ScreenCoordsXY{ 8, 51 };
// Expenditure / Income heading
DrawTextBasic(
2023-02-24 22:05:07 +01:00
dpi, screenCoords, STR_FINANCES_SUMMARY_EXPENDITURE_INCOME, {},
{ COLOUR_BLACK, TextUnderline::On, TextAlignment::LEFT });
screenCoords.y += 14;
// Expenditure / Income row labels
for (int32_t i = 0; i < static_cast<int32_t>(ExpenditureType::Count); i++)
{
// Darken every even row
if (i % 2 == 0)
GfxFillRect(
&dpi,
{ screenCoords - ScreenCoordsXY{ 0, 1 }, screenCoords + ScreenCoordsXY{ 121, (TABLE_CELL_HEIGHT - 2) } },
ColourMapA[colours[1]].lighter | 0x1000000);
2023-02-24 22:05:07 +01:00
DrawTextBasic(dpi, screenCoords - ScreenCoordsXY{ 0, 1 }, _windowFinancesSummaryRowLabels[i]);
screenCoords.y += TABLE_CELL_HEIGHT;
}
// Horizontal rule below expenditure / income table
GfxFillRectInset(
&dpi, { windowPos + ScreenCoordsXY{ 8, 272 }, windowPos + ScreenCoordsXY{ 8 + 513, 272 + 1 } }, colours[1],
INSET_RECT_FLAG_BORDER_INSET);
// Loan and interest rate
2023-02-24 22:05:07 +01:00
DrawTextBasic(dpi, windowPos + ScreenCoordsXY{ 8, 279 }, STR_FINANCES_SUMMARY_LOAN);
if (!(gParkFlags & PARK_FLAGS_RCT1_INTEREST))
{
auto ft = Formatter();
ft.Add<uint16_t>(gBankLoanInterestRate);
2023-02-24 22:05:07 +01:00
DrawTextBasic(dpi, windowPos + ScreenCoordsXY{ 167, 279 }, STR_FINANCES_SUMMARY_AT_X_PER_YEAR, ft);
}
// Current cash
auto ft = Formatter();
ft.Add<money64>(gCash);
2022-07-31 14:22:58 +02:00
StringId stringId = gCash >= 0 ? STR_CASH_LABEL : STR_CASH_NEGATIVE_LABEL;
2023-02-24 22:05:07 +01:00
DrawTextBasic(dpi, windowPos + ScreenCoordsXY{ 8, 294 }, stringId, ft);
// Objective related financial information
if (gScenarioObjective.Type == OBJECTIVE_MONTHLY_FOOD_INCOME)
{
auto lastMonthProfit = FinanceGetLastMonthShopProfit();
ft = Formatter();
ft.Add<money64>(lastMonthProfit);
DrawTextBasic(
2023-02-24 22:05:07 +01:00
dpi, windowPos + ScreenCoordsXY{ 280, 279 }, STR_LAST_MONTH_PROFIT_FROM_FOOD_DRINK_MERCHANDISE_SALES_LABEL, ft);
}
else
{
// Park value and company value
ft = Formatter();
ft.Add<money64>(gParkValue);
2023-02-24 22:05:07 +01:00
DrawTextBasic(dpi, windowPos + ScreenCoordsXY{ 280, 279 }, STR_PARK_VALUE_LABEL, ft);
ft = Formatter();
ft.Add<money64>(gCompanyValue);
2023-02-24 22:05:07 +01:00
DrawTextBasic(dpi, windowPos + ScreenCoordsXY{ 280, 294 }, STR_COMPANY_VALUE_LABEL, ft);
}
}
uint16_t SummaryMaxAvailableMonth()
2018-06-22 23:21:44 +02:00
{
return std::min<uint16_t>(gDateMonthsElapsed, EXPENDITURE_TABLE_MONTH_COUNT - 1);
}
#pragma endregion
#pragma region Financial Graph Events
void OnDrawFinancialGraph(DrawPixelInfo& dpi)
{
2022-12-24 16:50:29 +01:00
Widget* pageWidget = &_windowFinancesCashWidgets[WIDX_PAGE_BACKGROUND];
auto graphTopLeft = windowPos + ScreenCoordsXY{ pageWidget->left + 4, pageWidget->top + 15 };
auto graphBottomRight = windowPos + ScreenCoordsXY{ pageWidget->right - 4, pageWidget->bottom - 4 };
// Cash (less loan)
auto cashLessLoan = gCash - gBankLoan;
auto ft = Formatter();
ft.Add<money64>(cashLessLoan);
DrawTextBasic(
2023-02-24 22:05:07 +01:00
dpi, graphTopLeft - ScreenCoordsXY{ 0, 11 },
cashLessLoan >= 0 ? STR_FINANCES_FINANCIAL_GRAPH_CASH_LESS_LOAN_POSITIVE
: STR_FINANCES_FINANCIAL_GRAPH_CASH_LESS_LOAN_NEGATIVE,
ft);
// Graph
GfxFillRectInset(&dpi, { graphTopLeft, graphBottomRight }, colours[1], INSET_RECT_F_30);
// Calculate the Y axis scale (log2 of highest [+/-]balance)
int32_t yAxisScale = 0;
for (int32_t i = 0; i < 64; i++)
2018-06-22 23:21:44 +02:00
{
auto balance = gCashHistory[i];
if (balance == MONEY64_UNDEFINED)
continue;
// Modifier balance then keep halving until less than 127 pixels
balance = std::abs(balance) >> yAxisScale;
while (balance > 127)
{
balance /= 2;
yAxisScale++;
}
}
// Y axis labels
auto coords = graphTopLeft + ScreenCoordsXY{ 18, 14 };
money64 axisBase;
for (axisBase = 12.00_GBP; axisBase >= -12.00_GBP; axisBase -= 6.00_GBP)
{
auto axisValue = axisBase << yAxisScale;
ft = Formatter();
ft.Add<money64>(axisValue);
DrawTextBasic(
2023-02-24 22:05:07 +01:00
dpi, coords + ScreenCoordsXY{ 70, 0 }, STR_FINANCES_FINANCIAL_GRAPH_CASH_VALUE, ft,
{ FontStyle::Small, TextAlignment::RIGHT });
GfxFillRectInset(
&dpi, { coords + ScreenCoordsXY{ 70, 5 }, { graphTopLeft.x + 482, coords.y + 5 } }, colours[2],
INSET_RECT_FLAG_BORDER_INSET);
coords.y += 39;
}
// X axis labels and values
coords = graphTopLeft + ScreenCoordsXY{ 98, 17 };
Graph::Draw(&dpi, gCashHistory, 64, coords, yAxisScale, 128);
}
#pragma endregion
#pragma region Park Value Graph Events
void OnDrawParkValueGraph(DrawPixelInfo& dpi)
{
2022-12-24 16:50:29 +01:00
Widget* pageWidget = &_windowFinancesCashWidgets[WIDX_PAGE_BACKGROUND];
auto graphTopLeft = windowPos + ScreenCoordsXY{ pageWidget->left + 4, pageWidget->top + 15 };
auto graphBottomRight = windowPos + ScreenCoordsXY{ pageWidget->right - 4, pageWidget->bottom - 4 };
// Park value
auto ft = Formatter();
ft.Add<money64>(gParkValue);
2023-02-24 22:05:07 +01:00
DrawTextBasic(dpi, graphTopLeft - ScreenCoordsXY{ 0, 11 }, STR_FINANCES_PARK_VALUE, ft);
// Graph
GfxFillRectInset(&dpi, { graphTopLeft, graphBottomRight }, colours[1], INSET_RECT_F_30);
// Calculate the Y axis scale (log2 of highest [+/-]balance)
int32_t yAxisScale = 0;
for (int32_t i = 0; i < 64; i++)
{
auto balance = gParkValueHistory[i];
if (balance == MONEY64_UNDEFINED)
continue;
// Modifier balance then keep halving until less than 255 pixels
balance = std::abs(balance) >> yAxisScale;
while (balance > 255)
{
balance /= 2;
yAxisScale++;
}
}
// Y axis labels
auto coords = graphTopLeft + ScreenCoordsXY{ 18, 14 };
money64 axisBase;
for (axisBase = 24.00_GBP; axisBase >= 0.00_GBP; axisBase -= 6.00_GBP)
2018-06-22 23:21:44 +02:00
{
auto axisValue = axisBase << yAxisScale;
ft = Formatter();
ft.Add<money64>(axisValue);
DrawTextBasic(
2023-02-24 22:05:07 +01:00
dpi, coords + ScreenCoordsXY{ 70, 0 }, STR_FINANCES_FINANCIAL_GRAPH_CASH_VALUE, ft,
{ FontStyle::Small, TextAlignment::RIGHT });
GfxFillRectInset(
&dpi, { coords + ScreenCoordsXY{ 70, 5 }, { graphTopLeft.x + 482, coords.y + 5 } }, colours[2],
INSET_RECT_FLAG_BORDER_INSET);
coords.y += 39;
}
// X axis labels and values
coords = graphTopLeft + ScreenCoordsXY{ 98, 17 };
Graph::Draw(&dpi, gParkValueHistory, 64, coords, yAxisScale, 0);
}
#pragma endregion
#pragma region Profit Graph Events
void OnDrawProfitGraph(DrawPixelInfo& dpi)
2018-06-22 23:21:44 +02:00
{
2022-12-24 16:50:29 +01:00
Widget* pageWidget = &_windowFinancesCashWidgets[WIDX_PAGE_BACKGROUND];
auto graphTopLeft = windowPos + ScreenCoordsXY{ pageWidget->left + 4, pageWidget->top + 15 };
auto graphBottomRight = windowPos + ScreenCoordsXY{ pageWidget->right - 4, pageWidget->bottom - 4 };
// Weekly profit
auto ft = Formatter();
ft.Add<money64>(gCurrentProfit);
DrawTextBasic(
2023-02-24 22:05:07 +01:00
dpi, graphTopLeft - ScreenCoordsXY{ 0, 11 },
gCurrentProfit >= 0 ? STR_FINANCES_WEEKLY_PROFIT_POSITIVE : STR_FINANCES_WEEKLY_PROFIT_LOSS, ft);
// Graph
GfxFillRectInset(&dpi, { graphTopLeft, graphBottomRight }, colours[1], INSET_RECT_F_30);
// Calculate the Y axis scale (log2 of highest [+/-]balance)
int32_t yAxisScale = 0;
for (int32_t i = 0; i < 64; i++)
{
auto balance = gWeeklyProfitHistory[i];
if (balance == MONEY64_UNDEFINED)
continue;
// Modifier balance then keep halving until less than 127 pixels
balance = std::abs(balance) >> yAxisScale;
while (balance > 127)
{
balance /= 2;
yAxisScale++;
}
}
// Y axis labels
auto screenPos = graphTopLeft + ScreenCoordsXY{ 18, 14 };
money64 axisBase;
for (axisBase = 12.00_GBP; axisBase >= -12.00_GBP; axisBase -= 6.00_GBP)
{
money64 axisValue = axisBase << yAxisScale;
ft = Formatter();
ft.Add<money64>(axisValue);
DrawTextBasic(
2023-02-24 22:05:07 +01:00
dpi, screenPos + ScreenCoordsXY{ 70, 0 }, STR_FINANCES_FINANCIAL_GRAPH_CASH_VALUE, ft,
{ FontStyle::Small, TextAlignment::RIGHT });
GfxFillRectInset(
&dpi, { screenPos + ScreenCoordsXY{ 70, 5 }, { graphTopLeft.x + 482, screenPos.y + 5 } }, colours[2],
INSET_RECT_FLAG_BORDER_INSET);
screenPos.y += 39;
}
// X axis labels and values
screenPos = graphTopLeft + ScreenCoordsXY{ 98, 17 };
Graph::Draw(&dpi, gWeeklyProfitHistory, 64, screenPos, yAxisScale, 128);
}
#pragma endregion
#pragma region Marketing Events
2022-08-21 18:49:23 +02:00
void OnMouseUpMarketing(WidgetIndex widgetIndex)
2018-06-22 23:21:44 +02:00
{
if (widgetIndex >= WIDX_CAMPAIGN_1 && widgetIndex <= WIDX_CAMPAIGN_6)
{
2022-11-06 21:49:07 +01:00
ContextOpenDetailWindow(WD_NEW_CAMPAIGN, widgetIndex - WIDX_CAMPAIGN_1);
}
}
void OnPrepareDrawMarketing()
2018-06-22 23:21:44 +02:00
{
// Count number of active campaigns
int32_t numActiveCampaigns = static_cast<int32_t>(gMarketingCampaigns.size());
int32_t y = std::max(1, numActiveCampaigns) * LIST_ROW_HEIGHT + 92;
// Update group box positions
_windowFinancesMarketingWidgets[WIDX_ACTIVE_CAMPAIGNS_GROUP].bottom = y - 22;
_windowFinancesMarketingWidgets[WIDX_CAMPAIGNS_AVAILABLE_GROUP].top = y - 13;
// Update new campaign button visibility
y += 3;
for (int32_t i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++)
2018-06-22 23:21:44 +02:00
{
auto campaignButton = &_windowFinancesMarketingWidgets[WIDX_CAMPAIGN_1 + i];
auto marketingCampaign = MarketingGetCampaign(i);
if (marketingCampaign == nullptr && MarketingIsCampaignTypeApplicable(i))
{
campaignButton->type = WindowWidgetType::Button;
campaignButton->top = y;
campaignButton->bottom = y + BUTTON_FACE_HEIGHT + 1;
y += BUTTON_FACE_HEIGHT + 2;
}
else
{
campaignButton->type = WindowWidgetType::Empty;
}
}
}
void OnDrawMarketing(DrawPixelInfo& dpi)
{
auto screenCoords = windowPos + ScreenCoordsXY{ 8, 62 };
int32_t noCampaignsActive = 1;
for (int32_t i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++)
{
auto marketingCampaign = MarketingGetCampaign(i);
if (marketingCampaign == nullptr)
continue;
noCampaignsActive = 0;
auto ft = Formatter();
// Set special parameters
switch (i)
{
case ADVERTISING_CAMPAIGN_RIDE_FREE:
case ADVERTISING_CAMPAIGN_RIDE:
{
auto campaignRide = GetRide(marketingCampaign->RideId);
if (campaignRide != nullptr)
{
campaignRide->FormatNameTo(ft);
}
else
{
2022-07-31 14:22:58 +02:00
ft.Add<StringId>(STR_NONE);
}
break;
}
case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE:
2022-07-31 14:22:58 +02:00
ft.Add<StringId>(GetShopItemDescriptor(marketingCampaign->ShopItemType).Naming.Plural);
break;
default:
{
auto& park = OpenRCT2::GetContext()->GetGameState()->GetPark();
auto parkName = park.Name.c_str();
2022-07-31 14:22:58 +02:00
ft.Add<StringId>(STR_STRING);
ft.Add<const char*>(parkName);
}
}
// Advertisement
2023-02-24 22:05:07 +01:00
DrawTextEllipsised(dpi, screenCoords + ScreenCoordsXY{ 4, 0 }, 296, MarketingCampaignNames[i][1], ft);
// Duration
uint16_t weeksRemaining = marketingCampaign->WeeksLeft;
ft = Formatter();
ft.Add<uint16_t>(weeksRemaining);
DrawTextBasic(
2023-02-24 22:05:07 +01:00
dpi, screenCoords + ScreenCoordsXY{ 304, 0 },
weeksRemaining == 1 ? STR_1_WEEK_REMAINING : STR_X_WEEKS_REMAINING, ft);
screenCoords.y += LIST_ROW_HEIGHT;
}
if (noCampaignsActive)
{
2023-02-24 22:05:07 +01:00
DrawTextBasic(dpi, screenCoords + ScreenCoordsXY{ 4, 0 }, STR_MARKETING_CAMPAIGNS_NONE);
screenCoords.y += LIST_ROW_HEIGHT;
}
screenCoords.y += 34;
// Draw campaign button text
for (int32_t i = 0; i < ADVERTISING_CAMPAIGN_COUNT; i++)
{
auto campaignButton = &_windowFinancesMarketingWidgets[WIDX_CAMPAIGN_1 + i];
if (campaignButton->type != WindowWidgetType::Empty)
{
// Draw button text
2023-02-24 22:05:07 +01:00
DrawTextBasic(dpi, screenCoords + ScreenCoordsXY{ 4, 0 }, MarketingCampaignNames[i][0]);
auto ft = Formatter();
ft.Add<money64>(AdvertisingCampaignPricePerWeek[i]);
2023-02-24 22:05:07 +01:00
DrawTextBasic(dpi, screenCoords + ScreenCoordsXY{ WH_SUMMARY, 0 }, STR_MARKETING_PER_WEEK, ft);
screenCoords.y += BUTTON_FACE_HEIGHT + 2;
}
}
}
#pragma endregion
#pragma region Research Events
2022-08-21 18:49:23 +02:00
void OnMouseUpResearch(WidgetIndex widgetIndex)
2018-06-22 23:21:44 +02:00
{
if (widgetIndex >= WIDX_TRANSPORT_RIDES && widgetIndex <= WIDX_SCENERY_AND_THEMING)
{
auto activeResearchTypes = gResearchPriorities;
2022-10-17 19:21:18 +02:00
activeResearchTypes ^= 1uLL << (widgetIndex - WIDX_TRANSPORT_RIDES);
auto gameAction = ParkSetResearchFundingAction(activeResearchTypes, gResearchFundingLevel);
GameActions::Execute(&gameAction);
}
}
2022-08-21 18:49:23 +02:00
void OnMouseDownResearch(WidgetIndex widgetIndex)
2018-06-22 23:21:44 +02:00
{
if (widgetIndex != WIDX_RESEARCH_FUNDING_DROPDOWN_BUTTON)
return;
2022-12-24 16:50:29 +01:00
Widget* dropdownWidget = &widgets[widgetIndex - 1];
2014-08-12 23:22:16 +02:00
for (std::size_t i = 0; i < std::size(ResearchFundingLevelNames); i++)
{
gDropdownItems[i].Format = STR_DROPDOWN_MENU_LABEL;
gDropdownItems[i].Args = ResearchFundingLevelNames[i];
}
2014-08-12 23:22:16 +02:00
WindowDropdownShowTextCustomWidth(
{ windowPos.x + dropdownWidget->left, windowPos.y + dropdownWidget->top }, dropdownWidget->height() + 1, colours[1],
0, Dropdown::Flag::StayOpen, 4, dropdownWidget->width() - 3);
2014-08-12 23:22:16 +02:00
int32_t currentResearchLevel = gResearchFundingLevel;
Dropdown::SetChecked(currentResearchLevel, true);
}
2022-08-21 18:49:23 +02:00
void OnDropdownResearch(WidgetIndex widgetIndex, int32_t selectedIndex)
{
if (widgetIndex != WIDX_RESEARCH_FUNDING_DROPDOWN_BUTTON || selectedIndex == -1)
return;
auto gameAction = ParkSetResearchFundingAction(gResearchPriorities, selectedIndex);
GameActions::Execute(&gameAction);
}
void OnPrepareDrawResearch()
2018-06-22 23:21:44 +02:00
{
if (gResearchProgressStage == RESEARCH_STAGE_FINISHED_ALL)
2018-06-22 23:21:44 +02:00
{
_windowFinancesResearchWidgets[WIDX_RESEARCH_FUNDING].type = WindowWidgetType::Empty;
_windowFinancesResearchWidgets[WIDX_RESEARCH_FUNDING_DROPDOWN_BUTTON].type = WindowWidgetType::Empty;
2018-06-22 23:21:44 +02:00
}
else
{
_windowFinancesResearchWidgets[WIDX_RESEARCH_FUNDING].type = WindowWidgetType::DropdownMenu;
_windowFinancesResearchWidgets[WIDX_RESEARCH_FUNDING_DROPDOWN_BUTTON].type = WindowWidgetType::Button;
}
int32_t currentResearchLevel = gResearchFundingLevel;
2014-08-12 23:22:16 +02:00
// Current funding
_windowFinancesResearchWidgets[WIDX_RESEARCH_FUNDING].text = ResearchFundingLevelNames[currentResearchLevel];
2014-08-12 23:22:16 +02:00
// Checkboxes
uint8_t activeResearchTypes = gResearchPriorities;
int32_t uncompletedResearchTypes = gResearchUncompletedCategories;
for (int32_t i = 0; i < 7; i++)
{
int32_t mask = 1 << i;
2022-10-17 19:21:18 +02:00
int32_t widgetMask = 1uLL << (i + WIDX_TRANSPORT_RIDES);
// Set checkbox disabled if research type is complete
if (uncompletedResearchTypes & mask)
{
disabled_widgets &= ~widgetMask;
2014-05-26 02:29:59 +02:00
// Set checkbox ticked if research type is active
if (activeResearchTypes & mask)
pressed_widgets |= widgetMask;
else
pressed_widgets &= ~widgetMask;
}
else
{
disabled_widgets |= widgetMask;
pressed_widgets &= ~widgetMask;
}
}
2018-06-22 23:21:44 +02:00
}
void OnDrawResearch(DrawPixelInfo& dpi)
2018-06-22 23:21:44 +02:00
{
WindowResearchFundingPagePaint(this, &dpi, WIDX_RESEARCH_FUNDING);
}
#pragma endregion
2014-05-26 02:29:59 +02:00
2022-08-21 18:49:23 +02:00
void InitialiseScrollPosition(WidgetIndex widgetIndex, int32_t scrollId)
{
const auto& widget = this->widgets[widgetIndex];
scrolls[scrollId].h_left = std::max(0, scrolls[scrollId].h_right - (widget.width() - 2));
2014-05-26 02:29:59 +02:00
WidgetScrollUpdateThumbs(*this, widgetIndex);
}
void DrawTabImage(DrawPixelInfo& dpi, int32_t tabPage, int32_t spriteIndex)
2018-06-22 23:21:44 +02:00
{
2022-08-21 18:49:23 +02:00
WidgetIndex widgetIndex = WIDX_TAB_1 + tabPage;
if (!IsWidgetDisabled(widgetIndex))
2018-06-22 23:21:44 +02:00
{
if (this->page == tabPage)
{
int32_t frame = frame_no / 2;
spriteIndex += (frame % _windowFinancesTabAnimationFrames[this->page]);
}
GfxDrawSprite(
&dpi, ImageId(spriteIndex), windowPos + ScreenCoordsXY{ widgets[widgetIndex].left, widgets[widgetIndex].top });
}
}
void DrawTabImages(DrawPixelInfo& dpi)
{
DrawTabImage(dpi, WINDOW_FINANCES_PAGE_SUMMARY, SPR_TAB_FINANCES_SUMMARY_0);
DrawTabImage(dpi, WINDOW_FINANCES_PAGE_FINANCIAL_GRAPH, SPR_TAB_FINANCES_FINANCIAL_GRAPH_0);
DrawTabImage(dpi, WINDOW_FINANCES_PAGE_VALUE_GRAPH, SPR_TAB_FINANCES_VALUE_GRAPH_0);
DrawTabImage(dpi, WINDOW_FINANCES_PAGE_PROFIT_GRAPH, SPR_TAB_FINANCES_PROFIT_GRAPH_0);
DrawTabImage(dpi, WINDOW_FINANCES_PAGE_MARKETING, SPR_TAB_FINANCES_MARKETING_0);
DrawTabImage(dpi, WINDOW_FINANCES_PAGE_RESEARCH, SPR_TAB_FINANCES_RESEARCH_0);
}
};
2014-08-09 15:47:58 +02:00
static FinancesWindow* FinancesWindowOpen(uint8_t page)
{
auto* window = WindowFocusOrCreate<FinancesWindow>(WindowClass::Finances, WW_OTHER_TABS, WH_SUMMARY, WF_10);
if (window != nullptr && page != WINDOW_FINANCES_PAGE_SUMMARY)
window->SetPage(page);
return window;
}
WindowBase* WindowFinancesOpen()
2014-08-09 15:47:58 +02:00
{
return WindowFocusOrCreate<FinancesWindow>(WindowClass::Finances, WW_OTHER_TABS, WH_SUMMARY, WF_10);
2014-08-09 15:47:58 +02:00
}
WindowBase* WindowFinancesResearchOpen()
{
return FinancesWindowOpen(WINDOW_FINANCES_PAGE_RESEARCH);
}
WindowBase* WindowFinancesMarketingOpen()
{
return FinancesWindowOpen(WINDOW_FINANCES_PAGE_MARKETING);
}