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

3930 lines
132 KiB
C++
Raw Normal View History

2014-04-11 03:42:39 +02:00
/*****************************************************************************
2020-05-01 22:32:41 +02:00
* Copyright (c) 2014-2020 OpenRCT2 developers
2014-04-11 03:42:39 +02:00
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
2014-04-11 03:42:39 +02:00
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
2014-04-11 03:42:39 +02:00
*****************************************************************************/
2018-06-22 23:21:44 +02:00
#include "../UiContext.h"
#include "../interface/InGameConsole.h"
2020-02-11 22:26:05 +01:00
#include "../scripting/CustomMenu.h"
2017-10-17 22:31:05 +02:00
#include <algorithm>
2018-11-21 23:16:04 +01:00
#include <iterator>
#include <limits>
2018-06-22 23:21:44 +02:00
#include <openrct2-ui/interface/Dropdown.h>
#include <openrct2-ui/interface/LandTool.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
2017-12-13 13:02:24 +01:00
#include <openrct2/Cheats.h>
2017-11-11 02:57:45 +01:00
#include <openrct2/Context.h>
#include <openrct2/Editor.h>
#include <openrct2/Game.h>
2017-12-12 14:52:57 +01:00
#include <openrct2/Input.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/OpenRCT2.h>
#include <openrct2/ParkImporter.h>
#include <openrct2/Version.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/BannerPlaceAction.h>
#include <openrct2/actions/BannerSetColourAction.h>
#include <openrct2/actions/ClearAction.h>
#include <openrct2/actions/FootpathAdditionPlaceAction.h>
#include <openrct2/actions/LandLowerAction.h>
#include <openrct2/actions/LandRaiseAction.h>
#include <openrct2/actions/LandSmoothAction.h>
#include <openrct2/actions/LargeSceneryPlaceAction.h>
#include <openrct2/actions/LargeScenerySetColourAction.h>
#include <openrct2/actions/LoadOrQuitAction.h>
#include <openrct2/actions/PauseToggleAction.h>
#include <openrct2/actions/SmallSceneryPlaceAction.h>
#include <openrct2/actions/SmallScenerySetColourAction.h>
#include <openrct2/actions/SurfaceSetStyleAction.h>
#include <openrct2/actions/WallPlaceAction.h>
#include <openrct2/actions/WallSetColourAction.h>
#include <openrct2/actions/WaterLowerAction.h>
#include <openrct2/actions/WaterRaiseAction.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/audio/audio.h>
#include <openrct2/config/Config.h>
2021-11-25 22:47:24 +01:00
#include <openrct2/entity/Staff.h>
#include <openrct2/interface/Chat.h>
#include <openrct2/interface/InteractiveConsole.h>
2017-11-11 02:57:45 +01:00
#include <openrct2/interface/Screenshot.h>
2021-12-12 00:06:06 +01:00
#include <openrct2/localisation/Formatter.h>
2017-11-11 02:57:45 +01:00
#include <openrct2/network/network.h>
#include <openrct2/paint/VirtualFloor.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/scenario/Scenario.h>
#include <openrct2/ui/UiContext.h>
#include <openrct2/util/Math.hpp>
2017-11-11 02:57:45 +01:00
#include <openrct2/windows/Intent.h>
2018-01-11 10:59:26 +01:00
#include <openrct2/world/Footpath.h>
2017-11-20 11:13:55 +01:00
#include <openrct2/world/LargeScenery.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/world/Park.h>
2018-01-11 10:59:26 +01:00
#include <openrct2/world/Scenery.h>
2017-11-20 11:13:55 +01:00
#include <openrct2/world/SmallScenery.h>
2018-05-01 16:33:16 +02:00
#include <openrct2/world/Surface.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/world/Wall.h>
#include <string>
2018-03-11 23:25:34 +01:00
using namespace OpenRCT2;
2018-03-11 23:25:34 +01:00
using namespace OpenRCT2::Ui;
2014-04-11 03:42:39 +02:00
enum
{
WIDX_PAUSE,
WIDX_FILE_MENU,
WIDX_MUTE,
WIDX_ZOOM_OUT,
WIDX_ZOOM_IN,
WIDX_ROTATE,
WIDX_VIEW_MENU,
WIDX_MAP,
WIDX_LAND,
WIDX_WATER,
WIDX_SCENERY,
WIDX_PATH,
WIDX_CONSTRUCT_RIDE,
WIDX_RIDES,
WIDX_PARK,
WIDX_STAFF,
WIDX_GUESTS,
WIDX_CLEAR_SCENERY,
WIDX_FASTFORWARD,
WIDX_CHEATS,
WIDX_DEBUG,
WIDX_FINANCES,
WIDX_RESEARCH,
WIDX_NEWS,
WIDX_NETWORK,
WIDX_CHAT,
WIDX_SEPARATOR,
2014-04-11 03:42:39 +02:00
};
validate_global_widx(WC_TOP_TOOLBAR, WIDX_PAUSE);
validate_global_widx(WC_TOP_TOOLBAR, WIDX_LAND);
validate_global_widx(WC_TOP_TOOLBAR, WIDX_WATER);
validate_global_widx(WC_TOP_TOOLBAR, WIDX_SCENERY);
validate_global_widx(WC_TOP_TOOLBAR, WIDX_PATH);
enum FileMenuDdidx
{
DDIDX_NEW_GAME = 0,
DDIDX_LOAD_GAME = 1,
DDIDX_SAVE_GAME = 2,
DDIDX_SAVE_GAME_AS = 3,
// separator
DDIDX_ABOUT = 5,
DDIDX_OPTIONS = 6,
DDIDX_SCREENSHOT = 7,
DDIDX_GIANT_SCREENSHOT = 8,
// separator
DDIDX_FILE_BUG_ON_GITHUB = 10,
DDIDX_UPDATE_AVAILABLE = 11,
// separator
DDIDX_QUIT_TO_MENU = 13,
DDIDX_EXIT_OPENRCT2 = 14,
};
enum TopToolbarViewMenuDdidx
{
DDIDX_UNDERGROUND_INSIDE = 0,
2021-05-24 16:54:30 +02:00
DDIDX_TRANSPARENT_WATER = 1,
2021-05-24 16:30:46 +02:00
DDIDX_HIDE_BASE = 2,
DDIDX_HIDE_VERTICAL = 3,
// separator
2022-03-06 16:04:11 +01:00
DDIDX_HIDE_RIDES = 5,
DDIDX_HIDE_VEHICLES = 6,
DDIDX_HIDE_VEGETATION = 7,
2022-03-06 16:04:11 +01:00
DDIDX_HIDE_SCENERY = 8,
DDIDX_HIDE_PATHS = 9,
DDIDX_HIDE_SUPPORTS = 10,
DDIDX_HIDE_GUESTS = 11,
DDIDX_HIDE_STAFF = 12,
2021-05-24 16:30:46 +02:00
// separator
2022-03-06 16:04:11 +01:00
DDIDX_LAND_HEIGHTS = 14,
DDIDX_TRACK_HEIGHTS = 15,
DDIDX_PATH_HEIGHTS = 16,
2021-05-24 16:30:46 +02:00
// separator
2022-03-06 16:04:11 +01:00
DDIDX_VIEW_CLIPPING = 18,
DDIDX_HIGHLIGHT_PATH_ISSUES = 19,
// separator
2022-03-06 16:04:11 +01:00
DDIDX_TRANSPARENCY = 21,
TOP_TOOLBAR_VIEW_MENU_COUNT,
};
enum TopToolbarDebugDdidx
{
DDIDX_CONSOLE = 0,
DDIDX_DEBUG_PAINT = 1,
TOP_TOOLBAR_DEBUG_COUNT,
};
enum TopToolbarNetworkDdidx
{
2019-01-29 19:51:07 +01:00
DDIDX_MULTIPLAYER = 0,
DDIDX_MULTIPLAYER_RECONNECT = 1,
TOP_TOOLBAR_NETWORK_COUNT,
};
2015-07-16 19:32:43 +02:00
enum
{
DDIDX_CHEATS,
DDIDX_TILE_INSPECTOR = 1,
DDIDX_OBJECT_SELECTION = 2,
DDIDX_INVENTIONS_LIST = 3,
DDIDX_SCENARIO_OPTIONS = 4,
2020-10-11 18:41:23 +02:00
DDIDX_OBJECTIVE_OPTIONS = 5,
// 6 is a separator
DDIDX_ENABLE_SANDBOX_MODE = 7,
DDIDX_DISABLE_CLEARANCE_CHECKS = 8,
DDIDX_DISABLE_SUPPORT_LIMITS = 9,
TOP_TOOLBAR_CHEATS_COUNT,
2015-06-26 23:40:09 +02:00
};
enum
{
DDIDX_SHOW_MAP,
DDIDX_OPEN_VIEWPORT,
};
enum
{
DDIDX_ROTATE_CLOCKWISE,
DDIDX_ROTATE_ANTI_CLOCKWISE,
};
#pragma region Toolbar_widget_ordering
// clang-format off
// from left to right
static constexpr const int32_t left_aligned_widgets_order[] = {
WIDX_PAUSE,
WIDX_FASTFORWARD,
WIDX_FILE_MENU,
WIDX_MUTE,
WIDX_NETWORK,
WIDX_CHAT,
WIDX_CHEATS,
WIDX_DEBUG,
WIDX_SEPARATOR,
WIDX_ZOOM_OUT,
WIDX_ZOOM_IN,
WIDX_ROTATE,
WIDX_VIEW_MENU,
WIDX_MAP,
};
// from right to left
static constexpr const int32_t right_aligned_widgets_order[] = {
WIDX_NEWS,
WIDX_GUESTS,
WIDX_STAFF,
WIDX_PARK,
WIDX_RIDES,
WIDX_RESEARCH,
WIDX_FINANCES,
WIDX_SEPARATOR,
WIDX_CONSTRUCT_RIDE,
WIDX_PATH,
WIDX_SCENERY,
WIDX_WATER,
WIDX_LAND,
WIDX_CLEAR_SCENERY,
};
#pragma endregion
2015-02-09 19:32:58 +01:00
static rct_widget window_top_toolbar_widgets[] = {
MakeRemapWidget({ 0, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TOOLBAR_PAUSE, STR_PAUSE_GAME_TIP ), // Pause
MakeRemapWidget({ 60, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TOOLBAR_FILE, STR_DISC_AND_GAME_OPTIONS_TIP ), // File menu
MakeRemapWidget({250, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_G2_TOOLBAR_MUTE, STR_TOOLBAR_MUTE_TIP ), // Mute
MakeRemapWidget({100, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_ZOOM_OUT, STR_ZOOM_OUT_TIP ), // Zoom out
MakeRemapWidget({130, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_ZOOM_IN, STR_ZOOM_IN_TIP ), // Zoom in
MakeRemapWidget({160, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_ROTATE, STR_ROTATE_TIP ), // Rotate camera
MakeRemapWidget({190, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_VIEW, STR_VIEW_OPTIONS_TIP ), // Transparency menu
MakeRemapWidget({220, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Secondary , SPR_TOOLBAR_MAP, STR_SHOW_MAP_TIP ), // Map
MakeRemapWidget({267, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_LAND, STR_ADJUST_LAND_TIP ), // Land
MakeRemapWidget({297, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_WATER, STR_ADJUST_WATER_TIP ), // Water
MakeRemapWidget({327, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_SCENERY, STR_PLACE_SCENERY_TIP ), // Scenery
MakeRemapWidget({357, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_FOOTPATH, STR_BUILD_FOOTPATH_TIP ), // Path
MakeRemapWidget({387, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_CONSTRUCT_RIDE, STR_BUILD_RIDE_TIP ), // Construct ride
MakeRemapWidget({490, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TOOLBAR_RIDES, STR_RIDES_IN_PARK_TIP ), // Rides
MakeRemapWidget({520, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TOOLBAR_PARK, STR_PARK_INFORMATION_TIP ), // Park
MakeRemapWidget({550, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_STAFF_TIP ), // Staff
MakeRemapWidget({560, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TOOLBAR_GUESTS, STR_GUESTS_TIP ), // Guests
MakeRemapWidget({560, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Tertiary , SPR_TOOLBAR_CLEAR_SCENERY, STR_CLEAR_SCENERY_TIP ), // Clear scenery
MakeRemapWidget({ 30, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_GAME_SPEED_TIP ), // Fast forward
MakeRemapWidget({ 30, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_CHEATS_TIP ), // Cheats
MakeRemapWidget({ 30, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_DEBUG_TIP ), // Debug
MakeRemapWidget({ 30, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_SCENARIO_OPTIONS_FINANCIAL_TIP), // Finances
MakeRemapWidget({ 30, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_FINANCES_RESEARCH_TIP ), // Research
MakeRemapWidget({ 30, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Quaternary, SPR_TAB_TOOLBAR, STR_SHOW_RECENT_MESSAGES_TIP ), // News
MakeRemapWidget({ 30, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_G2_TOOLBAR_MULTIPLAYER, STR_SHOW_MULTIPLAYER_STATUS_TIP ), // Network
MakeRemapWidget({ 30, 0}, {30, TOP_TOOLBAR_HEIGHT + 1}, WindowWidgetType::TrnBtn, WindowColour::Primary , SPR_TAB_TOOLBAR, STR_TOOLBAR_CHAT_TIP ), // Chat
MakeWidget ({ 0, 0}, {10, 1}, WindowWidgetType::Empty, WindowColour::Primary ), // Artificial widget separator
2021-09-26 11:11:42 +02:00
WIDGETS_END,
2014-04-11 03:42:39 +02:00
};
// clang-format on
2014-04-11 03:42:39 +02:00
static void WindowTopToolbarMouseup(rct_window* w, rct_widgetindex widgetIndex);
static void WindowTopToolbarMousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget);
static void WindowTopToolbarDropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex);
static void WindowTopToolbarToolUpdate(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
static void WindowTopToolbarToolDown(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
static void WindowTopToolbarToolDrag(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
static void WindowTopToolbarToolUp(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoordsy);
static void WindowTopToolbarToolAbort(rct_window* w, rct_widgetindex widgetIndex);
static void WindowTopToolbarInvalidate(rct_window* w);
static void WindowTopToolbarPaint(rct_window* w, rct_drawpixelinfo* dpi);
static rct_window_event_list window_top_toolbar_events([](auto& events) {
events.mouse_up = &WindowTopToolbarMouseup;
events.mouse_down = &WindowTopToolbarMousedown;
events.dropdown = &WindowTopToolbarDropdown;
events.tool_update = &WindowTopToolbarToolUpdate;
events.tool_down = &WindowTopToolbarToolDown;
events.tool_drag = &WindowTopToolbarToolDrag;
events.tool_up = &WindowTopToolbarToolUp;
events.tool_abort = &WindowTopToolbarToolAbort;
events.invalidate = &WindowTopToolbarInvalidate;
events.paint = &WindowTopToolbarPaint;
});
2014-04-11 03:42:39 +02:00
static void TopToolbarInitViewMenu(rct_window* window, rct_widget* widget);
static void TopToolbarViewMenuDropdown(int16_t dropdownIndex);
static void TopToolbarInitMapMenu(rct_window* window, rct_widget* widget);
static void TopToolbarMapMenuDropdown(int16_t dropdownIndex);
static void TopToolbarInitFastforwardMenu(rct_window* window, rct_widget* widget);
static void TopToolbarFastforwardMenuDropdown(int16_t dropdownIndex);
static void TopToolbarInitRotateMenu(rct_window* window, rct_widget* widget);
static void TopToolbarRotateMenuDropdown(int16_t dropdownIndex);
static void TopToolbarInitCheatsMenu(rct_window* window, rct_widget* widget);
static void TopToolbarCheatsMenuDropdown(int16_t dropdownIndex);
static void TopToolbarInitDebugMenu(rct_window* window, rct_widget* widget);
static void TopToolbarDebugMenuDropdown(int16_t dropdownIndex);
static void TopToolbarInitNetworkMenu(rct_window* window, rct_widget* widget);
static void TopToolbarNetworkMenuDropdown(int16_t dropdownIndex);
static void ToggleFootpathWindow();
static void ToggleLandWindow(rct_window* topToolbar, rct_widgetindex widgetIndex);
static void ToggleClearSceneryWindow(rct_window* topToolbar, rct_widgetindex widgetIndex);
static void ToggleWaterWindow(rct_window* topToolbar, rct_widgetindex widgetIndex);
static money64 SelectionLowerLand(uint8_t flags);
static money64 SelectionRaiseLand(uint8_t flags);
2015-05-26 21:36:05 +02:00
2019-01-02 12:59:37 +01:00
static ClearAction GetClearAction();
static bool _landToolBlocked;
2018-06-22 23:21:44 +02:00
static uint8_t _unkF64F0E;
static int16_t _unkF64F0A;
2015-05-25 21:36:40 +02:00
2014-04-11 03:42:39 +02:00
/**
* Creates the main game top toolbar window.
* rct2: 0x0066B485 (part of 0x0066B3E8)
*/
rct_window* WindowTopToolbarOpen()
2014-04-11 03:42:39 +02:00
{
rct_window* window = WindowCreate(
ScreenCoordsXY(0, 0), context_get_width(), TOP_TOOLBAR_HEIGHT + 1, &window_top_toolbar_events, WC_TOP_TOOLBAR,
2018-06-22 23:21:44 +02:00
WF_STICK_TO_FRONT | WF_TRANSPARENT | WF_NO_BACKGROUND);
window->widgets = window_top_toolbar_widgets;
WindowInitScrollWidgets(*window);
2017-11-11 02:57:45 +01:00
return window;
2014-04-11 03:42:39 +02:00
}
/**
2015-10-20 20:16:30 +02:00
*
2014-04-11 03:42:39 +02:00
* rct2: 0x0066C957
*/
static void WindowTopToolbarMouseup(rct_window* w, rct_widgetindex widgetIndex)
2014-04-11 03:42:39 +02:00
{
2018-06-22 23:21:44 +02:00
rct_window* mainWindow;
2018-06-22 23:21:44 +02:00
switch (widgetIndex)
{
case WIDX_PAUSE:
if (network_get_mode() != NETWORK_MODE_CLIENT)
{
auto pauseToggleAction = PauseToggleAction();
GameActions::Execute(&pauseToggleAction);
2018-06-22 23:21:44 +02:00
}
break;
case WIDX_ZOOM_OUT:
if ((mainWindow = window_get_main()) != nullptr)
window_zoom_out(mainWindow, false);
break;
case WIDX_ZOOM_IN:
if ((mainWindow = window_get_main()) != nullptr)
window_zoom_in(mainWindow, false);
break;
case WIDX_CLEAR_SCENERY:
ToggleClearSceneryWindow(w, WIDX_CLEAR_SCENERY);
2018-06-22 23:21:44 +02:00
break;
case WIDX_LAND:
ToggleLandWindow(w, WIDX_LAND);
2018-06-22 23:21:44 +02:00
break;
case WIDX_WATER:
ToggleWaterWindow(w, WIDX_WATER);
2018-06-22 23:21:44 +02:00
break;
case WIDX_SCENERY:
if (!tool_set(*w, WIDX_SCENERY, Tool::Arrow))
2018-06-22 23:21:44 +02:00
{
input_set_flag(INPUT_FLAG_6, true);
context_open_window(WC_SCENERY);
}
break;
case WIDX_PATH:
ToggleFootpathWindow();
2018-06-22 23:21:44 +02:00
break;
case WIDX_CONSTRUCT_RIDE:
context_open_window(WC_CONSTRUCT_RIDE);
break;
case WIDX_RIDES:
context_open_window(WC_RIDE_LIST);
break;
case WIDX_PARK:
context_open_window(WC_PARK_INFORMATION);
break;
case WIDX_STAFF:
context_open_window(WC_STAFF_LIST);
break;
case WIDX_GUESTS:
context_open_window(WC_GUEST_LIST);
break;
case WIDX_FINANCES:
context_open_window(WC_FINANCES);
break;
case WIDX_RESEARCH:
context_open_window(WC_RESEARCH);
break;
case WIDX_NEWS:
context_open_window(WC_RECENT_NEWS);
break;
case WIDX_MUTE:
OpenRCT2::Audio::ToggleAllSounds();
2018-06-22 23:21:44 +02:00
break;
case WIDX_CHAT:
if (chat_available())
{
chat_toggle();
}
else
{
context_show_error(STR_CHAT_UNAVAILABLE, STR_NONE, {});
}
break;
}
2014-04-11 03:42:39 +02:00
}
/**
2015-10-20 20:16:30 +02:00
*
2014-04-11 03:42:39 +02:00
* rct2: 0x0066CA3B
*/
static void WindowTopToolbarMousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget)
2014-04-11 03:42:39 +02:00
{
2021-09-04 17:38:17 +02:00
int32_t numItems = 0;
2018-06-22 23:21:44 +02:00
switch (widgetIndex)
{
case WIDX_FILE_MENU:
if (gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER))
{
gDropdownItems[numItems++].Format = STR_ABOUT;
gDropdownItems[numItems++].Format = STR_OPTIONS;
gDropdownItems[numItems++].Format = STR_SCREENSHOT;
gDropdownItems[numItems++].Format = STR_GIANT_SCREENSHOT;
gDropdownItems[numItems++].Format = STR_EMPTY;
gDropdownItems[numItems++].Format = STR_FILE_BUG_ON_GITHUB;
if (OpenRCT2::GetContext()->HasNewVersionInfo())
gDropdownItems[numItems++].Format = STR_UPDATE_AVAILABLE;
gDropdownItems[numItems++].Format = STR_EMPTY;
2018-06-22 23:21:44 +02:00
if (gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER)
gDropdownItems[numItems++].Format = STR_QUIT_ROLLERCOASTER_DESIGNER;
else
gDropdownItems[numItems++].Format = STR_QUIT_TRACK_DESIGNS_MANAGER;
gDropdownItems[numItems++].Format = STR_EXIT_OPENRCT2;
2018-06-22 23:21:44 +02:00
}
else if (gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR)
{
gDropdownItems[numItems++].Format = STR_LOAD_LANDSCAPE;
gDropdownItems[numItems++].Format = STR_SAVE_LANDSCAPE;
gDropdownItems[numItems++].Format = STR_EMPTY;
gDropdownItems[numItems++].Format = STR_ABOUT;
gDropdownItems[numItems++].Format = STR_OPTIONS;
gDropdownItems[numItems++].Format = STR_SCREENSHOT;
gDropdownItems[numItems++].Format = STR_GIANT_SCREENSHOT;
gDropdownItems[numItems++].Format = STR_EMPTY;
gDropdownItems[numItems++].Format = STR_FILE_BUG_ON_GITHUB;
if (OpenRCT2::GetContext()->HasNewVersionInfo())
gDropdownItems[numItems++].Format = STR_UPDATE_AVAILABLE;
gDropdownItems[numItems++].Format = STR_EMPTY;
gDropdownItems[numItems++].Format = STR_QUIT_SCENARIO_EDITOR;
gDropdownItems[numItems++].Format = STR_EXIT_OPENRCT2;
2018-06-22 23:21:44 +02:00
}
else
{
gDropdownItems[numItems++].Format = STR_NEW_GAME;
gDropdownItems[numItems++].Format = STR_LOAD_GAME;
gDropdownItems[numItems++].Format = STR_SAVE_GAME;
gDropdownItems[numItems++].Format = STR_SAVE_GAME_AS;
gDropdownItems[numItems++].Format = STR_EMPTY;
gDropdownItems[numItems++].Format = STR_ABOUT;
gDropdownItems[numItems++].Format = STR_OPTIONS;
gDropdownItems[numItems++].Format = STR_SCREENSHOT;
gDropdownItems[numItems++].Format = STR_GIANT_SCREENSHOT;
gDropdownItems[numItems++].Format = STR_EMPTY;
gDropdownItems[numItems++].Format = STR_FILE_BUG_ON_GITHUB;
if (OpenRCT2::GetContext()->HasNewVersionInfo())
gDropdownItems[numItems++].Format = STR_UPDATE_AVAILABLE;
gDropdownItems[numItems++].Format = STR_EMPTY;
gDropdownItems[numItems++].Format = STR_QUIT_TO_MENU;
gDropdownItems[numItems++].Format = STR_EXIT_OPENRCT2;
2018-06-22 23:21:44 +02:00
}
WindowDropdownShowText(
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, w->colours[0] | 0x80,
Dropdown::Flag::StayOpen, numItems);
2018-06-22 23:21:44 +02:00
break;
case WIDX_CHEATS:
TopToolbarInitCheatsMenu(w, widget);
2018-06-22 23:21:44 +02:00
break;
case WIDX_VIEW_MENU:
TopToolbarInitViewMenu(w, widget);
2018-06-22 23:21:44 +02:00
break;
case WIDX_MAP:
TopToolbarInitMapMenu(w, widget);
2018-06-22 23:21:44 +02:00
break;
case WIDX_FASTFORWARD:
TopToolbarInitFastforwardMenu(w, widget);
2018-06-22 23:21:44 +02:00
break;
case WIDX_ROTATE:
TopToolbarInitRotateMenu(w, widget);
2018-06-22 23:21:44 +02:00
break;
case WIDX_DEBUG:
TopToolbarInitDebugMenu(w, widget);
2018-06-22 23:21:44 +02:00
break;
case WIDX_NETWORK:
TopToolbarInitNetworkMenu(w, widget);
2018-06-22 23:21:44 +02:00
break;
}
2014-04-11 03:42:39 +02:00
}
static void WindowTopToolbarScenarioselectCallback(const utf8* path)
{
window_close_by_class(WC_EDITOR_OBJECT_SELECTION);
game_notify_map_change();
GetContext()->LoadParkFromFile(path, false, true);
game_load_scripts();
2022-02-20 03:05:24 +01:00
game_notify_map_changed();
}
2014-04-11 03:42:39 +02:00
/**
2015-06-26 23:40:09 +02:00
*
2014-04-11 03:42:39 +02:00
* rct2: 0x0066C9EA
*/
static void WindowTopToolbarDropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex)
2014-04-11 03:42:39 +02:00
{
2018-06-22 23:21:44 +02:00
switch (widgetIndex)
{
case WIDX_FILE_MENU:
2018-06-22 23:21:44 +02:00
// New game is only available in the normal game. Skip one position to avoid incorrect mappings in the menus of the
// other modes.
if (gScreenFlags & (SCREEN_FLAGS_SCENARIO_EDITOR))
dropdownIndex += 1;
2018-06-22 23:21:44 +02:00
// Quicksave is only available in the normal game. Skip one position to avoid incorrect mappings in the menus of the
// other modes.
if (gScreenFlags & (SCREEN_FLAGS_SCENARIO_EDITOR) && dropdownIndex > DDIDX_LOAD_GAME)
dropdownIndex += 1;
2018-06-22 23:21:44 +02:00
// Track designer and track designs manager start with About, not Load/save
if (gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER))
dropdownIndex += DDIDX_ABOUT;
// The "Update available" menu item is only available when there is one
if (dropdownIndex >= DDIDX_UPDATE_AVAILABLE && !OpenRCT2::GetContext()->HasNewVersionInfo())
dropdownIndex += 1;
2018-06-22 23:21:44 +02:00
switch (dropdownIndex)
{
case DDIDX_NEW_GAME:
{
auto intent = Intent(WC_SCENARIO_SELECT);
intent.putExtra(INTENT_EXTRA_CALLBACK, reinterpret_cast<void*>(WindowTopToolbarScenarioselectCallback));
2018-06-22 23:21:44 +02:00
context_open_intent(&intent);
break;
}
case DDIDX_LOAD_GAME:
2019-02-21 10:34:30 +01:00
{
auto loadOrQuitAction = LoadOrQuitAction(LoadOrQuitModes::OpenSavePrompt);
GameActions::Execute(&loadOrQuitAction);
2018-06-22 23:21:44 +02:00
break;
2019-02-21 10:34:30 +01:00
}
2018-06-22 23:21:44 +02:00
case DDIDX_SAVE_GAME:
tool_cancel();
save_game();
break;
case DDIDX_SAVE_GAME_AS:
if (gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR)
{
auto intent = Intent(WC_LOADSAVE);
intent.putExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_SAVE | LOADSAVETYPE_LANDSCAPE);
2021-04-05 19:01:43 +02:00
intent.putExtra(INTENT_EXTRA_PATH, gScenarioName);
2018-06-22 23:21:44 +02:00
context_open_intent(&intent);
}
else
{
tool_cancel();
save_game_as();
}
break;
case DDIDX_ABOUT:
context_open_window(WC_ABOUT);
break;
case DDIDX_OPTIONS:
context_open_window(WC_OPTIONS);
break;
case DDIDX_SCREENSHOT:
gScreenshotCountdown = 10;
break;
case DDIDX_GIANT_SCREENSHOT:
screenshot_giant();
break;
case DDIDX_FILE_BUG_ON_GITHUB:
{
std::string url = "https://github.com/OpenRCT2/OpenRCT2/issues/"
"new?assignees=&labels=bug&template=bug_report.yaml";
auto versionStr = String::URLEncode(gVersionInfoFull);
url.append("&openrct2_build=" + versionStr);
OpenRCT2::GetContext()->GetUiContext()->OpenURL(url);
}
break;
case DDIDX_UPDATE_AVAILABLE:
context_open_window_view(WV_NEW_VERSION_INFO);
break;
2018-06-22 23:21:44 +02:00
case DDIDX_QUIT_TO_MENU:
2019-02-21 10:34:30 +01:00
{
2018-06-22 23:21:44 +02:00
window_close_by_class(WC_MANAGE_TRACK_DESIGN);
window_close_by_class(WC_TRACK_DELETE_PROMPT);
auto loadOrQuitAction = LoadOrQuitAction(LoadOrQuitModes::OpenSavePrompt, PromptMode::SaveBeforeQuit);
2019-02-21 10:34:30 +01:00
GameActions::Execute(&loadOrQuitAction);
2018-06-22 23:21:44 +02:00
break;
2019-02-21 10:34:30 +01:00
}
2018-06-22 23:21:44 +02:00
case DDIDX_EXIT_OPENRCT2:
context_quit();
break;
}
break;
2018-06-22 23:21:44 +02:00
case WIDX_CHEATS:
TopToolbarCheatsMenuDropdown(dropdownIndex);
break;
2018-06-22 23:21:44 +02:00
case WIDX_VIEW_MENU:
TopToolbarViewMenuDropdown(dropdownIndex);
break;
2018-06-22 23:21:44 +02:00
case WIDX_MAP:
TopToolbarMapMenuDropdown(dropdownIndex);
break;
2018-06-22 23:21:44 +02:00
case WIDX_FASTFORWARD:
TopToolbarFastforwardMenuDropdown(dropdownIndex);
break;
2018-06-22 23:21:44 +02:00
case WIDX_ROTATE:
TopToolbarRotateMenuDropdown(dropdownIndex);
break;
2018-06-22 23:21:44 +02:00
case WIDX_DEBUG:
TopToolbarDebugMenuDropdown(dropdownIndex);
2018-06-22 23:21:44 +02:00
break;
case WIDX_NETWORK:
TopToolbarNetworkMenuDropdown(dropdownIndex);
break;
}
2014-04-11 03:42:39 +02:00
}
/**
2015-10-20 20:16:30 +02:00
*
2014-04-11 03:42:39 +02:00
* rct2: 0x0066C810
*/
static void WindowTopToolbarInvalidate(rct_window* w)
2014-04-11 03:42:39 +02:00
{
int32_t x, widgetIndex, widgetWidth, firstAlignment;
2018-06-22 23:21:44 +02:00
rct_widget* widget;
// Enable / disable buttons
window_top_toolbar_widgets[WIDX_PAUSE].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_FILE_MENU].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_ZOOM_OUT].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_ZOOM_IN].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_ROTATE].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_VIEW_MENU].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_MAP].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_MUTE].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_CHAT].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_LAND].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_WATER].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_SCENERY].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_PATH].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_CONSTRUCT_RIDE].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_RIDES].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_PARK].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_STAFF].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_GUESTS].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_CLEAR_SCENERY].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_FINANCES].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_RESEARCH].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_FASTFORWARD].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_CHEATS].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_DEBUG].type = gConfigGeneral.debugging_tools ? WindowWidgetType::TrnBtn
: WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_NEWS].type = WindowWidgetType::TrnBtn;
window_top_toolbar_widgets[WIDX_NETWORK].type = WindowWidgetType::TrnBtn;
if (!gConfigInterface.toolbar_show_mute)
window_top_toolbar_widgets[WIDX_MUTE].type = WindowWidgetType::Empty;
if (!gConfigInterface.toolbar_show_chat)
window_top_toolbar_widgets[WIDX_CHAT].type = WindowWidgetType::Empty;
if (!gConfigInterface.toolbar_show_research)
window_top_toolbar_widgets[WIDX_RESEARCH].type = WindowWidgetType::Empty;
if (!gConfigInterface.toolbar_show_cheats)
window_top_toolbar_widgets[WIDX_CHEATS].type = WindowWidgetType::Empty;
if (!gConfigInterface.toolbar_show_news)
window_top_toolbar_widgets[WIDX_NEWS].type = WindowWidgetType::Empty;
if (!gConfigInterface.toolbar_show_zoom)
{
window_top_toolbar_widgets[WIDX_ZOOM_IN].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_ZOOM_OUT].type = WindowWidgetType::Empty;
}
if (gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR || gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)
2018-06-22 23:21:44 +02:00
{
window_top_toolbar_widgets[WIDX_PAUSE].type = WindowWidgetType::Empty;
}
if ((gParkFlags & PARK_FLAGS_NO_MONEY) || !gConfigInterface.toolbar_show_finances)
window_top_toolbar_widgets[WIDX_FINANCES].type = WindowWidgetType::Empty;
if (gScreenFlags & SCREEN_FLAGS_EDITOR)
{
window_top_toolbar_widgets[WIDX_PARK].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_STAFF].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_GUESTS].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_FINANCES].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_RESEARCH].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_NEWS].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_NETWORK].type = WindowWidgetType::Empty;
2021-04-05 19:01:43 +02:00
if (gEditorStep != EditorStep::LandscapeEditor)
2018-06-22 23:21:44 +02:00
{
window_top_toolbar_widgets[WIDX_LAND].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_WATER].type = WindowWidgetType::Empty;
}
2021-04-05 19:01:43 +02:00
if (gEditorStep != EditorStep::RollercoasterDesigner)
2018-06-22 23:21:44 +02:00
{
window_top_toolbar_widgets[WIDX_RIDES].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_CONSTRUCT_RIDE].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_FASTFORWARD].type = WindowWidgetType::Empty;
}
2021-04-05 19:01:43 +02:00
if (gEditorStep != EditorStep::LandscapeEditor && gEditorStep != EditorStep::RollercoasterDesigner)
2018-06-22 23:21:44 +02:00
{
window_top_toolbar_widgets[WIDX_MAP].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_SCENERY].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_PATH].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_CLEAR_SCENERY].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_ZOOM_OUT].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_ZOOM_IN].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_ROTATE].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_VIEW_MENU].type = WindowWidgetType::Empty;
}
2018-06-22 23:21:44 +02:00
}
switch (network_get_mode())
{
case NETWORK_MODE_NONE:
window_top_toolbar_widgets[WIDX_NETWORK].type = WindowWidgetType::Empty;
window_top_toolbar_widgets[WIDX_CHAT].type = WindowWidgetType::Empty;
break;
case NETWORK_MODE_CLIENT:
window_top_toolbar_widgets[WIDX_PAUSE].type = WindowWidgetType::Empty;
[[fallthrough]];
case NETWORK_MODE_SERVER:
window_top_toolbar_widgets[WIDX_FASTFORWARD].type = WindowWidgetType::Empty;
break;
}
// Align left hand side toolbar buttons
firstAlignment = 1;
x = 0;
2018-11-21 23:16:04 +01:00
for (size_t i = 0; i < std::size(left_aligned_widgets_order); ++i)
2018-06-22 23:21:44 +02:00
{
widgetIndex = left_aligned_widgets_order[i];
widget = &window_top_toolbar_widgets[widgetIndex];
if (widget->type == WindowWidgetType::Empty && widgetIndex != WIDX_SEPARATOR)
continue;
if (firstAlignment && widgetIndex == WIDX_SEPARATOR)
continue;
widgetWidth = widget->width();
widget->left = x;
x += widgetWidth;
widget->right = x;
x += 1;
firstAlignment = 0;
}
// Align right hand side toolbar buttons
int32_t screenWidth = context_get_width();
firstAlignment = 1;
x = std::max(640, screenWidth);
2018-11-21 23:16:04 +01:00
for (size_t i = 0; i < std::size(right_aligned_widgets_order); ++i)
2018-06-22 23:21:44 +02:00
{
widgetIndex = right_aligned_widgets_order[i];
widget = &window_top_toolbar_widgets[widgetIndex];
if (widget->type == WindowWidgetType::Empty && widgetIndex != WIDX_SEPARATOR)
continue;
if (firstAlignment && widgetIndex == WIDX_SEPARATOR)
continue;
widgetWidth = widget->width();
x -= 1;
widget->right = x;
x -= widgetWidth;
widget->left = x;
firstAlignment = 0;
}
// Footpath button pressed down
2017-08-15 10:07:44 +02:00
if (window_find_by_class(WC_FOOTPATH) == nullptr)
w->pressed_widgets &= ~(1ULL << WIDX_PATH);
else
w->pressed_widgets |= (1ULL << WIDX_PATH);
if (gGamePaused & GAME_PAUSED_NORMAL)
w->pressed_widgets |= (1ULL << WIDX_PAUSE);
else
w->pressed_widgets &= ~(1ULL << WIDX_PAUSE);
if (!OpenRCT2::Audio::gGameSoundsOff)
window_top_toolbar_widgets[WIDX_MUTE].image = IMAGE_TYPE_REMAP | SPR_G2_TOOLBAR_MUTE;
else
window_top_toolbar_widgets[WIDX_MUTE].image = IMAGE_TYPE_REMAP | SPR_G2_TOOLBAR_UNMUTE;
// Set map button to the right image.
if (window_top_toolbar_widgets[WIDX_MAP].type != WindowWidgetType::Empty)
{
2021-11-24 18:08:41 +01:00
static constexpr uint32_t _imageIdByRotation[] = {
SPR_G2_MAP_NORTH,
SPR_G2_MAP_WEST,
SPR_G2_MAP_SOUTH,
SPR_G2_MAP_EAST,
};
2021-11-24 18:08:41 +01:00
uint32_t mapImageId = _imageIdByRotation[get_current_rotation()];
window_top_toolbar_widgets[WIDX_MAP].image = IMAGE_TYPE_REMAP | mapImageId;
}
// Zoomed out/in disable. Not sure where this code is in the original.
const auto* mainWindow = window_get_main();
if (mainWindow == nullptr || mainWindow->viewport == nullptr)
{
log_error("mainWindow or mainWindow->viewport is null!");
return;
}
if (mainWindow->viewport->zoom == ZoomLevel::min())
2017-11-30 22:21:25 +01:00
{
w->disabled_widgets |= (1ULL << WIDX_ZOOM_IN);
2017-11-30 22:21:25 +01:00
}
else if (mainWindow->viewport->zoom >= ZoomLevel::max())
2017-11-30 22:21:25 +01:00
{
w->disabled_widgets |= (1ULL << WIDX_ZOOM_OUT);
2017-11-30 22:21:25 +01:00
}
else
{
w->disabled_widgets &= ~((1ULL << WIDX_ZOOM_IN) | (1ULL << WIDX_ZOOM_OUT));
}
2014-04-11 03:42:39 +02:00
}
/**
2015-10-20 20:16:30 +02:00
*
2014-04-11 03:42:39 +02:00
* rct2: 0x0066C8EC
*/
static void WindowTopToolbarPaint(rct_window* w, rct_drawpixelinfo* dpi)
2014-04-11 03:42:39 +02:00
{
int32_t imgId;
WindowDrawWidgets(*w, dpi);
ScreenCoordsXY screenPos{};
// Draw staff button image (setting masks to the staff colours)
if (window_top_toolbar_widgets[WIDX_STAFF].type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
screenPos = { w->windowPos.x + window_top_toolbar_widgets[WIDX_STAFF].left,
w->windowPos.y + window_top_toolbar_widgets[WIDX_STAFF].top };
imgId = SPR_TOOLBAR_STAFF;
if (WidgetIsPressed(*w, WIDX_STAFF))
imgId++;
gfx_draw_sprite(dpi, ImageId(imgId, gStaffHandymanColour, gStaffMechanicColour), screenPos);
}
// Draw fast forward button
if (window_top_toolbar_widgets[WIDX_FASTFORWARD].type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
screenPos = { w->windowPos.x + window_top_toolbar_widgets[WIDX_FASTFORWARD].left + 0,
w->windowPos.y + window_top_toolbar_widgets[WIDX_FASTFORWARD].top + 0 };
if (WidgetIsPressed(*w, WIDX_FASTFORWARD))
screenPos.y++;
gfx_draw_sprite(dpi, ImageId(SPR_G2_FASTFORWARD), screenPos + ScreenCoordsXY{ 6, 3 });
2018-06-22 23:21:44 +02:00
for (int32_t i = 0; i < gGameSpeed && gGameSpeed <= 4; i++)
{
gfx_draw_sprite(dpi, ImageId(SPR_G2_SPEED_ARROW), screenPos + ScreenCoordsXY{ 5 + i * 5, 15 });
}
2018-06-22 23:21:44 +02:00
for (int32_t i = 0; i < 3 && i < gGameSpeed - 4 && gGameSpeed >= 5; i++)
{
gfx_draw_sprite(dpi, ImageId(SPR_G2_HYPER_ARROW), screenPos + ScreenCoordsXY{ 5 + i * 6, 15 });
}
}
// Draw cheats button
if (window_top_toolbar_widgets[WIDX_CHEATS].type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
screenPos = w->windowPos
+ ScreenCoordsXY{ window_top_toolbar_widgets[WIDX_CHEATS].left - 1,
window_top_toolbar_widgets[WIDX_CHEATS].top - 1 };
if (WidgetIsPressed(*w, WIDX_CHEATS))
screenPos.y++;
gfx_draw_sprite(dpi, ImageId(SPR_G2_SANDBOX), screenPos);
// Draw an overlay if clearance checks are disabled
if (gCheatsDisableClearanceChecks)
{
DrawTextBasic(
dpi, screenPos + ScreenCoordsXY{ 26, 2 }, STR_OVERLAY_CLEARANCE_CHECKS_DISABLED, {},
2021-02-27 14:32:13 +01:00
{ COLOUR_DARK_ORANGE | COLOUR_FLAG_OUTLINE, TextAlignment::RIGHT });
}
}
// Draw chat button
if (window_top_toolbar_widgets[WIDX_CHAT].type != WindowWidgetType::Empty)
{
screenPos = w->windowPos
+ ScreenCoordsXY{ window_top_toolbar_widgets[WIDX_CHAT].left, window_top_toolbar_widgets[WIDX_CHAT].top - 2 };
if (WidgetIsPressed(*w, WIDX_CHAT))
screenPos.y++;
gfx_draw_sprite(dpi, ImageId(SPR_G2_CHAT), screenPos);
}
// Draw debug button
if (window_top_toolbar_widgets[WIDX_DEBUG].type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
screenPos = w->windowPos
+ ScreenCoordsXY{ window_top_toolbar_widgets[WIDX_DEBUG].left, window_top_toolbar_widgets[WIDX_DEBUG].top - 1 };
if (WidgetIsPressed(*w, WIDX_DEBUG))
screenPos.y++;
gfx_draw_sprite(dpi, ImageId(SPR_TAB_GEARS_0), screenPos);
}
// Draw research button
if (window_top_toolbar_widgets[WIDX_RESEARCH].type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
screenPos = w->windowPos
+ ScreenCoordsXY{ window_top_toolbar_widgets[WIDX_RESEARCH].left - 1,
window_top_toolbar_widgets[WIDX_RESEARCH].top };
if (WidgetIsPressed(*w, WIDX_RESEARCH))
screenPos.y++;
gfx_draw_sprite(dpi, ImageId(SPR_TAB_FINANCES_RESEARCH_0), screenPos);
}
// Draw finances button
if (window_top_toolbar_widgets[WIDX_FINANCES].type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
screenPos = w->windowPos
+ ScreenCoordsXY{ window_top_toolbar_widgets[WIDX_FINANCES].left + 3,
window_top_toolbar_widgets[WIDX_FINANCES].top + 1 };
if (WidgetIsPressed(*w, WIDX_FINANCES))
screenPos.y++;
gfx_draw_sprite(dpi, ImageId(SPR_FINANCE), screenPos);
}
// Draw news button
if (window_top_toolbar_widgets[WIDX_NEWS].type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
screenPos = w->windowPos
+ ScreenCoordsXY{ window_top_toolbar_widgets[WIDX_NEWS].left + 3, window_top_toolbar_widgets[WIDX_NEWS].top + 0 };
if (WidgetIsPressed(*w, WIDX_NEWS))
screenPos.y++;
gfx_draw_sprite(dpi, ImageId(SPR_G2_TAB_NEWS), screenPos);
}
// Draw network button
if (window_top_toolbar_widgets[WIDX_NETWORK].type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
screenPos = w->windowPos
+ ScreenCoordsXY{ window_top_toolbar_widgets[WIDX_NETWORK].left + 3,
window_top_toolbar_widgets[WIDX_NETWORK].top + 0 };
if (WidgetIsPressed(*w, WIDX_NETWORK))
screenPos.y++;
// Draw (de)sync icon.
2019-02-05 10:43:27 +01:00
imgId = (network_is_desynchronised() ? SPR_G2_MULTIPLAYER_DESYNC : SPR_G2_MULTIPLAYER_SYNC);
gfx_draw_sprite(dpi, ImageId(imgId), screenPos + ScreenCoordsXY{ 3, 11 });
2019-02-05 10:43:27 +01:00
// Draw number of players.
auto ft = Formatter();
ft.Add<int32_t>(network_get_num_players());
DrawTextBasic(
2021-02-27 14:32:13 +01:00
dpi, screenPos + ScreenCoordsXY{ 23, 1 }, STR_COMMA16, ft,
{ COLOUR_WHITE | COLOUR_FLAG_OUTLINE, TextAlignment::RIGHT });
}
}
2014-10-21 18:59:47 +02:00
/**
*
* rct2: 0x006E3158
*/
static void RepaintSceneryToolDown(const ScreenCoordsXY& windowPos, rct_widgetindex widgetIndex)
2018-06-22 23:21:44 +02:00
{
auto flags = EnumsToFlags(
ViewportInteractionItem::Scenery, ViewportInteractionItem::Wall, ViewportInteractionItem::LargeScenery,
ViewportInteractionItem::Banner);
auto info = get_map_coordinates_from_pos(windowPos, flags);
switch (info.SpriteType)
{
case ViewportInteractionItem::Scenery:
2018-06-22 23:21:44 +02:00
{
2021-06-04 03:14:41 +02:00
auto* sceneryEntry = info.Element->AsSmallScenery()->GetEntry();
2018-06-22 23:21:44 +02:00
// If can't repaint
if (!sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR | SMALL_SCENERY_FLAG_HAS_GLASS))
2018-06-22 23:21:44 +02:00
return;
uint8_t quadrant = info.Element->AsSmallScenery()->GetSceneryQuadrant();
auto repaintScenery = SmallScenerySetColourAction(
{ info.Loc, info.Element->GetBaseZ() }, quadrant, info.Element->AsSmallScenery()->GetEntryIndex(),
gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
GameActions::Execute(&repaintScenery);
2018-06-22 23:21:44 +02:00
break;
}
case ViewportInteractionItem::Wall:
2018-06-22 23:21:44 +02:00
{
auto* scenery_entry = info.Element->AsWall()->GetEntry();
2018-06-22 23:21:44 +02:00
// If can't repaint
if (!(scenery_entry->flags & (WALL_SCENERY_HAS_PRIMARY_COLOUR | WALL_SCENERY_HAS_GLASS)))
2018-06-22 23:21:44 +02:00
return;
2019-04-06 20:36:44 +02:00
auto repaintScenery = WallSetColourAction(
{ info.Loc, info.Element->GetBaseZ(), info.Element->GetDirection() }, gWindowSceneryPrimaryColour,
gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
2019-04-06 20:36:44 +02:00
GameActions::Execute(&repaintScenery);
2018-06-22 23:21:44 +02:00
break;
}
case ViewportInteractionItem::LargeScenery:
2017-11-22 23:06:56 +01:00
{
auto* sceneryEntry = info.Element->AsLargeScenery()->GetEntry();
2018-06-22 23:21:44 +02:00
// If can't repaint
if (!(sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR))
2018-06-22 23:21:44 +02:00
return;
auto repaintScenery = LargeScenerySetColourAction(
{ info.Loc, info.Element->GetBaseZ(), info.Element->GetDirection() },
info.Element->AsLargeScenery()->GetSequenceIndex(), gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour,
gWindowSceneryTertiaryColour);
GameActions::Execute(&repaintScenery);
2018-06-22 23:21:44 +02:00
break;
2017-11-22 23:06:56 +01:00
}
case ViewportInteractionItem::Banner:
2018-06-22 23:21:44 +02:00
{
auto banner = info.Element->AsBanner()->GetBanner();
2019-07-25 18:51:22 +02:00
if (banner != nullptr)
2018-06-22 23:21:44 +02:00
{
auto* bannerEntry = get_banner_entry(banner->type);
if (bannerEntry->flags & BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR)
2019-07-25 18:51:22 +02:00
{
auto repaintScenery = BannerSetColourAction(
{ info.Loc, info.Element->GetBaseZ(), info.Element->AsBanner()->GetPosition() },
2019-07-25 18:51:22 +02:00
gWindowSceneryPrimaryColour);
2019-04-07 10:15:41 +02:00
2019-07-25 18:51:22 +02:00
GameActions::Execute(&repaintScenery);
}
2018-06-22 23:21:44 +02:00
}
break;
}
default:
return;
}
2015-04-15 21:52:19 +02:00
}
static void SceneryEyedropperToolDown(const ScreenCoordsXY& windowPos, rct_widgetindex widgetIndex)
2017-03-13 19:05:13 +01:00
{
auto flags = EnumsToFlags(
ViewportInteractionItem::Scenery, ViewportInteractionItem::Wall, ViewportInteractionItem::LargeScenery,
ViewportInteractionItem::Banner, ViewportInteractionItem::FootpathItem);
auto info = get_map_coordinates_from_pos(windowPos, flags);
switch (info.SpriteType)
{
case ViewportInteractionItem::Scenery:
{
SmallSceneryElement* sceneryElement = info.Element->AsSmallScenery();
2020-03-18 16:22:08 +01:00
auto entryIndex = sceneryElement->GetEntryIndex();
2021-06-04 03:14:41 +02:00
auto* sceneryEntry = get_small_scenery_entry(entryIndex);
2018-06-22 23:21:44 +02:00
if (sceneryEntry != nullptr)
{
WindowScenerySetSelectedItem(
{ SCENERY_TYPE_SMALL, entryIndex }, sceneryElement->GetPrimaryColour(),
sceneryElement->GetSecondaryColour(), std::nullopt,
sceneryElement->GetDirectionWithOffset(get_current_rotation()));
}
2018-06-22 23:21:44 +02:00
break;
}
case ViewportInteractionItem::Wall:
{
auto entryIndex = info.Element->AsWall()->GetEntryIndex();
auto* sceneryEntry = get_wall_entry(entryIndex);
2018-06-22 23:21:44 +02:00
if (sceneryEntry != nullptr)
{
WindowScenerySetSelectedItem(
{ SCENERY_TYPE_WALL, entryIndex }, info.Element->AsWall()->GetPrimaryColour(),
info.Element->AsWall()->GetSecondaryColour(), info.Element->AsWall()->GetTertiaryColour(), std::nullopt);
}
2018-06-22 23:21:44 +02:00
break;
}
case ViewportInteractionItem::LargeScenery:
{
auto entryIndex = info.Element->AsLargeScenery()->GetEntryIndex();
auto* sceneryEntry = get_large_scenery_entry(entryIndex);
2018-06-22 23:21:44 +02:00
if (sceneryEntry != nullptr)
{
WindowScenerySetSelectedItem(
{ SCENERY_TYPE_LARGE, entryIndex }, info.Element->AsLargeScenery()->GetPrimaryColour(),
info.Element->AsLargeScenery()->GetSecondaryColour(), std::nullopt,
(get_current_rotation() + info.Element->GetDirection()) & 3);
}
2018-06-22 23:21:44 +02:00
break;
}
case ViewportInteractionItem::Banner:
2018-06-22 23:21:44 +02:00
{
auto banner = info.Element->AsBanner()->GetBanner();
2019-07-25 18:51:22 +02:00
if (banner != nullptr)
2018-06-22 23:21:44 +02:00
{
2019-07-25 18:51:22 +02:00
auto sceneryEntry = get_banner_entry(banner->type);
if (sceneryEntry != nullptr)
2018-06-22 23:21:44 +02:00
{
WindowScenerySetSelectedItem(
{ SCENERY_TYPE_BANNER, banner->type }, std::nullopt, std::nullopt, std::nullopt, std::nullopt);
2018-06-22 23:21:44 +02:00
}
}
2018-06-22 23:21:44 +02:00
break;
}
case ViewportInteractionItem::FootpathItem:
2018-06-22 23:21:44 +02:00
{
auto entryIndex = info.Element->AsPath()->GetAdditionEntryIndex();
auto* pathBitEntry = get_footpath_item_entry(entryIndex);
if (pathBitEntry != nullptr)
2018-06-22 23:21:44 +02:00
{
WindowScenerySetSelectedItem(
{ SCENERY_TYPE_PATH_ITEM, entryIndex }, std::nullopt, std::nullopt, std::nullopt, std::nullopt);
}
2018-06-22 23:21:44 +02:00
break;
}
default:
break;
}
2017-03-13 19:05:13 +01:00
}
static void Sub6E1F34UpdateScreenCoordsAndButtonsPressed(bool canRaiseItem, ScreenCoordsXY& screenPos)
2018-06-22 23:21:44 +02:00
{
2020-11-15 14:58:36 +01:00
if (!canRaiseItem && !gCheatsDisableSupportLimits)
2018-06-22 23:21:44 +02:00
{
gSceneryCtrlPressed = false;
gSceneryShiftPressed = false;
}
2018-06-22 23:21:44 +02:00
else
{
if (!gSceneryCtrlPressed)
{
if (InputTestPlaceObjectModifier(PLACE_OBJECT_MODIFIER_COPY_Z))
2018-06-22 23:21:44 +02:00
{
// CTRL pressed
constexpr auto flags = EnumsToFlags(
ViewportInteractionItem::Terrain, ViewportInteractionItem::Ride, ViewportInteractionItem::Scenery,
ViewportInteractionItem::Footpath, ViewportInteractionItem::Wall, ViewportInteractionItem::LargeScenery);
auto info = get_map_coordinates_from_pos(screenPos, flags);
if (info.SpriteType != ViewportInteractionItem::None)
2018-06-22 23:21:44 +02:00
{
gSceneryCtrlPressed = true;
gSceneryCtrlPressZ = info.Element->GetBaseZ();
}
}
}
2018-06-22 23:21:44 +02:00
else
{
if (!(InputTestPlaceObjectModifier(PLACE_OBJECT_MODIFIER_COPY_Z)))
2018-06-22 23:21:44 +02:00
{
// CTRL not pressed
gSceneryCtrlPressed = false;
}
}
2018-06-22 23:21:44 +02:00
if (!gSceneryShiftPressed)
{
if (InputTestPlaceObjectModifier(PLACE_OBJECT_MODIFIER_SHIFT_Z))
2018-06-22 23:21:44 +02:00
{
// SHIFT pressed
gSceneryShiftPressed = true;
gSceneryShiftPressX = screenPos.x;
gSceneryShiftPressY = screenPos.y;
gSceneryShiftPressZOffset = 0;
}
}
2018-06-22 23:21:44 +02:00
else
{
if (InputTestPlaceObjectModifier(PLACE_OBJECT_MODIFIER_SHIFT_Z))
2018-06-22 23:21:44 +02:00
{
// SHIFT pressed
gSceneryShiftPressZOffset = (gSceneryShiftPressY - screenPos.y + 4);
// Scale delta by zoom to match mouse position.
auto* mainWnd = window_get_main();
if (mainWnd != nullptr && mainWnd->viewport != nullptr)
{
gSceneryShiftPressZOffset = mainWnd->viewport->zoom.ApplyTo(gSceneryShiftPressZOffset);
}
gSceneryShiftPressZOffset = floor2(gSceneryShiftPressZOffset, 8);
screenPos.x = gSceneryShiftPressX;
screenPos.y = gSceneryShiftPressY;
}
2018-06-22 23:21:44 +02:00
else
{
// SHIFT not pressed
gSceneryShiftPressed = false;
}
}
}
2020-11-15 14:58:36 +01:00
}
static void Sub6E1F34SmallScenery(
2020-11-15 14:58:36 +01:00
const ScreenCoordsXY& sourceScreenPos, ObjectEntryIndex sceneryIndex, CoordsXY& gridPos, uint8_t* outQuadrant,
Direction* outRotation)
2020-11-15 14:58:36 +01:00
{
rct_window* w = window_find_by_class(WC_SCENERY);
2018-06-22 23:21:44 +02:00
2020-11-15 14:58:36 +01:00
if (w == nullptr)
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
2018-06-22 23:21:44 +02:00
2020-11-15 14:58:36 +01:00
auto screenPos = sourceScreenPos;
uint16_t maxPossibleHeight = ZoomLevel::max().ApplyTo(std::numeric_limits<decltype(TileElement::base_height)>::max() - 32);
2020-11-15 14:58:36 +01:00
bool can_raise_item = false;
2018-06-22 23:21:44 +02:00
const auto* sceneryEntry = get_small_scenery_entry(sceneryIndex);
if (sceneryEntry == nullptr)
{
gridPos.SetNull();
return;
}
2021-06-04 03:14:41 +02:00
maxPossibleHeight -= sceneryEntry->height;
if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_STACKABLE))
2020-11-15 14:58:36 +01:00
{
can_raise_item = true;
}
Sub6E1F34UpdateScreenCoordsAndButtonsPressed(can_raise_item, screenPos);
2018-06-22 23:21:44 +02:00
2020-11-15 14:58:36 +01:00
// Small scenery
if (!sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_FULL_TILE))
2020-11-15 14:58:36 +01:00
{
uint8_t quadrant = 0;
2018-06-22 23:21:44 +02:00
2020-11-15 14:58:36 +01:00
// If CTRL not pressed
if (!gSceneryCtrlPressed)
{
auto gridCoords = screen_get_map_xy_quadrant(screenPos, &quadrant);
2021-09-13 18:47:13 +02:00
if (!gridCoords.has_value())
2020-11-15 14:58:36 +01:00
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
2021-09-13 18:47:13 +02:00
gridPos = gridCoords.value();
2020-11-15 14:58:36 +01:00
gSceneryPlaceZ = 0;
2020-11-15 14:58:36 +01:00
// If SHIFT pressed
if (gSceneryShiftPressed)
{
auto* surfaceElement = map_get_surface_element_at(gridPos);
2018-06-22 23:21:44 +02:00
2020-11-15 14:58:36 +01:00
if (surfaceElement == nullptr)
2018-06-22 23:21:44 +02:00
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
2018-06-22 23:21:44 +02:00
}
2020-11-15 14:58:36 +01:00
int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0;
z += gSceneryShiftPressZOffset;
2018-06-22 23:21:44 +02:00
2020-11-15 14:58:36 +01:00
z = std::clamp<int16_t>(z, 16, maxPossibleHeight);
2018-06-22 23:21:44 +02:00
2020-11-15 14:58:36 +01:00
gSceneryPlaceZ = z;
}
}
else
{
int16_t z = gSceneryCtrlPressZ;
2018-06-22 23:21:44 +02:00
2020-11-15 14:58:36 +01:00
auto mapCoords = screen_get_map_xy_quadrant_with_z(screenPos, z, &quadrant);
2021-09-13 18:47:13 +02:00
if (!mapCoords.has_value())
2020-11-15 14:58:36 +01:00
{
gridPos.SetNull();
2018-06-22 23:21:44 +02:00
return;
}
2021-09-13 18:47:13 +02:00
gridPos = mapCoords.value();
2018-06-22 23:21:44 +02:00
2020-11-15 14:58:36 +01:00
// If SHIFT pressed
if (gSceneryShiftPressed)
2018-06-22 23:21:44 +02:00
{
2020-11-15 14:58:36 +01:00
z += gSceneryShiftPressZOffset;
}
2018-06-22 23:21:44 +02:00
2020-11-15 14:58:36 +01:00
z = std::clamp<int16_t>(z, 16, maxPossibleHeight);
2018-06-22 23:21:44 +02:00
2020-11-15 14:58:36 +01:00
gSceneryPlaceZ = z;
}
if (gridPos.IsNull())
2020-11-15 14:58:36 +01:00
return;
2020-11-15 14:58:36 +01:00
uint8_t rotation = gWindowSceneryRotation;
if (!sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_ROTATABLE))
2020-11-15 14:58:36 +01:00
{
rotation = util_rand() & 0xFF;
}
2020-11-15 14:58:36 +01:00
rotation -= get_current_rotation();
rotation &= 0x3;
2020-11-15 14:58:36 +01:00
if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off)
{
virtual_floor_set_height(gSceneryPlaceZ);
}
2020-11-15 14:58:36 +01:00
*outQuadrant = quadrant ^ 2;
*outRotation = rotation;
2020-11-15 14:58:36 +01:00
return;
}
2020-11-15 14:58:36 +01:00
// If CTRL not pressed
if (!gSceneryCtrlPressed)
{
constexpr auto flags = EnumsToFlags(ViewportInteractionItem::Terrain, ViewportInteractionItem::Water);
2020-11-15 14:58:36 +01:00
auto info = get_map_coordinates_from_pos(screenPos, flags);
gridPos = info.Loc;
if (info.SpriteType == ViewportInteractionItem::None)
2020-11-15 14:58:36 +01:00
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
2020-11-15 14:58:36 +01:00
// If CTRL and SHIFT not pressed
gSceneryPlaceZ = 0;
2020-11-15 14:58:36 +01:00
// If SHIFT pressed
if (gSceneryShiftPressed)
2018-06-22 23:21:44 +02:00
{
2020-11-15 14:58:36 +01:00
auto surfaceElement = map_get_surface_element_at(gridPos);
2020-11-15 14:58:36 +01:00
if (surfaceElement == nullptr)
2018-06-22 23:21:44 +02:00
{
gridPos.SetNull();
return;
}
2020-11-15 14:58:36 +01:00
int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0;
z += gSceneryShiftPressZOffset;
z = std::clamp<int16_t>(z, 16, maxPossibleHeight);
gSceneryPlaceZ = z;
}
}
else
{
int16_t z = gSceneryCtrlPressZ;
auto coords = screen_get_map_xy_with_z(screenPos, z);
2021-09-13 18:47:13 +02:00
if (coords.has_value())
2020-11-15 14:58:36 +01:00
{
gridPos = *coords;
}
2020-11-15 14:58:36 +01:00
else
2017-12-04 20:09:38 +01:00
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
}
// If SHIFT pressed
if (gSceneryShiftPressed)
{
z += gSceneryShiftPressZOffset;
}
2020-11-15 14:58:36 +01:00
z = std::clamp<int16_t>(z, 16, maxPossibleHeight);
2020-11-15 14:58:36 +01:00
gSceneryPlaceZ = z;
}
if (gridPos.IsNull())
2020-11-15 14:58:36 +01:00
return;
2020-11-15 14:58:36 +01:00
gridPos = gridPos.ToTileStart();
uint8_t rotation = gWindowSceneryRotation;
if (!sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_ROTATABLE))
2020-11-15 14:58:36 +01:00
{
rotation = util_rand() & 0xFF;
}
2020-11-15 14:58:36 +01:00
rotation -= get_current_rotation();
rotation &= 0x3;
2020-11-15 14:58:36 +01:00
if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off)
{
virtual_floor_set_height(gSceneryPlaceZ);
}
2020-11-15 14:58:36 +01:00
*outQuadrant = 0;
*outRotation = rotation;
}
static void Sub6E1F34PathItem(
2020-11-15 14:58:36 +01:00
const ScreenCoordsXY& sourceScreenPos, ObjectEntryIndex sceneryIndex, CoordsXY& gridPos, int32_t* outZ)
{
rct_window* w = window_find_by_class(WC_SCENERY);
2020-11-15 14:58:36 +01:00
if (w == nullptr)
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
2020-11-15 14:58:36 +01:00
auto screenPos = sourceScreenPos;
Sub6E1F34UpdateScreenCoordsAndButtonsPressed(false, screenPos);
2020-11-15 14:58:36 +01:00
// Path bits
constexpr auto flags = EnumsToFlags(ViewportInteractionItem::Footpath, ViewportInteractionItem::FootpathItem);
2020-11-15 14:58:36 +01:00
auto info = get_map_coordinates_from_pos(screenPos, flags);
gridPos = info.Loc;
if (info.SpriteType == ViewportInteractionItem::None)
2020-11-15 14:58:36 +01:00
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off)
{
virtual_floor_set_height(gSceneryPlaceZ);
}
*outZ = info.Element->GetBaseZ();
}
static void Sub6E1F34Wall(
const ScreenCoordsXY& sourceScreenPos, ObjectEntryIndex sceneryIndex, CoordsXY& gridPos, uint8_t* outEdges)
2020-11-15 14:58:36 +01:00
{
rct_window* w = window_find_by_class(WC_SCENERY);
if (w == nullptr)
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
auto screenPos = sourceScreenPos;
uint16_t maxPossibleHeight = ZoomLevel::max().ApplyTo(std::numeric_limits<decltype(TileElement::base_height)>::max() - 32);
2020-11-15 14:58:36 +01:00
auto* wallEntry = get_wall_entry(sceneryIndex);
if (wallEntry != nullptr)
2020-11-15 14:58:36 +01:00
{
maxPossibleHeight -= wallEntry->height;
2020-11-15 14:58:36 +01:00
}
Sub6E1F34UpdateScreenCoordsAndButtonsPressed(true, screenPos);
2020-11-15 14:58:36 +01:00
// Walls
uint8_t edge;
// If CTRL not pressed
if (!gSceneryCtrlPressed)
{
auto gridCoords = screen_get_map_xy_side(screenPos, &edge);
2021-09-13 18:47:13 +02:00
if (!gridCoords.has_value())
2020-11-15 14:58:36 +01:00
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
2021-09-13 18:47:13 +02:00
gridPos = gridCoords.value();
2020-11-15 14:58:36 +01:00
gSceneryPlaceZ = 0;
// If SHIFT pressed
if (gSceneryShiftPressed)
2018-06-22 23:21:44 +02:00
{
2020-11-15 14:58:36 +01:00
auto* surfaceElement = map_get_surface_element_at(gridPos);
if (surfaceElement == nullptr)
2018-06-22 23:21:44 +02:00
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
2020-11-15 14:58:36 +01:00
int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0;
z += gSceneryShiftPressZOffset;
2020-11-15 14:58:36 +01:00
z = std::clamp<int16_t>(z, 16, maxPossibleHeight);
2020-11-15 14:58:36 +01:00
gSceneryPlaceZ = z;
}
}
else
{
int16_t z = gSceneryCtrlPressZ;
auto mapCoords = screen_get_map_xy_side_with_z(screenPos, z, &edge);
2021-09-13 18:47:13 +02:00
if (!mapCoords.has_value())
2020-11-15 14:58:36 +01:00
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
2021-09-13 18:47:13 +02:00
gridPos = mapCoords.value();
2020-11-15 14:58:36 +01:00
// If SHIFT pressed
if (gSceneryShiftPressed)
{
z += gSceneryShiftPressZOffset;
}
2020-11-15 14:58:36 +01:00
z = std::clamp<int16_t>(z, 16, maxPossibleHeight);
2020-11-15 14:58:36 +01:00
gSceneryPlaceZ = z;
}
2018-06-22 23:21:44 +02:00
if (gridPos.IsNull())
2020-11-15 14:58:36 +01:00
return;
2020-11-15 14:58:36 +01:00
if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off)
{
virtual_floor_set_height(gSceneryPlaceZ);
}
2020-11-15 14:58:36 +01:00
*outEdges = edge;
}
static void Sub6E1F34LargeScenery(
const ScreenCoordsXY& sourceScreenPos, ObjectEntryIndex sceneryIndex, CoordsXY& gridPos, Direction* outDirection)
2020-11-15 14:58:36 +01:00
{
rct_window* w = window_find_by_class(WC_SCENERY);
2020-11-15 14:58:36 +01:00
if (w == nullptr)
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
2020-11-15 14:58:36 +01:00
auto screenPos = sourceScreenPos;
uint16_t maxPossibleHeight = ZoomLevel::max().ApplyTo(std::numeric_limits<decltype(TileElement::base_height)>::max() - 32);
auto* sceneryEntry = get_large_scenery_entry(sceneryIndex);
if (sceneryEntry)
2020-11-15 14:58:36 +01:00
{
int16_t maxClearZ = 0;
for (int32_t i = 0; sceneryEntry->tiles[i].x_offset != -1; ++i)
2018-06-22 23:21:44 +02:00
{
maxClearZ = std::max<int16_t>(maxClearZ, sceneryEntry->tiles[i].z_clearance);
2020-11-15 14:58:36 +01:00
}
maxPossibleHeight = std::max(0, maxPossibleHeight - maxClearZ);
}
Sub6E1F34UpdateScreenCoordsAndButtonsPressed(true, screenPos);
2020-11-15 14:58:36 +01:00
// Large scenery
// If CTRL not pressed
if (!gSceneryCtrlPressed)
{
const CoordsXY mapCoords = ViewportInteractionGetTileStartAtCursor(screenPos);
gridPos = mapCoords;
if (gridPos.IsNull())
2020-11-15 14:58:36 +01:00
return;
gSceneryPlaceZ = 0;
// If SHIFT pressed
if (gSceneryShiftPressed)
{
auto* surfaceElement = map_get_surface_element_at(gridPos);
if (surfaceElement == nullptr)
2018-06-22 23:21:44 +02:00
{
gridPos.SetNull();
2018-06-22 23:21:44 +02:00
return;
}
2020-11-15 14:58:36 +01:00
int16_t z = (surfaceElement->GetBaseZ()) & 0xFFF0;
z += gSceneryShiftPressZOffset;
2020-11-15 14:58:36 +01:00
z = std::clamp<int16_t>(z, 16, maxPossibleHeight);
2020-11-15 14:58:36 +01:00
gSceneryPlaceZ = z;
}
}
else
{
int16_t z = gSceneryCtrlPressZ;
auto coords = screen_get_map_xy_with_z(screenPos, z);
2021-09-13 18:47:13 +02:00
if (coords.has_value())
2020-11-15 14:58:36 +01:00
{
gridPos = *coords;
}
else
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
}
2020-11-15 14:58:36 +01:00
// If SHIFT pressed
if (gSceneryShiftPressed)
{
z += gSceneryShiftPressZOffset;
2018-06-22 23:21:44 +02:00
}
2020-11-15 14:58:36 +01:00
z = std::clamp<int16_t>(z, 16, maxPossibleHeight);
gSceneryPlaceZ = z;
}
if (gridPos.IsNull())
2020-11-15 14:58:36 +01:00
return;
gridPos = gridPos.ToTileStart();
Direction rotation = gWindowSceneryRotation;
rotation -= get_current_rotation();
rotation &= 0x3;
if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off)
{
virtual_floor_set_height(gSceneryPlaceZ);
}
2020-11-15 14:58:36 +01:00
*outDirection = rotation;
2015-04-18 13:17:44 +02:00
}
static void Sub6E1F34Banner(
2020-11-15 14:58:36 +01:00
const ScreenCoordsXY& sourceScreenPos, ObjectEntryIndex sceneryIndex, CoordsXY& gridPos, int32_t* outZ,
Direction* outDirection)
2020-03-13 14:44:34 +01:00
{
2020-11-15 14:58:36 +01:00
rct_window* w = window_find_by_class(WC_SCENERY);
2020-03-13 14:44:34 +01:00
2020-11-15 14:58:36 +01:00
if (w == nullptr)
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
2020-03-13 14:44:34 +01:00
2020-11-15 14:58:36 +01:00
auto screenPos = sourceScreenPos;
Sub6E1F34UpdateScreenCoordsAndButtonsPressed(false, screenPos);
2020-03-13 14:44:34 +01:00
2020-11-15 14:58:36 +01:00
// Banner
constexpr auto flags = EnumsToFlags(ViewportInteractionItem::Footpath, ViewportInteractionItem::FootpathItem);
2020-11-15 14:58:36 +01:00
auto info = get_map_coordinates_from_pos(screenPos, flags);
gridPos = info.Loc;
2020-03-13 14:44:34 +01:00
if (info.SpriteType == ViewportInteractionItem::None)
2020-11-15 14:58:36 +01:00
{
gridPos.SetNull();
2020-11-15 14:58:36 +01:00
return;
}
2020-03-13 14:44:34 +01:00
2020-11-15 14:58:36 +01:00
uint8_t rotation = gWindowSceneryRotation;
rotation -= get_current_rotation();
rotation &= 0x3;
2020-03-13 14:44:34 +01:00
2020-11-15 14:58:36 +01:00
auto z = info.Element->GetBaseZ();
2020-03-13 14:44:34 +01:00
2020-11-15 14:58:36 +01:00
if (info.Element->AsPath()->IsSloped())
{
if (rotation != direction_reverse(info.Element->AsPath()->GetSlopeDirection()))
{
z += (2 * COORDS_Z_STEP);
}
}
if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off)
{
virtual_floor_set_height(gSceneryPlaceZ);
}
2020-03-13 14:44:34 +01:00
2020-11-15 14:58:36 +01:00
*outDirection = rotation;
*outZ = z;
2020-03-13 14:44:34 +01:00
}
2014-10-21 18:59:47 +02:00
/**
2015-10-20 20:16:30 +02:00
*
2015-08-31 00:45:45 +02:00
* rct2: 0x006E2CC6
2014-10-21 18:59:47 +02:00
*/
static void WindowTopToolbarSceneryToolDown(const ScreenCoordsXY& windowPos, rct_window* w, rct_widgetindex widgetIndex)
2015-08-31 00:45:45 +02:00
{
scenery_remove_ghost_tool_placement();
2018-06-22 23:21:44 +02:00
if (gWindowSceneryPaintEnabled & 1)
{
RepaintSceneryToolDown(windowPos, widgetIndex);
return;
2018-06-22 23:21:44 +02:00
}
2021-09-15 22:22:15 +02:00
if (gWindowSceneryEyedropperEnabled)
2018-06-22 23:21:44 +02:00
{
SceneryEyedropperToolDown(windowPos, widgetIndex);
return;
}
auto selectedTab = WindowSceneryGetTabSelection();
2020-03-13 14:44:34 +01:00
uint8_t sceneryType = selectedTab.SceneryType;
uint16_t selectedScenery = selectedTab.EntryIndex;
CoordsXY gridPos;
2018-06-22 23:21:44 +02:00
switch (sceneryType)
{
2018-06-22 23:21:44 +02:00
case SCENERY_TYPE_SMALL:
{
2020-03-13 14:44:34 +01:00
uint8_t quadrant;
Direction rotation;
Sub6E1F34SmallScenery(windowPos, selectedScenery, gridPos, &quadrant, &rotation);
if (gridPos.IsNull())
2020-03-13 14:44:34 +01:00
return;
2018-06-22 23:21:44 +02:00
int32_t quantity = 1;
2019-12-12 16:42:19 +01:00
bool isCluster = gWindowSceneryScatterEnabled
2018-06-22 23:21:44 +02:00
&& (network_get_mode() != NETWORK_MODE_CLIENT
|| network_can_perform_command(network_get_current_player_group_index(), -2));
2017-12-04 20:09:38 +01:00
if (isCluster)
{
switch (gWindowSceneryScatterDensity)
{
case ScatterToolDensity::LowDensity:
quantity = gWindowSceneryScatterSize;
break;
case ScatterToolDensity::MediumDensity:
quantity = gWindowSceneryScatterSize * 2;
break;
case ScatterToolDensity::HighDensity:
quantity = gWindowSceneryScatterSize * 3;
break;
}
2018-06-22 23:21:44 +02:00
}
bool forceError = true;
for (int32_t q = 0; q < quantity; q++)
2018-06-22 23:21:44 +02:00
{
int32_t zCoordinate = gSceneryPlaceZ;
2021-06-04 03:14:41 +02:00
auto* sceneryEntry = get_small_scenery_entry(selectedScenery);
2018-06-22 23:21:44 +02:00
int16_t cur_grid_x = gridPos.x;
int16_t cur_grid_y = gridPos.y;
2018-06-22 23:21:44 +02:00
if (isCluster)
{
if (!sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_FULL_TILE))
2018-06-22 23:21:44 +02:00
{
2020-03-13 14:44:34 +01:00
quadrant = util_rand() & 3;
2018-06-22 23:21:44 +02:00
}
int16_t grid_x_offset = (util_rand() % gWindowSceneryScatterSize) - (gWindowSceneryScatterSize / 2);
int16_t grid_y_offset = (util_rand() % gWindowSceneryScatterSize) - (gWindowSceneryScatterSize / 2);
if (gWindowSceneryScatterSize % 2 == 0)
2019-12-12 16:42:19 +01:00
{
grid_x_offset += 1;
grid_y_offset += 1;
2019-12-12 16:42:19 +01:00
}
cur_grid_x += grid_x_offset * COORDS_XY_STEP;
cur_grid_y += grid_y_offset * COORDS_XY_STEP;
2018-06-22 23:21:44 +02:00
if (!sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_ROTATABLE))
2018-06-22 23:21:44 +02:00
{
gSceneryPlaceRotation = (gSceneryPlaceRotation + 1) & 3;
}
}
uint8_t zAttemptRange = 1;
if (gSceneryPlaceZ != 0 && gSceneryShiftPressed)
2017-12-04 20:09:38 +01:00
{
2018-06-22 23:21:44 +02:00
zAttemptRange = 20;
}
auto success = GameActions::Status::Unknown;
// Try find a valid z coordinate
2018-06-22 23:21:44 +02:00
for (; zAttemptRange != 0; zAttemptRange--)
{
auto smallSceneryPlaceAction = SmallSceneryPlaceAction(
2020-03-13 14:44:34 +01:00
{ cur_grid_x, cur_grid_y, gSceneryPlaceZ, gSceneryPlaceRotation }, quadrant, selectedScenery,
gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
auto res = GameActions::Query(&smallSceneryPlaceAction);
success = res.Error;
if (res.Error == GameActions::Status::Ok)
2018-06-22 23:21:44 +02:00
{
break;
}
if (res.Error == GameActions::Status::InsufficientFunds)
2018-06-22 23:21:44 +02:00
{
break;
}
if (zAttemptRange != 1)
{
gSceneryPlaceZ += 8;
}
2018-06-22 23:21:44 +02:00
}
// Actually place
if (success == GameActions::Status::Ok || ((q + 1 == quantity) && forceError))
2018-06-22 23:21:44 +02:00
{
auto smallSceneryPlaceAction = SmallSceneryPlaceAction(
2020-03-13 14:44:34 +01:00
{ cur_grid_x, cur_grid_y, gSceneryPlaceZ, gSceneryPlaceRotation }, quadrant, selectedScenery,
gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
smallSceneryPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) {
if (result->Error == GameActions::Status::Ok)
{
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::PlaceItem, result->Position);
}
});
auto res = GameActions::Execute(&smallSceneryPlaceAction);
if (res.Error == GameActions::Status::Ok)
{
forceError = false;
}
if (res.Error == GameActions::Status::InsufficientFunds)
2018-06-22 23:21:44 +02:00
{
break;
}
}
2018-06-22 23:21:44 +02:00
gSceneryPlaceZ = zCoordinate;
}
2018-06-22 23:21:44 +02:00
break;
}
case SCENERY_TYPE_PATH_ITEM:
{
2020-03-13 14:44:34 +01:00
int32_t z;
Sub6E1F34PathItem(windowPos, selectedScenery, gridPos, &z);
if (gridPos.IsNull())
2020-03-13 14:44:34 +01:00
return;
auto footpathAdditionPlaceAction = FootpathAdditionPlaceAction({ gridPos, z }, selectedScenery + 1);
2018-06-22 23:21:44 +02:00
footpathAdditionPlaceAction.SetCallback([](const GameAction* ga, const GameActions::Result* result) {
if (result->Error != GameActions::Status::Ok)
2019-03-01 11:53:52 +01:00
{
return;
}
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::PlaceItem, result->Position);
2019-03-01 11:53:52 +01:00
});
auto res = GameActions::Execute(&footpathAdditionPlaceAction);
2018-06-22 23:21:44 +02:00
break;
}
case SCENERY_TYPE_WALL:
{
2020-03-13 14:44:34 +01:00
uint8_t edges;
Sub6E1F34Wall(windowPos, selectedScenery, gridPos, &edges);
if (gridPos.IsNull())
2020-03-13 14:44:34 +01:00
return;
uint8_t zAttemptRange = 1;
2018-06-22 23:21:44 +02:00
if (gSceneryPlaceZ != 0 && gSceneryShiftPressed)
{
zAttemptRange = 20;
}
2018-06-22 23:21:44 +02:00
for (; zAttemptRange != 0; zAttemptRange--)
{
2019-03-25 20:20:31 +01:00
auto wallPlaceAction = WallPlaceAction(
selectedScenery, { gridPos, gSceneryPlaceZ }, edges, gWindowSceneryPrimaryColour,
gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
2019-03-25 20:20:31 +01:00
auto res = GameActions::Query(&wallPlaceAction);
if (res.Error == GameActions::Status::Ok)
2018-06-22 23:21:44 +02:00
{
2019-03-25 20:20:31 +01:00
break;
}
if (const auto* message = std::get_if<rct_string_id>(&res.ErrorMessage))
2018-06-22 23:21:44 +02:00
{
if (*message == STR_NOT_ENOUGH_CASH_REQUIRES || *message == STR_CAN_ONLY_BUILD_THIS_ON_WATER)
{
break;
}
}
2019-03-28 18:45:39 +01:00
if (zAttemptRange != 1)
{
gSceneryPlaceZ += 8;
}
}
2019-03-25 20:20:31 +01:00
auto wallPlaceAction = WallPlaceAction(
selectedScenery, { gridPos, gSceneryPlaceZ }, edges, gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour,
gWindowSceneryTertiaryColour);
2019-03-25 20:20:31 +01:00
wallPlaceAction.SetCallback([](const GameAction* ga, const GameActions::Result* result) {
if (result->Error == GameActions::Status::Ok)
2019-03-25 20:20:31 +01:00
{
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::PlaceItem, result->Position);
2019-03-25 20:20:31 +01:00
}
});
auto res = GameActions::Execute(&wallPlaceAction);
2018-06-22 23:21:44 +02:00
break;
}
2018-06-22 23:21:44 +02:00
case SCENERY_TYPE_LARGE:
{
2020-03-13 14:44:34 +01:00
Direction direction;
Sub6E1F34LargeScenery(windowPos, selectedScenery, gridPos, &direction);
if (gridPos.IsNull())
2020-03-13 14:44:34 +01:00
return;
2018-06-22 23:21:44 +02:00
uint8_t zAttemptRange = 1;
if (gSceneryPlaceZ != 0 && gSceneryShiftPressed)
{
zAttemptRange = 20;
}
2018-06-22 23:21:44 +02:00
for (; zAttemptRange != 0; zAttemptRange--)
{
CoordsXYZD loc = { gridPos, gSceneryPlaceZ, direction };
auto sceneryPlaceAction = LargeSceneryPlaceAction(
loc, selectedScenery, gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour,
gWindowSceneryTertiaryColour);
2019-04-05 20:16:23 +02:00
auto res = GameActions::Query(&sceneryPlaceAction);
if (res.Error == GameActions::Status::Ok)
2018-06-22 23:21:44 +02:00
{
2019-04-05 20:16:23 +02:00
break;
2018-06-22 23:21:44 +02:00
}
if (const auto* message = std::get_if<rct_string_id>(&res.ErrorMessage))
2018-06-22 23:21:44 +02:00
{
if (*message == STR_NOT_ENOUGH_CASH_REQUIRES || *message == STR_CAN_ONLY_BUILD_THIS_ON_WATER)
{
break;
}
2018-06-22 23:21:44 +02:00
}
2019-04-05 20:16:23 +02:00
if (zAttemptRange != 1)
{
gSceneryPlaceZ += 8;
}
}
2020-03-13 14:44:34 +01:00
CoordsXYZD loc = { gridPos, gSceneryPlaceZ, direction };
auto sceneryPlaceAction = LargeSceneryPlaceAction(
loc, selectedScenery, gWindowSceneryPrimaryColour, gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
sceneryPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) {
if (result->Error == GameActions::Status::Ok)
2019-04-05 20:16:23 +02:00
{
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::PlaceItem, result->Position);
2019-04-05 20:16:23 +02:00
}
else
{
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::Error, { loc.x, loc.y, gSceneryPlaceZ });
2019-04-05 20:16:23 +02:00
}
});
auto res = GameActions::Execute(&sceneryPlaceAction);
2018-06-22 23:21:44 +02:00
break;
}
2018-06-22 23:21:44 +02:00
case SCENERY_TYPE_BANNER:
{
2020-03-13 14:44:34 +01:00
int32_t z;
Direction direction;
Sub6E1F34Banner(windowPos, selectedScenery, gridPos, &z, &direction);
if (gridPos.IsNull())
2020-03-13 14:44:34 +01:00
return;
CoordsXYZD loc{ gridPos, z, direction };
2019-04-06 10:44:07 +02:00
auto primaryColour = gWindowSceneryPrimaryColour;
auto bannerPlaceAction = BannerPlaceAction(loc, selectedScenery, primaryColour);
bannerPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) {
if (result->Error == GameActions::Status::Ok)
2019-04-06 10:44:07 +02:00
{
auto data = result->GetData<BannerPlaceActionResult>();
OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::PlaceItem, result->Position);
2021-11-24 18:58:07 +01:00
context_open_detail_window(WD_BANNER, data.bannerId.ToUnderlying());
2019-04-06 10:44:07 +02:00
}
});
GameActions::Execute(&bannerPlaceAction);
2018-06-22 23:21:44 +02:00
break;
}
}
2014-10-21 18:59:47 +02:00
}
static uint8_t TopToolbarToolUpdateLandPaint(const ScreenCoordsXY& screenPos)
2018-06-22 23:21:44 +02:00
{
uint8_t state_changed = 0;
map_invalidate_selection_rect();
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
auto mapTile = screen_get_map_xy(screenPos, nullptr);
2021-09-13 18:47:13 +02:00
if (!mapTile.has_value())
2018-06-22 23:21:44 +02:00
{
2021-07-27 17:59:49 +02:00
if (gClearSceneryCost != MONEY64_UNDEFINED)
2018-06-22 23:21:44 +02:00
{
2021-07-27 17:59:49 +02:00
gClearSceneryCost = MONEY64_UNDEFINED;
window_invalidate_by_class(WC_CLEAR_SCENERY);
}
return state_changed;
}
2018-06-22 23:21:44 +02:00
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
{
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
state_changed++;
}
2018-06-22 23:21:44 +02:00
if (gMapSelectType != MAP_SELECT_TYPE_FULL)
{
gMapSelectType = MAP_SELECT_TYPE_FULL;
state_changed++;
}
int16_t tool_size = std::max<uint16_t>(1, gLandToolSize);
int16_t tool_length = (tool_size - 1) * 32;
// Move to tool bottom left
mapTile->x -= (tool_size - 1) * 16;
mapTile->y -= (tool_size - 1) * 16;
mapTile = mapTile->ToTileStart();
if (gMapSelectPositionA.x != mapTile->x)
2018-06-22 23:21:44 +02:00
{
gMapSelectPositionA.x = mapTile->x;
state_changed++;
}
if (gMapSelectPositionA.y != mapTile->y)
2018-06-22 23:21:44 +02:00
{
gMapSelectPositionA.y = mapTile->y;
state_changed++;
}
mapTile->x += tool_length;
mapTile->y += tool_length;
if (gMapSelectPositionB.x != mapTile->x)
2018-06-22 23:21:44 +02:00
{
gMapSelectPositionB.x = mapTile->x;
state_changed++;
}
if (gMapSelectPositionB.y != mapTile->y)
2018-06-22 23:21:44 +02:00
{
gMapSelectPositionB.y = mapTile->y;
state_changed++;
}
map_invalidate_selection_rect();
return state_changed;
}
/**
*
* rct2: 0x0068E213
*/
static void TopToolbarToolUpdateSceneryClear(const ScreenCoordsXY& screenPos)
{
if (!TopToolbarToolUpdateLandPaint(screenPos))
return;
2019-01-02 12:59:37 +01:00
auto action = GetClearAction();
auto result = GameActions::Query(&action);
auto cost = (result.Error == GameActions::Status::Ok ? result.Cost : MONEY64_UNDEFINED);
2018-06-22 23:21:44 +02:00
if (gClearSceneryCost != cost)
{
gClearSceneryCost = cost;
window_invalidate_by_class(WC_CLEAR_SCENERY);
}
}
2015-05-26 21:36:05 +02:00
/**
2018-06-22 23:21:44 +02:00
*
* rct2: 0x00664280
*/
static void TopToolbarToolUpdateLand(const ScreenCoordsXY& screenPos)
{
const bool mapCtrlPressed = InputTestPlaceObjectModifier(PLACE_OBJECT_MODIFIER_COPY_Z);
map_invalidate_selection_rect();
if (gCurrentToolId == Tool::UpDownArrow)
{
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
return;
money64 lower_cost = SelectionLowerLand(0);
money64 raise_cost = SelectionRaiseLand(0);
if (gLandToolRaiseCost != raise_cost || gLandToolLowerCost != lower_cost)
{
gLandToolRaiseCost = raise_cost;
gLandToolLowerCost = lower_cost;
window_invalidate_by_class(WC_LAND);
}
return;
}
2018-06-22 23:21:44 +02:00
int16_t tool_size = gLandToolSize;
std::optional<CoordsXY> mapTile;
uint8_t side{};
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
if (tool_size == 1)
{
int32_t selectionType;
// Get selection type and map coordinates from mouse x,y position
screen_pos_to_map_pos(screenPos, &selectionType);
mapTile = screen_get_map_xy_side(screenPos, &side);
2021-09-13 18:47:13 +02:00
if (!mapTile.has_value())
{
money64 lower_cost = MONEY64_UNDEFINED;
money64 raise_cost = MONEY64_UNDEFINED;
if (gLandToolRaiseCost != raise_cost || gLandToolLowerCost != lower_cost)
{
gLandToolRaiseCost = raise_cost;
gLandToolLowerCost = lower_cost;
window_invalidate_by_class(WC_LAND);
}
return;
}
uint8_t state_changed = 0;
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
{
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
state_changed++;
}
if (gMapSelectType != selectionType)
{
gMapSelectType = selectionType;
state_changed++;
}
if ((gMapSelectType != MAP_SELECT_TYPE_EDGE_0 + (side & 0xFF)) && mapCtrlPressed)
{
gMapSelectType = MAP_SELECT_TYPE_EDGE_0 + (side & 0xFF);
state_changed++;
}
if (gMapSelectPositionA.x != mapTile->x)
{
gMapSelectPositionA.x = mapTile->x;
state_changed++;
}
if (gMapSelectPositionA.y != mapTile->y)
{
gMapSelectPositionA.y = mapTile->y;
state_changed++;
}
if (gMapSelectPositionB.x != mapTile->x)
{
gMapSelectPositionB.x = mapTile->x;
state_changed++;
}
if (gMapSelectPositionB.y != mapTile->y)
{
gMapSelectPositionB.y = mapTile->y;
state_changed++;
}
map_invalidate_selection_rect();
if (!state_changed)
return;
money64 lower_cost = SelectionLowerLand(0);
money64 raise_cost = SelectionRaiseLand(0);
2018-06-22 23:21:44 +02:00
if (gLandToolRaiseCost != raise_cost || gLandToolLowerCost != lower_cost)
{
gLandToolRaiseCost = raise_cost;
gLandToolLowerCost = lower_cost;
window_invalidate_by_class(WC_LAND);
}
return;
}
// Get map coordinates and the side of the tile that is being hovered over
mapTile = screen_get_map_xy_side(screenPos, &side);
2021-09-13 18:47:13 +02:00
if (!mapTile.has_value())
2018-06-22 23:21:44 +02:00
{
money64 lower_cost = MONEY64_UNDEFINED;
money64 raise_cost = MONEY64_UNDEFINED;
2018-06-22 23:21:44 +02:00
if (gLandToolRaiseCost != raise_cost || gLandToolLowerCost != lower_cost)
{
gLandToolRaiseCost = raise_cost;
gLandToolLowerCost = lower_cost;
window_invalidate_by_class(WC_LAND);
}
return;
}
uint8_t state_changed = 0;
2018-06-22 23:21:44 +02:00
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
{
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
state_changed++;
}
2018-06-22 23:21:44 +02:00
if (gMapSelectType != MAP_SELECT_TYPE_FULL)
{
gMapSelectType = MAP_SELECT_TYPE_FULL;
state_changed++;
}
if ((gMapSelectType != MAP_SELECT_TYPE_EDGE_0 + (side & 0xFF)) && mapCtrlPressed)
{
gMapSelectType = MAP_SELECT_TYPE_EDGE_0 + (side & 0xFF);
state_changed++;
}
if (tool_size == 0)
tool_size = 1;
int16_t tool_length = (tool_size - 1) * 32;
// Decide on shape of the brush for bigger selection size
switch (gMapSelectType)
{
2018-06-22 23:21:44 +02:00
case MAP_SELECT_TYPE_EDGE_0:
case MAP_SELECT_TYPE_EDGE_2:
// Line
mapTile->y -= (tool_size - 1) * 16;
mapTile->y = mapTile->ToTileStart().y;
2018-06-22 23:21:44 +02:00
break;
case MAP_SELECT_TYPE_EDGE_1:
case MAP_SELECT_TYPE_EDGE_3:
// Line
mapTile->x -= (tool_size - 1) * 16;
mapTile->x = mapTile->ToTileStart().x;
2018-06-22 23:21:44 +02:00
break;
default:
// Move to tool bottom left
mapTile->x -= (tool_size - 1) * 16;
mapTile->y -= (tool_size - 1) * 16;
mapTile = mapTile->ToTileStart();
2018-06-22 23:21:44 +02:00
break;
}
if (gMapSelectPositionA.x != mapTile->x)
{
gMapSelectPositionA.x = mapTile->x;
state_changed++;
}
if (gMapSelectPositionA.y != mapTile->y)
{
gMapSelectPositionA.y = mapTile->y;
state_changed++;
}
// Go to other side
switch (gMapSelectType)
{
2018-06-22 23:21:44 +02:00
case MAP_SELECT_TYPE_EDGE_0:
case MAP_SELECT_TYPE_EDGE_2:
// Line
mapTile->y += tool_length;
2018-06-22 23:21:44 +02:00
gMapSelectType = MAP_SELECT_TYPE_FULL;
break;
case MAP_SELECT_TYPE_EDGE_1:
case MAP_SELECT_TYPE_EDGE_3:
// Line
mapTile->x += tool_length;
2018-06-22 23:21:44 +02:00
gMapSelectType = MAP_SELECT_TYPE_FULL;
break;
default:
mapTile->x += tool_length;
mapTile->y += tool_length;
2018-06-22 23:21:44 +02:00
break;
}
if (gMapSelectPositionB.x != mapTile->x)
2018-06-22 23:21:44 +02:00
{
gMapSelectPositionB.x = mapTile->x;
state_changed++;
}
if (gMapSelectPositionB.y != mapTile->y)
2018-06-22 23:21:44 +02:00
{
gMapSelectPositionB.y = mapTile->y;
state_changed++;
}
map_invalidate_selection_rect();
if (!state_changed)
return;
money64 lower_cost = SelectionLowerLand(0);
money64 raise_cost = SelectionRaiseLand(0);
2018-06-22 23:21:44 +02:00
if (gLandToolRaiseCost != raise_cost || gLandToolLowerCost != lower_cost)
{
gLandToolRaiseCost = raise_cost;
gLandToolLowerCost = lower_cost;
window_invalidate_by_class(WC_LAND);
}
2015-05-26 21:36:05 +02:00
}
/**
2018-06-22 23:21:44 +02:00
*
* rct2: 0x006E6BDC
*/
static void TopToolbarToolUpdateWater(const ScreenCoordsXY& screenPos)
2018-06-22 23:21:44 +02:00
{
map_invalidate_selection_rect();
if (gCurrentToolId == Tool::UpDownArrow)
2018-06-22 23:21:44 +02:00
{
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
return;
2019-03-04 17:57:01 +01:00
auto waterLowerAction = WaterLowerAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
auto waterRaiseAction = WaterRaiseAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
2019-03-04 17:57:01 +01:00
auto res = GameActions::Query(&waterLowerAction);
money64 lowerCost = res.Error == GameActions::Status::Ok ? res.Cost : MONEY64_UNDEFINED;
2019-03-04 17:57:01 +01:00
res = GameActions::Query(&waterRaiseAction);
money64 raiseCost = res.Error == GameActions::Status::Ok ? res.Cost : MONEY64_UNDEFINED;
2019-03-04 17:57:01 +01:00
if (gWaterToolRaiseCost != raiseCost || gWaterToolLowerCost != lowerCost)
2018-06-22 23:21:44 +02:00
{
2019-03-04 17:57:01 +01:00
gWaterToolRaiseCost = raiseCost;
gWaterToolLowerCost = lowerCost;
window_invalidate_by_class(WC_WATER);
}
return;
}
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
auto info = get_map_coordinates_from_pos(
screenPos, EnumsToFlags(ViewportInteractionItem::Terrain, ViewportInteractionItem::Water));
if (info.SpriteType == ViewportInteractionItem::None)
2018-06-22 23:21:44 +02:00
{
if (gWaterToolRaiseCost != MONEY64_UNDEFINED || gWaterToolLowerCost != MONEY64_UNDEFINED)
2018-06-22 23:21:44 +02:00
{
gWaterToolRaiseCost = MONEY64_UNDEFINED;
gWaterToolLowerCost = MONEY64_UNDEFINED;
window_invalidate_by_class(WC_WATER);
}
return;
}
auto mapTile = info.Loc.ToTileCentre();
uint8_t state_changed = 0;
2018-06-22 23:21:44 +02:00
if (!(gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
{
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
state_changed++;
}
2018-06-22 23:21:44 +02:00
if (gMapSelectType != MAP_SELECT_TYPE_FULL_WATER)
{
gMapSelectType = MAP_SELECT_TYPE_FULL_WATER;
state_changed++;
}
int16_t tool_size = std::max<uint16_t>(1, gLandToolSize);
int16_t tool_length = (tool_size - 1) * 32;
// Move to tool bottom left
mapTile.x -= (tool_size - 1) * 16;
mapTile.y -= (tool_size - 1) * 16;
mapTile.x &= 0xFFE0;
mapTile.y &= 0xFFE0;
2018-06-22 23:21:44 +02:00
if (gMapSelectPositionA.x != mapTile.x)
{
gMapSelectPositionA.x = mapTile.x;
state_changed++;
}
2018-06-22 23:21:44 +02:00
if (gMapSelectPositionA.y != mapTile.y)
{
gMapSelectPositionA.y = mapTile.y;
state_changed++;
}
mapTile.x += tool_length;
mapTile.y += tool_length;
2018-06-22 23:21:44 +02:00
if (gMapSelectPositionB.x != mapTile.x)
{
gMapSelectPositionB.x = mapTile.x;
state_changed++;
}
2018-06-22 23:21:44 +02:00
if (gMapSelectPositionB.y != mapTile.y)
{
gMapSelectPositionB.y = mapTile.y;
state_changed++;
}
map_invalidate_selection_rect();
if (!state_changed)
return;
2019-03-04 17:57:01 +01:00
auto waterLowerAction = WaterLowerAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
auto waterRaiseAction = WaterRaiseAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
auto res = GameActions::Query(&waterLowerAction);
money64 lowerCost = res.Error == GameActions::Status::Ok ? res.Cost : MONEY64_UNDEFINED;
2018-06-22 23:21:44 +02:00
2019-03-04 17:57:01 +01:00
res = GameActions::Query(&waterRaiseAction);
money64 raiseCost = res.Error == GameActions::Status::Ok ? res.Cost : MONEY64_UNDEFINED;
2018-06-22 23:21:44 +02:00
2019-03-04 17:57:01 +01:00
if (gWaterToolRaiseCost != raiseCost || gWaterToolLowerCost != lowerCost)
2018-06-22 23:21:44 +02:00
{
2019-03-04 17:57:01 +01:00
gWaterToolRaiseCost = raiseCost;
gWaterToolLowerCost = lowerCost;
window_invalidate_by_class(WC_WATER);
}
}
/**
*
* rct2: 0x006E24F6
* On failure returns MONEY64_UNDEFINED
* On success places ghost scenery and returns cost to place proper
*/
static money64 TryPlaceGhostSmallScenery(
CoordsXYZD loc, uint8_t quadrant, ObjectEntryIndex entryIndex, colour_t primaryColour, colour_t secondaryColour,
colour_t tertiaryColour)
2018-06-22 23:21:44 +02:00
{
scenery_remove_ghost_tool_placement();
// 6e252b
auto smallSceneryPlaceAction = SmallSceneryPlaceAction(
loc, quadrant, entryIndex, primaryColour, secondaryColour, tertiaryColour);
smallSceneryPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED);
auto res = GameActions::Execute(&smallSceneryPlaceAction);
if (res.Error != GameActions::Status::Ok)
return MONEY64_UNDEFINED;
const auto placementData = res.GetData<SmallSceneryPlaceActionResult>();
gSceneryPlaceRotation = loc.direction;
gSceneryPlaceObject.SceneryType = SCENERY_TYPE_SMALL;
gSceneryPlaceObject.EntryIndex = entryIndex;
gSceneryGhostPosition = { loc, placementData.BaseHeight };
gSceneryQuadrant = placementData.SceneryQuadrant;
if (placementData.GroundFlags & ELEMENT_IS_UNDERGROUND)
2018-06-22 23:21:44 +02:00
{
// Set underground on
viewport_set_visibility(4);
}
else
{
// Set underground off
viewport_set_visibility(5);
}
gSceneryGhostType |= SCENERY_GHOST_FLAG_0;
return res.Cost;
}
static money64 TryPlaceGhostPathAddition(CoordsXYZ loc, ObjectEntryIndex entryIndex)
{
scenery_remove_ghost_tool_placement();
// 6e265b
auto footpathAdditionPlaceAction = FootpathAdditionPlaceAction(loc, entryIndex + 1);
footpathAdditionPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED);
footpathAdditionPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) {
if (result->Error != GameActions::Status::Ok)
2019-03-25 20:20:31 +01:00
{
return;
}
gSceneryGhostPosition = loc;
gSceneryGhostType |= SCENERY_GHOST_FLAG_1;
});
auto res = GameActions::Execute(&footpathAdditionPlaceAction);
if (res.Error != GameActions::Status::Ok)
return MONEY64_UNDEFINED;
return res.Cost;
}
2018-06-22 23:21:44 +02:00
static money64 TryPlaceGhostWall(
CoordsXYZ loc, uint8_t edge, ObjectEntryIndex entryIndex, colour_t primaryColour, colour_t secondaryColour,
colour_t tertiaryColour)
{
scenery_remove_ghost_tool_placement();
2018-06-22 23:21:44 +02:00
// 6e26b0
auto wallPlaceAction = WallPlaceAction(entryIndex, loc, edge, primaryColour, secondaryColour, tertiaryColour);
wallPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND);
wallPlaceAction.SetCallback([=](const GameAction* ga, const GameActions::Result* result) {
if (result->Error != GameActions::Status::Ok)
return;
2018-06-22 23:21:44 +02:00
const auto placementData = result->GetData<WallPlaceActionResult>();
gSceneryGhostPosition = { loc, placementData.BaseHeight };
gSceneryGhostWallRotation = edge;
2018-06-22 23:21:44 +02:00
gSceneryGhostType |= SCENERY_GHOST_FLAG_2;
});
2018-06-22 23:21:44 +02:00
auto res = GameActions::Execute(&wallPlaceAction);
if (res.Error != GameActions::Status::Ok)
return MONEY64_UNDEFINED;
return res.Cost;
}
static money64 TryPlaceGhostLargeScenery(
CoordsXYZD loc, ObjectEntryIndex entryIndex, colour_t primaryColour, colour_t secondaryColour, colour_t tertiaryColour)
{
scenery_remove_ghost_tool_placement();
// 6e25a7
auto sceneryPlaceAction = LargeSceneryPlaceAction(loc, entryIndex, primaryColour, secondaryColour, tertiaryColour);
sceneryPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND);
auto res = GameActions::Execute(&sceneryPlaceAction);
if (res.Error != GameActions::Status::Ok)
return MONEY64_UNDEFINED;
const auto placementData = res.GetData<LargeSceneryPlaceActionResult>();
gSceneryPlaceRotation = loc.direction;
gSceneryGhostPosition = { loc, placementData.firstTileHeight };
if (placementData.GroundFlags & ELEMENT_IS_UNDERGROUND)
{
// Set underground on
viewport_set_visibility(4);
}
else
{
// Set underground off
viewport_set_visibility(5);
}
gSceneryGhostType |= SCENERY_GHOST_FLAG_3;
return res.Cost;
}
static money64 TryPlaceGhostBanner(CoordsXYZD loc, ObjectEntryIndex entryIndex)
{
scenery_remove_ghost_tool_placement();
// 6e2612
auto primaryColour = gWindowSceneryPrimaryColour;
auto bannerPlaceAction = BannerPlaceAction(loc, entryIndex, primaryColour);
bannerPlaceAction.SetFlags(GAME_COMMAND_FLAG_GHOST | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND);
auto res = GameActions::Execute(&bannerPlaceAction);
if (res.Error != GameActions::Status::Ok)
return MONEY64_UNDEFINED;
gSceneryGhostPosition = loc;
gSceneryGhostPosition.z += PATH_HEIGHT_STEP;
gSceneryPlaceRotation = loc.direction;
gSceneryGhostType |= SCENERY_GHOST_FLAG_4;
return res.Cost;
}
2015-05-28 20:33:09 +02:00
/**
2018-06-22 23:21:44 +02:00
*
* rct2: 0x006E287B
*/
static void TopToolbarToolUpdateScenery(const ScreenCoordsXY& screenPos)
2018-06-22 23:21:44 +02:00
{
map_invalidate_selection_rect();
map_invalidate_map_selection_tiles();
if (gConfigGeneral.virtual_floor_style != VirtualFloorStyles::Off)
{
virtual_floor_invalidate();
}
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
if (gWindowSceneryPaintEnabled)
return;
if (gWindowSceneryEyedropperEnabled)
return;
const auto selection = WindowSceneryGetTabSelection();
2020-03-18 16:22:08 +01:00
if (selection.IsUndefined())
2018-06-22 23:21:44 +02:00
{
scenery_remove_ghost_tool_placement();
return;
}
money64 cost = 0;
switch (selection.SceneryType)
2018-06-22 23:21:44 +02:00
{
case SCENERY_TYPE_SMALL:
{
CoordsXY mapTile = {};
uint8_t quadrant;
Direction rotation;
Sub6E1F34SmallScenery(screenPos, selection.EntryIndex, mapTile, &quadrant, &rotation);
if (mapTile.IsNull())
{
scenery_remove_ghost_tool_placement();
return;
}
2018-06-22 23:21:44 +02:00
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
2019-12-12 16:42:19 +01:00
if (gWindowSceneryScatterEnabled)
2018-06-22 23:21:44 +02:00
{
uint16_t cluster_size = (gWindowSceneryScatterSize - 1) * COORDS_XY_STEP;
gMapSelectPositionA.x = mapTile.x - cluster_size / 2;
gMapSelectPositionA.y = mapTile.y - cluster_size / 2;
gMapSelectPositionB.x = mapTile.x + cluster_size / 2;
gMapSelectPositionB.y = mapTile.y + cluster_size / 2;
if (gWindowSceneryScatterSize % 2 == 0)
2019-12-12 16:42:19 +01:00
{
gMapSelectPositionB.x += COORDS_XY_STEP;
gMapSelectPositionB.y += COORDS_XY_STEP;
2019-12-12 16:42:19 +01:00
}
2018-06-22 23:21:44 +02:00
}
else
{
gMapSelectPositionA.x = mapTile.x;
gMapSelectPositionA.y = mapTile.y;
gMapSelectPositionB.x = mapTile.x;
gMapSelectPositionB.y = mapTile.y;
}
2021-06-04 03:14:41 +02:00
auto* sceneryEntry = get_small_scenery_entry(selection.EntryIndex);
2018-06-22 23:21:44 +02:00
gMapSelectType = MAP_SELECT_TYPE_FULL;
if (!sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_FULL_TILE) && !gWindowSceneryScatterEnabled)
2018-06-22 23:21:44 +02:00
{
gMapSelectType = MAP_SELECT_TYPE_QUARTER_0 + (quadrant ^ 2);
2018-06-22 23:21:44 +02:00
}
2018-06-22 23:21:44 +02:00
map_invalidate_selection_rect();
2018-06-22 23:21:44 +02:00
// If no change in ghost placement
if ((gSceneryGhostType & SCENERY_GHOST_FLAG_0) && mapTile == gSceneryGhostPosition && quadrant == _unkF64F0E
&& gSceneryPlaceZ == _unkF64F0A && gSceneryPlaceObject.SceneryType == SCENERY_TYPE_SMALL
&& gSceneryPlaceObject.EntryIndex == selection.EntryIndex)
2018-06-22 23:21:44 +02:00
{
return;
}
2018-06-22 23:21:44 +02:00
scenery_remove_ghost_tool_placement();
_unkF64F0E = quadrant;
2018-06-22 23:21:44 +02:00
_unkF64F0A = gSceneryPlaceZ;
uint8_t attemptsLeft = 1;
2018-06-22 23:21:44 +02:00
if (gSceneryPlaceZ != 0 && gSceneryShiftPressed)
{
attemptsLeft = 20;
2018-06-22 23:21:44 +02:00
}
for (; attemptsLeft != 0; attemptsLeft--)
2018-06-22 23:21:44 +02:00
{
cost = TryPlaceGhostSmallScenery(
{ mapTile, gSceneryPlaceZ, rotation }, quadrant, selection.EntryIndex, gWindowSceneryPrimaryColour,
gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
if (cost != MONEY64_UNDEFINED)
2018-06-22 23:21:44 +02:00
break;
gSceneryPlaceZ += 8;
}
2018-06-22 23:21:44 +02:00
gSceneryPlaceCost = cost;
break;
}
2018-06-22 23:21:44 +02:00
case SCENERY_TYPE_PATH_ITEM:
{
CoordsXY mapTile = {};
int32_t z;
Sub6E1F34PathItem(screenPos, selection.EntryIndex, mapTile, &z);
if (mapTile.IsNull())
{
scenery_remove_ghost_tool_placement();
return;
}
2018-06-22 23:21:44 +02:00
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
gMapSelectPositionA.x = mapTile.x;
gMapSelectPositionA.y = mapTile.y;
gMapSelectPositionB.x = mapTile.x;
gMapSelectPositionB.y = mapTile.y;
gMapSelectType = MAP_SELECT_TYPE_FULL;
2018-06-22 23:21:44 +02:00
map_invalidate_selection_rect();
2018-06-22 23:21:44 +02:00
// If no change in ghost placement
if ((gSceneryGhostType & SCENERY_GHOST_FLAG_1) && mapTile == gSceneryGhostPosition && z == gSceneryGhostPosition.z)
2018-06-22 23:21:44 +02:00
{
return;
}
2018-06-22 23:21:44 +02:00
scenery_remove_ghost_tool_placement();
cost = TryPlaceGhostPathAddition({ mapTile, z }, selection.EntryIndex);
2018-06-22 23:21:44 +02:00
gSceneryPlaceCost = cost;
break;
}
2018-06-22 23:21:44 +02:00
case SCENERY_TYPE_WALL:
{
CoordsXY mapTile = {};
uint8_t edge;
Sub6E1F34Wall(screenPos, selection.EntryIndex, mapTile, &edge);
if (mapTile.IsNull())
{
scenery_remove_ghost_tool_placement();
return;
}
2018-06-22 23:21:44 +02:00
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
gMapSelectPositionA.x = mapTile.x;
gMapSelectPositionA.y = mapTile.y;
gMapSelectPositionB.x = mapTile.x;
gMapSelectPositionB.y = mapTile.y;
gMapSelectType = MAP_SELECT_TYPE_EDGE_0 + edge;
2018-06-22 23:21:44 +02:00
map_invalidate_selection_rect();
2018-06-22 23:21:44 +02:00
// If no change in ghost placement
if ((gSceneryGhostType & SCENERY_GHOST_FLAG_2) && mapTile == gSceneryGhostPosition
&& edge == gSceneryGhostWallRotation && gSceneryPlaceZ == _unkF64F0A)
2018-06-22 23:21:44 +02:00
{
return;
}
scenery_remove_ghost_tool_placement();
gSceneryGhostWallRotation = edge;
2018-06-22 23:21:44 +02:00
_unkF64F0A = gSceneryPlaceZ;
uint8_t attemptsLeft = 1;
2018-06-22 23:21:44 +02:00
if (gSceneryPlaceZ != 0 && gSceneryShiftPressed)
{
attemptsLeft = 20;
2018-06-22 23:21:44 +02:00
}
2018-06-22 23:21:44 +02:00
cost = 0;
for (; attemptsLeft != 0; attemptsLeft--)
2018-06-22 23:21:44 +02:00
{
cost = TryPlaceGhostWall(
{ mapTile, gSceneryPlaceZ }, edge, selection.EntryIndex, gWindowSceneryPrimaryColour,
gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
if (cost != MONEY64_UNDEFINED)
2018-06-22 23:21:44 +02:00
break;
gSceneryPlaceZ += 8;
}
2018-06-22 23:21:44 +02:00
gSceneryPlaceCost = cost;
break;
}
2018-06-22 23:21:44 +02:00
case SCENERY_TYPE_LARGE:
{
CoordsXY mapTile = {};
Direction direction;
Sub6E1F34LargeScenery(screenPos, selection.EntryIndex, mapTile, &direction);
if (mapTile.IsNull())
{
scenery_remove_ghost_tool_placement();
return;
}
auto* sceneryEntry = get_large_scenery_entry(selection.EntryIndex);
2019-03-28 19:29:51 +01:00
gMapSelectionTiles.clear();
for (rct_large_scenery_tile* tile = sceneryEntry->tiles;
tile->x_offset != static_cast<int16_t>(static_cast<uint16_t>(0xFFFF)); tile++)
2018-06-22 23:21:44 +02:00
{
CoordsXY tileLocation = { tile->x_offset, tile->y_offset };
auto rotatedTileCoords = tileLocation.Rotate(direction);
rotatedTileCoords.x += mapTile.x;
rotatedTileCoords.y += mapTile.y;
gMapSelectionTiles.push_back(rotatedTileCoords);
2018-06-22 23:21:44 +02:00
}
2018-06-22 23:21:44 +02:00
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
map_invalidate_map_selection_tiles();
2018-06-22 23:21:44 +02:00
// If no change in ghost placement
if ((gSceneryGhostType & SCENERY_GHOST_FLAG_3) && mapTile == gSceneryGhostPosition && gSceneryPlaceZ == _unkF64F0A
&& gSceneryPlaceObject.SceneryType == SCENERY_TYPE_LARGE
&& gSceneryPlaceObject.EntryIndex == selection.EntryIndex)
2018-06-22 23:21:44 +02:00
{
return;
}
2018-06-22 23:21:44 +02:00
scenery_remove_ghost_tool_placement();
2020-03-13 14:44:34 +01:00
gSceneryPlaceObject.SceneryType = SCENERY_TYPE_LARGE;
gSceneryPlaceObject.EntryIndex = selection.EntryIndex;
2018-06-22 23:21:44 +02:00
_unkF64F0A = gSceneryPlaceZ;
uint8_t attemptsLeft = 1;
2018-06-22 23:21:44 +02:00
if (gSceneryPlaceZ != 0 && gSceneryShiftPressed)
{
attemptsLeft = 20;
2018-06-22 23:21:44 +02:00
}
2018-06-22 23:21:44 +02:00
cost = 0;
for (; attemptsLeft != 0; attemptsLeft--)
2018-06-22 23:21:44 +02:00
{
cost = TryPlaceGhostLargeScenery(
{ mapTile, gSceneryPlaceZ, direction }, selection.EntryIndex, gWindowSceneryPrimaryColour,
gWindowScenerySecondaryColour, gWindowSceneryTertiaryColour);
if (cost != MONEY64_UNDEFINED)
2018-06-22 23:21:44 +02:00
break;
gSceneryPlaceZ += COORDS_Z_STEP;
2018-06-22 23:21:44 +02:00
}
2018-06-22 23:21:44 +02:00
gSceneryPlaceCost = cost;
break;
}
2018-06-22 23:21:44 +02:00
case SCENERY_TYPE_BANNER:
{
CoordsXY mapTile = {};
Direction direction;
int32_t z;
Sub6E1F34Banner(screenPos, selection.EntryIndex, mapTile, &z, &direction);
if (mapTile.IsNull())
{
scenery_remove_ghost_tool_placement();
return;
}
2018-06-22 23:21:44 +02:00
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
gMapSelectPositionA.x = mapTile.x;
gMapSelectPositionA.y = mapTile.y;
gMapSelectPositionB.x = mapTile.x;
gMapSelectPositionB.y = mapTile.y;
gMapSelectType = MAP_SELECT_TYPE_FULL;
2018-06-22 23:21:44 +02:00
map_invalidate_selection_rect();
2018-06-22 23:21:44 +02:00
// If no change in ghost placement
if ((gSceneryGhostType & SCENERY_GHOST_FLAG_4) && mapTile == gSceneryGhostPosition && z == gSceneryGhostPosition.z
&& direction == gSceneryPlaceRotation)
2018-06-22 23:21:44 +02:00
{
return;
}
2018-06-22 23:21:44 +02:00
scenery_remove_ghost_tool_placement();
cost = TryPlaceGhostBanner({ mapTile, z, direction }, selection.EntryIndex);
2018-06-22 23:21:44 +02:00
gSceneryPlaceCost = cost;
break;
}
}
2015-05-28 20:33:09 +02:00
}
/**
*
* rct2: 0x0066CB25
*/
static void WindowTopToolbarToolUpdate(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
{
2018-06-22 23:21:44 +02:00
switch (widgetIndex)
{
case WIDX_CLEAR_SCENERY:
TopToolbarToolUpdateSceneryClear(screenCoords);
2018-06-22 23:21:44 +02:00
break;
case WIDX_LAND:
if (gLandPaintMode)
TopToolbarToolUpdateLandPaint(screenCoords);
2018-06-22 23:21:44 +02:00
else
TopToolbarToolUpdateLand(screenCoords);
2018-06-22 23:21:44 +02:00
break;
case WIDX_WATER:
TopToolbarToolUpdateWater(screenCoords);
2018-06-22 23:21:44 +02:00
break;
case WIDX_SCENERY:
TopToolbarToolUpdateScenery(screenCoords);
2018-06-22 23:21:44 +02:00
break;
2020-05-01 22:32:41 +02:00
#ifdef ENABLE_SCRIPTING
default:
auto& customTool = OpenRCT2::Scripting::ActiveCustomTool;
if (customTool)
{
customTool->OnUpdate(screenCoords);
}
break;
#endif
}
}
2014-10-21 18:59:47 +02:00
/**
*
* rct2: 0x0066CB73
2014-10-21 18:59:47 +02:00
*/
static void WindowTopToolbarToolDown(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
{
2018-06-22 23:21:44 +02:00
switch (widgetIndex)
{
case WIDX_CLEAR_SCENERY:
2019-01-02 12:59:37 +01:00
if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE)
{
auto action = GetClearAction();
GameActions::Execute(&action);
gCurrentToolId = Tool::Crosshair;
2019-01-02 12:59:37 +01:00
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_LAND:
if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE)
{
auto surfaceSetStyleAction = SurfaceSetStyleAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
gLandToolTerrainSurface, gLandToolTerrainEdge);
GameActions::Execute(&surfaceSetStyleAction);
gCurrentToolId = Tool::UpDownArrow;
2018-06-22 23:21:44 +02:00
}
else
{
_landToolBlocked = true;
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_WATER:
if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE)
{
gCurrentToolId = Tool::UpDownArrow;
2018-06-22 23:21:44 +02:00
}
else
{
_landToolBlocked = true;
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_SCENERY:
WindowTopToolbarSceneryToolDown(screenCoords, w, widgetIndex);
2018-06-22 23:21:44 +02:00
break;
2020-05-01 22:32:41 +02:00
#ifdef ENABLE_SCRIPTING
default:
auto& customTool = OpenRCT2::Scripting::ActiveCustomTool;
if (customTool)
{
customTool->OnDown(screenCoords);
}
break;
#endif
}
}
/**
2018-06-22 23:21:44 +02:00
*
* rct2: 0x006644DD
*/
static money64 SelectionRaiseLand(uint8_t flags)
{
int32_t centreX = (gMapSelectPositionA.x + gMapSelectPositionB.x) / 2;
int32_t centreY = (gMapSelectPositionA.y + gMapSelectPositionB.y) / 2;
centreX += 16;
centreY += 16;
2018-06-22 23:21:44 +02:00
if (gLandMountainMode)
{
2019-03-16 23:04:58 +01:00
auto landSmoothAction = LandSmoothAction(
{ centreX, centreY },
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y }, gMapSelectType,
false);
auto res = (flags & GAME_COMMAND_FLAG_APPLY) ? GameActions::Execute(&landSmoothAction)
: GameActions::Query(&landSmoothAction);
return res.Error == GameActions::Status::Ok ? res.Cost : MONEY64_UNDEFINED;
2018-06-22 23:21:44 +02:00
}
2019-03-04 17:57:01 +01:00
2021-09-15 22:22:15 +02:00
auto landRaiseAction = LandRaiseAction(
{ centreX, centreY }, { gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
gMapSelectType);
auto res = (flags & GAME_COMMAND_FLAG_APPLY) ? GameActions::Execute(&landRaiseAction)
: GameActions::Query(&landRaiseAction);
return res.Error == GameActions::Status::Ok ? res.Cost : MONEY64_UNDEFINED;
}
/**
2018-06-22 23:21:44 +02:00
*
* rct2: 0x006645B3
*/
static money64 SelectionLowerLand(uint8_t flags)
{
int32_t centreX = (gMapSelectPositionA.x + gMapSelectPositionB.x) / 2;
int32_t centreY = (gMapSelectPositionA.y + gMapSelectPositionB.y) / 2;
centreX += 16;
centreY += 16;
2018-06-22 23:21:44 +02:00
if (gLandMountainMode)
{
2019-03-16 23:04:58 +01:00
auto landSmoothAction = LandSmoothAction(
{ centreX, centreY },
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y }, gMapSelectType,
true);
auto res = (flags & GAME_COMMAND_FLAG_APPLY) ? GameActions::Execute(&landSmoothAction)
: GameActions::Query(&landSmoothAction);
return res.Error == GameActions::Status::Ok ? res.Cost : MONEY64_UNDEFINED;
2018-06-22 23:21:44 +02:00
}
2019-03-04 17:57:01 +01:00
2021-09-15 22:22:15 +02:00
auto landLowerAction = LandLowerAction(
{ centreX, centreY }, { gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
gMapSelectType);
auto res = (flags & GAME_COMMAND_FLAG_APPLY) ? GameActions::Execute(&landLowerAction)
: GameActions::Query(&landLowerAction);
return res.Error == GameActions::Status::Ok ? res.Cost : MONEY64_UNDEFINED;
}
/**
2018-06-22 23:21:44 +02:00
* part of window_top_toolbar_tool_drag(0x0066CB4E)
* rct2: 0x00664454
*/
static void WindowTopToolbarLandToolDrag(const ScreenCoordsXY& screenPos)
{
rct_window* window = window_find_from_point(screenPos);
if (window == nullptr)
return;
rct_widgetindex widget_index = window_find_widget_from_point(window, screenPos);
if (widget_index == -1)
return;
const auto& widget = window->widgets[widget_index];
if (widget.type != WindowWidgetType::Viewport)
return;
2018-06-22 23:21:44 +02:00
rct_viewport* viewport = window->viewport;
if (viewport == nullptr)
return;
int16_t tile_height = viewport->zoom.ApplyInversedTo(-16);
int32_t y_diff = screenPos.y - gInputDragLast.y;
2018-06-22 23:21:44 +02:00
if (y_diff <= tile_height)
{
gInputDragLast.y += tile_height;
SelectionRaiseLand(GAME_COMMAND_FLAG_APPLY);
gLandToolRaiseCost = MONEY64_UNDEFINED;
gLandToolLowerCost = MONEY64_UNDEFINED;
2018-06-22 23:21:44 +02:00
}
else if (y_diff >= -tile_height)
{
gInputDragLast.y -= tile_height;
SelectionLowerLand(GAME_COMMAND_FLAG_APPLY);
gLandToolRaiseCost = MONEY64_UNDEFINED;
gLandToolLowerCost = MONEY64_UNDEFINED;
}
}
/**
2018-06-22 23:21:44 +02:00
* part of window_top_toolbar_tool_drag(0x0066CB4E)
* rct2: 0x006E6D4B
*/
static void WindowTopToolbarWaterToolDrag(const ScreenCoordsXY& screenPos)
{
rct_window* window = window_find_from_point(screenPos);
if (!window)
return;
rct_widgetindex widget_index = window_find_widget_from_point(window, screenPos);
if (widget_index == -1)
return;
const auto& widget = window->widgets[widget_index];
if (widget.type != WindowWidgetType::Viewport)
return;
2018-06-22 23:21:44 +02:00
rct_viewport* viewport = window->viewport;
if (viewport == nullptr)
return;
int16_t dx = viewport->zoom.ApplyInversedTo(-16);
auto offsetPos = screenPos - ScreenCoordsXY{ 0, gInputDragLast.y };
if (offsetPos.y <= dx)
2018-06-22 23:21:44 +02:00
{
gInputDragLast.y += dx;
2019-03-04 17:57:01 +01:00
auto waterRaiseAction = WaterRaiseAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
GameActions::Execute(&waterRaiseAction);
gWaterToolRaiseCost = MONEY64_UNDEFINED;
gWaterToolLowerCost = MONEY64_UNDEFINED;
return;
}
dx = -dx;
if (offsetPos.y >= dx)
2018-06-22 23:21:44 +02:00
{
gInputDragLast.y += dx;
2019-03-04 17:57:01 +01:00
auto waterLowerAction = WaterLowerAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y });
GameActions::Execute(&waterLowerAction);
gWaterToolRaiseCost = MONEY64_UNDEFINED;
gWaterToolLowerCost = MONEY64_UNDEFINED;
return;
}
}
/**
*
* rct2: 0x0066CB4E
*/
static void WindowTopToolbarToolDrag(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
{
2018-06-22 23:21:44 +02:00
switch (widgetIndex)
{
case WIDX_CLEAR_SCENERY:
2019-01-02 12:59:37 +01:00
if (window_find_by_class(WC_ERROR) == nullptr && (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
{
auto action = GetClearAction();
GameActions::Execute(&action);
gCurrentToolId = Tool::Crosshair;
2019-01-02 12:59:37 +01:00
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_LAND:
// Custom setting to only change land style instead of raising or lowering land
if (gLandPaintMode)
{
if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE)
{
auto surfaceSetStyleAction = SurfaceSetStyleAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
gLandToolTerrainSurface, gLandToolTerrainEdge);
GameActions::Execute(&surfaceSetStyleAction);
2019-02-21 10:34:30 +01:00
// The tool is set to 12 here instead of 3 so that the dragging cursor is not the elevation change
// cursor
gCurrentToolId = Tool::Crosshair;
2018-06-22 23:21:44 +02:00
}
}
2018-06-22 23:21:44 +02:00
else
{
if (!_landToolBlocked)
{
WindowTopToolbarLandToolDrag(screenCoords);
}
2018-06-22 23:21:44 +02:00
}
break;
case WIDX_WATER:
if (!_landToolBlocked)
{
WindowTopToolbarWaterToolDrag(screenCoords);
}
2018-06-22 23:21:44 +02:00
break;
case WIDX_SCENERY:
if (gWindowSceneryPaintEnabled & 1)
WindowTopToolbarSceneryToolDown(screenCoords, w, widgetIndex);
2018-06-22 23:21:44 +02:00
if (gWindowSceneryEyedropperEnabled)
WindowTopToolbarSceneryToolDown(screenCoords, w, widgetIndex);
2018-06-22 23:21:44 +02:00
break;
2020-05-01 22:32:41 +02:00
#ifdef ENABLE_SCRIPTING
default:
auto& customTool = OpenRCT2::Scripting::ActiveCustomTool;
if (customTool)
{
customTool->OnDrag(screenCoords);
}
break;
#endif
}
}
/**
2015-10-20 20:16:30 +02:00
*
* rct2: 0x0066CC5B
*/
static void WindowTopToolbarToolUp(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
2015-10-20 20:16:30 +02:00
{
_landToolBlocked = false;
2018-06-22 23:21:44 +02:00
switch (widgetIndex)
{
case WIDX_LAND:
map_invalidate_selection_rect();
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
gCurrentToolId = Tool::DigDown;
2018-06-22 23:21:44 +02:00
break;
case WIDX_WATER:
map_invalidate_selection_rect();
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
gCurrentToolId = Tool::WaterDown;
2018-06-22 23:21:44 +02:00
break;
case WIDX_CLEAR_SCENERY:
map_invalidate_selection_rect();
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
gCurrentToolId = Tool::Crosshair;
2018-06-22 23:21:44 +02:00
break;
2020-05-01 22:32:41 +02:00
#ifdef ENABLE_SCRIPTING
default:
auto& customTool = OpenRCT2::Scripting::ActiveCustomTool;
if (customTool)
{
customTool->OnUp(screenCoords);
}
break;
#endif
}
}
/**
2015-10-20 20:16:30 +02:00
*
* rct2: 0x0066CA58
*/
static void WindowTopToolbarToolAbort(rct_window* w, rct_widgetindex widgetIndex)
{
2018-06-22 23:21:44 +02:00
switch (widgetIndex)
{
case WIDX_LAND:
case WIDX_WATER:
case WIDX_CLEAR_SCENERY:
hide_gridlines();
break;
2020-05-01 22:32:41 +02:00
#ifdef ENABLE_SCRIPTING
default:
auto& customTool = OpenRCT2::Scripting::ActiveCustomTool;
if (customTool)
{
customTool->OnAbort();
customTool = {};
}
break;
#endif
}
}
2015-05-19 00:16:43 +02:00
static void TopToolbarInitMapMenu(rct_window* w, rct_widget* widget)
2020-02-11 22:26:05 +01:00
{
auto i = 0;
gDropdownItems[i++].Format = STR_SHORTCUT_SHOW_MAP;
gDropdownItems[i++].Format = STR_EXTRA_VIEWPORT;
2021-04-05 19:01:43 +02:00
if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && gEditorStep == EditorStep::LandscapeEditor)
2020-02-11 22:26:05 +01:00
{
gDropdownItems[i++].Format = STR_MAPGEN_WINDOW_TITLE;
2020-02-11 22:26:05 +01:00
}
#ifdef ENABLE_SCRIPTING
2020-02-11 22:26:05 +01:00
const auto& customMenuItems = OpenRCT2::Scripting::CustomMenuItems;
if (!customMenuItems.empty())
{
gDropdownItems[i++].Format = STR_EMPTY;
2020-02-11 22:26:05 +01:00
for (const auto& item : customMenuItems)
{
2022-02-20 20:27:43 +01:00
if (item.Kind == OpenRCT2::Scripting::CustomToolbarMenuItemKind::Standard)
{
gDropdownItems[i].Format = STR_STRING;
auto sz = item.Text.c_str();
std::memcpy(&gDropdownItems[i].Args, &sz, sizeof(const char*));
i++;
}
2020-02-11 22:26:05 +01:00
}
}
2020-02-23 13:55:48 +01:00
#endif
2020-02-11 22:26:05 +01:00
WindowDropdownShowText(
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, w->colours[1] | 0x80, 0, i);
2020-02-11 22:26:05 +01:00
gDropdownDefaultIndex = DDIDX_SHOW_MAP;
}
static void TopToolbarMapMenuDropdown(int16_t dropdownIndex)
2020-02-11 22:26:05 +01:00
{
int32_t customStartIndex = 3;
2021-04-05 19:01:43 +02:00
if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && gEditorStep == EditorStep::LandscapeEditor)
2020-02-11 22:26:05 +01:00
{
customStartIndex++;
}
if (dropdownIndex < customStartIndex)
{
switch (dropdownIndex)
{
case 0:
context_open_window(WC_MAP);
break;
case 1:
context_open_window(WC_VIEWPORT);
break;
case 2:
context_open_window(WC_MAPGEN);
break;
}
}
else
{
#ifdef ENABLE_SCRIPTING
2020-02-11 22:26:05 +01:00
const auto& customMenuItems = OpenRCT2::Scripting::CustomMenuItems;
2020-02-22 19:04:27 +01:00
auto customIndex = static_cast<size_t>(dropdownIndex - customStartIndex);
2022-02-20 20:27:43 +01:00
size_t i = 0;
for (const auto& item : customMenuItems)
2020-02-11 22:26:05 +01:00
{
2022-02-20 20:27:43 +01:00
if (item.Kind == OpenRCT2::Scripting::CustomToolbarMenuItemKind::Standard)
{
if (i == customIndex)
{
item.Invoke();
break;
}
i++;
}
2020-02-11 22:26:05 +01:00
}
2020-02-23 13:55:48 +01:00
#endif
2020-02-11 22:26:05 +01:00
}
}
static void TopToolbarInitFastforwardMenu(rct_window* w, rct_widget* widget)
2018-06-22 23:21:44 +02:00
{
int32_t num_items = 4;
gDropdownItems[0].Format = STR_TOGGLE_OPTION;
gDropdownItems[1].Format = STR_TOGGLE_OPTION;
gDropdownItems[2].Format = STR_TOGGLE_OPTION;
gDropdownItems[3].Format = STR_TOGGLE_OPTION;
2018-06-22 23:21:44 +02:00
if (gConfigGeneral.debugging_tools)
{
gDropdownItems[4].Format = STR_EMPTY;
gDropdownItems[5].Format = STR_TOGGLE_OPTION;
gDropdownItems[5].Args = STR_SPEED_HYPER;
num_items = 6;
}
gDropdownItems[0].Args = STR_SPEED_NORMAL;
gDropdownItems[1].Args = STR_SPEED_QUICK;
gDropdownItems[2].Args = STR_SPEED_FAST;
gDropdownItems[3].Args = STR_SPEED_TURBO;
WindowDropdownShowText(
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, w->colours[0] | 0x80, 0,
num_items);
// Set checkmarks
2018-06-22 23:21:44 +02:00
if (gGameSpeed <= 4)
{
Dropdown::SetChecked(gGameSpeed - 1, true);
}
2018-06-22 23:21:44 +02:00
if (gGameSpeed == 8)
{
Dropdown::SetChecked(5, true);
}
2018-06-22 23:21:44 +02:00
if (gConfigGeneral.debugging_tools)
{
gDropdownDefaultIndex = (gGameSpeed == 8 ? 0 : gGameSpeed);
2018-06-22 23:21:44 +02:00
}
else
{
gDropdownDefaultIndex = (gGameSpeed >= 4 ? 0 : gGameSpeed);
}
2018-06-22 23:21:44 +02:00
if (gDropdownDefaultIndex == 4)
{
gDropdownDefaultIndex = 5;
}
2015-05-19 00:16:43 +02:00
}
static void TopToolbarFastforwardMenuDropdown(int16_t dropdownIndex)
{
rct_window* w = window_get_main();
2018-06-22 23:21:44 +02:00
if (w)
{
if (dropdownIndex >= 0 && dropdownIndex <= 5)
{
gGameSpeed = dropdownIndex + 1;
if (gGameSpeed >= 5)
gGameSpeed = 8;
w->Invalidate();
}
}
2015-05-19 00:16:43 +02:00
}
static void TopToolbarInitRotateMenu(rct_window* w, rct_widget* widget)
{
gDropdownItems[0].Format = STR_ROTATE_CLOCKWISE;
gDropdownItems[1].Format = STR_ROTATE_ANTI_CLOCKWISE;
WindowDropdownShowText(
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, w->colours[1] | 0x80, 0, 2);
gDropdownDefaultIndex = DDIDX_ROTATE_CLOCKWISE;
}
static void TopToolbarRotateMenuDropdown(int16_t dropdownIndex)
{
rct_window* w = window_get_main();
2018-06-22 23:21:44 +02:00
if (w)
{
if (dropdownIndex == 0)
{
window_rotate_camera(w, 1);
w->Invalidate();
}
2018-06-22 23:21:44 +02:00
else if (dropdownIndex == 1)
{
window_rotate_camera(w, -1);
w->Invalidate();
}
}
}
static void TopToolbarInitCheatsMenu(rct_window* w, rct_widget* widget)
{
using namespace Dropdown;
2022-02-12 23:42:59 +01:00
constexpr ItemExt items[] = {
ToggleOption(DDIDX_CHEATS, STR_CHEAT_TITLE),
ToggleOption(DDIDX_TILE_INSPECTOR, STR_DEBUG_DROPDOWN_TILE_INSPECTOR),
ToggleOption(DDIDX_OBJECT_SELECTION, STR_DEBUG_DROPDOWN_OBJECT_SELECTION),
ToggleOption(DDIDX_INVENTIONS_LIST, STR_DEBUG_DROPDOWN_INVENTIONS_LIST),
ToggleOption(DDIDX_SCENARIO_OPTIONS, STR_DEBUG_DROPDOWN_SCENARIO_OPTIONS),
2020-10-11 18:41:23 +02:00
ToggleOption(DDIDX_OBJECTIVE_OPTIONS, STR_CHEATS_MENU_OBJECTIVE_OPTIONS),
Separator(),
ToggleOption(DDIDX_ENABLE_SANDBOX_MODE, STR_ENABLE_SANDBOX_MODE),
ToggleOption(DDIDX_DISABLE_CLEARANCE_CHECKS, STR_DISABLE_CLEARANCE_CHECKS),
ToggleOption(DDIDX_DISABLE_SUPPORT_LIMITS, STR_DISABLE_SUPPORT_LIMITS),
};
static_assert(ItemIDsMatchIndices(items));
SetItems(items);
WindowDropdownShowText(
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, w->colours[0] | 0x80, 0,
TOP_TOOLBAR_CHEATS_COUNT);
// Disable items that are not yet available in multiplayer
2018-06-22 23:21:44 +02:00
if (network_get_mode() != NETWORK_MODE_NONE)
{
Dropdown::SetDisabled(DDIDX_OBJECT_SELECTION, true);
Dropdown::SetDisabled(DDIDX_INVENTIONS_LIST, true);
Dropdown::SetDisabled(DDIDX_OBJECTIVE_OPTIONS, true);
}
if (gScreenFlags & SCREEN_FLAGS_EDITOR)
{
Dropdown::SetDisabled(DDIDX_OBJECT_SELECTION, true);
Dropdown::SetDisabled(DDIDX_INVENTIONS_LIST, true);
Dropdown::SetDisabled(DDIDX_SCENARIO_OPTIONS, true);
Dropdown::SetDisabled(DDIDX_OBJECTIVE_OPTIONS, true);
Dropdown::SetDisabled(DDIDX_ENABLE_SANDBOX_MODE, true);
}
if (gCheatsSandboxMode)
{
Dropdown::SetChecked(DDIDX_ENABLE_SANDBOX_MODE, true);
}
if (gCheatsDisableClearanceChecks)
{
Dropdown::SetChecked(DDIDX_DISABLE_CLEARANCE_CHECKS, true);
}
if (gCheatsDisableSupportLimits)
{
Dropdown::SetChecked(DDIDX_DISABLE_SUPPORT_LIMITS, true);
}
gDropdownDefaultIndex = DDIDX_CHEATS;
}
static void TopToolbarCheatsMenuDropdown(int16_t dropdownIndex)
{
switch (dropdownIndex)
{
case DDIDX_CHEATS:
context_open_window(WC_CHEATS);
break;
case DDIDX_TILE_INSPECTOR:
context_open_window(WC_TILE_INSPECTOR);
break;
case DDIDX_OBJECT_SELECTION:
window_close_all();
context_open_window(WC_EDITOR_OBJECT_SELECTION);
break;
case DDIDX_INVENTIONS_LIST:
context_open_window(WC_EDITOR_INVENTION_LIST);
break;
case DDIDX_SCENARIO_OPTIONS:
context_open_window(WC_EDITOR_SCENARIO_OPTIONS);
break;
2020-10-11 18:41:23 +02:00
case DDIDX_OBJECTIVE_OPTIONS:
context_open_window(WC_EDITOR_OBJECTIVE_OPTIONS);
2020-10-11 18:41:23 +02:00
break;
case DDIDX_ENABLE_SANDBOX_MODE:
CheatsSet(CheatType::SandboxMode, !gCheatsSandboxMode);
break;
case DDIDX_DISABLE_CLEARANCE_CHECKS:
CheatsSet(CheatType::DisableClearanceChecks, !gCheatsDisableClearanceChecks);
break;
case DDIDX_DISABLE_SUPPORT_LIMITS:
CheatsSet(CheatType::DisableSupportLimits, !gCheatsDisableSupportLimits);
break;
}
}
static void TopToolbarInitDebugMenu(rct_window* w, rct_widget* widget)
{
gDropdownItems[DDIDX_CONSOLE].Format = STR_TOGGLE_OPTION;
gDropdownItems[DDIDX_CONSOLE].Args = STR_DEBUG_DROPDOWN_CONSOLE;
gDropdownItems[DDIDX_DEBUG_PAINT].Format = STR_TOGGLE_OPTION;
gDropdownItems[DDIDX_DEBUG_PAINT].Args = STR_DEBUG_DROPDOWN_DEBUG_PAINT;
WindowDropdownShowText(
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, w->colours[0] | 0x80,
Dropdown::Flag::StayOpen, TOP_TOOLBAR_DEBUG_COUNT);
Dropdown::SetChecked(DDIDX_DEBUG_PAINT, window_find_by_class(WC_DEBUG_PAINT) != nullptr);
}
static void TopToolbarInitNetworkMenu(rct_window* w, rct_widget* widget)
{
gDropdownItems[DDIDX_MULTIPLAYER].Format = STR_MULTIPLAYER;
gDropdownItems[DDIDX_MULTIPLAYER_RECONNECT].Format = STR_MULTIPLAYER_RECONNECT;
2019-01-29 19:51:07 +01:00
WindowDropdownShowText(
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, w->colours[0] | 0x80, 0,
TOP_TOOLBAR_NETWORK_COUNT);
Dropdown::SetDisabled(DDIDX_MULTIPLAYER_RECONNECT, !network_is_desynchronised());
gDropdownDefaultIndex = DDIDX_MULTIPLAYER;
2015-07-16 19:32:43 +02:00
}
static void TopToolbarDebugMenuDropdown(int16_t dropdownIndex)
{
rct_window* w = window_get_main();
if (w != nullptr)
2018-06-22 23:21:44 +02:00
{
switch (dropdownIndex)
2018-03-11 23:25:34 +01:00
{
2018-06-22 23:21:44 +02:00
case DDIDX_CONSOLE:
{
auto& console = GetInGameConsole();
console.Open();
break;
}
2018-06-22 23:21:44 +02:00
case DDIDX_DEBUG_PAINT:
if (window_find_by_class(WC_DEBUG_PAINT) == nullptr)
{
context_open_window(WC_DEBUG_PAINT);
}
else
{
window_close_by_class(WC_DEBUG_PAINT);
}
break;
}
}
}
static void TopToolbarNetworkMenuDropdown(int16_t dropdownIndex)
{
rct_window* w = window_get_main();
if (w != nullptr)
2018-06-22 23:21:44 +02:00
{
switch (dropdownIndex)
{
case DDIDX_MULTIPLAYER:
context_open_window(WC_MULTIPLAYER);
break;
case DDIDX_MULTIPLAYER_RECONNECT:
network_reconnect();
break;
}
}
2015-07-16 19:32:43 +02:00
}
/**
*
* rct2: 0x0066CDE4
*/
static void TopToolbarInitViewMenu(rct_window* w, rct_widget* widget)
2018-06-22 23:21:44 +02:00
{
using namespace Dropdown;
2022-02-12 23:42:59 +01:00
constexpr ItemExt items[] = {
ToggleOption(DDIDX_UNDERGROUND_INSIDE, STR_UNDERGROUND_VIEW),
2021-05-24 16:54:30 +02:00
ToggleOption(DDIDX_TRANSPARENT_WATER, STR_VIEWPORT_TRANSPARENT_WATER),
ToggleOption(DDIDX_HIDE_BASE, STR_REMOVE_BASE_LAND),
ToggleOption(DDIDX_HIDE_VERTICAL, STR_REMOVE_VERTICAL_FACES),
Separator(),
2022-03-06 16:04:11 +01:00
ToggleOption(DDIDX_HIDE_RIDES, STR_SEE_THROUGH_RIDES),
ToggleOption(DDIDX_HIDE_VEHICLES, STR_SEE_THROUGH_VEHICLES),
ToggleOption(DDIDX_HIDE_VEGETATION, STR_SEE_THROUGH_VEGETATION),
2022-03-06 16:04:11 +01:00
ToggleOption(DDIDX_HIDE_SCENERY, STR_SEE_THROUGH_SCENERY),
ToggleOption(DDIDX_HIDE_PATHS, STR_SEE_THROUGH_PATHS),
ToggleOption(DDIDX_HIDE_SUPPORTS, STR_SEE_THROUGH_SUPPORTS),
ToggleOption(DDIDX_HIDE_GUESTS, STR_SEE_THROUGH_GUESTS),
ToggleOption(DDIDX_HIDE_STAFF, STR_SEE_THROUGH_STAFF),
Separator(),
ToggleOption(DDIDX_LAND_HEIGHTS, STR_HEIGHT_MARKS_ON_LAND),
ToggleOption(DDIDX_TRACK_HEIGHTS, STR_HEIGHT_MARKS_ON_RIDE_TRACKS),
ToggleOption(DDIDX_PATH_HEIGHTS, STR_HEIGHT_MARKS_ON_PATHS),
Separator(),
ToggleOption(DDIDX_VIEW_CLIPPING, STR_VIEW_CLIPPING_MENU),
ToggleOption(DDIDX_HIGHLIGHT_PATH_ISSUES, STR_HIGHLIGHT_PATH_ISSUES_MENU),
Separator(),
ToggleOption(DDIDX_TRANSPARENCY, STR_TRANSPARENCY_OPTIONS),
};
2021-05-24 16:30:46 +02:00
static_assert(ItemIDsMatchIndices(items));
SetItems(items);
WindowDropdownShowText(
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, w->colours[1] | 0x80, 0,
TOP_TOOLBAR_VIEW_MENU_COUNT);
// Set checkmarks
rct_viewport* mainViewport = window_get_main()->viewport;
if (mainViewport->flags & VIEWPORT_FLAG_UNDERGROUND_INSIDE)
2021-05-24 16:30:46 +02:00
Dropdown::SetChecked(DDIDX_UNDERGROUND_INSIDE, true);
2021-05-24 16:54:30 +02:00
if (gConfigGeneral.transparent_water)
Dropdown::SetChecked(DDIDX_TRANSPARENT_WATER, true);
if (mainViewport->flags & VIEWPORT_FLAG_HIDE_BASE)
2021-05-24 16:30:46 +02:00
Dropdown::SetChecked(DDIDX_HIDE_BASE, true);
if (mainViewport->flags & VIEWPORT_FLAG_HIDE_VERTICAL)
2021-05-24 16:30:46 +02:00
Dropdown::SetChecked(DDIDX_HIDE_VERTICAL, true);
2022-03-06 15:26:36 +01:00
if (mainViewport->flags & VIEWPORT_FLAG_HIDE_RIDES)
2022-03-06 16:04:11 +01:00
Dropdown::SetChecked(DDIDX_HIDE_RIDES, true);
if (mainViewport->flags & VIEWPORT_FLAG_HIDE_VEHICLES)
Dropdown::SetChecked(DDIDX_HIDE_VEHICLES, true);
if (mainViewport->flags & VIEWPORT_FLAG_HIDE_VEGETATION)
Dropdown::SetChecked(DDIDX_HIDE_VEGETATION, true);
2022-03-06 15:26:36 +01:00
if (mainViewport->flags & VIEWPORT_FLAG_HIDE_SCENERY)
2022-03-06 16:04:11 +01:00
Dropdown::SetChecked(DDIDX_HIDE_SCENERY, true);
2022-03-06 15:26:36 +01:00
if (mainViewport->flags & VIEWPORT_FLAG_HIDE_PATHS)
2022-03-06 16:04:11 +01:00
Dropdown::SetChecked(DDIDX_HIDE_PATHS, true);
2022-03-06 15:26:36 +01:00
if (mainViewport->flags & VIEWPORT_FLAG_HIDE_SUPPORTS)
2022-03-06 16:04:11 +01:00
Dropdown::SetChecked(DDIDX_HIDE_SUPPORTS, true);
if (mainViewport->flags & VIEWPORT_FLAG_HIDE_GUESTS)
Dropdown::SetChecked(DDIDX_HIDE_GUESTS, true);
if (mainViewport->flags & VIEWPORT_FLAG_HIDE_STAFF)
Dropdown::SetChecked(DDIDX_HIDE_STAFF, true);
if (mainViewport->flags & VIEWPORT_FLAG_LAND_HEIGHTS)
2021-05-24 16:30:46 +02:00
Dropdown::SetChecked(DDIDX_LAND_HEIGHTS, true);
if (mainViewport->flags & VIEWPORT_FLAG_TRACK_HEIGHTS)
2021-05-24 16:30:46 +02:00
Dropdown::SetChecked(DDIDX_TRACK_HEIGHTS, true);
if (mainViewport->flags & VIEWPORT_FLAG_PATH_HEIGHTS)
2021-05-24 16:30:46 +02:00
Dropdown::SetChecked(DDIDX_PATH_HEIGHTS, true);
if (mainViewport->flags & VIEWPORT_FLAG_CLIP_VIEW)
Dropdown::SetChecked(DDIDX_VIEW_CLIPPING, true);
if (mainViewport->flags & VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES)
Dropdown::SetChecked(DDIDX_HIGHLIGHT_PATH_ISSUES, true);
gDropdownDefaultIndex = DDIDX_UNDERGROUND_INSIDE;
2021-05-24 16:30:46 +02:00
// Opaque water relies on RCT1 sprites.
if (!is_csg_loaded())
{
2021-05-24 16:54:30 +02:00
Dropdown::SetDisabled(DDIDX_TRANSPARENT_WATER, true);
2021-05-24 16:30:46 +02:00
}
}
/**
*
* rct2: 0x0066CF8A
*/
static void TopToolbarViewMenuDropdown(int16_t dropdownIndex)
{
rct_window* w = window_get_main();
if (w != nullptr)
2018-06-22 23:21:44 +02:00
{
switch (dropdownIndex)
{
case DDIDX_UNDERGROUND_INSIDE:
w->viewport->flags ^= VIEWPORT_FLAG_UNDERGROUND_INSIDE;
break;
2021-05-24 16:54:30 +02:00
case DDIDX_TRANSPARENT_WATER:
gConfigGeneral.transparent_water ^= 1;
2021-05-24 16:30:46 +02:00
config_save_default();
break;
2018-06-22 23:21:44 +02:00
case DDIDX_HIDE_BASE:
w->viewport->flags ^= VIEWPORT_FLAG_HIDE_BASE;
break;
case DDIDX_HIDE_VERTICAL:
w->viewport->flags ^= VIEWPORT_FLAG_HIDE_VERTICAL;
break;
2022-03-06 16:04:11 +01:00
case DDIDX_HIDE_RIDES:
2022-03-06 15:26:36 +01:00
w->viewport->flags ^= VIEWPORT_FLAG_HIDE_RIDES;
2021-08-01 16:12:57 +02:00
break;
2022-03-06 16:04:11 +01:00
case DDIDX_HIDE_VEHICLES:
w->viewport->flags ^= VIEWPORT_FLAG_HIDE_VEHICLES;
2018-06-22 23:21:44 +02:00
break;
case DDIDX_HIDE_VEGETATION:
w->viewport->flags ^= VIEWPORT_FLAG_HIDE_VEGETATION;
2018-06-22 23:21:44 +02:00
break;
2022-03-06 16:04:11 +01:00
case DDIDX_HIDE_SCENERY:
2022-03-06 15:26:36 +01:00
w->viewport->flags ^= VIEWPORT_FLAG_HIDE_SCENERY;
2018-06-22 23:21:44 +02:00
break;
2022-03-06 16:04:11 +01:00
case DDIDX_HIDE_PATHS:
2022-03-06 15:26:36 +01:00
w->viewport->flags ^= VIEWPORT_FLAG_HIDE_PATHS;
2018-06-22 23:21:44 +02:00
break;
2022-03-06 16:04:11 +01:00
case DDIDX_HIDE_SUPPORTS:
w->viewport->flags ^= VIEWPORT_FLAG_HIDE_SUPPORTS;
2018-06-22 23:21:44 +02:00
break;
2022-03-06 16:04:11 +01:00
case DDIDX_HIDE_GUESTS:
w->viewport->flags ^= VIEWPORT_FLAG_HIDE_GUESTS;
break;
case DDIDX_HIDE_STAFF:
w->viewport->flags ^= VIEWPORT_FLAG_HIDE_STAFF;
2018-06-22 23:21:44 +02:00
break;
case DDIDX_LAND_HEIGHTS:
w->viewport->flags ^= VIEWPORT_FLAG_LAND_HEIGHTS;
break;
case DDIDX_TRACK_HEIGHTS:
w->viewport->flags ^= VIEWPORT_FLAG_TRACK_HEIGHTS;
break;
case DDIDX_PATH_HEIGHTS:
w->viewport->flags ^= VIEWPORT_FLAG_PATH_HEIGHTS;
break;
case DDIDX_VIEW_CLIPPING:
if (window_find_by_class(WC_VIEW_CLIPPING) == nullptr)
{
context_open_window(WC_VIEW_CLIPPING);
}
else
{
// If window is already open, toggle the view clipping on/off
w->viewport->flags ^= VIEWPORT_FLAG_CLIP_VIEW;
}
break;
case DDIDX_HIGHLIGHT_PATH_ISSUES:
w->viewport->flags ^= VIEWPORT_FLAG_HIGHLIGHT_PATH_ISSUES;
break;
case DDIDX_TRANSPARENCY:
context_open_window(WC_TRANSPARENCY);
break;
2018-06-22 23:21:44 +02:00
default:
return;
}
w->Invalidate();
}
}
/**
*
* rct2: 0x0066CCE7
*/
static void ToggleFootpathWindow()
{
2018-06-22 23:21:44 +02:00
if (window_find_by_class(WC_FOOTPATH) == nullptr)
{
2017-08-12 23:06:12 +02:00
context_open_window(WC_FOOTPATH);
2018-06-22 23:21:44 +02:00
}
else
{
tool_cancel();
window_close_by_class(WC_FOOTPATH);
}
}
/**
*
* rct2: 0x0066CD54
*/
static void ToggleLandWindow(rct_window* topToolbar, rct_widgetindex widgetIndex)
{
2018-06-22 23:21:44 +02:00
if ((input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) && gCurrentToolWidget.window_classification == WC_TOP_TOOLBAR
&& gCurrentToolWidget.widget_index == WIDX_LAND)
{
tool_cancel();
2018-06-22 23:21:44 +02:00
}
else
{
_landToolBlocked = false;
show_gridlines();
tool_set(*topToolbar, widgetIndex, Tool::DigDown);
input_set_flag(INPUT_FLAG_6, true);
2017-08-12 23:06:12 +02:00
context_open_window(WC_LAND);
}
}
/**
*
* rct2: 0x0066CD0C
*/
static void ToggleClearSceneryWindow(rct_window* topToolbar, rct_widgetindex widgetIndex)
{
2018-06-22 23:21:44 +02:00
if ((input_test_flag(INPUT_FLAG_TOOL_ACTIVE) && gCurrentToolWidget.window_classification == WC_TOP_TOOLBAR
&& gCurrentToolWidget.widget_index == WIDX_CLEAR_SCENERY))
{
tool_cancel();
2018-06-22 23:21:44 +02:00
}
else
{
show_gridlines();
tool_set(*topToolbar, widgetIndex, Tool::Crosshair);
input_set_flag(INPUT_FLAG_6, true);
2017-08-12 23:06:12 +02:00
context_open_window(WC_CLEAR_SCENERY);
}
}
/**
*
* rct2: 0x0066CD9C
*/
static void ToggleWaterWindow(rct_window* topToolbar, rct_widgetindex widgetIndex)
{
2018-06-22 23:21:44 +02:00
if ((input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) && gCurrentToolWidget.window_classification == WC_TOP_TOOLBAR
&& gCurrentToolWidget.widget_index == WIDX_WATER)
{
tool_cancel();
2018-06-22 23:21:44 +02:00
}
else
{
_landToolBlocked = false;
show_gridlines();
tool_set(*topToolbar, widgetIndex, Tool::WaterDown);
input_set_flag(INPUT_FLAG_6, true);
2017-08-12 23:06:12 +02:00
context_open_window(WC_WATER);
}
}
2015-07-02 18:00:39 +02:00
/**
*
* rct2: 0x0066D104
*/
bool LandToolIsActive()
2015-07-02 18:00:39 +02:00
{
if (!(input_test_flag(INPUT_FLAG_TOOL_ACTIVE)))
return false;
if (gCurrentToolWidget.window_classification != WC_TOP_TOOLBAR)
return false;
if (gCurrentToolWidget.widget_index != WIDX_LAND)
return false;
return true;
2015-07-02 18:00:39 +02:00
}
/**
*
* rct2: 0x0066D125
*/
bool ClearSceneryToolIsActive()
{
if (!(input_test_flag(INPUT_FLAG_TOOL_ACTIVE)))
return false;
if (gCurrentToolWidget.window_classification != WC_TOP_TOOLBAR)
return false;
if (gCurrentToolWidget.widget_index != WIDX_CLEAR_SCENERY)
return false;
return true;
}
/**
*
* rct2: 0x0066D125
*/
bool WaterToolIsActive()
{
if (!(input_test_flag(INPUT_FLAG_TOOL_ACTIVE)))
return false;
if (gCurrentToolWidget.window_classification != WC_TOP_TOOLBAR)
return false;
if (gCurrentToolWidget.widget_index != WIDX_WATER)
return false;
return true;
}
2019-01-02 12:59:37 +01:00
static ClearAction GetClearAction()
{
auto range = MapRange(gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y);
ClearableItems itemsToClear = 0;
if (gClearSmallScenery)
itemsToClear |= CLEARABLE_ITEMS::SCENERY_SMALL;
if (gClearLargeScenery)
itemsToClear |= CLEARABLE_ITEMS::SCENERY_LARGE;
if (gClearFootpath)
itemsToClear |= CLEARABLE_ITEMS::SCENERY_FOOTPATH;
return ClearAction(range, itemsToClear);
}