From d907c58a138c19f5b81a63736a9be7fe617dfb9c Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 10 Jan 2021 11:41:55 +0000 Subject: [PATCH] Start window refactor framework --- src/openrct2-ui/interface/Window.cpp | 79 +- src/openrct2-ui/interface/Window.h | 12 + src/openrct2-ui/windows/Cheats.cpp | 1586 +++++++++++----------- src/openrct2/interface/Window.cpp | 142 +- src/openrct2/interface/Window.h | 32 +- src/openrct2/interface/Window_internal.h | 103 +- 6 files changed, 1033 insertions(+), 921 deletions(-) diff --git a/src/openrct2-ui/interface/Window.cpp b/src/openrct2-ui/interface/Window.cpp index c437c33629..3ed26793a7 100644 --- a/src/openrct2-ui/interface/Window.cpp +++ b/src/openrct2-ui/interface/Window.cpp @@ -87,8 +87,8 @@ static bool WindowFitsOnScreen(const ScreenCoordsXY& loc, int32_t width, int32_t } rct_window* WindowCreate( - const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, rct_window_event_list* event_handlers, - rct_windowclass cls, uint16_t flags) + std::unique_ptr&& wp, rct_windowclass cls, const ScreenCoordsXY& pos, int32_t width, int32_t height, + uint16_t flags) { // Check if there are any window slots left // include WINDOW_LIMIT_RESERVED for items such as the main viewport and toolbars to not appear to be counted. @@ -129,7 +129,7 @@ rct_window* WindowCreate( } } - auto itNew = g_window_list.insert(itDestPos, std::make_unique()); + auto itNew = g_window_list.insert(itDestPos, std::move(wp)); auto w = itNew->get(); // Setup window @@ -140,23 +140,17 @@ rct_window* WindowCreate( if (!(flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT))) { w->flags |= WF_WHITE_BORDER_MASK; - OpenRCT2::Audio::Play(OpenRCT2::Audio::SoundId::WindowOpen, 0, screenCoords.x + (width / 2)); + OpenRCT2::Audio::Play(OpenRCT2::Audio::SoundId::WindowOpen, 0, pos.x + (width / 2)); } - w->number = 0; - w->windowPos = screenCoords; + w->windowPos = pos; w->width = width; w->height = height; w->min_width = width; w->max_width = width; w->min_height = height; w->max_height = height; - w->viewport = nullptr; - w->event_handlers = event_handlers; - w->enabled_widgets = 0; - w->disabled_widgets = 0; - w->pressed_widgets = 0; - w->hold_down_widgets = 0; + w->viewport_focus_coordinates.var_480 = 0; w->viewport_focus_coordinates.x = 0; w->viewport_focus_coordinates.y = 0; @@ -164,18 +158,23 @@ rct_window* WindowCreate( w->viewport_focus_coordinates.rotation = 0; w->page = 0; w->var_48C = 0; - w->frame_no = 0; - w->list_information_type = 0; w->var_492 = 0; - w->selected_tab = 0; - w->var_4AE = 0; - w->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; ColourSchemeUpdate(w); w->Invalidate(); + w->OnOpen(); return w; } +rct_window* WindowCreate( + const ScreenCoordsXY& pos, int32_t width, int32_t height, rct_window_event_list* event_handlers, rct_windowclass cls, + uint16_t flags) +{ + auto w = std::make_unique(); + w->event_handlers = event_handlers; + return WindowCreate(std::move(w), cls, pos, width, height, flags); +} + static ScreenCoordsXY ClampWindowToScreen(const ScreenCoordsXY& pos, const int32_t screenWidth, const int32_t width) { auto screenPos = pos; @@ -654,3 +653,49 @@ void InvalidateAllWindowsAfterInput() window_event_resize_call(w); }); } + +void Window::InvalidateWidget(rct_widgetindex widgetIndex) +{ + widget_invalidate(this, widgetIndex); +} + +bool Window::IsWidgetDisabled(rct_widgetindex widgetIndex) const +{ + return (disabled_widgets & (1LL << widgetIndex)) != 0; +} + +bool Window::IsWidgetPressed(rct_widgetindex widgetIndex) const +{ + return (pressed_widgets & (1LL << widgetIndex)) != 0; +} + +void Window::SetWidgetDisabled(rct_widgetindex widgetIndex, bool value) +{ + if (value) + disabled_widgets |= (1ULL << widgetIndex); + else + disabled_widgets &= ~(1ULL << widgetIndex); +} + +void Window::SetWidgetPressed(rct_widgetindex widgetIndex, bool value) +{ + if (value) + pressed_widgets |= (1ULL << widgetIndex); + else + pressed_widgets &= ~(1ULL << widgetIndex); +} + +void Window::SetCheckboxValue(rct_widgetindex widgetIndex, bool value) +{ + SetWidgetPressed(widgetIndex, value); +} + +void Window::DrawWidgets(rct_drawpixelinfo& dpi) +{ + WindowDrawWidgets(this, &dpi); +} + +void Window::Close() +{ + window_close(this); +} diff --git a/src/openrct2-ui/interface/Window.h b/src/openrct2-ui/interface/Window.h index cf96f4192d..ee1de33ffa 100644 --- a/src/openrct2-ui/interface/Window.h +++ b/src/openrct2-ui/interface/Window.h @@ -12,5 +12,17 @@ #include #include +struct Window : rct_window +{ + void InvalidateWidget(rct_widgetindex widgetIndex); + bool IsWidgetDisabled(rct_widgetindex widgetIndex) const; + bool IsWidgetPressed(rct_widgetindex widgetIndex) const; + void SetWidgetDisabled(rct_widgetindex widgetIndex, bool value); + void SetWidgetPressed(rct_widgetindex widgetIndex, bool value); + void SetCheckboxValue(rct_widgetindex widgetIndex, bool value); + void DrawWidgets(rct_drawpixelinfo& dpi); + void Close(); +}; + void WindowAllWheelInput(); void ApplyScreenSaverLockSetting(); diff --git a/src/openrct2-ui/windows/Cheats.cpp b/src/openrct2-ui/windows/Cheats.cpp index c4c34a6998..39cc90b0e4 100644 --- a/src/openrct2-ui/windows/Cheats.cpp +++ b/src/openrct2-ui/windows/Cheats.cpp @@ -29,13 +29,6 @@ #define CHEATS_MONEY_DEFAULT MONEY(10000, 00) #define CHEATS_MONEY_INCREMENT_DIV MONEY(5000, 00) -static utf8 _moneySpinnerText[MONEY_STRING_MAXLENGTH]; -static money32 _moneySpinnerValue = CHEATS_MONEY_DEFAULT; -static int32_t _selectedStaffSpeed = 1; -static int32_t _parkRatingSpinnerValue; -static int32_t _yearSpinnerValue = 1; -static int32_t _monthSpinnerValue = 1; -static int32_t _daySpinnerValue = 1; // clang-format off enum @@ -44,6 +37,7 @@ enum WINDOW_CHEATS_PAGE_GUESTS, WINDOW_CHEATS_PAGE_MISC, WINDOW_CHEATS_PAGE_RIDES, + WINDOW_CHEATS_PAGE_COUNT, }; static rct_string_id _staffSpeedNames[] = @@ -324,66 +318,6 @@ static rct_widget *window_cheats_page_widgets[] = window_cheats_rides_widgets, }; -static void window_cheats_money_mouseup(rct_window *w, rct_widgetindex widgetIndex); -static void window_cheats_money_mousedown(rct_window *w, rct_widgetindex widgetIndex, rct_widget* widget); -static void window_cheats_misc_mousedown(rct_window *w, rct_widgetindex widgetIndex, rct_widget* widget); -static void window_cheats_misc_dropdown(rct_window *w, rct_widgetindex widgetIndex, int32_t dropdownIndex); -static void window_cheats_guests_mouseup(rct_window *w, rct_widgetindex widgetIndex); -static void window_cheats_misc_mouseup(rct_window *w, rct_widgetindex widgetIndex); -static void window_cheats_rides_mouseup(rct_window *w, rct_widgetindex widgetIndex); -static OpenRCT2String window_cheats_rides_tooltip(rct_window* const w, rct_widgetindex widgetIndex, rct_string_id fallback); -static void window_cheats_update(rct_window *w); -static void window_cheats_invalidate(rct_window *w); -static void window_cheats_paint(rct_window *w, rct_drawpixelinfo *dpi); -static void window_cheats_set_page(rct_window *w, int32_t page); -static void window_cheats_text_input(rct_window *w, rct_widgetindex widgetIndex, char *text); - -static rct_window_event_list window_cheats_money_events([](auto& events) -{ - events.mouse_up = &window_cheats_money_mouseup; - events.mouse_down = &window_cheats_money_mousedown; - events.update = &window_cheats_update; - events.text_input = &window_cheats_text_input; - events.invalidate = &window_cheats_invalidate; - events.paint = &window_cheats_paint; -}); - -static rct_window_event_list window_cheats_guests_events([](auto& events) -{ - events.mouse_up = &window_cheats_guests_mouseup; - events.update = &window_cheats_update; - events.invalidate = &window_cheats_invalidate; - events.paint = &window_cheats_paint; -}); - -static rct_window_event_list window_cheats_misc_events([](auto& events) -{ - events.mouse_up = &window_cheats_misc_mouseup; - events.mouse_down = &window_cheats_misc_mousedown; - events.dropdown = &window_cheats_misc_dropdown; - events.update = &window_cheats_update; - events.invalidate = &window_cheats_invalidate; - events.paint = &window_cheats_paint; -}); - -static rct_window_event_list window_cheats_rides_events([](auto& events) -{ - events.mouse_up = &window_cheats_rides_mouseup; - events.update = &window_cheats_update; - events.tooltip = &window_cheats_rides_tooltip; - events.invalidate = &window_cheats_invalidate; - events.paint = &window_cheats_paint; -}); - - -static rct_window_event_list *window_cheats_page_events[] = -{ - &window_cheats_money_events, - &window_cheats_guests_events, - &window_cheats_misc_events, - &window_cheats_rides_events, -}; - #define MAIN_CHEAT_ENABLED_WIDGETS (1ULL << WIDX_CLOSE) | (1ULL << WIDX_TAB_1) | (1ULL << WIDX_TAB_2) | (1ULL << WIDX_TAB_3) | (1ULL << WIDX_TAB_4) static uint64_t window_cheats_page_enabled_widgets[] = { @@ -509,757 +443,777 @@ static rct_string_id window_cheats_page_titles[] = { }; // clang-format on -static void window_cheats_draw_tab_images(rct_drawpixelinfo* dpi, rct_window* w); +class CheatsWindow final : public Window +{ +private: + char _moneySpinnerText[MONEY_STRING_MAXLENGTH]; + money32 _moneySpinnerValue = CHEATS_MONEY_DEFAULT; + int32_t _selectedStaffSpeed = 1; + int32_t _parkRatingSpinnerValue; + int32_t _yearSpinnerValue = 1; + int32_t _monthSpinnerValue = 1; + int32_t _daySpinnerValue = 1; + +public: + void OnOpen() override + { + SetPage(WINDOW_CHEATS_PAGE_MONEY); + _parkRatingSpinnerValue = get_forced_park_rating() >= 0 ? get_forced_park_rating() : 999; + } + + void OnUpdate() override + { + frame_no++; + InvalidateWidget(WIDX_TAB_1 + page); + } + + void OnMouseDown(rct_widgetindex widgetIndex) override + { + switch (page) + { + case WINDOW_CHEATS_PAGE_MONEY: + OnMouseDownMoney(widgetIndex); + break; + case WINDOW_CHEATS_PAGE_MISC: + OnMouseDownMisc(widgetIndex); + break; + } + } + + void OnMouseUp(rct_widgetindex widgetIndex) override + { + switch (widgetIndex) + { + case WIDX_CLOSE: + Close(); + break; + case WIDX_TAB_1: + case WIDX_TAB_2: + case WIDX_TAB_3: + case WIDX_TAB_4: + SetPage(widgetIndex - WIDX_TAB_1); + break; + default: + switch (page) + { + case WINDOW_CHEATS_PAGE_MONEY: + OnMouseUpMoney(widgetIndex); + break; + case WINDOW_CHEATS_PAGE_GUESTS: + OnMouseUpGuests(widgetIndex); + break; + case WINDOW_CHEATS_PAGE_MISC: + OnMouseUpMisc(widgetIndex); + break; + case WINDOW_CHEATS_PAGE_RIDES: + OnMouseUpRides(widgetIndex); + break; + } + break; + } + } + + void OnDropdown(rct_widgetindex widgetIndex, int32_t selectedIndex) override + { + if (page == WINDOW_CHEATS_PAGE_MISC) + { + OnDropdownMisc(widgetIndex, selectedIndex); + } + } + + void OnPrepareDraw() override + { + auto* targetWidgets = window_cheats_page_widgets[page]; + if (widgets != targetWidgets) + { + widgets = targetWidgets; + WindowInitScrollWidgets(this); + } + + pressed_widgets = 0; + disabled_widgets = 0; + + // Set correct active tab + for (auto i = 0; i < WINDOW_CHEATS_PAGE_COUNT; i++) + SetWidgetPressed(WIDX_TAB_1 + i, false); + SetWidgetPressed(WIDX_TAB_1 + page, false); + + // Set title + widgets[WIDX_TITLE].text = window_cheats_page_titles[page]; + + switch (page) + { + case WINDOW_CHEATS_PAGE_MONEY: + { + auto moneyEnabled = (gParkFlags & PARK_FLAGS_NO_MONEY) != 0; + SetCheckboxValue(WIDX_NO_MONEY, !moneyEnabled); + SetWidgetDisabled(WIDX_ADD_SET_MONEY_GROUP, moneyEnabled); + SetWidgetDisabled(WIDX_MONEY_SPINNER, moneyEnabled); + SetWidgetDisabled(WIDX_MONEY_SPINNER_INCREMENT, moneyEnabled); + SetWidgetDisabled(WIDX_MONEY_SPINNER_DECREMENT, moneyEnabled); + SetWidgetDisabled(WIDX_ADD_MONEY, moneyEnabled); + SetWidgetDisabled(WIDX_SET_MONEY, moneyEnabled); + SetWidgetDisabled(WIDX_CLEAR_LOAN, moneyEnabled); + break; + } + case WINDOW_CHEATS_PAGE_GUESTS: + { + auto ft = Formatter::Common(); + ft.Add(MONEY(1000, 00)); + SetCheckboxValue(WIDX_GUEST_IGNORE_RIDE_INTENSITY, gCheatsIgnoreRideIntensity); + SetCheckboxValue(WIDX_DISABLE_VANDALISM, gCheatsDisableVandalism); + SetCheckboxValue(WIDX_DISABLE_LITTERING, gCheatsDisableLittering); + break; + } + case WINDOW_CHEATS_PAGE_MISC: + widgets[WIDX_OPEN_CLOSE_PARK].text = (gParkFlags & PARK_FLAGS_PARK_OPEN) ? STR_CHEAT_CLOSE_PARK + : STR_CHEAT_OPEN_PARK; + SetCheckboxValue(WIDX_FORCE_PARK_RATING, get_forced_park_rating() >= 0); + SetCheckboxValue(WIDX_FREEZE_WEATHER, gCheatsFreezeWeather); + SetCheckboxValue(WIDX_NEVERENDING_MARKETING, gCheatsNeverendingMarketing); + SetCheckboxValue(WIDX_DISABLE_PLANT_AGING, gCheatsDisablePlantAging); + break; + case WINDOW_CHEATS_PAGE_RIDES: + SetCheckboxValue(WIDX_FAST_LIFT_HILL, gCheatsFastLiftHill); + SetCheckboxValue(WIDX_DISABLE_BRAKES_FAILURE, gCheatsDisableBrakesFailure); + SetCheckboxValue(WIDX_DISABLE_ALL_BREAKDOWNS, gCheatsDisableAllBreakdowns); + SetCheckboxValue(WIDX_BUILD_IN_PAUSE_MODE, gCheatsBuildInPauseMode); + SetCheckboxValue(WIDX_SHOW_ALL_OPERATING_MODES, gCheatsShowAllOperatingModes); + SetCheckboxValue(WIDX_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES, gCheatsShowVehiclesFromOtherTrackTypes); + SetCheckboxValue(WIDX_DISABLE_TRAIN_LENGTH_LIMITS, gCheatsDisableTrainLengthLimit); + SetCheckboxValue(WIDX_ENABLE_CHAIN_LIFT_ON_ALL_TRACK, gCheatsEnableChainLiftOnAllTrack); + SetCheckboxValue(WIDX_ENABLE_ARBITRARY_RIDE_TYPE_CHANGES, gCheatsAllowArbitraryRideTypeChanges); + SetCheckboxValue(WIDX_DISABLE_RIDE_VALUE_AGING, gCheatsDisableRideValueAging); + SetCheckboxValue(WIDX_IGNORE_RESEARCH_STATUS, gCheatsIgnoreResearchStatus); + SetCheckboxValue(WIDX_ENABLE_ALL_DRAWABLE_TRACK_PIECES, gCheatsEnableAllDrawableTrackPieces); + SetCheckboxValue(WIDX_ALLOW_TRACK_PLACE_INVALID_HEIGHTS, gCheatsAllowTrackPlaceInvalidHeights); + break; + } + + // Current weather + window_cheats_misc_widgets[WIDX_WEATHER].text = WeatherTypes[EnumValue(gClimateCurrent.Weather)]; + // Staff speed + window_cheats_misc_widgets[WIDX_STAFF_SPEED].text = _staffSpeedNames[_selectedStaffSpeed]; + + if (gScreenFlags & SCREEN_FLAGS_EDITOR) + { + SetWidgetDisabled(WIDX_TAB_2, true); + SetWidgetDisabled(WIDX_TAB_3, true); + SetWidgetDisabled(WIDX_NO_MONEY, true); + } + } + + void OnDraw(rct_drawpixelinfo& dpi) override + { + UpdateTabPositions(); + DrawWidgets(dpi); + DrawTabImages(dpi); + + static constexpr int16_t X_LCOL = 14; + static constexpr int16_t X_RCOL = 208; + + if (page == WINDOW_CHEATS_PAGE_MONEY) + { + uint8_t colour = colours[1]; + auto ft = Formatter(); + ft.Add(_moneySpinnerValue); + if (IsWidgetDisabled(WIDX_MONEY_SPINNER)) + { + colour |= COLOUR_FLAG_INSET; + } + int32_t actual_month = _monthSpinnerValue - 1; + gfx_draw_string_left(&dpi, STR_BOTTOM_TOOLBAR_CASH, ft.Data(), colour, windowPos + ScreenCoordsXY{ X_LCOL, 93 }); + gfx_draw_string_left(&dpi, STR_YEAR, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL, 198 }); + gfx_draw_string_left(&dpi, STR_MONTH, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL, 219 }); + gfx_draw_string_left(&dpi, STR_DAY, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL, 240 }); + ft = Formatter(); + ft.Add(_yearSpinnerValue); + DrawTextBasic( + &dpi, windowPos + ScreenCoordsXY{ X_RCOL, 198 }, STR_FORMAT_INTEGER, ft, colours[1], TextAlignment::RIGHT); + ft = Formatter(); + ft.Add(actual_month); + DrawTextBasic( + &dpi, windowPos + ScreenCoordsXY{ X_RCOL, 219 }, STR_FORMAT_MONTH, ft, colours[1], TextAlignment::RIGHT); + ft = Formatter(); + ft.Add(_daySpinnerValue); + DrawTextBasic( + &dpi, windowPos + ScreenCoordsXY{ X_RCOL, 240 }, STR_FORMAT_INTEGER, ft, colours[1], TextAlignment::RIGHT); + } + else if (page == WINDOW_CHEATS_PAGE_MISC) + { + { + auto& widget = widgets[WIDX_WEATHER]; + gfx_draw_string_left( + &dpi, STR_CHANGE_WEATHER, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL - 3, widget.top + 1 }); + } + + { + auto ft = Formatter(); + ft.Add(_parkRatingSpinnerValue); + + auto& widget = widgets[WIDX_PARK_RATING_SPINNER]; + DrawTextBasic( + &dpi, windowPos + ScreenCoordsXY{ widget.left + 1, widget.top + 2 }, STR_FORMAT_INTEGER, ft, colours[1]); + } + + { + auto& widget = widgets[WIDX_STAFF_SPEED]; + gfx_draw_string_left( + &dpi, STR_CHEAT_STAFF_SPEED, nullptr, COLOUR_BLACK, + windowPos + ScreenCoordsXY{ X_LCOL - 3, widget.top + 1 }); + } + } + else if (page == WINDOW_CHEATS_PAGE_GUESTS) + { + gfx_draw_string_left( + &dpi, STR_CHEAT_GUEST_HAPPINESS, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL, 72 }); + gfx_draw_string_left(&dpi, STR_CHEAT_GUEST_ENERGY, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL, 93 }); + gfx_draw_string_left( + &dpi, STR_CHEAT_GUEST_HUNGER, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL, 114 }); + gfx_draw_string_left( + &dpi, STR_CHEAT_GUEST_THIRST, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL, 135 }); + gfx_draw_string_left( + &dpi, STR_CHEAT_GUEST_NAUSEA, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL, 156 }); + gfx_draw_string_left( + &dpi, STR_CHEAT_GUEST_NAUSEA_TOLERANCE, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL, 177 }); + gfx_draw_string_left( + &dpi, STR_CHEAT_GUEST_TOILET, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL, 198 }); + gfx_draw_string_left( + &dpi, STR_CHEAT_GUEST_PREFERRED_INTENSITY, nullptr, COLOUR_BLACK, windowPos + ScreenCoordsXY{ X_LCOL, 219 }); + } + } + + void OnTextInput(rct_widgetindex widgetIndex, std::string_view text) override + { + if (page == WINDOW_CHEATS_PAGE_MONEY && widgetIndex == WIDX_MONEY_SPINNER) + { + auto val = string_to_money(std::string(text).c_str()); + if (val != MONEY32_UNDEFINED) + { + _moneySpinnerValue = val; + } + Invalidate(); + } + } + + OpenRCT2String OnTooltip(rct_widgetindex widgetIndex, rct_string_id fallback) override + { + if (page == WINDOW_CHEATS_PAGE_RIDES && widgetIndex == WIDX_FAST_LIFT_HILL) + { + auto ft = Formatter{}; + ft.Add(255); + return { fallback, ft }; + } + return { fallback, {} }; + } + +private: + void SetPage(int32_t p) + { + page = p; + frame_no = 0; + + enabled_widgets = window_cheats_page_enabled_widgets[p]; + hold_down_widgets = window_cheats_page_hold_down_widgets[p]; + pressed_widgets = 0; + widgets = window_cheats_page_widgets[p]; + + auto maxY = 0; + auto* widget = &widgets[WIDX_TAB_CONTENT]; + while (widget->type != WindowWidgetType::Last) + { + maxY = std::max(maxY, widget->bottom); + widget++; + } + maxY += 6; + + Invalidate(); + height = maxY; + widgets[WIDX_BACKGROUND].bottom = maxY - 1; + widgets[WIDX_PAGE_BACKGROUND].bottom = maxY - 1; + Invalidate(); + } + + void UpdateTabPositions() + { + constexpr const uint16_t tabs[] = { + WIDX_TAB_1, + WIDX_TAB_2, + WIDX_TAB_3, + WIDX_TAB_4, + }; + + auto left = TAB_START; + for (auto tab : tabs) + { + widgets[tab].left = left; + if (!IsWidgetDisabled(tab)) + { + left += TAB_WIDTH; + } + } + } + + void DrawTabImages(rct_drawpixelinfo& dpi) + { + // Money tab + if (!IsWidgetDisabled(WIDX_TAB_1)) + { + uint32_t sprite_idx = SPR_TAB_FINANCES_SUMMARY_0; + if (page == WINDOW_CHEATS_PAGE_MONEY) + sprite_idx += (frame_no / 2) % 8; + gfx_draw_sprite( + &dpi, sprite_idx, windowPos + ScreenCoordsXY{ widgets[WIDX_TAB_1].left, widgets[WIDX_TAB_1].top }, 0); + } + + // Guests tab + if (!IsWidgetDisabled(WIDX_TAB_2)) + { + uint32_t sprite_idx = SPR_TAB_GUESTS_0; + if (page == WINDOW_CHEATS_PAGE_GUESTS) + sprite_idx += (frame_no / 3) % 8; + gfx_draw_sprite( + &dpi, sprite_idx, windowPos + ScreenCoordsXY{ widgets[WIDX_TAB_2].left, widgets[WIDX_TAB_2].top }, 0); + } + + // Misc tab + if (!IsWidgetDisabled(WIDX_TAB_3)) + { + uint32_t sprite_idx = SPR_TAB_PARK; + gfx_draw_sprite( + &dpi, sprite_idx, windowPos + ScreenCoordsXY{ widgets[WIDX_TAB_3].left, widgets[WIDX_TAB_3].top }, 0); + } + + // Rides tab + if (!IsWidgetDisabled(WIDX_TAB_4)) + { + uint32_t sprite_idx = SPR_TAB_RIDE_0; + if (page == WINDOW_CHEATS_PAGE_RIDES) + sprite_idx += (frame_no / 4) % 16; + gfx_draw_sprite( + &dpi, sprite_idx, windowPos + ScreenCoordsXY{ widgets[WIDX_TAB_4].left, widgets[WIDX_TAB_4].top }, 0); + } + } + + void OnMouseDownMoney(rct_widgetindex widgetIndex) + { + switch (widgetIndex) + { + case WIDX_MONEY_SPINNER_INCREMENT: + _moneySpinnerValue = add_clamp_money32( + CHEATS_MONEY_INCREMENT_DIV * (_moneySpinnerValue / CHEATS_MONEY_INCREMENT_DIV), CHEATS_MONEY_INCREMENT_DIV); + InvalidateWidget(WIDX_MONEY_SPINNER); + break; + case WIDX_MONEY_SPINNER_DECREMENT: + _moneySpinnerValue = add_clamp_money32( + CHEATS_MONEY_INCREMENT_DIV * (_moneySpinnerValue / CHEATS_MONEY_INCREMENT_DIV), + -CHEATS_MONEY_INCREMENT_DIV); + InvalidateWidget(WIDX_MONEY_SPINNER); + break; + case WIDX_ADD_MONEY: + CheatsSet(CheatType::AddMoney, _moneySpinnerValue); + break; + case WIDX_YEAR_UP: + _yearSpinnerValue++; + _yearSpinnerValue = std::clamp(_yearSpinnerValue, 1, MAX_YEAR); + InvalidateWidget(WIDX_YEAR_BOX); + break; + case WIDX_YEAR_DOWN: + _yearSpinnerValue--; + _yearSpinnerValue = std::clamp(_yearSpinnerValue, 1, MAX_YEAR); + InvalidateWidget(WIDX_YEAR_BOX); + break; + case WIDX_MONTH_UP: + _monthSpinnerValue++; + _monthSpinnerValue = std::clamp(_monthSpinnerValue, 1, static_cast(MONTH_COUNT)); + _daySpinnerValue = std::clamp(_daySpinnerValue, 1, static_cast(days_in_month[_monthSpinnerValue - 1])); + InvalidateWidget(WIDX_MONTH_BOX); + InvalidateWidget(WIDX_DAY_BOX); + break; + case WIDX_MONTH_DOWN: + _monthSpinnerValue--; + _monthSpinnerValue = std::clamp(_monthSpinnerValue, 1, static_cast(MONTH_COUNT)); + _daySpinnerValue = std::clamp(_daySpinnerValue, 1, static_cast(days_in_month[_monthSpinnerValue - 1])); + InvalidateWidget(WIDX_MONTH_BOX); + InvalidateWidget(WIDX_DAY_BOX); + break; + case WIDX_DAY_UP: + _daySpinnerValue++; + _daySpinnerValue = std::clamp(_daySpinnerValue, 1, static_cast(days_in_month[_monthSpinnerValue - 1])); + InvalidateWidget(WIDX_DAY_BOX); + break; + case WIDX_DAY_DOWN: + _daySpinnerValue--; + _daySpinnerValue = std::clamp(_daySpinnerValue, 1, static_cast(days_in_month[_monthSpinnerValue - 1])); + InvalidateWidget(WIDX_DAY_BOX); + break; + case WIDX_DATE_SET: + { + auto setDateAction = ParkSetDateAction(_yearSpinnerValue, _monthSpinnerValue, _daySpinnerValue); + GameActions::Execute(&setDateAction); + window_invalidate_by_class(WC_BOTTOM_TOOLBAR); + break; + } + case WIDX_DATE_RESET: + { + auto setDateAction = ParkSetDateAction(1, 1, 1); + GameActions::Execute(&setDateAction); + window_invalidate_by_class(WC_BOTTOM_TOOLBAR); + InvalidateWidget(WIDX_YEAR_BOX); + InvalidateWidget(WIDX_MONTH_BOX); + InvalidateWidget(WIDX_DAY_BOX); + break; + } + } + } + + void OnMouseUpMoney(rct_widgetindex widgetIndex) + { + switch (widgetIndex) + { + case WIDX_NO_MONEY: + CheatsSet(CheatType::NoMoney, gParkFlags & PARK_FLAGS_NO_MONEY ? 0 : 1); + break; + case WIDX_MONEY_SPINNER: + money_to_string(_moneySpinnerValue, _moneySpinnerText, MONEY_STRING_MAXLENGTH, false); + window_text_input_raw_open( + this, WIDX_MONEY_SPINNER, STR_ENTER_NEW_VALUE, STR_ENTER_NEW_VALUE, _moneySpinnerText, + MONEY_STRING_MAXLENGTH); + break; + case WIDX_SET_MONEY: + CheatsSet(CheatType::SetMoney, _moneySpinnerValue); + break; + case WIDX_CLEAR_LOAN: + CheatsSet(CheatType::ClearLoan, CHEATS_MONEY_DEFAULT); + break; + } + } + + void OnMouseDownMisc(rct_widgetindex widgetIndex) + { + auto* widget = &widgets[widgetIndex]; + switch (widgetIndex) + { + case WIDX_INCREASE_PARK_RATING: + _parkRatingSpinnerValue = std::min(999, 10 * (_parkRatingSpinnerValue / 10 + 1)); + InvalidateWidget(WIDX_PARK_RATING_SPINNER); + if (get_forced_park_rating() >= 0) + { + auto setCheatAction = SetCheatAction(CheatType::SetForcedParkRating, _parkRatingSpinnerValue); + GameActions::Execute(&setCheatAction); + } + break; + case WIDX_DECREASE_PARK_RATING: + _parkRatingSpinnerValue = std::max(0, 10 * (_parkRatingSpinnerValue / 10 - 1)); + InvalidateWidget(WIDX_PARK_RATING_SPINNER); + if (get_forced_park_rating() >= 0) + { + CheatsSet(CheatType::SetForcedParkRating, _parkRatingSpinnerValue); + } + break; + case WIDX_WEATHER_DROPDOWN_BUTTON: + { + rct_widget* dropdownWidget = widget - 1; + + for (size_t i = 0; i < std::size(WeatherTypes); i++) + { + gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; + gDropdownItemsArgs[i] = WeatherTypes[i]; + } + WindowDropdownShowTextCustomWidth( + { windowPos.x + dropdownWidget->left, windowPos.y + dropdownWidget->top }, dropdownWidget->height() + 1, + colours[1], 0, Dropdown::Flag::StayOpen, std::size(WeatherTypes), dropdownWidget->width() - 3); + + auto currentWeather = gClimateCurrent.Weather; + Dropdown::SetChecked(EnumValue(currentWeather), true); + } + break; + case WIDX_STAFF_SPEED_DROPDOWN_BUTTON: + { + rct_widget* dropdownWidget; + + dropdownWidget = widget - 1; + + for (size_t i = 0; i < std::size(_staffSpeedNames); i++) + { + gDropdownItemsArgs[i] = _staffSpeedNames[i]; + gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; + } + + WindowDropdownShowTextCustomWidth( + { windowPos.x + dropdownWidget->left, windowPos.y + dropdownWidget->top }, dropdownWidget->height() + 1, + colours[1], 0, Dropdown::Flag::StayOpen, 3, dropdownWidget->width() - 3); + Dropdown::SetChecked(_selectedStaffSpeed, true); + } + } + } + + void OnMouseUpMisc(rct_widgetindex widgetIndex) + { + switch (widgetIndex) + { + case WIDX_FREEZE_WEATHER: + CheatsSet(CheatType::FreezeWeather, !gCheatsFreezeWeather); + break; + case WIDX_OPEN_CLOSE_PARK: + CheatsSet(CheatType::OpenClosePark); + break; + case WIDX_CREATE_DUCKS: + CheatsSet(CheatType::CreateDucks, CHEATS_DUCK_INCREMENT); + break; + case WIDX_REMOVE_DUCKS: + CheatsSet(CheatType::RemoveDucks); + break; + case WIDX_CLEAR_GRASS: + CheatsSet(CheatType::SetGrassLength, GRASS_LENGTH_CLEAR_0); + break; + case WIDX_MOWED_GRASS: + CheatsSet(CheatType::SetGrassLength, GRASS_LENGTH_MOWED); + break; + case WIDX_WATER_PLANTS: + CheatsSet(CheatType::WaterPlants); + break; + case WIDX_FIX_VANDALISM: + CheatsSet(CheatType::FixVandalism); + break; + case WIDX_REMOVE_LITTER: + CheatsSet(CheatType::RemoveLitter); + break; + case WIDX_DISABLE_PLANT_AGING: + CheatsSet(CheatType::DisablePlantAging, !gCheatsDisablePlantAging); + break; + case WIDX_WIN_SCENARIO: + CheatsSet(CheatType::WinScenario); + break; + case WIDX_HAVE_FUN: + CheatsSet(CheatType::HaveFun); + break; + case WIDX_OWN_ALL_LAND: + CheatsSet(CheatType::OwnAllLand); + break; + case WIDX_NEVERENDING_MARKETING: + CheatsSet(CheatType::NeverEndingMarketing, !gCheatsNeverendingMarketing); + break; + case WIDX_FORCE_PARK_RATING: + if (get_forced_park_rating() >= 0) + { + CheatsSet(CheatType::SetForcedParkRating, -1); + } + else + { + CheatsSet(CheatType::SetForcedParkRating, _parkRatingSpinnerValue); + } + break; + } + } + + void OnDropdownMisc(rct_widgetindex widgetIndex, int32_t dropdownIndex) + { + if (dropdownIndex == -1) + { + return; + } + else if (widgetIndex == WIDX_WEATHER_DROPDOWN_BUTTON) + { + CheatsSet(CheatType::ForceWeather, dropdownIndex); + } + else if (widgetIndex == WIDX_STAFF_SPEED_DROPDOWN_BUTTON) + { + int32_t speed = CHEATS_STAFF_FAST_SPEED; + switch (dropdownIndex) + { + case 0: + speed = CHEATS_STAFF_FREEZE_SPEED; + break; + case 1: + speed = CHEATS_STAFF_NORMAL_SPEED; + } + + CheatsSet(CheatType::SetStaffSpeed, speed); + _selectedStaffSpeed = dropdownIndex; + } + } + + void OnMouseUpGuests(rct_widgetindex widgetIndex) + { + switch (widgetIndex) + { + case WIDX_GUEST_HAPPINESS_MAX: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_HAPPINESS, PEEP_MAX_HAPPINESS); + break; + case WIDX_GUEST_HAPPINESS_MIN: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_HAPPINESS, 0); + break; + case WIDX_GUEST_ENERGY_MAX: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_ENERGY, PEEP_MAX_ENERGY); + break; + case WIDX_GUEST_ENERGY_MIN: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_ENERGY, PEEP_MIN_ENERGY); + break; + case WIDX_GUEST_HUNGER_MAX: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_HUNGER, 0); + break; + case WIDX_GUEST_HUNGER_MIN: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_HUNGER, PEEP_MAX_HUNGER); + break; + case WIDX_GUEST_THIRST_MAX: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_THIRST, 0); + break; + case WIDX_GUEST_THIRST_MIN: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_THIRST, PEEP_MAX_THIRST); + break; + case WIDX_GUEST_NAUSEA_MAX: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_NAUSEA, PEEP_MAX_NAUSEA); + break; + case WIDX_GUEST_NAUSEA_MIN: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_NAUSEA, 0); + break; + case WIDX_GUEST_NAUSEA_TOLERANCE_MAX: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_NAUSEA_TOLERANCE, EnumValue(PeepNauseaTolerance::High)); + break; + case WIDX_GUEST_NAUSEA_TOLERANCE_MIN: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_NAUSEA_TOLERANCE, EnumValue(PeepNauseaTolerance::None)); + break; + case WIDX_GUEST_TOILET_MAX: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_TOILET, PEEP_MAX_TOILET); + break; + case WIDX_GUEST_TOILET_MIN: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_TOILET, 0); + break; + case WIDX_GUEST_RIDE_INTENSITY_MORE_THAN_1: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY, 1); + break; + case WIDX_GUEST_RIDE_INTENSITY_LESS_THAN_15: + CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY, 0); + break; + case WIDX_TRAM_GUESTS: + CheatsSet(CheatType::GenerateGuests, CHEATS_TRAM_INCREMENT); + break; + case WIDX_REMOVE_ALL_GUESTS: + CheatsSet(CheatType::RemoveAllGuests); + break; + case WIDX_GIVE_GUESTS_MONEY: + CheatsSet(CheatType::GiveAllGuests, OBJECT_MONEY); + break; + case WIDX_GIVE_GUESTS_PARK_MAPS: + CheatsSet(CheatType::GiveAllGuests, OBJECT_PARK_MAP); + break; + case WIDX_GIVE_GUESTS_BALLOONS: + CheatsSet(CheatType::GiveAllGuests, OBJECT_BALLOON); + break; + case WIDX_GIVE_GUESTS_UMBRELLAS: + CheatsSet(CheatType::GiveAllGuests, OBJECT_UMBRELLA); + break; + case WIDX_GUEST_IGNORE_RIDE_INTENSITY: + CheatsSet(CheatType::IgnoreRideIntensity, !gCheatsIgnoreRideIntensity); + break; + case WIDX_DISABLE_VANDALISM: + CheatsSet(CheatType::DisableVandalism, !gCheatsDisableVandalism); + break; + case WIDX_DISABLE_LITTERING: + CheatsSet(CheatType::DisableLittering, !gCheatsDisableLittering); + break; + } + } + + void OnMouseUpRides(rct_widgetindex widgetIndex) + { + switch (widgetIndex) + { + case WIDX_RENEW_RIDES: + CheatsSet(CheatType::RenewRides); + break; + case WIDX_MAKE_DESTRUCTIBLE: + CheatsSet(CheatType::MakeDestructible); + break; + case WIDX_FIX_ALL: + CheatsSet(CheatType::FixRides); + break; + case WIDX_FAST_LIFT_HILL: + CheatsSet(CheatType::FastLiftHill, !gCheatsFastLiftHill); + break; + case WIDX_DISABLE_BRAKES_FAILURE: + CheatsSet(CheatType::DisableBrakesFailure, !gCheatsDisableBrakesFailure); + break; + case WIDX_DISABLE_ALL_BREAKDOWNS: + CheatsSet(CheatType::DisableAllBreakdowns, !gCheatsDisableAllBreakdowns); + break; + case WIDX_BUILD_IN_PAUSE_MODE: + CheatsSet(CheatType::BuildInPauseMode, !gCheatsBuildInPauseMode); + break; + case WIDX_RESET_CRASH_STATUS: + CheatsSet(CheatType::ResetCrashStatus); + break; + case WIDX_10_MINUTE_INSPECTIONS: + CheatsSet(CheatType::TenMinuteInspections); + break; + case WIDX_SHOW_ALL_OPERATING_MODES: + { + if (!gCheatsShowAllOperatingModes) + { + context_show_error(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE, {}); + } + CheatsSet(CheatType::ShowAllOperatingModes, !gCheatsShowAllOperatingModes); + } + break; + case WIDX_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES: + { + if (!gCheatsShowVehiclesFromOtherTrackTypes) + { + context_show_error(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE, {}); + } + CheatsSet(CheatType::ShowVehiclesFromOtherTrackTypes, !gCheatsShowVehiclesFromOtherTrackTypes); + } + break; + case WIDX_DISABLE_TRAIN_LENGTH_LIMITS: + { + if (!gCheatsDisableTrainLengthLimit) + { + context_show_error(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE, {}); + } + CheatsSet(CheatType::DisableTrainLengthLimit, !gCheatsDisableTrainLengthLimit); + } + break; + case WIDX_ENABLE_CHAIN_LIFT_ON_ALL_TRACK: + CheatsSet(CheatType::EnableChainLiftOnAllTrack, !gCheatsEnableChainLiftOnAllTrack); + break; + case WIDX_ENABLE_ARBITRARY_RIDE_TYPE_CHANGES: + { + if (!gCheatsAllowArbitraryRideTypeChanges) + { + context_show_error(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE, {}); + } + CheatsSet(CheatType::AllowArbitraryRideTypeChanges, !gCheatsAllowArbitraryRideTypeChanges); + } + break; + case WIDX_DISABLE_RIDE_VALUE_AGING: + CheatsSet(CheatType::DisableRideValueAging, !gCheatsDisableRideValueAging); + break; + case WIDX_IGNORE_RESEARCH_STATUS: + CheatsSet(CheatType::IgnoreResearchStatus, !gCheatsIgnoreResearchStatus); + break; + case WIDX_ENABLE_ALL_DRAWABLE_TRACK_PIECES: + CheatsSet(CheatType::EnableAllDrawableTrackPieces, !gCheatsEnableAllDrawableTrackPieces); + break; + case WIDX_ALLOW_TRACK_PLACE_INVALID_HEIGHTS: + { + if (!gCheatsAllowTrackPlaceInvalidHeights) + { + context_show_error(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE, {}); + } + CheatsSet(CheatType::AllowTrackPlaceInvalidHeights, !gCheatsAllowTrackPlaceInvalidHeights); + } + break; + } + } +}; rct_window* window_cheats_open() { - rct_window* window; - - // Check if window is already open - window = window_bring_to_front_by_class(WC_CHEATS); - if (window != nullptr) - return window; - - window = WindowCreate(ScreenCoordsXY(32, 32), WW, WH, &window_cheats_money_events, WC_CHEATS, 0); - window->widgets = window_cheats_money_widgets; - window->enabled_widgets = window_cheats_page_enabled_widgets[0]; - window->hold_down_widgets = window_cheats_page_hold_down_widgets[0]; - WindowInitScrollWidgets(window); - window_cheats_set_page(window, WINDOW_CHEATS_PAGE_MONEY); - _parkRatingSpinnerValue = get_forced_park_rating() >= 0 ? get_forced_park_rating() : 999; - + auto* window = window_bring_to_front_by_class(WC_CHEATS); + if (window == nullptr) + { + window = WindowCreate(WC_CHEATS, ScreenCoordsXY(32, 32), WW, WH); + } return window; } - -static void window_cheats_money_mousedown(rct_window* w, rct_widgetindex widgetIndex, [[maybe_unused]] rct_widget* widget) -{ - switch (widgetIndex) - { - case WIDX_MONEY_SPINNER_INCREMENT: - _moneySpinnerValue = add_clamp_money32( - CHEATS_MONEY_INCREMENT_DIV * (_moneySpinnerValue / CHEATS_MONEY_INCREMENT_DIV), CHEATS_MONEY_INCREMENT_DIV); - widget_invalidate_by_class(WC_CHEATS, WIDX_MONEY_SPINNER); - break; - case WIDX_MONEY_SPINNER_DECREMENT: - _moneySpinnerValue = add_clamp_money32( - CHEATS_MONEY_INCREMENT_DIV * (_moneySpinnerValue / CHEATS_MONEY_INCREMENT_DIV), -CHEATS_MONEY_INCREMENT_DIV); - widget_invalidate_by_class(WC_CHEATS, WIDX_MONEY_SPINNER); - break; - case WIDX_ADD_MONEY: - CheatsSet(CheatType::AddMoney, _moneySpinnerValue); - break; - case WIDX_YEAR_UP: - _yearSpinnerValue++; - _yearSpinnerValue = std::clamp(_yearSpinnerValue, 1, MAX_YEAR); - widget_invalidate(w, WIDX_YEAR_BOX); - break; - case WIDX_YEAR_DOWN: - _yearSpinnerValue--; - _yearSpinnerValue = std::clamp(_yearSpinnerValue, 1, MAX_YEAR); - widget_invalidate(w, WIDX_YEAR_BOX); - break; - case WIDX_MONTH_UP: - _monthSpinnerValue++; - _monthSpinnerValue = std::clamp(_monthSpinnerValue, 1, static_cast(MONTH_COUNT)); - _daySpinnerValue = std::clamp(_daySpinnerValue, 1, static_cast(days_in_month[_monthSpinnerValue - 1])); - widget_invalidate(w, WIDX_MONTH_BOX); - widget_invalidate(w, WIDX_DAY_BOX); - break; - case WIDX_MONTH_DOWN: - _monthSpinnerValue--; - _monthSpinnerValue = std::clamp(_monthSpinnerValue, 1, static_cast(MONTH_COUNT)); - _daySpinnerValue = std::clamp(_daySpinnerValue, 1, static_cast(days_in_month[_monthSpinnerValue - 1])); - widget_invalidate(w, WIDX_MONTH_BOX); - widget_invalidate(w, WIDX_DAY_BOX); - break; - case WIDX_DAY_UP: - _daySpinnerValue++; - _daySpinnerValue = std::clamp(_daySpinnerValue, 1, static_cast(days_in_month[_monthSpinnerValue - 1])); - widget_invalidate(w, WIDX_DAY_BOX); - break; - case WIDX_DAY_DOWN: - _daySpinnerValue--; - _daySpinnerValue = std::clamp(_daySpinnerValue, 1, static_cast(days_in_month[_monthSpinnerValue - 1])); - widget_invalidate(w, WIDX_DAY_BOX); - break; - case WIDX_DATE_SET: - { - auto setDateAction = ParkSetDateAction(_yearSpinnerValue, _monthSpinnerValue, _daySpinnerValue); - GameActions::Execute(&setDateAction); - window_invalidate_by_class(WC_BOTTOM_TOOLBAR); - break; - } - case WIDX_DATE_RESET: - { - auto setDateAction = ParkSetDateAction(1, 1, 1); - GameActions::Execute(&setDateAction); - window_invalidate_by_class(WC_BOTTOM_TOOLBAR); - widget_invalidate(w, WIDX_YEAR_BOX); - widget_invalidate(w, WIDX_MONTH_BOX); - widget_invalidate(w, WIDX_DAY_BOX); - break; - } - } -} - -static void window_cheats_misc_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget) -{ - switch (widgetIndex) - { - case WIDX_INCREASE_PARK_RATING: - _parkRatingSpinnerValue = std::min(999, 10 * (_parkRatingSpinnerValue / 10 + 1)); - widget_invalidate_by_class(WC_CHEATS, WIDX_PARK_RATING_SPINNER); - if (get_forced_park_rating() >= 0) - { - auto setCheatAction = SetCheatAction(CheatType::SetForcedParkRating, _parkRatingSpinnerValue); - GameActions::Execute(&setCheatAction); - } - break; - case WIDX_DECREASE_PARK_RATING: - _parkRatingSpinnerValue = std::max(0, 10 * (_parkRatingSpinnerValue / 10 - 1)); - widget_invalidate_by_class(WC_CHEATS, WIDX_PARK_RATING_SPINNER); - if (get_forced_park_rating() >= 0) - { - CheatsSet(CheatType::SetForcedParkRating, _parkRatingSpinnerValue); - } - break; - case WIDX_WEATHER_DROPDOWN_BUTTON: - { - rct_widget* dropdownWidget = widget - 1; - - for (size_t i = 0; i < std::size(WeatherTypes); i++) - { - gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; - gDropdownItemsArgs[i] = WeatherTypes[i]; - } - WindowDropdownShowTextCustomWidth( - { w->windowPos.x + dropdownWidget->left, w->windowPos.y + dropdownWidget->top }, dropdownWidget->height() + 1, - w->colours[1], 0, Dropdown::Flag::StayOpen, std::size(WeatherTypes), dropdownWidget->width() - 3); - - auto currentWeather = gClimateCurrent.Weather; - Dropdown::SetChecked(EnumValue(currentWeather), true); - } - break; - case WIDX_STAFF_SPEED_DROPDOWN_BUTTON: - { - rct_widget* dropdownWidget; - - dropdownWidget = widget - 1; - - for (size_t i = 0; i < std::size(_staffSpeedNames); i++) - { - gDropdownItemsArgs[i] = _staffSpeedNames[i]; - gDropdownItemsFormat[i] = STR_DROPDOWN_MENU_LABEL; - } - - WindowDropdownShowTextCustomWidth( - { w->windowPos.x + dropdownWidget->left, w->windowPos.y + dropdownWidget->top }, dropdownWidget->height() + 1, - w->colours[1], 0, Dropdown::Flag::StayOpen, 3, dropdownWidget->width() - 3); - Dropdown::SetChecked(_selectedStaffSpeed, true); - } - } -} - -static void window_cheats_misc_dropdown([[maybe_unused]] rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex) -{ - if (dropdownIndex == -1) - { - return; - } - else if (widgetIndex == WIDX_WEATHER_DROPDOWN_BUTTON) - { - CheatsSet(CheatType::ForceWeather, dropdownIndex); - } - else if (widgetIndex == WIDX_STAFF_SPEED_DROPDOWN_BUTTON) - { - int32_t speed = CHEATS_STAFF_FAST_SPEED; - switch (dropdownIndex) - { - case 0: - speed = CHEATS_STAFF_FREEZE_SPEED; - break; - case 1: - speed = CHEATS_STAFF_NORMAL_SPEED; - } - - CheatsSet(CheatType::SetStaffSpeed, speed); - _selectedStaffSpeed = dropdownIndex; - } -} - -static void window_cheats_money_mouseup(rct_window* w, rct_widgetindex widgetIndex) -{ - switch (widgetIndex) - { - case WIDX_CLOSE: - window_close(w); - break; - case WIDX_TAB_1: - case WIDX_TAB_2: - case WIDX_TAB_3: - case WIDX_TAB_4: - window_cheats_set_page(w, widgetIndex - WIDX_TAB_1); - break; - case WIDX_NO_MONEY: - CheatsSet(CheatType::NoMoney, gParkFlags & PARK_FLAGS_NO_MONEY ? 0 : 1); - break; - case WIDX_MONEY_SPINNER: - money_to_string(_moneySpinnerValue, _moneySpinnerText, MONEY_STRING_MAXLENGTH, false); - window_text_input_raw_open( - w, WIDX_MONEY_SPINNER, STR_ENTER_NEW_VALUE, STR_ENTER_NEW_VALUE, _moneySpinnerText, MONEY_STRING_MAXLENGTH); - break; - case WIDX_SET_MONEY: - CheatsSet(CheatType::SetMoney, _moneySpinnerValue); - break; - case WIDX_CLEAR_LOAN: - CheatsSet(CheatType::ClearLoan, CHEATS_MONEY_DEFAULT); - break; - } -} - -static void window_cheats_guests_mouseup(rct_window* w, rct_widgetindex widgetIndex) -{ - switch (widgetIndex) - { - case WIDX_CLOSE: - window_close(w); - break; - case WIDX_TAB_1: - case WIDX_TAB_2: - case WIDX_TAB_3: - case WIDX_TAB_4: - window_cheats_set_page(w, widgetIndex - WIDX_TAB_1); - break; - case WIDX_GUEST_HAPPINESS_MAX: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_HAPPINESS, PEEP_MAX_HAPPINESS); - break; - case WIDX_GUEST_HAPPINESS_MIN: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_HAPPINESS, 0); - break; - case WIDX_GUEST_ENERGY_MAX: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_ENERGY, PEEP_MAX_ENERGY); - break; - case WIDX_GUEST_ENERGY_MIN: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_ENERGY, PEEP_MIN_ENERGY); - break; - case WIDX_GUEST_HUNGER_MAX: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_HUNGER, 0); - break; - case WIDX_GUEST_HUNGER_MIN: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_HUNGER, PEEP_MAX_HUNGER); - break; - case WIDX_GUEST_THIRST_MAX: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_THIRST, 0); - break; - case WIDX_GUEST_THIRST_MIN: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_THIRST, PEEP_MAX_THIRST); - break; - case WIDX_GUEST_NAUSEA_MAX: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_NAUSEA, PEEP_MAX_NAUSEA); - break; - case WIDX_GUEST_NAUSEA_MIN: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_NAUSEA, 0); - break; - case WIDX_GUEST_NAUSEA_TOLERANCE_MAX: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_NAUSEA_TOLERANCE, EnumValue(PeepNauseaTolerance::High)); - break; - case WIDX_GUEST_NAUSEA_TOLERANCE_MIN: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_NAUSEA_TOLERANCE, EnumValue(PeepNauseaTolerance::None)); - break; - case WIDX_GUEST_TOILET_MAX: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_TOILET, PEEP_MAX_TOILET); - break; - case WIDX_GUEST_TOILET_MIN: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_TOILET, 0); - break; - case WIDX_GUEST_RIDE_INTENSITY_MORE_THAN_1: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY, 1); - break; - case WIDX_GUEST_RIDE_INTENSITY_LESS_THAN_15: - CheatsSet(CheatType::SetGuestParameter, GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY, 0); - break; - case WIDX_TRAM_GUESTS: - CheatsSet(CheatType::GenerateGuests, CHEATS_TRAM_INCREMENT); - break; - case WIDX_REMOVE_ALL_GUESTS: - CheatsSet(CheatType::RemoveAllGuests); - break; - case WIDX_GIVE_GUESTS_MONEY: - CheatsSet(CheatType::GiveAllGuests, OBJECT_MONEY); - break; - case WIDX_GIVE_GUESTS_PARK_MAPS: - CheatsSet(CheatType::GiveAllGuests, OBJECT_PARK_MAP); - break; - case WIDX_GIVE_GUESTS_BALLOONS: - CheatsSet(CheatType::GiveAllGuests, OBJECT_BALLOON); - break; - case WIDX_GIVE_GUESTS_UMBRELLAS: - CheatsSet(CheatType::GiveAllGuests, OBJECT_UMBRELLA); - break; - case WIDX_GUEST_IGNORE_RIDE_INTENSITY: - CheatsSet(CheatType::IgnoreRideIntensity, !gCheatsIgnoreRideIntensity); - break; - case WIDX_DISABLE_VANDALISM: - CheatsSet(CheatType::DisableVandalism, !gCheatsDisableVandalism); - break; - case WIDX_DISABLE_LITTERING: - CheatsSet(CheatType::DisableLittering, !gCheatsDisableLittering); - break; - } -} - -static void window_cheats_misc_mouseup(rct_window* w, rct_widgetindex widgetIndex) -{ - switch (widgetIndex) - { - case WIDX_CLOSE: - window_close(w); - break; - case WIDX_TAB_1: - case WIDX_TAB_2: - case WIDX_TAB_3: - case WIDX_TAB_4: - window_cheats_set_page(w, widgetIndex - WIDX_TAB_1); - break; - case WIDX_FREEZE_WEATHER: - CheatsSet(CheatType::FreezeWeather, !gCheatsFreezeWeather); - break; - case WIDX_OPEN_CLOSE_PARK: - CheatsSet(CheatType::OpenClosePark); - break; - case WIDX_CREATE_DUCKS: - CheatsSet(CheatType::CreateDucks, CHEATS_DUCK_INCREMENT); - break; - case WIDX_REMOVE_DUCKS: - CheatsSet(CheatType::RemoveDucks); - break; - case WIDX_CLEAR_GRASS: - CheatsSet(CheatType::SetGrassLength, GRASS_LENGTH_CLEAR_0); - break; - case WIDX_MOWED_GRASS: - CheatsSet(CheatType::SetGrassLength, GRASS_LENGTH_MOWED); - break; - case WIDX_WATER_PLANTS: - CheatsSet(CheatType::WaterPlants); - break; - case WIDX_FIX_VANDALISM: - CheatsSet(CheatType::FixVandalism); - break; - case WIDX_REMOVE_LITTER: - CheatsSet(CheatType::RemoveLitter); - break; - case WIDX_DISABLE_PLANT_AGING: - CheatsSet(CheatType::DisablePlantAging, !gCheatsDisablePlantAging); - break; - case WIDX_WIN_SCENARIO: - CheatsSet(CheatType::WinScenario); - break; - case WIDX_HAVE_FUN: - CheatsSet(CheatType::HaveFun); - break; - case WIDX_OWN_ALL_LAND: - CheatsSet(CheatType::OwnAllLand); - break; - case WIDX_NEVERENDING_MARKETING: - CheatsSet(CheatType::NeverEndingMarketing, !gCheatsNeverendingMarketing); - break; - case WIDX_FORCE_PARK_RATING: - if (get_forced_park_rating() >= 0) - { - CheatsSet(CheatType::SetForcedParkRating, -1); - } - else - { - CheatsSet(CheatType::SetForcedParkRating, _parkRatingSpinnerValue); - } - break; - } -} - -static void window_cheats_rides_mouseup(rct_window* w, rct_widgetindex widgetIndex) -{ - switch (widgetIndex) - { - case WIDX_CLOSE: - window_close(w); - break; - case WIDX_TAB_1: - case WIDX_TAB_2: - case WIDX_TAB_3: - case WIDX_TAB_4: - window_cheats_set_page(w, widgetIndex - WIDX_TAB_1); - break; - case WIDX_RENEW_RIDES: - CheatsSet(CheatType::RenewRides); - break; - case WIDX_MAKE_DESTRUCTIBLE: - CheatsSet(CheatType::MakeDestructible); - break; - case WIDX_FIX_ALL: - CheatsSet(CheatType::FixRides); - break; - case WIDX_FAST_LIFT_HILL: - CheatsSet(CheatType::FastLiftHill, !gCheatsFastLiftHill); - - break; - case WIDX_DISABLE_BRAKES_FAILURE: - CheatsSet(CheatType::DisableBrakesFailure, !gCheatsDisableBrakesFailure); - break; - case WIDX_DISABLE_ALL_BREAKDOWNS: - CheatsSet(CheatType::DisableAllBreakdowns, !gCheatsDisableAllBreakdowns); - break; - case WIDX_BUILD_IN_PAUSE_MODE: - CheatsSet(CheatType::BuildInPauseMode, !gCheatsBuildInPauseMode); - break; - case WIDX_RESET_CRASH_STATUS: - CheatsSet(CheatType::ResetCrashStatus); - break; - case WIDX_10_MINUTE_INSPECTIONS: - CheatsSet(CheatType::TenMinuteInspections); - break; - case WIDX_SHOW_ALL_OPERATING_MODES: - { - if (!gCheatsShowAllOperatingModes) - { - context_show_error(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE, {}); - } - CheatsSet(CheatType::ShowAllOperatingModes, !gCheatsShowAllOperatingModes); - } - break; - case WIDX_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES: - { - if (!gCheatsShowVehiclesFromOtherTrackTypes) - { - context_show_error(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE, {}); - } - CheatsSet(CheatType::ShowVehiclesFromOtherTrackTypes, !gCheatsShowVehiclesFromOtherTrackTypes); - } - break; - case WIDX_DISABLE_TRAIN_LENGTH_LIMITS: - { - if (!gCheatsDisableTrainLengthLimit) - { - context_show_error(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE, {}); - } - CheatsSet(CheatType::DisableTrainLengthLimit, !gCheatsDisableTrainLengthLimit); - } - break; - case WIDX_ENABLE_CHAIN_LIFT_ON_ALL_TRACK: - CheatsSet(CheatType::EnableChainLiftOnAllTrack, !gCheatsEnableChainLiftOnAllTrack); - break; - case WIDX_ENABLE_ARBITRARY_RIDE_TYPE_CHANGES: - { - if (!gCheatsAllowArbitraryRideTypeChanges) - { - context_show_error(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE, {}); - } - CheatsSet(CheatType::AllowArbitraryRideTypeChanges, !gCheatsAllowArbitraryRideTypeChanges); - } - break; - case WIDX_DISABLE_RIDE_VALUE_AGING: - CheatsSet(CheatType::DisableRideValueAging, !gCheatsDisableRideValueAging); - break; - case WIDX_IGNORE_RESEARCH_STATUS: - CheatsSet(CheatType::IgnoreResearchStatus, !gCheatsIgnoreResearchStatus); - break; - case WIDX_ENABLE_ALL_DRAWABLE_TRACK_PIECES: - CheatsSet(CheatType::EnableAllDrawableTrackPieces, !gCheatsEnableAllDrawableTrackPieces); - break; - case WIDX_ALLOW_TRACK_PLACE_INVALID_HEIGHTS: - { - if (!gCheatsAllowTrackPlaceInvalidHeights) - { - context_show_error(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE, {}); - } - CheatsSet(CheatType::AllowTrackPlaceInvalidHeights, !gCheatsAllowTrackPlaceInvalidHeights); - } - break; - } -} - -static void window_cheats_text_input(rct_window* w, rct_widgetindex widgetIndex, char* text) -{ - if (text == nullptr) - return; - - if (w->page == WINDOW_CHEATS_PAGE_MONEY && widgetIndex == WIDX_MONEY_SPINNER) - { - money32 val = string_to_money(text); - if (val != MONEY32_UNDEFINED) - { - _moneySpinnerValue = val; - } - w->Invalidate(); - } -} - -static void window_cheats_update(rct_window* w) -{ - w->frame_no++; - widget_invalidate(w, WIDX_TAB_1 + w->page); -} - -static OpenRCT2String window_cheats_rides_tooltip(rct_window* const w, rct_widgetindex widgetIndex, rct_string_id fallback) -{ - if (widgetIndex == WIDX_FAST_LIFT_HILL) - { - auto ft = Formatter{}; - ft.Add(255); - return { fallback, ft }; - } - return { fallback, {} }; -} - -static void window_cheats_invalidate(rct_window* w) -{ - int32_t i; - - rct_widget* widgets = window_cheats_page_widgets[w->page]; - if (w->widgets != widgets) - { - w->widgets = widgets; - WindowInitScrollWidgets(w); - } - - w->pressed_widgets = 0; - w->disabled_widgets = 0; - - // Set correct active tab - for (i = 0; i < 7; i++) - w->pressed_widgets &= ~(1 << (WIDX_TAB_1 + i)); - w->pressed_widgets |= 1LL << (WIDX_TAB_1 + w->page); - - // Set title - w->widgets[WIDX_TITLE].text = window_cheats_page_titles[w->page]; - - switch (w->page) - { - case WINDOW_CHEATS_PAGE_MONEY: - { - WidgetSetCheckboxValue(w, WIDX_NO_MONEY, gParkFlags & PARK_FLAGS_NO_MONEY); - - uint64_t money_widgets = (1 << WIDX_ADD_SET_MONEY_GROUP) | (1 << WIDX_MONEY_SPINNER) - | (1 << WIDX_MONEY_SPINNER_INCREMENT) | (1 << WIDX_MONEY_SPINNER_DECREMENT) | (1 << WIDX_ADD_MONEY) - | (1 << WIDX_SET_MONEY) | (1 << WIDX_CLEAR_LOAN); - if (gParkFlags & PARK_FLAGS_NO_MONEY) - { - w->disabled_widgets |= money_widgets; - } - else - { - w->disabled_widgets &= ~money_widgets; - } - } - break; - case WINDOW_CHEATS_PAGE_GUESTS: - { - auto ft = Formatter::Common(); - ft.Add(MONEY(1000, 00)); - WidgetSetCheckboxValue(w, WIDX_GUEST_IGNORE_RIDE_INTENSITY, gCheatsIgnoreRideIntensity); - WidgetSetCheckboxValue(w, WIDX_DISABLE_VANDALISM, gCheatsDisableVandalism); - WidgetSetCheckboxValue(w, WIDX_DISABLE_LITTERING, gCheatsDisableLittering); - } - break; - - case WINDOW_CHEATS_PAGE_MISC: - w->widgets[WIDX_OPEN_CLOSE_PARK].text = (gParkFlags & PARK_FLAGS_PARK_OPEN) ? STR_CHEAT_CLOSE_PARK - : STR_CHEAT_OPEN_PARK; - WidgetSetCheckboxValue(w, WIDX_FORCE_PARK_RATING, get_forced_park_rating() >= 0); - WidgetSetCheckboxValue(w, WIDX_FREEZE_WEATHER, gCheatsFreezeWeather); - WidgetSetCheckboxValue(w, WIDX_NEVERENDING_MARKETING, gCheatsNeverendingMarketing); - WidgetSetCheckboxValue(w, WIDX_DISABLE_PLANT_AGING, gCheatsDisablePlantAging); - break; - case WINDOW_CHEATS_PAGE_RIDES: - WidgetSetCheckboxValue(w, WIDX_FAST_LIFT_HILL, gCheatsFastLiftHill); - WidgetSetCheckboxValue(w, WIDX_DISABLE_BRAKES_FAILURE, gCheatsDisableBrakesFailure); - WidgetSetCheckboxValue(w, WIDX_DISABLE_ALL_BREAKDOWNS, gCheatsDisableAllBreakdowns); - WidgetSetCheckboxValue(w, WIDX_BUILD_IN_PAUSE_MODE, gCheatsBuildInPauseMode); - WidgetSetCheckboxValue(w, WIDX_SHOW_ALL_OPERATING_MODES, gCheatsShowAllOperatingModes); - WidgetSetCheckboxValue(w, WIDX_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES, gCheatsShowVehiclesFromOtherTrackTypes); - WidgetSetCheckboxValue(w, WIDX_DISABLE_TRAIN_LENGTH_LIMITS, gCheatsDisableTrainLengthLimit); - WidgetSetCheckboxValue(w, WIDX_ENABLE_CHAIN_LIFT_ON_ALL_TRACK, gCheatsEnableChainLiftOnAllTrack); - WidgetSetCheckboxValue(w, WIDX_ENABLE_ARBITRARY_RIDE_TYPE_CHANGES, gCheatsAllowArbitraryRideTypeChanges); - WidgetSetCheckboxValue(w, WIDX_DISABLE_RIDE_VALUE_AGING, gCheatsDisableRideValueAging); - WidgetSetCheckboxValue(w, WIDX_IGNORE_RESEARCH_STATUS, gCheatsIgnoreResearchStatus); - WidgetSetCheckboxValue(w, WIDX_ENABLE_ALL_DRAWABLE_TRACK_PIECES, gCheatsEnableAllDrawableTrackPieces); - WidgetSetCheckboxValue(w, WIDX_ALLOW_TRACK_PLACE_INVALID_HEIGHTS, gCheatsAllowTrackPlaceInvalidHeights); - break; - } - - // Current weather - window_cheats_misc_widgets[WIDX_WEATHER].text = WeatherTypes[EnumValue(gClimateCurrent.Weather)]; - // Staff speed - window_cheats_misc_widgets[WIDX_STAFF_SPEED].text = _staffSpeedNames[_selectedStaffSpeed]; - - if (gScreenFlags & SCREEN_FLAGS_EDITOR) - { - w->disabled_widgets |= (1 << WIDX_TAB_2) | (1 << WIDX_TAB_3) | (1 << WIDX_NO_MONEY); - } -} - -static void window_cheats_update_tab_positions(rct_window* w) -{ - constexpr const uint16_t tabs[] = { - WIDX_TAB_1, - WIDX_TAB_2, - WIDX_TAB_3, - WIDX_TAB_4, - }; - - int32_t left = TAB_START; - - for (auto tab : tabs) - { - w->widgets[tab].left = left; - if (!(w->disabled_widgets & (1ULL << tab))) - { - left += TAB_WIDTH; - } - } -} - -static void window_cheats_paint(rct_window* w, rct_drawpixelinfo* dpi) -{ - window_cheats_update_tab_positions(w); - WindowDrawWidgets(w, dpi); - window_cheats_draw_tab_images(dpi, w); - - static constexpr int16_t X_LCOL = 14; - static constexpr int16_t X_RCOL = 208; - - if (w->page == WINDOW_CHEATS_PAGE_MONEY) - { - uint8_t colour = w->colours[1]; - auto ft = Formatter(); - ft.Add(_moneySpinnerValue); - if (WidgetIsDisabled(w, WIDX_MONEY_SPINNER)) - { - colour |= COLOUR_FLAG_INSET; - } - int32_t actual_month = _monthSpinnerValue - 1; - gfx_draw_string_left(dpi, STR_BOTTOM_TOOLBAR_CASH, ft.Data(), colour, w->windowPos + ScreenCoordsXY{ X_LCOL, 93 }); - gfx_draw_string_left(dpi, STR_YEAR, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL, 198 }); - gfx_draw_string_left(dpi, STR_MONTH, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL, 219 }); - gfx_draw_string_left(dpi, STR_DAY, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL, 240 }); - ft = Formatter(); - ft.Add(_yearSpinnerValue); - DrawTextBasic( - dpi, w->windowPos + ScreenCoordsXY{ X_RCOL, 198 }, STR_FORMAT_INTEGER, ft, w->colours[1], TextAlignment::RIGHT); - ft = Formatter(); - ft.Add(actual_month); - DrawTextBasic( - dpi, w->windowPos + ScreenCoordsXY{ X_RCOL, 219 }, STR_FORMAT_MONTH, ft, w->colours[1], TextAlignment::RIGHT); - ft = Formatter(); - ft.Add(_daySpinnerValue); - DrawTextBasic( - dpi, w->windowPos + ScreenCoordsXY{ X_RCOL, 240 }, STR_FORMAT_INTEGER, ft, w->colours[1], TextAlignment::RIGHT); - } - else if (w->page == WINDOW_CHEATS_PAGE_MISC) - { - { - auto& widget = w->widgets[WIDX_WEATHER]; - gfx_draw_string_left( - dpi, STR_CHANGE_WEATHER, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL - 3, widget.top + 1 }); - } - - { - auto ft = Formatter(); - ft.Add(_parkRatingSpinnerValue); - - auto& widget = w->widgets[WIDX_PARK_RATING_SPINNER]; - DrawTextBasic( - dpi, w->windowPos + ScreenCoordsXY{ widget.left + 1, widget.top + 2 }, STR_FORMAT_INTEGER, ft, w->colours[1]); - } - - { - auto& widget = w->widgets[WIDX_STAFF_SPEED]; - gfx_draw_string_left( - dpi, STR_CHEAT_STAFF_SPEED, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL - 3, widget.top + 1 }); - } - } - else if (w->page == WINDOW_CHEATS_PAGE_GUESTS) - { - gfx_draw_string_left( - dpi, STR_CHEAT_GUEST_HAPPINESS, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL, 72 }); - gfx_draw_string_left(dpi, STR_CHEAT_GUEST_ENERGY, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL, 93 }); - gfx_draw_string_left(dpi, STR_CHEAT_GUEST_HUNGER, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL, 114 }); - gfx_draw_string_left(dpi, STR_CHEAT_GUEST_THIRST, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL, 135 }); - gfx_draw_string_left(dpi, STR_CHEAT_GUEST_NAUSEA, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL, 156 }); - gfx_draw_string_left( - dpi, STR_CHEAT_GUEST_NAUSEA_TOLERANCE, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL, 177 }); - gfx_draw_string_left(dpi, STR_CHEAT_GUEST_TOILET, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL, 198 }); - gfx_draw_string_left( - dpi, STR_CHEAT_GUEST_PREFERRED_INTENSITY, nullptr, COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ X_LCOL, 219 }); - } -} - -static void window_cheats_draw_tab_images(rct_drawpixelinfo* dpi, rct_window* w) -{ - int32_t sprite_idx; - - // Money tab - if (!(w->disabled_widgets & (1 << WIDX_TAB_1))) - { - sprite_idx = SPR_TAB_FINANCES_SUMMARY_0; - if (w->page == WINDOW_CHEATS_PAGE_MONEY) - sprite_idx += (w->frame_no / 2) % 8; - gfx_draw_sprite( - dpi, sprite_idx, w->windowPos + ScreenCoordsXY{ w->widgets[WIDX_TAB_1].left, w->widgets[WIDX_TAB_1].top }, 0); - } - - // Guests tab - if (!(w->disabled_widgets & (1 << WIDX_TAB_2))) - { - sprite_idx = SPR_TAB_GUESTS_0; - if (w->page == WINDOW_CHEATS_PAGE_GUESTS) - sprite_idx += (w->frame_no / 3) % 8; - gfx_draw_sprite( - dpi, sprite_idx, w->windowPos + ScreenCoordsXY{ w->widgets[WIDX_TAB_2].left, w->widgets[WIDX_TAB_2].top }, 0); - } - - // Misc tab - if (!(w->disabled_widgets & (1 << WIDX_TAB_3))) - { - sprite_idx = SPR_TAB_PARK; - gfx_draw_sprite( - dpi, sprite_idx, w->windowPos + ScreenCoordsXY{ w->widgets[WIDX_TAB_3].left, w->widgets[WIDX_TAB_3].top }, 0); - } - - // Rides tab - if (!(w->disabled_widgets & (1 << WIDX_TAB_4))) - { - sprite_idx = SPR_TAB_RIDE_0; - if (w->page == WINDOW_CHEATS_PAGE_RIDES) - sprite_idx += (w->frame_no / 4) % 16; - gfx_draw_sprite( - dpi, sprite_idx, w->windowPos + ScreenCoordsXY{ w->widgets[WIDX_TAB_4].left, w->widgets[WIDX_TAB_4].top }, 0); - } -} - -static void window_cheats_set_page(rct_window* w, int32_t page) -{ - w->page = page; - w->frame_no = 0; - - w->enabled_widgets = window_cheats_page_enabled_widgets[page]; - w->hold_down_widgets = window_cheats_page_hold_down_widgets[page]; - w->pressed_widgets = 0; - - w->event_handlers = window_cheats_page_events[page]; - w->widgets = window_cheats_page_widgets[page]; - - int32_t maxY = 0; - rct_widget* widget = &w->widgets[WIDX_TAB_CONTENT]; - while (widget->type != WindowWidgetType::Last) - { - maxY = std::max(maxY, static_cast(widget->bottom)); - widget++; - } - maxY += 6; - - w->Invalidate(); - w->height = maxY; - w->widgets[WIDX_BACKGROUND].bottom = maxY - 1; - w->widgets[WIDX_PAGE_BACKGROUND].bottom = maxY - 1; - w->Invalidate(); -} diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index 37b2ff5958..e3545fae0d 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -1387,141 +1387,178 @@ void tool_cancel() void window_event_close_call(rct_window* w) { - if (w->event_handlers->close != nullptr) + if (w->event_handlers == nullptr) + w->OnClose(); + else if (w->event_handlers->close != nullptr) w->event_handlers->close(w); } void window_event_mouse_up_call(rct_window* w, rct_widgetindex widgetIndex) { - if (w->event_handlers->mouse_up != nullptr) + if (w->event_handlers == nullptr) + w->OnMouseUp(widgetIndex); + else if (w->event_handlers->mouse_up != nullptr) w->event_handlers->mouse_up(w, widgetIndex); } void window_event_resize_call(rct_window* w) { - if (w->event_handlers->resize != nullptr) - w->event_handlers->resize(w); + if (w->event_handlers != nullptr) + if (w->event_handlers->resize != nullptr) + w->event_handlers->resize(w); } void window_event_mouse_down_call(rct_window* w, rct_widgetindex widgetIndex) { - if (w->event_handlers->mouse_down != nullptr) + if (w->event_handlers == nullptr) + w->OnMouseDown(widgetIndex); + else if (w->event_handlers->mouse_down != nullptr) w->event_handlers->mouse_down(w, widgetIndex, &w->widgets[widgetIndex]); } void window_event_dropdown_call(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex) { - if (w->event_handlers->dropdown != nullptr) + if (w->event_handlers == nullptr) + w->OnDropdown(widgetIndex, dropdownIndex); + else if (w->event_handlers->dropdown != nullptr) w->event_handlers->dropdown(w, widgetIndex, dropdownIndex); } void window_event_unknown_05_call(rct_window* w) { - if (w->event_handlers->unknown_05 != nullptr) - w->event_handlers->unknown_05(w); + if (w->event_handlers != nullptr) + if (w->event_handlers->unknown_05 != nullptr) + w->event_handlers->unknown_05(w); } void window_event_update_call(rct_window* w) { - if (w->event_handlers->update != nullptr) + if (w->event_handlers == nullptr) + w->OnUpdate(); + else if (w->event_handlers->update != nullptr) w->event_handlers->update(w); } void window_event_periodic_update_call(rct_window* w) { - if (w->event_handlers->periodic_update != nullptr) - w->event_handlers->periodic_update(w); + if (w->event_handlers != nullptr) + if (w->event_handlers->periodic_update != nullptr) + w->event_handlers->periodic_update(w); } void window_event_unknown_08_call(rct_window* w) { - if (w->event_handlers->unknown_08 != nullptr) - w->event_handlers->unknown_08(w); + if (w->event_handlers != nullptr) + if (w->event_handlers->unknown_08 != nullptr) + w->event_handlers->unknown_08(w); } void window_event_tool_update_call(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers->tool_update != nullptr) - w->event_handlers->tool_update(w, widgetIndex, screenCoords); + if (w->event_handlers != nullptr) + if (w->event_handlers->tool_update != nullptr) + w->event_handlers->tool_update(w, widgetIndex, screenCoords); } void window_event_tool_down_call(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers->tool_down != nullptr) - w->event_handlers->tool_down(w, widgetIndex, screenCoords); + if (w->event_handlers != nullptr) + if (w->event_handlers->tool_down != nullptr) + w->event_handlers->tool_down(w, widgetIndex, screenCoords); } void window_event_tool_drag_call(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers->tool_drag != nullptr) - w->event_handlers->tool_drag(w, widgetIndex, screenCoords); + if (w->event_handlers != nullptr) + if (w->event_handlers->tool_drag != nullptr) + w->event_handlers->tool_drag(w, widgetIndex, screenCoords); } void window_event_tool_up_call(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers->tool_up != nullptr) - w->event_handlers->tool_up(w, widgetIndex, screenCoords); + if (w->event_handlers != nullptr) + if (w->event_handlers->tool_up != nullptr) + w->event_handlers->tool_up(w, widgetIndex, screenCoords); } void window_event_tool_abort_call(rct_window* w, rct_widgetindex widgetIndex) { - if (w->event_handlers->tool_abort != nullptr) - w->event_handlers->tool_abort(w, widgetIndex); + if (w->event_handlers != nullptr) + if (w->event_handlers->tool_abort != nullptr) + w->event_handlers->tool_abort(w, widgetIndex); } void window_event_unknown_0E_call(rct_window* w) { - if (w->event_handlers->unknown_0E != nullptr) - w->event_handlers->unknown_0E(w); + if (w->event_handlers != nullptr) + if (w->event_handlers->unknown_0E != nullptr) + w->event_handlers->unknown_0E(w); } void window_get_scroll_size(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height) { - if (w->event_handlers->get_scroll_size != nullptr) - { - w->event_handlers->get_scroll_size(w, scrollIndex, width, height); - } + if (w->event_handlers != nullptr) + if (w->event_handlers->get_scroll_size != nullptr) + w->event_handlers->get_scroll_size(w, scrollIndex, width, height); } void window_event_scroll_mousedown_call(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers->scroll_mousedown != nullptr) - w->event_handlers->scroll_mousedown(w, scrollIndex, screenCoords); + if (w->event_handlers != nullptr) + if (w->event_handlers->scroll_mousedown != nullptr) + w->event_handlers->scroll_mousedown(w, scrollIndex, screenCoords); } void window_event_scroll_mousedrag_call(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers->scroll_mousedrag != nullptr) - w->event_handlers->scroll_mousedrag(w, scrollIndex, screenCoords); + if (w->event_handlers != nullptr) + if (w->event_handlers->scroll_mousedrag != nullptr) + w->event_handlers->scroll_mousedrag(w, scrollIndex, screenCoords); } void window_event_scroll_mouseover_call(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers->scroll_mouseover != nullptr) - w->event_handlers->scroll_mouseover(w, scrollIndex, screenCoords); + if (w->event_handlers != nullptr) + if (w->event_handlers->scroll_mouseover != nullptr) + w->event_handlers->scroll_mouseover(w, scrollIndex, screenCoords); } void window_event_textinput_call(rct_window* w, rct_widgetindex widgetIndex, char* text) { - if (w->event_handlers->text_input != nullptr) + if (w->event_handlers == nullptr) + { + if (text != nullptr) + { + w->OnTextInput(widgetIndex, text); + } + } + else if (w->event_handlers->text_input != nullptr) + { w->event_handlers->text_input(w, widgetIndex, text); + } } void window_event_viewport_rotate_call(rct_window* w) { - if (w->event_handlers->viewport_rotate != nullptr) - w->event_handlers->viewport_rotate(w); + if (w->event_handlers != nullptr) + if (w->event_handlers->viewport_rotate != nullptr) + w->event_handlers->viewport_rotate(w); } void window_event_unknown_15_call(rct_window* w, int32_t scrollIndex, int32_t scrollAreaType) { - if (w->event_handlers->unknown_15 != nullptr) - w->event_handlers->unknown_15(w, scrollIndex, scrollAreaType); + if (w->event_handlers != nullptr) + if (w->event_handlers->unknown_15 != nullptr) + w->event_handlers->unknown_15(w, scrollIndex, scrollAreaType); } OpenRCT2String window_event_tooltip_call(rct_window* w, const rct_widgetindex widgetIndex, const rct_string_id fallback) { - if (w->event_handlers->tooltip != nullptr) + if (w->event_handlers == nullptr) + { + return w->OnTooltip(widgetIndex, fallback); + } + else if (w->event_handlers->tooltip != nullptr) { return w->event_handlers->tooltip(w, widgetIndex, fallback); } @@ -1534,33 +1571,40 @@ OpenRCT2String window_event_tooltip_call(rct_window* w, const rct_widgetindex wi CursorID window_event_cursor_call(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) { CursorID cursorId = CursorID::Arrow; - if (w->event_handlers->cursor != nullptr) - w->event_handlers->cursor(w, widgetIndex, screenCoords, &cursorId); + if (w->event_handlers != nullptr) + if (w->event_handlers->cursor != nullptr) + w->event_handlers->cursor(w, widgetIndex, screenCoords, &cursorId); return cursorId; } void window_event_moved_call(rct_window* w, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers->moved != nullptr) - w->event_handlers->moved(w, screenCoords); + if (w->event_handlers != nullptr) + if (w->event_handlers->moved != nullptr) + w->event_handlers->moved(w, screenCoords); } void window_event_invalidate_call(rct_window* w) { - if (w->event_handlers->invalidate != nullptr) + if (w->event_handlers == nullptr) + w->OnPrepareDraw(); + else if (w->event_handlers->invalidate != nullptr) w->event_handlers->invalidate(w); } void window_event_paint_call(rct_window* w, rct_drawpixelinfo* dpi) { - if (w->event_handlers->paint != nullptr) + if (w->event_handlers == nullptr) + w->OnDraw(*dpi); + else if (w->event_handlers->paint != nullptr) w->event_handlers->paint(w, dpi); } void window_event_scroll_paint_call(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex) { - if (w->event_handlers->scroll_paint != nullptr) - w->event_handlers->scroll_paint(w, dpi, scrollIndex); + if (w->event_handlers != nullptr) + if (w->event_handlers->scroll_paint != nullptr) + w->event_handlers->scroll_paint(w, dpi, scrollIndex); } /** diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index c72bb4cf08..55db8ea851 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -173,15 +173,15 @@ struct rct_viewport */ struct rct_scroll { - uint16_t flags; // 0x00 - uint16_t h_left; // 0x02 - uint16_t h_right; // 0x04 - uint16_t h_thumb_left; // 0x06 - uint16_t h_thumb_right; // 0x08 - uint16_t v_top; // 0x0A - uint16_t v_bottom; // 0x0C - uint16_t v_thumb_top; // 0x0E - uint16_t v_thumb_bottom; // 0x10 + uint16_t flags{}; // 0x00 + uint16_t h_left{}; // 0x02 + uint16_t h_right{}; // 0x04 + uint16_t h_thumb_left{}; // 0x06 + uint16_t h_thumb_right{}; // 0x08 + uint16_t v_top{}; // 0x0A + uint16_t v_bottom{}; // 0x0C + uint16_t v_thumb_top{}; // 0x0E + uint16_t v_thumb_bottom{}; // 0x10 }; constexpr auto WINDOW_SCROLL_UNDEFINED = std::numeric_limits::max(); @@ -673,12 +673,22 @@ void window_update_all(); void window_set_window_limit(int32_t value); rct_window* WindowCreate( - const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, rct_window_event_list* event_handlers, - rct_windowclass cls, uint16_t flags); + std::unique_ptr&& w, rct_windowclass cls, const ScreenCoordsXY& pos, int32_t width, int32_t height, + uint16_t flags); +template::value>::type* = nullptr> +T* WindowCreate(rct_windowclass cls, const ScreenCoordsXY& pos, int32_t width, int32_t height, uint16_t flags = 0) +{ + return static_cast(WindowCreate(std::make_unique(), cls, pos, width, height, flags)); +} + +rct_window* WindowCreate( + const ScreenCoordsXY& pos, int32_t width, int32_t height, rct_window_event_list* event_handlers, rct_windowclass cls, + uint16_t flags); rct_window* WindowCreateAutoPos( int32_t width, int32_t height, rct_window_event_list* event_handlers, rct_windowclass cls, uint16_t flags); rct_window* WindowCreateCentred( int32_t width, int32_t height, rct_window_event_list* event_handlers, rct_windowclass cls, uint16_t flags); + void window_close(rct_window* window); void window_close_by_class(rct_windowclass cls); void window_close_by_number(rct_windowclass cls, rct_windownumber number); diff --git a/src/openrct2/interface/Window_internal.h b/src/openrct2/interface/Window_internal.h index 1b01dabaac..479bf4e7e8 100644 --- a/src/openrct2/interface/Window_internal.h +++ b/src/openrct2/interface/Window_internal.h @@ -9,6 +9,7 @@ #pragma once +#include "../world/Sprite.h" #include "Window.h" #include @@ -19,32 +20,38 @@ enum class TileInspectorPage : int16_t; struct ResearchItem; struct rct_object_entry; +#ifdef __WARN_SUGGEST_FINAL_METHODS__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wsuggest-final-methods" +# pragma GCC diagnostic ignored "-Wsuggest-final-types" +#endif + /** * Window structure * size: 0x4C0 */ struct rct_window { - rct_window_event_list* event_handlers; - rct_viewport* viewport; - uint64_t enabled_widgets; - uint64_t disabled_widgets; - uint64_t pressed_widgets; - uint64_t hold_down_widgets; - rct_widget* widgets; + rct_window_event_list* event_handlers{}; + rct_viewport* viewport{}; + uint64_t enabled_widgets{}; + uint64_t disabled_widgets{}; + uint64_t pressed_widgets{}; + uint64_t hold_down_widgets{}; + rct_widget* widgets{}; ScreenCoordsXY windowPos; - int16_t width; - int16_t height; - int16_t min_width; - int16_t max_width; - int16_t min_height; - int16_t max_height; - rct_windownumber number; - uint16_t flags; + int16_t width{}; + int16_t height{}; + int16_t min_width{}; + int16_t max_width{}; + int16_t min_height{}; + int16_t max_height{}; + rct_windownumber number{}; + uint16_t flags{}; rct_scroll scrolls[3]; - uint8_t list_item_positions[1024]; - uint16_t no_list_items; // 0 for no items - int16_t selected_list_item; // -1 for none selected + uint8_t list_item_positions[1024]{}; + uint16_t no_list_items{}; // 0 for no items + int16_t selected_list_item{}; // -1 for none selected union { coordinate_focus viewport_focus_coordinates; @@ -72,8 +79,8 @@ struct rct_window int16_t SceneryEntry; // Used in sign window. int16_t var_48C; }; - uint16_t frame_no; // updated every tic for motion in windows sprites - uint16_t list_information_type; // 0 for none, Used as current position of marquee in window_peep + uint16_t frame_no{}; // updated every tic for motion in windows sprites + uint16_t list_information_type{}; // 0 for none, Used as current position of marquee in window_peep union { int16_t picked_peep_frame; // Animation frame of picked peep in staff window and guest window @@ -88,20 +95,60 @@ struct rct_window const scenario_index_entry* highlighted_scenario; uint16_t var_496; }; - int16_t selected_tab; - int16_t var_4AE; - uint16_t viewport_target_sprite; - ScreenCoordsXY savedViewPos; - rct_windowclass classification; - colour_t colours[6]; - VisibilityCache visibility; - uint16_t viewport_smart_follow_sprite; // Handles setting viewport target sprite etc + int16_t selected_tab{}; + int16_t var_4AE{}; + uint16_t viewport_target_sprite{}; + ScreenCoordsXY savedViewPos{}; + rct_windowclass classification{}; + colour_t colours[6]{}; + VisibilityCache visibility{}; + uint16_t viewport_smart_follow_sprite = SPRITE_INDEX_NULL; // Handles setting viewport target sprite etc void SetLocation(const CoordsXYZ& coords); void ScrollToViewport(); void Invalidate(); void RemoveViewport(); + + rct_window() = default; + virtual ~rct_window() = default; + + // Events + virtual void OnOpen() + { + } + virtual void OnClose() + { + } + virtual void OnUpdate() + { + } + virtual void OnPrepareDraw() + { + } + virtual void OnDraw(rct_drawpixelinfo& dpi) + { + } + virtual OpenRCT2String OnTooltip(rct_widgetindex widgetIndex, rct_string_id fallback) + { + return { fallback, {} }; + } + virtual void OnMouseDown(rct_widgetindex widgetIndex) + { + } + virtual void OnMouseUp(rct_widgetindex widgetIndex) + { + } + virtual void OnDropdown(rct_widgetindex widgetIndex, int32_t selectedIndex) + { + } + virtual void OnTextInput(rct_widgetindex widgetIndex, std::string_view text) + { + } }; +#ifdef __WARN_SUGGEST_FINAL_METHODS__ +# pragma GCC diagnostic pop +#endif + // rct2: 0x01420078 extern std::list> g_window_list;