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

2344 lines
123 KiB
C++
Raw Normal View History

/*****************************************************************************
2020-07-21 15:04:34 +02:00
* Copyright (c) 2014-2020 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <algorithm>
2018-11-21 23:16:04 +01:00
#include <iterator>
2018-06-22 23:21:44 +02:00
#include <openrct2-ui/interface/Dropdown.h>
#include <openrct2-ui/interface/Widget.h>
2017-11-23 00:42:12 +01:00
#include <openrct2-ui/windows/Window.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/Game.h>
#include <openrct2/Input.h>
#include <openrct2/actions/TileModifyAction.hpp>
2019-05-18 10:23:33 +02:00
#include <openrct2/common.h>
2017-11-23 00:42:12 +01:00
#include <openrct2/core/Guard.hpp>
2018-01-06 18:32:25 +01:00
#include <openrct2/localisation/Localisation.h>
#include <openrct2/localisation/StringIds.h>
#include <openrct2/object/TerrainEdgeObject.h>
#include <openrct2/object/TerrainSurfaceObject.h>
2018-01-10 00:00:09 +01:00
#include <openrct2/ride/RideData.h>
2017-11-23 00:42:12 +01:00
#include <openrct2/ride/Track.h>
#include <openrct2/sprites.h>
#include <openrct2/windows/tile_inspector.h>
2018-06-22 23:21:44 +02:00
#include <openrct2/world/Banner.h>
2018-01-11 10:59:26 +01:00
#include <openrct2/world/Footpath.h>
2017-11-23 00:42:12 +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-12-04 20:09:38 +01:00
#include <openrct2/world/SmallScenery.h>
2018-05-01 16:33:16 +02:00
#include <openrct2/world/Surface.h>
// clang-format off
static constexpr const rct_string_id EntranceTypeStringIds[] = {
STR_TILE_INSPECTOR_ENTRANCE_TYPE_RIDE_ENTRANCE,
STR_TILE_INSPECTOR_ENTRANCE_TYPE_RIDE_EXIT,
STR_TILE_INSPECTOR_ENTRANCE_TYPE_PARK_ENTRANC,
};
static constexpr const rct_string_id ParkEntrancePartStringIds[] = {
STR_TILE_INSPECTOR_ENTRANCE_MIDDLE,
STR_TILE_INSPECTOR_ENTRANCE_LEFT,
STR_TILE_INSPECTOR_ENTRANCE_RIGHT
};
static constexpr const rct_string_id WallSlopeStringIds[] = {
STR_TILE_INSPECTOR_WALL_FLAT,
STR_TILE_INSPECTOR_WALL_SLOPED_LEFT,
STR_TILE_INSPECTOR_WALL_SLOPED_RIGHT,
STR_TILE_INSPECTOR_WALL_ANIMATION_FRAME
2016-10-01 22:57:09 +02:00
};
enum WINDOW_TILE_INSPECTOR_WIDGET_IDX {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_LIST,
WIDX_SPINNER_X,
WIDX_SPINNER_X_INCREASE,
WIDX_SPINNER_X_DECREASE,
WIDX_SPINNER_Y,
WIDX_SPINNER_Y_INCREASE,
WIDX_SPINNER_Y_DECREASE,
WIDX_BUTTON_CORRUPT,
WIDX_BUTTON_REMOVE,
WIDX_BUTTON_MOVE_UP,
WIDX_BUTTON_MOVE_DOWN,
WIDX_BUTTON_ROTATE,
WIDX_BUTTON_SORT,
WIDX_BUTTON_PASTE,
WIDX_BUTTON_COPY,
WIDX_COLUMN_TYPE,
WIDX_COLUMN_BASEHEIGHT,
WIDX_COLUMN_CLEARANCEHEIGHT,
WIDX_COLUMN_GHOSTFLAG,
WIDX_COLUMN_LASTFLAG,
WIDX_GROUPBOX_DETAILS,
WIDX_GROUPBOX_PROPERTIES,
PAGE_WIDGETS,
// Surface
WIDX_SURFACE_SPINNER_HEIGHT = PAGE_WIDGETS,
WIDX_SURFACE_SPINNER_HEIGHT_INCREASE,
WIDX_SURFACE_SPINNER_HEIGHT_DECREASE,
WIDX_SURFACE_BUTTON_REMOVE_FENCES,
WIDX_SURFACE_BUTTON_RESTORE_FENCES,
WIDX_SURFACE_CHECK_CORNER_N,
WIDX_SURFACE_CHECK_CORNER_E,
WIDX_SURFACE_CHECK_CORNER_S,
WIDX_SURFACE_CHECK_CORNER_W,
WIDX_SURFACE_CHECK_DIAGONAL,
// Path
WIDX_PATH_SPINNER_HEIGHT = PAGE_WIDGETS,
WIDX_PATH_SPINNER_HEIGHT_INCREASE,
WIDX_PATH_SPINNER_HEIGHT_DECREASE,
WIDX_PATH_CHECK_BROKEN,
WIDX_PATH_CHECK_SLOPED,
WIDX_PATH_CHECK_EDGE_NE, // Note: This is NOT named after the world orientation, but after the way
WIDX_PATH_CHECK_EDGE_E, // it looks in the window (top corner is north). Their order is important,
WIDX_PATH_CHECK_EDGE_SE, // as this is the same order paths use for their corners / edges.
WIDX_PATH_CHECK_EDGE_S, // N
WIDX_PATH_CHECK_EDGE_SW, // NW-------NE
WIDX_PATH_CHECK_EDGE_W, // W ------------- E
WIDX_PATH_CHECK_EDGE_NW, // SW-------SE
WIDX_PATH_CHECK_EDGE_N, // S
// Track
WIDX_TRACK_CHECK_APPLY_TO_ALL = PAGE_WIDGETS,
WIDX_TRACK_SPINNER_HEIGHT,
WIDX_TRACK_SPINNER_HEIGHT_INCREASE,
WIDX_TRACK_SPINNER_HEIGHT_DECREASE,
WIDX_TRACK_CHECK_CHAIN_LIFT,
WIDX_TRACK_CHECK_BLOCK_BRAKE_CLOSED,
WIDX_TRACK_CHECK_IS_INDESTRUCTIBLE,
// Scenery
WIDX_SCENERY_SPINNER_HEIGHT = PAGE_WIDGETS,
WIDX_SCENERY_SPINNER_HEIGHT_INCREASE,
WIDX_SCENERY_SPINNER_HEIGHT_DECREASE,
WIDX_SCENERY_CHECK_QUARTER_N,
WIDX_SCENERY_CHECK_QUARTER_E,
WIDX_SCENERY_CHECK_QUARTER_S,
WIDX_SCENERY_CHECK_QUARTER_W,
WIDX_SCENERY_CHECK_COLLISION_N,
WIDX_SCENERY_CHECK_COLLISION_E,
WIDX_SCENERY_CHECK_COLLISION_S,
WIDX_SCENERY_CHECK_COLLISION_W,
// Entrance
WIDX_ENTRANCE_SPINNER_HEIGHT = PAGE_WIDGETS,
WIDX_ENTRANCE_SPINNER_HEIGHT_INCREASE,
WIDX_ENTRANCE_SPINNER_HEIGHT_DECREASE,
WIDX_ENTRANCE_BUTTON_MAKE_USABLE,
// Wall
WIDX_WALL_SPINNER_HEIGHT = PAGE_WIDGETS,
WIDX_WALL_SPINNER_HEIGHT_INCREASE,
WIDX_WALL_SPINNER_HEIGHT_DECREASE,
WIDX_WALL_DROPDOWN_SLOPE,
WIDX_WALL_DROPDOWN_SLOPE_BUTTON,
WIDX_WALL_SPINNER_ANIMATION_FRAME,
WIDX_WALL_SPINNER_ANIMATION_FRAME_INCREASE,
WIDX_WALL_SPINNER_ANIMATION_FRAME_DECREASE,
// Large
WIDX_LARGE_SCENERY_SPINNER_HEIGHT = PAGE_WIDGETS,
WIDX_LARGE_SCENERY_SPINNER_HEIGHT_INCREASE,
WIDX_LARGE_SCENERY_SPINNER_HEIGHT_DECREASE,
// Banner
WIDX_BANNER_SPINNER_HEIGHT = PAGE_WIDGETS,
WIDX_BANNER_SPINNER_HEIGHT_INCREASE,
WIDX_BANNER_SPINNER_HEIGHT_DECREASE,
WIDX_BANNER_CHECK_BLOCK_NE,
WIDX_BANNER_CHECK_BLOCK_SE,
WIDX_BANNER_CHECK_BLOCK_SW,
WIDX_BANNER_CHECK_BLOCK_NW,
// Corrupt
WIDX_CORRUPT_SPINNER_HEIGHT = PAGE_WIDGETS,
WIDX_CORRUPT_SPINNER_HEIGHT_INCREASE,
WIDX_CORRUPT_SPINNER_HEIGHT_DECREASE,
WIDX_CORRUPT_BUTTON_CLAMP,
};
2020-05-05 22:26:14 +02:00
static constexpr const rct_string_id WINDOW_TITLE = STR_TILE_INSPECTOR_TITLE;
// Window sizes
2020-05-09 17:05:01 +02:00
static constexpr const int32_t WW = 400;
static constexpr const int32_t WH = 170;
2019-10-24 05:38:13 +02:00
constexpr int32_t MIN_WW = WW;
constexpr int32_t MAX_WW = WW;
constexpr int32_t MIN_WH = 130;
constexpr int32_t MAX_WH = 800;
// Button space for top buttons
2019-10-24 05:38:13 +02:00
constexpr int32_t BW = WW - 5; // Button's right side
constexpr int32_t BX = BW - 23; // Button's left side
constexpr int32_t BY = 17; // Button's Top
constexpr int32_t BH = BY + 23; // Button's Bottom
constexpr int32_t BS = 24;
2016-05-30 00:35:50 +02:00
// Column offsets for the table headers
2019-10-24 05:38:13 +02:00
constexpr int32_t COL_X_TYPE = 3; // Type
constexpr int32_t COL_X_BH = COL_X_TYPE + 312; // Base height
constexpr int32_t COL_X_CH = COL_X_BH + 20; // Clearance height
constexpr int32_t COL_X_GF = COL_X_CH + 20; // Ghost flag
constexpr int32_t COL_X_LF = COL_X_GF + 12; // Last for tile flag
constexpr int32_t PADDING_BOTTOM = 15;
constexpr int32_t GROUPBOX_PADDING = 6;
constexpr int32_t HORIZONTAL_GROUPBOX_PADDING = 5;
constexpr int32_t VERTICAL_GROUPBOX_PADDING = 4;
constexpr int32_t BUTTONW = 130;
constexpr int32_t BUTTONH = 17;
// Calculates the .left, .right, .top and .bottom for buttons in a group box.
// Buttons are used as reference points for all other widgets in the group boxes.
#define GBBL(col) (12 + col * (BUTTONW + HORIZONTAL_GROUPBOX_PADDING))
#define GBBR(col) (GBBL(col) + BUTTONW)
#define GBBT(GROUPTOP, row) ((GROUPTOP) + 14 + row * (BUTTONH + VERTICAL_GROUPBOX_PADDING))
#define GBBB(GROUPTOP, row) (GBBT((GROUPTOP), row) + BUTTONH)
#define GBB(GROUPTOP, col, row) GBBL(col), GBBR(col), GBBT((GROUPTOP), row), GBBB((GROUPTOP), row)
#define GBBF(GROUPTOP, col, row)GBBL(col), WW - 10, GBBT((GROUPTOP), row), GBBB((GROUPTOP), row) // Full width
// Dropdowns use the buttons as a reference
#define GBD(GBT, col, row) GBBL(col), GBBR(col), GBBT(GBT, row) + 3, GBBB(GBT, row) - 3 // Group box dropdown field
#define GBDB(GBT, col, row) GBBR(col) - 11, GBBR(col) - 1, GBBT(GBT, row) + 4, GBBB(GBT, row) - 4 // Group box dropdown button
// Checkbox - given topleft corner
#define CHK(x, y) x, x + 13, y + 2, y + 15
#define MAIN_TILE_INSPECTOR_WIDGETS \
2020-05-09 16:44:21 +02:00
WINDOW_SHIM(WINDOW_TITLE, WW, WH), \
{ WindowWidgetType::Scroll, 1, 3, WW - 4, 57, WH - PADDING_BOTTOM, 2, STR_NONE }, /* Element list */ \
2018-06-10 21:31:08 +02:00
SPINNER_WIDGETS (1, 20, 70, 23, 34, STR_NONE, STR_NONE), /* Spinner X (3 widgets) */ \
SPINNER_WIDGETS (1, 90, 140, 23, 34, STR_NONE, STR_NONE), /* Spinner Y (3 widgets) */ \
/* Buttons */ \
{ WindowWidgetType::FlatBtn, 1, BX, BW, BY, BH, SPR_MAP, STR_INSERT_CORRUPT_TIP }, /* Insert corrupt button */ \
{ WindowWidgetType::FlatBtn, 1, BX - BS * 1, BW - BS * 1, BY, BH, SPR_DEMOLISH, STR_REMOVE_SELECTED_ELEMENT_TIP }, /* Remove button */ \
{ WindowWidgetType::Button, 1, BX - BS * 2, BW - BS * 2, BY, BY + 11, STR_UP, STR_MOVE_SELECTED_ELEMENT_UP_TIP }, /* Move up */ \
{ WindowWidgetType::Button, 1, BX - BS * 2, BW - BS * 2, BH - 11, BH, STR_DOWN, STR_MOVE_SELECTED_ELEMENT_DOWN_TIP }, /* Move down */ \
{ WindowWidgetType::FlatBtn, 1, BX - BS * 3, BW - BS * 3, BY, BH, SPR_ROTATE_ARROW, STR_ROTATE_SELECTED_ELEMENT_TIP }, /* Rotate button */ \
{ WindowWidgetType::FlatBtn, 1, BX - BS * 4, BW - BS * 4, BY, BH, SPR_G2_SORT, STR_TILE_INSPECTOR_SORT_TIP }, /* Sort button */ \
{ WindowWidgetType::FlatBtn, 1, BX - BS * 5, BW - BS * 5, BY, BH, SPR_G2_PASTE, STR_TILE_INSPECTOR_PASTE_TIP }, /* Paste button */ \
{ WindowWidgetType::FlatBtn, 1, BX - BS * 6, BW - BS * 6, BY, BH, SPR_G2_COPY, STR_TILE_INSPECTOR_COPY_TIP }, /* Copy button */ \
/* Column headers */ \
{ WindowWidgetType::TableHeader, 1, COL_X_TYPE, COL_X_BH - 1, 42, 42 + 13, STR_NONE, STR_NONE }, /* Type */ \
{ WindowWidgetType::TableHeader, 1, COL_X_BH, COL_X_CH - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_BASE_HEIGHT }, /* Base height */ \
{ WindowWidgetType::TableHeader, 1, COL_X_CH, COL_X_GF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_CLEARANCE_HEIGHT }, /* Clearance height */ \
{ WindowWidgetType::TableHeader, 1, COL_X_GF, COL_X_LF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_GHOST }, /* Ghost flag */ \
{ WindowWidgetType::TableHeader, 1, COL_X_LF, WW - 3, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_LAST }, /* Last of tile flag */ \
{ WindowWidgetType::Groupbox, 1, 6, WW - 6, -1, -1, STR_NONE, STR_NONE }, /* Details group box */ \
{ WindowWidgetType::Groupbox, 1, 6, WW - 6, -1, -1, STR_TILE_INSPECTOR_GROUPBOX_PROPERTIES, STR_NONE } /* Properties group box */
static rct_widget DefaultWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WIDGETS_END },
};
// Group boxes .top and .bottom for a given window height offsets from the bottom
2019-10-24 05:38:13 +02:00
constexpr int32_t SUR_GBPB = PADDING_BOTTOM; // Surface group box properties bottom
constexpr int32_t SUR_GBPT = SUR_GBPB + 16 + 4 * 21; // Surface group box properties top
constexpr int32_t SUR_GBDB = SUR_GBPT + GROUPBOX_PADDING; // Surface group box details bottom
constexpr int32_t SUR_GBDT = SUR_GBDB + 20 + 4 * 11; // Surface group box details top
static rct_widget SurfaceWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
2018-06-10 21:31:08 +02:00
SPINNER_WIDGETS (1, GBBL(1), GBBR(1), GBBT(WH - SUR_GBPT, 0) + 3, GBBB(WH - SUR_GBPT, 0) - 3, STR_NONE, STR_NONE), // WIDX_SURFACE_SPINNER_HEIGHT{,_INCREASE,_DECREASE}
{ WindowWidgetType::Button, 1, GBB(WH - SUR_GBPT, 0, 1), STR_TILE_INSPECTOR_SURFACE_REMOVE_FENCES, STR_NONE }, // WIDX_SURFACE_BUTTON_REMOVE_FENCES
{ WindowWidgetType::Button, 1, GBB(WH - SUR_GBPT, 1, 1), STR_TILE_INSPECTOR_SURFACE_RESTORE_FENCES, STR_NONE }, // WIDX_SURFACE_BUTTON_RESTORE_FENCES
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SUR_GBPT, 2) + 7 * 0), STR_NONE, STR_NONE }, // WIDX_SURFACE_CHECK_CORNER_N
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 2, GBBT(WH - SUR_GBPT, 2) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_SURFACE_CHECK_CORNER_E
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SUR_GBPT, 2) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_SURFACE_CHECK_CORNER_S
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 0, GBBT(WH - SUR_GBPT, 2) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_SURFACE_CHECK_CORNER_W
{ WindowWidgetType::Checkbox, 1, GBBF(WH - SUR_GBPT, 0, 4), STR_TILE_INSPECTOR_SURFACE_DIAGONAL, STR_NONE }, // WIDX_SURFACE_CHECK_DIAGONAL
{ WIDGETS_END },
};
2019-10-24 05:38:13 +02:00
constexpr int32_t PAT_GBPB = PADDING_BOTTOM; // Path group box properties bottom
constexpr int32_t PAT_GBPT = PAT_GBPB + 16 + 5 * 21; // Path group box properties top
constexpr int32_t PAT_GBDB = PAT_GBPT + GROUPBOX_PADDING; // Path group box info bottom
constexpr int32_t PAT_GBDT = PAT_GBDB + 20 + 2 * 11; // Path group box info top
static rct_widget PathWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
2018-06-10 21:31:08 +02:00
SPINNER_WIDGETS (1, GBBL(1), GBBR(1), GBBT(WH - PAT_GBPT, 0) + 3, GBBB(WH - PAT_GBPT, 0) - 3, STR_NONE, STR_NONE), // WIDX_PATH_SPINNER_HEIGHT{,_INCREASE,_DECREASE}
{ WindowWidgetType::Checkbox, 1, GBBF(WH - PAT_GBPT, 0, 1), STR_TILE_INSPECTOR_PATH_BROKEN, STR_NONE }, // WIDX_PATH_CHECK_BROKEN
{ WindowWidgetType::Checkbox, 1, GBBF(WH - PAT_GBPT, 0, 2), STR_TILE_INSPECTOR_PATH_SLOPED, STR_NONE }, // WIDX_PATH_CHECK_SLOPED
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 3, GBBT(WH - PAT_GBPT, 2) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_NE
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 4, GBBT(WH - PAT_GBPT, 2) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_E
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 3, GBBT(WH - PAT_GBPT, 2) + 7 * 3), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_SE
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 2, GBBT(WH - PAT_GBPT, 2) + 7 * 4), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_S
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - PAT_GBPT, 2) + 7 * 3), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_SW
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 0, GBBT(WH - PAT_GBPT, 2) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_W
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - PAT_GBPT, 2) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_NW
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 2, GBBT(WH - PAT_GBPT, 2) + 7 * 0), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_N
{ WIDGETS_END },
};
2019-10-24 05:38:13 +02:00
constexpr int32_t TRA_GBPB = PADDING_BOTTOM; // Track group box properties bottom
constexpr int32_t TRA_GBPT = TRA_GBPB + 16 + 5 * 21; // Track group box properties top
constexpr int32_t TRA_GBDB = TRA_GBPT + GROUPBOX_PADDING; // Track group box info bottom
constexpr int32_t TRA_GBDT = TRA_GBDB + 20 + 7 * 11; // Track group box info top
static rct_widget TrackWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WindowWidgetType::Checkbox, 1, GBBF(WH - TRA_GBPT, 0, 0), STR_TILE_INSPECTOR_TRACK_ENTIRE_TRACK_PIECE, STR_NONE }, // WIDX_TRACK_CHECK_APPLY_TO_ALL
2018-06-10 21:31:08 +02:00
SPINNER_WIDGETS (1, GBBL(1), GBBR(1), GBBT(WH - TRA_GBPT, 1) + 3, GBBB(WH - TRA_GBPT, 1) - 3, STR_NONE, STR_NONE), // WIDX_TRACK_SPINNER_HEIGHT{,_INCREASE,_DECREASE}
{ WindowWidgetType::Checkbox, 1, GBBF(WH - TRA_GBPT, 0, 2), STR_TILE_INSPECTOR_TRACK_CHAIN_LIFT, STR_NONE }, // WIDX_TRACK_CHECK_CHAIN_LIFT
{ WindowWidgetType::Checkbox, 1, GBBF(WH - TRA_GBPT, 0, 3), STR_TILE_INSPECTOR_TRACK_BLOCK_BRAKE, STR_NONE }, // WIDX_PATH_CHECK_BLOCK_BRAKE_CLOSED
{ WindowWidgetType::Checkbox, 1, GBBF(WH - TRA_GBPT, 0, 4), STR_TILE_INSPECTOR_TRACK_IS_INDESTRUCTIBLE, STR_NONE }, // WIDX_PATH_CHECK_IS_INDESTRUCTIBLE
{ WIDGETS_END },
};
2019-10-24 05:38:13 +02:00
constexpr int32_t SCE_GBPB = PADDING_BOTTOM; // Scenery group box properties bottom
constexpr int32_t SCE_GBPT = SCE_GBPB + 16 + 4 * 21; // Scenery group box properties top
constexpr int32_t SCE_GBDB = SCE_GBPT + GROUPBOX_PADDING; // Scenery group box info bottom
constexpr int32_t SCE_GBDT = SCE_GBDB + 20 + 3 * 11; // Scenery group box info top
static rct_widget SceneryWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
2018-06-10 21:31:08 +02:00
SPINNER_WIDGETS (1, GBBL(1), GBBR(1), GBBT(WH - SCE_GBPT, 0) + 3, GBBB(WH - SCE_GBPT, 0) - 3, STR_NONE, STR_NONE), // WIDX_SCENERY_SPINNER_HEIGHT{,_INCREASE,_DECREASE}
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SCE_GBPT, 1) + 7 * 0), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_QUARTER_N
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 2, GBBT(WH - SCE_GBPT, 1) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_QUARTER_E
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SCE_GBPT, 1) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_QUARTER_S
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 0, GBBT(WH - SCE_GBPT, 1) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_QUARTER_W
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SCE_GBPT, 2) + 7 * 0), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_COLLISION_N
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 2, GBBT(WH - SCE_GBPT, 2) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_COLLISION_E
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SCE_GBPT, 2) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_COLLISION_S
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 0, GBBT(WH - SCE_GBPT, 2) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_COLLISION_W
{ WIDGETS_END },
};
2019-10-24 05:38:13 +02:00
constexpr int32_t ENT_GBPB = PADDING_BOTTOM; // Entrance group box properties bottom
constexpr int32_t ENT_GBPT = ENT_GBPB + 16 + 2 * 21; // Entrance group box properties top
constexpr int32_t ENT_GBDB = ENT_GBPT + GROUPBOX_PADDING; // Entrance group box info bottom
constexpr int32_t ENT_GBDT = ENT_GBDB + 20 + 4 * 11; // Entrance group box info top
static rct_widget EntranceWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
2018-06-10 21:31:08 +02:00
SPINNER_WIDGETS (1, GBBL(1), GBBR(1), GBBT(WH - ENT_GBPT, 0) + 3, GBBB(WH - ENT_GBPT, 0) - 3, STR_NONE, STR_NONE), // WIDX_ENTRANCE_SPINNER_HEIGHT{,_INCREASE,_DECREASE}
{ WindowWidgetType::Button, 1, GBB(WH - ENT_GBPT, 0, 1), STR_TILE_INSPECTOR_ENTRANCE_MAKE_USABLE, STR_TILE_INSPECTOR_ENTRANCE_MAKE_USABLE_TIP }, // WIDX_ENTRANCE_BUTTON_MAKE_USABLE
{ WIDGETS_END },
};
2019-10-24 05:38:13 +02:00
constexpr int32_t WALL_GBPB = PADDING_BOTTOM; // Wall group box properties bottom
constexpr int32_t WALL_GBPT = WALL_GBPB + 16 + 3 * 21; // Wall group box properties top
2019-10-24 05:38:13 +02:00
constexpr int32_t WALL_GBDB = WALL_GBPT + GROUPBOX_PADDING; // Wall group box info bottom
constexpr int32_t WALL_GBDT = WALL_GBDB + 20 + 2 * 11; // Wall group box info top
2017-02-21 21:22:03 +01:00
static rct_widget WallWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
2018-06-10 21:31:08 +02:00
SPINNER_WIDGETS (1, GBBL(1), GBBR(1), GBBT(WH - WALL_GBPT, 0) + 3, GBBB(WH - WALL_GBPT, 0) - 3, STR_NONE, STR_NONE), // WIDX_WALL_SPINNER_HEIGHT{,_INCREASE,_DECREASE}
{ WindowWidgetType::DropdownMenu, 1, GBD(WH - WALL_GBPT, 1, 1), STR_NONE, STR_NONE }, // WIDX_WALL_DROPDOWN_SLOPE
{ WindowWidgetType::Button, 1, GBDB(WH - WALL_GBPT, 1, 1), STR_DROPDOWN_GLYPH, STR_NONE }, // WIDX_WALL_DROPDOWN_SLOPE_BUTTON
SPINNER_WIDGETS (1, GBBL(1), GBBR(1), GBBT(WH - WALL_GBPT, 2) + 3, GBBB(WH - WALL_GBPT, 2) - 3, STR_NONE, STR_NONE), // WIDX_WALL_SPINNER_ANIMATION_FRAME{,_INCREASE,_DECREASE}
{ WIDGETS_END },
};
2019-10-24 05:38:13 +02:00
constexpr int32_t LAR_GBPB = PADDING_BOTTOM; // Large scenery group box properties bottom
constexpr int32_t LAR_GBPT = LAR_GBPB + 16 + 1 * 21; // Large scenery group box properties top
constexpr int32_t LAR_GBDB = LAR_GBPT + GROUPBOX_PADDING; // Large scenery group box info bottom
constexpr int32_t LAR_GBDT = LAR_GBDB + 20 + 3 * 11; // Large scenery group box info top
static rct_widget LargeSceneryWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
2018-06-10 21:31:08 +02:00
SPINNER_WIDGETS (1, GBBL(1), GBBR(1), GBBT(WH - LAR_GBPT, 0) + 3, GBBB(WH - LAR_GBPT, 0) - 3, STR_NONE, STR_NONE), // WIDX_LARGE_SCENERY_SPINNER_HEIGHT{,_INCREASE,_DECREASE}
{ WIDGETS_END },
};
2019-10-24 05:38:13 +02:00
constexpr int32_t BAN_GBPB = PADDING_BOTTOM; // Banner group box properties bottom
constexpr int32_t BAN_GBPT = BAN_GBPB + 16 + 3 * 21; // Banner group box properties top
constexpr int32_t BAN_GBDB = BAN_GBPT + GROUPBOX_PADDING; // Banner group box info bottom
constexpr int32_t BAN_GBDT = BAN_GBDB + 20 + 1 * 11; // Banner group box info top
static rct_widget BannerWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
2018-06-10 21:31:08 +02:00
SPINNER_WIDGETS (1, GBBL(1), GBBR(1), GBBT(WH - BAN_GBPT, 0) + 3, GBBB(WH - BAN_GBPT, 0) - 3, STR_NONE, STR_NONE), // WIDX_BANNER_SPINNER_HEIGHT{,_INCREASE,_DECREASE}
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 3, GBBT(WH - BAN_GBPT, 1) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_BANNER_CHECK_BLOCK_NE
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 3, GBBT(WH - BAN_GBPT, 1) + 7 * 3), STR_NONE, STR_NONE }, // WIDX_BANNER_CHECK_BLOCK_SE
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - BAN_GBPT, 1) + 7 * 3), STR_NONE, STR_NONE }, // WIDX_BANNER_CHECK_BLOCK_SW
{ WindowWidgetType::Checkbox, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - BAN_GBPT, 1) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_BANNER_CHECK_BLOCK_NW
{ WIDGETS_END },
};
2019-10-24 05:38:13 +02:00
constexpr int32_t COR_GBPB = PADDING_BOTTOM; // Corrupt element group box properties bottom
constexpr int32_t COR_GBPT = COR_GBPB + 16 + 2 * 21; // Corrupt element group box properties top
constexpr int32_t COR_GBDB = COR_GBPT + GROUPBOX_PADDING; // Corrupt element group box info bottom
constexpr int32_t COR_GBDT = COR_GBDB + 20 + 0 * 11; // Corrupt element group box info top
static rct_widget CorruptWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
2018-06-10 21:31:08 +02:00
SPINNER_WIDGETS (1, GBBL(1), GBBR(1), GBBT(WH - COR_GBPT, 0) + 3, GBBB(WH - COR_GBPT, 0) - 3, STR_NONE, STR_NONE), // WIDX_CORRUPT_SPINNER_HEIGHT{,_INCREASE,_DECREASE}
{ WindowWidgetType::Button, 1, GBB(WH - SUR_GBPT, 0, 1), STR_TILE_INSPECTOR_CLAMP_TO_NEXT, STR_TILE_INSPECTOR_CLAMP_TO_NEXT_TIP }, // WIDX_CORRUPT_BUTTON_CLAMP
{ WIDGETS_END },
};
static rct_widget *PageWidgets[] = {
DefaultWidgets,
SurfaceWidgets,
PathWidgets,
TrackWidgets,
SceneryWidgets,
EntranceWidgets,
WallWidgets,
LargeSceneryWidgets,
BannerWidgets,
CorruptWidgets,
};
static struct {
// Offsets from the bottom of the window
int16_t details_top_offset, details_bottom_offset;
int16_t properties_top_offset, properties_bottom_offset;
// String to be displayed in the details groupbox
rct_string_id string_id;
} PageGroupBoxSettings[] = {
{ SUR_GBDT, SUR_GBDB, SUR_GBPT, SUR_GBPB, STR_TILE_INSPECTOR_GROUPBOX_SURFACE_INFO },
{ PAT_GBDT, PAT_GBDB, PAT_GBPT, PAT_GBPB, STR_TILE_INSPECTOR_GROUPBOX_PATH_INFO },
{ TRA_GBDT, TRA_GBDB, TRA_GBPT, TRA_GBPB, STR_TILE_INSPECTOR_GROUPBOX_TRACK_INFO },
{ SCE_GBDT, SCE_GBDB, SCE_GBPT, SCE_GBPB, STR_TILE_INSPECTOR_GROUPBOX_SCENERY_INFO },
{ ENT_GBDT, ENT_GBDB, ENT_GBPT, ENT_GBPB, STR_TILE_INSPECTOR_GROUPBOX_ENTRANCE_INFO },
{ WALL_GBDT, WALL_GBDB, WALL_GBPT, WALL_GBPB, STR_TILE_INSPECTOR_GROUPBOX_WALL_INFO },
{ LAR_GBDT, LAR_GBDB, LAR_GBPT, LAR_GBPB, STR_TILE_INSPECTOR_GROUPBOX_LARGE_SCENERY_INFO },
{ BAN_GBDT, BAN_GBDB, BAN_GBPT, BAN_GBPB, STR_TILE_INSPECTOR_GROUPBOX_BANNER_INFO },
{ COR_GBDT, COR_GBDB, COR_GBPT, COR_GBPB, STR_TILE_INSPECTOR_GROUPBOX_CORRUPT_INFO }
};
// clang-format on
static constexpr int32_t ViewportInteractionFlags = VIEWPORT_INTERACTION_MASK_TERRAIN & VIEWPORT_INTERACTION_MASK_SPRITE
& VIEWPORT_INTERACTION_MASK_RIDE & VIEWPORT_INTERACTION_MASK_SCENERY & VIEWPORT_INTERACTION_MASK_FOOTPATH
& VIEWPORT_INTERACTION_MASK_FOOTPATH_ITEM & VIEWPORT_INTERACTION_MASK_PARK & VIEWPORT_INTERACTION_MASK_WALL
& VIEWPORT_INTERACTION_MASK_LARGE_SCENERY & VIEWPORT_INTERACTION_MASK_BANNER;
static int16_t windowTileInspectorHighlightedIndex = -1;
static bool windowTileInspectorTileSelected = false;
static int32_t windowTileInspectorToolMouseX = 0;
static int32_t windowTileInspectorToolMouseY = 0;
static bool windowTileInspectorToolCtrlDown = false;
2019-06-18 21:47:30 +02:00
static CoordsXY windowTileInspectorToolMap = {};
static bool windowTileInspectorApplyToAll = false;
static bool windowTileInspectorElementCopied = false;
2018-11-01 13:53:50 +01:00
static TileElement tileInspectorCopiedElement;
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_mouseup(rct_window* w, rct_widgetindex widgetIndex);
static void window_tile_inspector_resize(rct_window* w);
static void window_tile_inspector_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget);
static void window_tile_inspector_update(rct_window* w);
static void window_tile_inspector_dropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex);
static void window_tile_inspector_tool_update(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
static void window_tile_inspector_update_selected_tile(rct_window* w, const ScreenCoordsXY& screenCoords);
static void window_tile_inspector_tool_down(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
static void window_tile_inspector_tool_drag(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords);
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_scrollgetsize(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height);
static void window_tile_inspector_scrollmousedown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords);
static void window_tile_inspector_scrollmouseover(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords);
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_invalidate(rct_window* w);
static void window_tile_inspector_paint(rct_window* w, rct_drawpixelinfo* dpi);
static void window_tile_inspector_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex);
static void window_tile_inspector_set_page(rct_window* w, const TILE_INSPECTOR_PAGE page);
// clang-format off
static rct_window_event_list TileInspectorWindowEvents([](auto& events)
{
events.mouse_up = &window_tile_inspector_mouseup;
events.resize = &window_tile_inspector_resize;
events.mouse_down = &window_tile_inspector_mousedown;
events.dropdown = &window_tile_inspector_dropdown;
events.update = &window_tile_inspector_update;
events.tool_update = &window_tile_inspector_tool_update;
events.tool_down = &window_tile_inspector_tool_down;
events.tool_drag = &window_tile_inspector_tool_drag;
events.get_scroll_size = &window_tile_inspector_scrollgetsize;
events.scroll_mousedown = &window_tile_inspector_scrollmousedown;
events.scroll_mouseover = &window_tile_inspector_scrollmouseover;
events.invalidate = &window_tile_inspector_invalidate;
events.paint = &window_tile_inspector_paint;
events.scroll_paint = &window_tile_inspector_scrollpaint;
});
static uint64_t PageEnabledWidgets[] = {
(1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT),
(1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_ROTATE) | (1ULL << WIDX_BUTTON_COPY) | (1ULL << WIDX_SURFACE_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_SURFACE_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_SURFACE_BUTTON_REMOVE_FENCES) | (1ULL << WIDX_SURFACE_BUTTON_RESTORE_FENCES) | (1ULL << WIDX_SURFACE_CHECK_CORNER_N) | (1ULL << WIDX_SURFACE_CHECK_CORNER_E) | (1ULL << WIDX_SURFACE_CHECK_CORNER_S) | (1ULL << WIDX_SURFACE_CHECK_CORNER_W) | (1ULL << WIDX_SURFACE_CHECK_DIAGONAL),
(1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_ROTATE) | (1ULL << WIDX_BUTTON_COPY) | (1ULL << WIDX_PATH_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_PATH_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_PATH_CHECK_SLOPED) | (1ULL << WIDX_PATH_CHECK_BROKEN) | (1ULL << WIDX_PATH_CHECK_EDGE_N) | (1ULL << WIDX_PATH_CHECK_EDGE_NE) | (1ULL << WIDX_PATH_CHECK_EDGE_E) | (1ULL << WIDX_PATH_CHECK_EDGE_SE) | (1ULL << WIDX_PATH_CHECK_EDGE_S) | (1ULL << WIDX_PATH_CHECK_EDGE_SW) | (1ULL << WIDX_PATH_CHECK_EDGE_W) | (1ULL << WIDX_PATH_CHECK_EDGE_NW),
(1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_ROTATE) | (1ULL << WIDX_BUTTON_COPY) | (1ULL << WIDX_TRACK_CHECK_APPLY_TO_ALL) | (1ULL << WIDX_TRACK_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_TRACK_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_TRACK_CHECK_CHAIN_LIFT) | (1ULL << WIDX_TRACK_CHECK_BLOCK_BRAKE_CLOSED) | (1ULL << WIDX_TRACK_CHECK_IS_INDESTRUCTIBLE),
(1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_ROTATE) | (1ULL << WIDX_BUTTON_COPY) | (1ULL << WIDX_SCENERY_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_SCENERY_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_SCENERY_CHECK_QUARTER_N) | (1ULL << WIDX_SCENERY_CHECK_QUARTER_E) | (1ULL << WIDX_SCENERY_CHECK_QUARTER_S) | (1ULL << WIDX_SCENERY_CHECK_QUARTER_W) | (1ULL << WIDX_SCENERY_CHECK_COLLISION_N) | (1ULL << WIDX_SCENERY_CHECK_COLLISION_E) | (1ULL << WIDX_SCENERY_CHECK_COLLISION_S) | (1ULL << WIDX_SCENERY_CHECK_COLLISION_W),
(1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_ROTATE) | (1ULL << WIDX_BUTTON_COPY) | (1ULL << WIDX_ENTRANCE_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_ENTRANCE_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_ENTRANCE_BUTTON_MAKE_USABLE),
(1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_ROTATE) | (1ULL << WIDX_BUTTON_COPY) | (1ULL << WIDX_WALL_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_WALL_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_WALL_DROPDOWN_SLOPE) | (1ULL << WIDX_WALL_DROPDOWN_SLOPE_BUTTON) | (1ULL << WIDX_WALL_SPINNER_ANIMATION_FRAME_INCREASE) | (1ULL << WIDX_WALL_SPINNER_ANIMATION_FRAME_DECREASE),
(1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_COPY) | (1ULL << WIDX_LARGE_SCENERY_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_LARGE_SCENERY_SPINNER_HEIGHT_DECREASE),
(1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_ROTATE) | (1ULL << WIDX_BUTTON_COPY) | (1ULL << WIDX_BANNER_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_BANNER_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_BANNER_CHECK_BLOCK_NE) | (1ULL << WIDX_BANNER_CHECK_BLOCK_SE) | (1ULL << WIDX_BANNER_CHECK_BLOCK_SW) | (1ULL << WIDX_BANNER_CHECK_BLOCK_NW),
(1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_COPY) | (1ULL << WIDX_CORRUPT_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_CORRUPT_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_CORRUPT_BUTTON_CLAMP),
};
static uint64_t PageHoldDownWidgets[] = {
(1ULL << WIDX_SPINNER_X_INCREASE) | (1ULL << WIDX_SPINNER_X_DECREASE) | (1ULL << WIDX_SPINNER_Y_INCREASE) | (1ULL << WIDX_SPINNER_Y_DECREASE),
(1ULL << WIDX_SPINNER_X_INCREASE) | (1ULL << WIDX_SPINNER_X_DECREASE) | (1ULL << WIDX_SPINNER_Y_INCREASE) | (1ULL << WIDX_SPINNER_Y_DECREASE) | (1ULL << WIDX_SURFACE_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_SURFACE_SPINNER_HEIGHT_DECREASE),
(1ULL << WIDX_SPINNER_X_INCREASE) | (1ULL << WIDX_SPINNER_X_DECREASE) | (1ULL << WIDX_SPINNER_Y_INCREASE) | (1ULL << WIDX_SPINNER_Y_DECREASE) | (1ULL << WIDX_PATH_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_PATH_SPINNER_HEIGHT_DECREASE),
(1ULL << WIDX_SPINNER_X_INCREASE) | (1ULL << WIDX_SPINNER_X_DECREASE) | (1ULL << WIDX_SPINNER_Y_INCREASE) | (1ULL << WIDX_SPINNER_Y_DECREASE) | (1ULL << WIDX_TRACK_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_TRACK_SPINNER_HEIGHT_DECREASE),
(1ULL << WIDX_SPINNER_X_INCREASE) | (1ULL << WIDX_SPINNER_X_DECREASE) | (1ULL << WIDX_SPINNER_Y_INCREASE) | (1ULL << WIDX_SPINNER_Y_DECREASE) | (1ULL << WIDX_SCENERY_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_SCENERY_SPINNER_HEIGHT_DECREASE),
(1ULL << WIDX_SPINNER_X_INCREASE) | (1ULL << WIDX_SPINNER_X_DECREASE) | (1ULL << WIDX_SPINNER_Y_INCREASE) | (1ULL << WIDX_SPINNER_Y_DECREASE) | (1ULL << WIDX_ENTRANCE_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_ENTRANCE_SPINNER_HEIGHT_DECREASE),
(1ULL << WIDX_SPINNER_X_INCREASE) | (1ULL << WIDX_SPINNER_X_DECREASE) | (1ULL << WIDX_SPINNER_Y_INCREASE) | (1ULL << WIDX_SPINNER_Y_DECREASE) | (1ULL << WIDX_WALL_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_WALL_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_WALL_SPINNER_ANIMATION_FRAME_INCREASE) | (1ULL << WIDX_WALL_SPINNER_ANIMATION_FRAME_DECREASE),
(1ULL << WIDX_SPINNER_X_INCREASE) | (1ULL << WIDX_SPINNER_X_DECREASE) | (1ULL << WIDX_SPINNER_Y_INCREASE) | (1ULL << WIDX_SPINNER_Y_DECREASE) | (1ULL << WIDX_LARGE_SCENERY_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_LARGE_SCENERY_SPINNER_HEIGHT_DECREASE),
(1ULL << WIDX_SPINNER_X_INCREASE) | (1ULL << WIDX_SPINNER_X_DECREASE) | (1ULL << WIDX_SPINNER_Y_INCREASE) | (1ULL << WIDX_SPINNER_Y_DECREASE) | (1ULL << WIDX_BANNER_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_BANNER_SPINNER_HEIGHT_DECREASE),
(1ULL << WIDX_SPINNER_X_INCREASE) | (1ULL << WIDX_SPINNER_X_DECREASE) | (1ULL << WIDX_SPINNER_Y_INCREASE) | (1ULL << WIDX_SPINNER_Y_DECREASE) | (1ULL << WIDX_CORRUPT_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_CORRUPT_SPINNER_HEIGHT_DECREASE),
};
static uint64_t PageDisabledWidgets[] = {
(1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_MOVE_UP) | (1ULL << WIDX_BUTTON_MOVE_DOWN) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_ROTATE) | (1ULL << WIDX_BUTTON_COPY),
0,
0,
0,
0,
0,
0,
(1ULL << WIDX_BUTTON_ROTATE),
0,
(1ULL << WIDX_BUTTON_ROTATE),
};
// clang-format on
2018-06-22 23:21:44 +02:00
rct_window* window_tile_inspector_open()
{
rct_window* window;
// Check if window is already open
window = window_bring_to_front_by_class(WC_TILE_INSPECTOR);
2017-08-15 10:07:44 +02:00
if (window != nullptr)
2017-11-23 00:42:12 +01:00
return window;
window = WindowCreate(ScreenCoordsXY(0, 29), WW, WH, &TileInspectorWindowEvents, WC_TILE_INSPECTOR, WF_RESIZABLE);
window_tile_inspector_set_page(window, TILE_INSPECTOR_PAGE_DEFAULT);
window->min_width = MIN_WW;
window->min_height = MIN_WH;
window->max_width = MAX_WW;
window->max_height = MAX_WH;
windowTileInspectorSelectedIndex = -1;
WindowInitScrollWidgets(window);
windowTileInspectorTileSelected = false;
tool_set(window, WIDX_BACKGROUND, TOOL_CROSSHAIR);
2017-11-23 00:42:12 +01:00
return window;
}
void window_tile_inspector_clear_clipboard()
{
windowTileInspectorElementCopied = false;
}
2018-11-01 13:53:50 +01:00
static TileElement* window_tile_inspector_get_selected_element(rct_window* w)
{
2018-06-22 23:21:44 +02:00
openrct2_assert(
windowTileInspectorSelectedIndex >= 0 && windowTileInspectorSelectedIndex < windowTileInspectorElementCount,
"Selected list item out of range");
return map_get_first_element_at(windowTileInspectorToolMap) + windowTileInspectorSelectedIndex;
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_select_element_from_list(rct_window* w, int32_t index)
{
if (index < 0 || index >= windowTileInspectorElementCount)
{
windowTileInspectorSelectedIndex = -1;
}
else
{
windowTileInspectorSelectedIndex = index;
}
w->Invalidate();
}
2018-11-01 13:53:50 +01:00
static void window_tile_inspector_load_tile(rct_window* w, TileElement* elementToSelect)
{
windowTileInspectorSelectedIndex = -1;
w->scrolls[0].v_top = 0;
TileElement* element = map_get_first_element_at(windowTileInspectorToolMap);
int16_t numItems = 0;
do
{
if (element == nullptr)
break;
if (element == elementToSelect)
{
windowTileInspectorSelectedIndex = numItems;
}
numItems++;
} while (!(element++)->IsLastForTile());
windowTileInspectorElementCount = numItems;
w->Invalidate();
}
static void window_tile_inspector_insert_corrupt_element(int32_t elementIndex)
{
2018-06-22 23:21:44 +02:00
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::AnyInsertCorrupt, elementIndex);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_remove_element(int32_t elementIndex)
{
2018-06-22 23:21:44 +02:00
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::AnyRemove, elementIndex);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_rotate_element(int32_t elementIndex)
{
2018-06-22 23:21:44 +02:00
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::AnyRotate, elementIndex);
GameActions::Execute(&modifyTile);
}
// Swap element with its parent
static void window_tile_inspector_swap_elements(int16_t first, int16_t second)
{
2018-06-22 23:21:44 +02:00
openrct2_assert(first >= 0 && first < windowTileInspectorElementCount, "first out of range");
openrct2_assert(second >= 0 && second < windowTileInspectorElementCount, "second out of range");
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::AnySwap, first, second);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_sort_elements()
{
openrct2_assert(windowTileInspectorTileSelected, "No tile selected");
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::AnySort);
GameActions::Execute(&modifyTile);
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_copy_element(rct_window* w)
{
// Copy value, in case the element gets moved
tileInspectorCopiedElement = *window_tile_inspector_get_selected_element(w);
windowTileInspectorElementCopied = true;
w->Invalidate();
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_paste_element(rct_window* w)
{
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::AnyPaste, 0, 0, tileInspectorCopiedElement);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_base_height_offset(int16_t elementIndex, int8_t heightOffset)
2017-01-25 14:22:33 +01:00
{
auto modifyTile = TileModifyAction(
2019-06-18 21:47:30 +02:00
windowTileInspectorToolMap, TileModifyType::AnyBaseHeightOffset, elementIndex, heightOffset);
GameActions::Execute(&modifyTile);
2017-01-25 14:22:33 +01:00
}
static void window_tile_inspector_surface_show_park_fences(bool showFences)
2017-01-27 13:30:09 +01:00
{
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::SurfaceShowParkFences, showFences);
GameActions::Execute(&modifyTile);
2017-01-27 13:30:09 +01:00
}
static void window_tile_inspector_surface_toggle_corner(int32_t cornerIndex)
{
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::SurfaceToggleCorner, cornerIndex);
GameActions::Execute(&modifyTile);
}
2017-01-27 14:19:23 +01:00
static void window_tile_inspector_surface_toggle_diagonal()
{
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::SurfaceToggleDiagonal);
GameActions::Execute(&modifyTile);
2017-01-27 14:19:23 +01:00
}
static void window_tile_inspector_path_set_sloped(int32_t elementIndex, bool sloped)
2017-02-06 14:51:45 +01:00
{
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::PathSetSlope, elementIndex, sloped);
GameActions::Execute(&modifyTile);
2017-02-06 14:51:45 +01:00
}
static void window_tile_inspector_path_set_broken(int32_t elementIndex, bool broken)
{
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::PathSetBroken, elementIndex, broken);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_path_toggle_edge(int32_t elementIndex, int32_t cornerIndex)
2017-01-27 19:12:25 +01:00
{
2018-06-22 23:21:44 +02:00
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range");
openrct2_assert(cornerIndex >= 0 && cornerIndex < 8, "cornerIndex out of range");
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::PathToggleEdge, elementIndex, cornerIndex);
GameActions::Execute(&modifyTile);
2017-01-27 19:12:25 +01:00
}
static void window_tile_inspector_entrance_make_usable(int32_t elementIndex)
{
Guard::ArgumentInRange(elementIndex, 0, windowTileInspectorElementCount - 1);
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::EntranceMakeUsable, elementIndex);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_wall_set_slope(int32_t elementIndex, int32_t slopeValue)
2017-02-02 20:06:27 +01:00
{
// Make sure only the correct bits are set
openrct2_assert((slopeValue & 3) == slopeValue, "slopeValue doesn't match its mask");
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::WallSetSlope, elementIndex, slopeValue);
GameActions::Execute(&modifyTile);
2017-02-02 20:06:27 +01:00
}
static void window_tile_inspector_wall_animation_frame_offset(int16_t elementIndex, int8_t animationFrameOffset)
{
auto modifyTile = TileModifyAction(
windowTileInspectorToolMap, TileModifyType::WallSetAnimationFrame, elementIndex, animationFrameOffset);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_track_block_height_offset(int32_t elementIndex, int8_t heightOffset)
{
auto modifyTile = TileModifyAction(
2019-06-18 21:47:30 +02:00
windowTileInspectorToolMap, TileModifyType::TrackBaseHeightOffset, elementIndex, heightOffset);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_track_block_set_lift(int32_t elementIndex, bool entireTrackBlock, bool chain)
{
auto modifyTile = TileModifyAction(
2019-06-18 21:47:30 +02:00
windowTileInspectorToolMap, entireTrackBlock ? TileModifyType::TrackSetChainBlock : TileModifyType::TrackSetChain,
elementIndex, chain);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_track_set_block_brake(int32_t elementIndex, bool blockBrake)
{
auto modifyTile = TileModifyAction(
2019-06-18 21:47:30 +02:00
windowTileInspectorToolMap, TileModifyType::TrackSetBlockBrake, elementIndex, blockBrake);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_track_set_indestructible(int32_t elementIndex, bool isIndestructible)
{
auto modifyTile = TileModifyAction(
2019-06-18 21:47:30 +02:00
windowTileInspectorToolMap, TileModifyType::TrackSetIndestructible, elementIndex, isIndestructible);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_quarter_tile_set(int32_t elementIndex, const int32_t quarterIndex)
{
// quarterIndex is widget index relative to WIDX_SCENERY_CHECK_QUARTER_N, so a value from 0-3
openrct2_assert(quarterIndex >= 0 && quarterIndex < 4, "quarterIndex out of range");
auto modifyTile = TileModifyAction(
2019-06-18 21:47:30 +02:00
windowTileInspectorToolMap, TileModifyType::ScenerySetQuarterLocation, elementIndex,
(quarterIndex - get_current_rotation()) & 3);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_toggle_quadrant_collosion(int32_t elementIndex, const int32_t quadrantIndex)
{
auto modifyTile = TileModifyAction(
2019-06-18 21:47:30 +02:00
windowTileInspectorToolMap, TileModifyType::ScenerySetQuarterCollision, elementIndex,
(quadrantIndex + 2 - get_current_rotation()) & 3);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_banner_toggle_block(int32_t elementIndex, int32_t edgeIndex)
{
openrct2_assert(edgeIndex >= 0 && edgeIndex < 4, "edgeIndex out of range");
// Make edgeIndex abstract
edgeIndex = (edgeIndex - get_current_rotation()) & 3;
auto modifyTile = TileModifyAction(
2019-06-18 21:47:30 +02:00
windowTileInspectorToolMap, TileModifyType::BannerToggleBlockingEdge, elementIndex, edgeIndex);
GameActions::Execute(&modifyTile);
}
static void window_tile_inspector_clamp_corrupt(int32_t elementIndex)
2017-02-07 15:39:07 +01:00
{
2019-06-18 21:47:30 +02:00
auto modifyTile = TileModifyAction(windowTileInspectorToolMap, TileModifyType::CorruptClamp, elementIndex);
GameActions::Execute(&modifyTile);
2017-02-07 15:39:07 +01:00
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_mouseup(rct_window* w, rct_widgetindex widgetIndex)
{
2018-06-22 23:21:44 +02:00
switch (widgetIndex)
{
case WIDX_CLOSE:
tool_cancel();
window_close(w);
return;
2018-06-22 23:21:44 +02:00
case WIDX_BUTTON_CORRUPT:
window_tile_inspector_insert_corrupt_element(windowTileInspectorSelectedIndex);
break;
case WIDX_BUTTON_REMOVE:
{
int32_t nextItemToSelect = windowTileInspectorSelectedIndex - 1;
window_tile_inspector_remove_element(windowTileInspectorSelectedIndex);
window_tile_inspector_select_element_from_list(w, nextItemToSelect);
break;
}
case WIDX_BUTTON_ROTATE:
window_tile_inspector_rotate_element(windowTileInspectorSelectedIndex);
break;
case WIDX_BUTTON_SORT:
window_tile_inspector_sort_elements();
break;
case WIDX_BUTTON_COPY:
window_tile_inspector_copy_element(w);
break;
case WIDX_BUTTON_PASTE:
window_tile_inspector_paste_element(w);
break;
case WIDX_BUTTON_MOVE_UP:
2018-06-22 23:21:44 +02:00
window_tile_inspector_swap_elements(windowTileInspectorSelectedIndex, windowTileInspectorSelectedIndex + 1);
break;
case WIDX_BUTTON_MOVE_DOWN:
2018-06-22 23:21:44 +02:00
window_tile_inspector_swap_elements(windowTileInspectorSelectedIndex - 1, windowTileInspectorSelectedIndex);
break;
}
// Only element-specific widgets from now on
2018-06-22 23:21:44 +02:00
if (w->page == TILE_INSPECTOR_PAGE_DEFAULT || windowTileInspectorSelectedIndex == -1)
{
return;
}
// Get the selected map element
2018-11-01 13:53:50 +01:00
TileElement* const tileElement = window_tile_inspector_get_selected_element(w);
// Page widgets
2018-06-22 23:21:44 +02:00
switch (w->page)
{
case TILE_INSPECTOR_PAGE_SURFACE:
switch (widgetIndex)
{
case WIDX_SURFACE_BUTTON_REMOVE_FENCES:
window_tile_inspector_surface_show_park_fences(false);
break;
case WIDX_SURFACE_BUTTON_RESTORE_FENCES:
window_tile_inspector_surface_show_park_fences(true);
break;
case WIDX_SURFACE_CHECK_CORNER_N:
case WIDX_SURFACE_CHECK_CORNER_E:
case WIDX_SURFACE_CHECK_CORNER_S:
case WIDX_SURFACE_CHECK_CORNER_W:
window_tile_inspector_surface_toggle_corner(
((widgetIndex - WIDX_SURFACE_CHECK_CORNER_N) + 2 - get_current_rotation()) & 3);
break;
case WIDX_SURFACE_CHECK_DIAGONAL:
window_tile_inspector_surface_toggle_diagonal();
break;
} // switch widgetindex
break;
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_PATH:
switch (widgetIndex)
{
case WIDX_PATH_CHECK_SLOPED:
2018-10-03 21:45:52 +02:00
window_tile_inspector_path_set_sloped(windowTileInspectorSelectedIndex, !tileElement->AsPath()->IsSloped());
2018-06-22 23:21:44 +02:00
break;
case WIDX_PATH_CHECK_BROKEN:
window_tile_inspector_path_set_broken(windowTileInspectorSelectedIndex, !tileElement->AsPath()->IsBroken());
break;
2018-06-22 23:21:44 +02:00
case WIDX_PATH_CHECK_EDGE_E:
case WIDX_PATH_CHECK_EDGE_S:
case WIDX_PATH_CHECK_EDGE_W:
case WIDX_PATH_CHECK_EDGE_N:
{
// 0 = east/right, 1 = south/bottom, 2 = west/left, 3 = north/top
const int32_t eswn = (widgetIndex - WIDX_PATH_CHECK_EDGE_E) / 2;
// Transform to world orientation
const int32_t index = (eswn - get_current_rotation()) & 3;
window_tile_inspector_path_toggle_edge(
windowTileInspectorSelectedIndex,
index + 4); // The corners are stored in the 4 most significant bits, hence the + 4
break;
}
case WIDX_PATH_CHECK_EDGE_NE:
case WIDX_PATH_CHECK_EDGE_SE:
case WIDX_PATH_CHECK_EDGE_SW:
case WIDX_PATH_CHECK_EDGE_NW:
{
// 0 = NE, 1 = SE, 2 = SW, 3 = NW
const int32_t neseswnw = (widgetIndex - WIDX_PATH_CHECK_EDGE_NE) / 2;
// Transform to world orientation
const int32_t index = (neseswnw - get_current_rotation()) & 3;
window_tile_inspector_path_toggle_edge(windowTileInspectorSelectedIndex, index);
break;
}
} // switch widget index
break;
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_TRACK:
switch (widgetIndex)
{
case WIDX_TRACK_CHECK_APPLY_TO_ALL:
windowTileInspectorApplyToAll ^= 1;
widget_invalidate(w, widgetIndex);
break;
case WIDX_TRACK_CHECK_CHAIN_LIFT:
{
2020-11-03 22:29:22 +01:00
bool entireTrackBlock = WidgetIsPressed(w, WIDX_TRACK_CHECK_APPLY_TO_ALL);
2018-09-18 13:01:09 +02:00
bool newLift = !tileElement->AsTrack()->HasChain();
2018-06-22 23:21:44 +02:00
window_tile_inspector_track_block_set_lift(windowTileInspectorSelectedIndex, entireTrackBlock, newLift);
break;
}
case WIDX_TRACK_CHECK_BLOCK_BRAKE_CLOSED:
window_tile_inspector_track_set_block_brake(
windowTileInspectorSelectedIndex, !tileElement->AsTrack()->BlockBrakeClosed());
break;
case WIDX_TRACK_CHECK_IS_INDESTRUCTIBLE:
window_tile_inspector_track_set_indestructible(
windowTileInspectorSelectedIndex, !tileElement->AsTrack()->IsIndestructible());
break;
2018-06-22 23:21:44 +02:00
} // switch widget index
break;
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_SCENERY:
switch (widgetIndex)
{
case WIDX_SCENERY_CHECK_QUARTER_N:
case WIDX_SCENERY_CHECK_QUARTER_E:
case WIDX_SCENERY_CHECK_QUARTER_S:
case WIDX_SCENERY_CHECK_QUARTER_W:
window_tile_inspector_quarter_tile_set(
windowTileInspectorSelectedIndex, widgetIndex - WIDX_SCENERY_CHECK_QUARTER_N);
break;
case WIDX_SCENERY_CHECK_COLLISION_N:
case WIDX_SCENERY_CHECK_COLLISION_E:
case WIDX_SCENERY_CHECK_COLLISION_S:
case WIDX_SCENERY_CHECK_COLLISION_W:
window_tile_inspector_toggle_quadrant_collosion(
windowTileInspectorSelectedIndex, widgetIndex - WIDX_SCENERY_CHECK_COLLISION_N);
break;
} // switch widget index
break;
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_ENTRANCE:
switch (widgetIndex)
{
case WIDX_ENTRANCE_BUTTON_MAKE_USABLE:
window_tile_inspector_entrance_make_usable(windowTileInspectorSelectedIndex);
break;
} // switch widget index
break;
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_BANNER:
switch (widgetIndex)
{
case WIDX_BANNER_CHECK_BLOCK_NE:
case WIDX_BANNER_CHECK_BLOCK_SE:
case WIDX_BANNER_CHECK_BLOCK_SW:
case WIDX_BANNER_CHECK_BLOCK_NW:
window_tile_inspector_banner_toggle_block(
windowTileInspectorSelectedIndex, widgetIndex - WIDX_BANNER_CHECK_BLOCK_NE);
break;
} // switch widget index
break;
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_CORRUPT:
switch (widgetIndex)
{
case WIDX_CORRUPT_BUTTON_CLAMP:
window_tile_inspector_clamp_corrupt(windowTileInspectorSelectedIndex);
break;
} // switch widget index
break;
} // switch page
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_resize(rct_window* w)
{
w->min_width = WW;
w->min_height = MIN_WH;
2018-06-22 23:21:44 +02:00
if (w->width < w->min_width)
{
w->Invalidate();
w->width = w->min_width;
}
2018-06-22 23:21:44 +02:00
if (w->height < w->min_height)
{
w->Invalidate();
w->height = w->min_height;
}
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget)
{
switch (widgetIndex)
{
case WIDX_SPINNER_X_INCREASE:
windowTileInspectorTile.x = std::min<int32_t>(windowTileInspectorTile.x + 1, MAXIMUM_MAP_SIZE_TECHNICAL - 1);
windowTileInspectorToolMap.x = std::min<int32_t>(windowTileInspectorToolMap.x + 32, MAXIMUM_TILE_START_XY);
window_tile_inspector_load_tile(w, nullptr);
break;
case WIDX_SPINNER_X_DECREASE:
windowTileInspectorTile.x = std::max<int32_t>(windowTileInspectorTile.x - 1, 0);
2019-06-18 21:47:30 +02:00
windowTileInspectorToolMap.x = std::max<int32_t>(windowTileInspectorToolMap.x - 32, 0);
window_tile_inspector_load_tile(w, nullptr);
break;
case WIDX_SPINNER_Y_INCREASE:
windowTileInspectorTile.y = std::min<int32_t>(windowTileInspectorTile.y + 1, MAXIMUM_MAP_SIZE_TECHNICAL - 1);
windowTileInspectorToolMap.y = std::min<int32_t>(windowTileInspectorToolMap.y + 32, MAXIMUM_TILE_START_XY);
window_tile_inspector_load_tile(w, nullptr);
break;
case WIDX_SPINNER_Y_DECREASE:
windowTileInspectorTile.y = std::max<int32_t>(windowTileInspectorTile.y - 1, 0);
2019-06-18 21:47:30 +02:00
windowTileInspectorToolMap.y = std::max<int32_t>(windowTileInspectorToolMap.y - 32, 0);
window_tile_inspector_load_tile(w, nullptr);
break;
} // switch widget index
// Only element-specific widgets from now on
if (w->page == TILE_INSPECTOR_PAGE_DEFAULT || windowTileInspectorSelectedIndex == -1)
{
return;
}
switch (w->page)
{
case TILE_INSPECTOR_PAGE_SURFACE:
switch (widgetIndex)
{
case WIDX_SURFACE_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, 1);
break;
case WIDX_SURFACE_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, -1);
break;
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_PATH:
switch (widgetIndex)
{
case WIDX_PATH_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, 1);
break;
case WIDX_PATH_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, -1);
break;
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_TRACK:
switch (widgetIndex)
{
case WIDX_TRACK_SPINNER_HEIGHT_INCREASE:
2020-11-03 22:29:22 +01:00
if (WidgetIsPressed(w, WIDX_TRACK_CHECK_APPLY_TO_ALL))
{
window_tile_inspector_track_block_height_offset(windowTileInspectorSelectedIndex, 1);
}
else
{
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, 1);
}
break;
case WIDX_TRACK_SPINNER_HEIGHT_DECREASE:
2020-11-03 22:29:22 +01:00
if (WidgetIsPressed(w, WIDX_TRACK_CHECK_APPLY_TO_ALL))
{
window_tile_inspector_track_block_height_offset(windowTileInspectorSelectedIndex, -1);
}
else
{
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, -1);
}
break;
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_SCENERY:
switch (widgetIndex)
{
case WIDX_SCENERY_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, 1);
break;
case WIDX_SCENERY_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, -1);
break;
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_ENTRANCE:
switch (widgetIndex)
{
case WIDX_ENTRANCE_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, 1);
break;
case WIDX_ENTRANCE_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, -1);
break;
2018-06-22 23:21:44 +02:00
case WIDX_ENTRANCE_BUTTON_MAKE_USABLE:
window_tile_inspector_entrance_make_usable(windowTileInspectorSelectedIndex);
break;
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_WALL:
switch (widgetIndex)
{
case WIDX_WALL_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, 1);
break;
case WIDX_WALL_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, -1);
break;
case WIDX_WALL_DROPDOWN_SLOPE_BUTTON:
{
// Use dropdown instead of dropdown button
widget--;
// Fill dropdown list
gDropdownItemsFormat[0] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsFormat[1] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsFormat[2] = STR_DROPDOWN_MENU_LABEL;
gDropdownItemsArgs[0] = STR_TILE_INSPECTOR_WALL_FLAT;
gDropdownItemsArgs[1] = STR_TILE_INSPECTOR_WALL_SLOPED_LEFT;
gDropdownItemsArgs[2] = STR_TILE_INSPECTOR_WALL_SLOPED_RIGHT;
WindowDropdownShowTextCustomWidth(
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, w->colours[1], 0,
Dropdown::Flag::StayOpen, 3, widget->width() - 3);
// Set current value as checked
2018-11-01 13:53:50 +01:00
TileElement* const tileElement = window_tile_inspector_get_selected_element(w);
Dropdown::SetChecked(tileElement->AsWall()->GetSlope(), true);
break;
}
case WIDX_WALL_SPINNER_ANIMATION_FRAME_INCREASE:
window_tile_inspector_wall_animation_frame_offset(windowTileInspectorSelectedIndex, 1);
break;
case WIDX_WALL_SPINNER_ANIMATION_FRAME_DECREASE:
window_tile_inspector_wall_animation_frame_offset(windowTileInspectorSelectedIndex, -1);
break;
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_LARGE_SCENERY:
switch (widgetIndex)
{
case WIDX_LARGE_SCENERY_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, 1);
break;
case WIDX_LARGE_SCENERY_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, -1);
break;
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_BANNER:
switch (widgetIndex)
{
case WIDX_BANNER_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, 1);
break;
case WIDX_BANNER_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, -1);
break;
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_CORRUPT:
switch (widgetIndex)
{
case WIDX_CORRUPT_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, 1);
break;
case WIDX_CORRUPT_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(windowTileInspectorSelectedIndex, -1);
break;
} // switch widget index
2018-06-22 23:21:44 +02:00
} // switch page
2016-10-01 22:57:09 +02:00
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_update(rct_window* w)
{
// Check if the mouse is hovering over the list
2020-11-03 22:29:22 +01:00
if (!WidgetIsHighlighted(w, WIDX_LIST))
2018-06-22 23:21:44 +02:00
{
windowTileInspectorHighlightedIndex = -1;
widget_invalidate(w, WIDX_LIST);
}
if (gCurrentToolWidget.window_classification != WC_TILE_INSPECTOR)
window_close(w);
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_dropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex)
{
2018-06-22 23:21:44 +02:00
if (dropdownIndex == -1)
{
return;
}
// Get selected element
2018-11-01 13:53:50 +01:00
TileElement* const tileElement = window_tile_inspector_get_selected_element(w);
2018-06-22 23:21:44 +02:00
switch (w->page)
{
case TILE_INSPECTOR_PAGE_WALL:
openrct2_assert(tileElement->GetType() == TILE_ELEMENT_TYPE_WALL, "Element is not a wall");
2018-06-22 23:21:44 +02:00
switch (widgetIndex)
{
case WIDX_WALL_DROPDOWN_SLOPE_BUTTON:
window_tile_inspector_wall_set_slope(windowTileInspectorSelectedIndex, dropdownIndex);
2018-06-22 23:21:44 +02:00
break;
}
break;
}
2016-10-01 22:57:09 +02:00
}
static void window_tile_inspector_tool_update(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
{
map_invalidate_selection_rect();
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
CoordsXY mapCoords;
2018-11-01 13:53:50 +01:00
TileElement* clickedElement = nullptr;
bool mouseOnViewport = false;
if (InputTestPlaceObjectModifier(PLACE_OBJECT_MODIFIER_COPY_Z))
{
auto info = get_map_coordinates_from_pos(screenCoords, ViewportInteractionFlags);
clickedElement = info.Element;
mapCoords = info.Loc;
}
// Even if Ctrl was pressed, fall back to normal selection when there was nothing under the cursor
if (clickedElement == nullptr)
{
auto mouseCoords = screen_pos_to_map_pos(screenCoords, nullptr);
if (mouseCoords)
{
mouseOnViewport = true;
mapCoords = *mouseCoords;
}
}
if (mouseOnViewport)
{
2019-12-12 12:04:40 +01:00
gMapSelectPositionA = gMapSelectPositionB = mapCoords;
}
else if (windowTileInspectorTileSelected)
{
2019-12-12 12:04:40 +01:00
gMapSelectPositionA = gMapSelectPositionB = windowTileInspectorToolMap;
}
else
{
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
}
gMapSelectType = MAP_SELECT_TYPE_FULL;
map_invalidate_selection_rect();
}
static void window_tile_inspector_update_selected_tile(rct_window* w, const ScreenCoordsXY& screenCoords)
{
const bool ctrlIsHeldDown = InputTestPlaceObjectModifier(PLACE_OBJECT_MODIFIER_COPY_Z);
// Mouse hasn't moved
if (screenCoords.x == windowTileInspectorToolMouseX && screenCoords.y == windowTileInspectorToolMouseY
&& windowTileInspectorToolCtrlDown == ctrlIsHeldDown)
{
return;
}
windowTileInspectorToolMouseX = screenCoords.x;
windowTileInspectorToolMouseY = screenCoords.y;
windowTileInspectorToolCtrlDown = ctrlIsHeldDown;
CoordsXY mapCoords{};
2018-11-01 13:53:50 +01:00
TileElement* clickedElement = nullptr;
if (ctrlIsHeldDown)
{
auto info = get_map_coordinates_from_pos(screenCoords, ViewportInteractionFlags);
clickedElement = info.Element;
mapCoords = info.Loc;
}
// Even if Ctrl was pressed, fall back to normal selection when there was nothing under the cursor
if (clickedElement == nullptr)
{
auto mouseCoords = screen_pos_to_map_pos(screenCoords, nullptr);
if (!mouseCoords)
{
return;
}
mapCoords = *mouseCoords;
// Tile is already selected
if (windowTileInspectorTileSelected && mapCoords.x == windowTileInspectorToolMap.x
&& mapCoords.y == windowTileInspectorToolMap.y)
{
return;
}
}
windowTileInspectorTileSelected = true;
windowTileInspectorToolMap = mapCoords;
windowTileInspectorTile = TileCoordsXY(mapCoords);
window_tile_inspector_load_tile(w, clickedElement);
}
static void window_tile_inspector_tool_down(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
2017-01-09 20:30:42 +01:00
{
window_tile_inspector_update_selected_tile(w, screenCoords);
2017-01-09 20:30:42 +01:00
}
static void window_tile_inspector_tool_drag(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords)
2017-01-09 20:30:42 +01:00
{
window_tile_inspector_update_selected_tile(w, screenCoords);
2017-01-09 20:30:42 +01:00
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_scrollgetsize(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height)
{
*width = WW - 30;
*height = windowTileInspectorElementCount * SCROLLABLE_ROW_HEIGHT;
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_set_page(rct_window* w, const TILE_INSPECTOR_PAGE page)
{
// Invalidate the window already, because the size may change
w->Invalidate();
// subtract current page height, then add new page height
if (w->page != TILE_INSPECTOR_PAGE_DEFAULT)
{
w->height -= PageGroupBoxSettings[w->page - 1].details_top_offset - GROUPBOX_PADDING - 3;
w->min_height -= PageGroupBoxSettings[w->page - 1].details_top_offset - GROUPBOX_PADDING - 3;
}
if (page != TILE_INSPECTOR_PAGE_DEFAULT)
{
w->height += PageGroupBoxSettings[page - 1].details_top_offset - GROUPBOX_PADDING - 3;
w->min_height += PageGroupBoxSettings[page - 1].details_top_offset - GROUPBOX_PADDING - 3;
}
w->page = page;
w->widgets = PageWidgets[page];
w->enabled_widgets = PageEnabledWidgets[page];
w->hold_down_widgets = PageHoldDownWidgets[page];
w->disabled_widgets = PageDisabledWidgets[page];
w->pressed_widgets = 0;
}
static void window_tile_inspector_scrollmousedown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords)
{
// Because the list items are displayed in reverse order, subtract the calculated index from the amount of elements
const int16_t index = windowTileInspectorElementCount - (screenCoords.y - 1) / SCROLLABLE_ROW_HEIGHT - 1;
window_tile_inspector_select_element_from_list(w, index);
}
static void window_tile_inspector_scrollmouseover(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords)
{
int16_t index = windowTileInspectorElementCount - (screenCoords.y - 1) / SCROLLABLE_ROW_HEIGHT - 1;
if (index < 0 || index >= windowTileInspectorElementCount)
windowTileInspectorHighlightedIndex = -1;
else
windowTileInspectorHighlightedIndex = index;
widget_invalidate(w, WIDX_LIST);
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_invalidate(rct_window* w)
{
// Set the correct page automatically
TILE_INSPECTOR_PAGE page = TILE_INSPECTOR_PAGE_DEFAULT;
if (windowTileInspectorSelectedIndex != -1)
{
const auto element = window_tile_inspector_get_selected_element(w);
auto type = element->GetType();
switch (type)
{
2018-06-22 23:21:44 +02:00
case TILE_ELEMENT_TYPE_SURFACE:
page = TILE_INSPECTOR_PAGE_SURFACE;
break;
case TILE_ELEMENT_TYPE_PATH:
page = TILE_INSPECTOR_PAGE_PATH;
break;
case TILE_ELEMENT_TYPE_TRACK:
page = TILE_INSPECTOR_PAGE_TRACK;
break;
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
page = TILE_INSPECTOR_PAGE_SCENERY;
break;
case TILE_ELEMENT_TYPE_ENTRANCE:
page = TILE_INSPECTOR_PAGE_ENTRANCE;
break;
case TILE_ELEMENT_TYPE_WALL:
page = TILE_INSPECTOR_PAGE_WALL;
break;
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
page = TILE_INSPECTOR_PAGE_LARGE_SCENERY;
break;
case TILE_ELEMENT_TYPE_BANNER:
page = TILE_INSPECTOR_PAGE_BANNER;
break;
case TILE_ELEMENT_TYPE_CORRUPT:
default:
page = TILE_INSPECTOR_PAGE_CORRUPT;
break;
}
}
if (w->page != page)
{
window_tile_inspector_set_page(w, page);
w->Invalidate();
}
// X and Y spinners
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(
w, WIDX_SPINNER_X_INCREASE,
2019-06-18 21:47:30 +02:00
(windowTileInspectorTileSelected && ((windowTileInspectorToolMap.x / 32) < MAXIMUM_MAP_SIZE_TECHNICAL - 1)));
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(
2019-06-18 21:47:30 +02:00
w, WIDX_SPINNER_X_DECREASE, (windowTileInspectorTileSelected && ((windowTileInspectorToolMap.x / 32) > 0)));
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(
w, WIDX_SPINNER_Y_INCREASE,
2019-06-18 21:47:30 +02:00
(windowTileInspectorTileSelected && ((windowTileInspectorToolMap.y / 32) < MAXIMUM_MAP_SIZE_TECHNICAL - 1)));
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(
2019-06-18 21:47:30 +02:00
w, WIDX_SPINNER_Y_DECREASE, (windowTileInspectorTileSelected && ((windowTileInspectorToolMap.y / 32) > 0)));
// Sort buttons
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(w, WIDX_BUTTON_SORT, (windowTileInspectorTileSelected && windowTileInspectorElementCount > 1));
// Move Up button
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(
w, WIDX_BUTTON_MOVE_UP,
(windowTileInspectorSelectedIndex != -1 && windowTileInspectorSelectedIndex < windowTileInspectorElementCount - 1));
widget_invalidate(w, WIDX_BUTTON_MOVE_UP);
// Move Down button
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(w, WIDX_BUTTON_MOVE_DOWN, (windowTileInspectorSelectedIndex > 0));
widget_invalidate(w, WIDX_BUTTON_MOVE_DOWN);
// Copy button
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(w, WIDX_BUTTON_COPY, windowTileInspectorSelectedIndex >= 0);
widget_invalidate(w, WIDX_BUTTON_COPY);
// Paste button
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(w, WIDX_BUTTON_PASTE, windowTileInspectorTileSelected && windowTileInspectorElementCopied);
widget_invalidate(w, WIDX_BUTTON_PASTE);
w->widgets[WIDX_BACKGROUND].bottom = w->height - 1;
if (w->page == TILE_INSPECTOR_PAGE_DEFAULT)
{
w->widgets[WIDX_GROUPBOX_DETAILS].type = WindowWidgetType::Empty;
w->widgets[WIDX_GROUPBOX_PROPERTIES].type = WindowWidgetType::Empty;
w->widgets[WIDX_LIST].bottom = w->height - PADDING_BOTTOM;
}
else
{
w->widgets[WIDX_GROUPBOX_DETAILS].type = WindowWidgetType::Groupbox;
w->widgets[WIDX_GROUPBOX_PROPERTIES].type = WindowWidgetType::Groupbox;
w->widgets[WIDX_GROUPBOX_DETAILS].text = PageGroupBoxSettings[w->page - 1].string_id;
w->widgets[WIDX_GROUPBOX_DETAILS].top = w->height - PageGroupBoxSettings[w->page - 1].details_top_offset;
w->widgets[WIDX_GROUPBOX_DETAILS].bottom = w->height - PageGroupBoxSettings[w->page - 1].details_bottom_offset;
w->widgets[WIDX_GROUPBOX_PROPERTIES].top = w->height - PageGroupBoxSettings[w->page - 1].properties_top_offset;
w->widgets[WIDX_GROUPBOX_PROPERTIES].bottom = w->height - PageGroupBoxSettings[w->page - 1].properties_bottom_offset;
w->widgets[WIDX_LIST].bottom = w->widgets[WIDX_GROUPBOX_DETAILS].top - GROUPBOX_PADDING;
}
// The default page doesn't need further invalidation
2018-06-22 23:21:44 +02:00
if (w->page == TILE_INSPECTOR_PAGE_DEFAULT)
{
return;
}
// Using a switch, because I don't think giving each page their own callbacks is
// needed here, as only the mouseup and invalidate functions are different.
const int32_t propertiesAnchor = w->widgets[WIDX_GROUPBOX_PROPERTIES].top;
2018-11-01 13:53:50 +01:00
const TileElement* const tileElement = window_tile_inspector_get_selected_element(w);
2018-06-22 23:21:44 +02:00
switch (w->page)
{
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_SURFACE:
w->widgets[WIDX_SURFACE_SPINNER_HEIGHT].top = GBBT(propertiesAnchor, 0) + 3;
w->widgets[WIDX_SURFACE_SPINNER_HEIGHT].bottom = GBBB(propertiesAnchor, 0) - 3;
w->widgets[WIDX_SURFACE_SPINNER_HEIGHT_INCREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_SURFACE_SPINNER_HEIGHT_INCREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_SURFACE_SPINNER_HEIGHT_DECREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_SURFACE_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_SURFACE_BUTTON_REMOVE_FENCES].top = GBBT(propertiesAnchor, 1);
w->widgets[WIDX_SURFACE_BUTTON_REMOVE_FENCES].bottom = GBBB(propertiesAnchor, 1);
w->widgets[WIDX_SURFACE_BUTTON_RESTORE_FENCES].top = GBBT(propertiesAnchor, 1);
w->widgets[WIDX_SURFACE_BUTTON_RESTORE_FENCES].bottom = GBBB(propertiesAnchor, 1);
w->widgets[WIDX_SURFACE_CHECK_CORNER_N].top = GBBT(propertiesAnchor, 2) + 7 * 0;
w->widgets[WIDX_SURFACE_CHECK_CORNER_N].bottom = w->widgets[WIDX_SURFACE_CHECK_CORNER_N].top + 13;
w->widgets[WIDX_SURFACE_CHECK_CORNER_E].top = GBBT(propertiesAnchor, 2) + 7 * 1;
w->widgets[WIDX_SURFACE_CHECK_CORNER_E].bottom = w->widgets[WIDX_SURFACE_CHECK_CORNER_E].top + 13;
w->widgets[WIDX_SURFACE_CHECK_CORNER_S].top = GBBT(propertiesAnchor, 2) + 7 * 2;
w->widgets[WIDX_SURFACE_CHECK_CORNER_S].bottom = w->widgets[WIDX_SURFACE_CHECK_CORNER_S].top + 13;
w->widgets[WIDX_SURFACE_CHECK_CORNER_W].top = GBBT(propertiesAnchor, 2) + 7 * 1;
w->widgets[WIDX_SURFACE_CHECK_CORNER_W].bottom = w->widgets[WIDX_SURFACE_CHECK_CORNER_W].top + 13;
w->widgets[WIDX_SURFACE_CHECK_DIAGONAL].top = GBBT(propertiesAnchor, 3) + 7 * 1;
w->widgets[WIDX_SURFACE_CHECK_DIAGONAL].bottom = w->widgets[WIDX_SURFACE_CHECK_DIAGONAL].top + 13;
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_SURFACE_CHECK_CORNER_N,
2018-09-14 14:54:12 +02:00
tileElement->AsSurface()->GetSlope() & (1 << ((2 - get_current_rotation()) & 3)));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_SURFACE_CHECK_CORNER_E,
2018-09-14 14:54:12 +02:00
tileElement->AsSurface()->GetSlope() & (1 << ((3 - get_current_rotation()) & 3)));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_SURFACE_CHECK_CORNER_S,
2018-09-14 14:54:12 +02:00
tileElement->AsSurface()->GetSlope() & (1 << ((0 - get_current_rotation()) & 3)));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_SURFACE_CHECK_CORNER_W,
2018-09-14 14:54:12 +02:00
tileElement->AsSurface()->GetSlope() & (1 << ((1 - get_current_rotation()) & 3)));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
2018-09-14 14:54:12 +02:00
w, WIDX_SURFACE_CHECK_DIAGONAL, tileElement->AsSurface()->GetSlope() & TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT);
2018-06-22 23:21:44 +02:00
break;
case TILE_INSPECTOR_PAGE_PATH:
w->widgets[WIDX_PATH_SPINNER_HEIGHT].top = GBBT(propertiesAnchor, 0) + 3;
w->widgets[WIDX_PATH_SPINNER_HEIGHT].bottom = GBBB(propertiesAnchor, 0) - 3;
w->widgets[WIDX_PATH_SPINNER_HEIGHT_INCREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_PATH_SPINNER_HEIGHT_INCREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_PATH_SPINNER_HEIGHT_DECREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_PATH_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_PATH_CHECK_BROKEN].top = GBBT(propertiesAnchor, 1);
w->widgets[WIDX_PATH_CHECK_BROKEN].bottom = GBBB(propertiesAnchor, 1);
w->widgets[WIDX_PATH_CHECK_SLOPED].top = GBBT(propertiesAnchor, 2);
w->widgets[WIDX_PATH_CHECK_SLOPED].bottom = GBBB(propertiesAnchor, 2);
w->widgets[WIDX_PATH_CHECK_EDGE_N].top = GBBT(propertiesAnchor, 3) + 7 * 0;
2018-06-22 23:21:44 +02:00
w->widgets[WIDX_PATH_CHECK_EDGE_N].bottom = w->widgets[WIDX_PATH_CHECK_EDGE_N].top + 13;
w->widgets[WIDX_PATH_CHECK_EDGE_NE].top = GBBT(propertiesAnchor, 3) + 7 * 1;
2018-06-22 23:21:44 +02:00
w->widgets[WIDX_PATH_CHECK_EDGE_NE].bottom = w->widgets[WIDX_PATH_CHECK_EDGE_NE].top + 13;
w->widgets[WIDX_PATH_CHECK_EDGE_E].top = GBBT(propertiesAnchor, 3) + 7 * 2;
2018-06-22 23:21:44 +02:00
w->widgets[WIDX_PATH_CHECK_EDGE_E].bottom = w->widgets[WIDX_PATH_CHECK_EDGE_E].top + 13;
w->widgets[WIDX_PATH_CHECK_EDGE_SE].top = GBBT(propertiesAnchor, 3) + 7 * 3;
2018-06-22 23:21:44 +02:00
w->widgets[WIDX_PATH_CHECK_EDGE_SE].bottom = w->widgets[WIDX_PATH_CHECK_EDGE_SE].top + 13;
w->widgets[WIDX_PATH_CHECK_EDGE_S].top = GBBT(propertiesAnchor, 3) + 7 * 4;
2018-06-22 23:21:44 +02:00
w->widgets[WIDX_PATH_CHECK_EDGE_S].bottom = w->widgets[WIDX_PATH_CHECK_EDGE_S].top + 13;
w->widgets[WIDX_PATH_CHECK_EDGE_SW].top = GBBT(propertiesAnchor, 3) + 7 * 3;
2018-06-22 23:21:44 +02:00
w->widgets[WIDX_PATH_CHECK_EDGE_SW].bottom = w->widgets[WIDX_PATH_CHECK_EDGE_SW].top + 13;
w->widgets[WIDX_PATH_CHECK_EDGE_W].top = GBBT(propertiesAnchor, 3) + 7 * 2;
2018-06-22 23:21:44 +02:00
w->widgets[WIDX_PATH_CHECK_EDGE_W].bottom = w->widgets[WIDX_PATH_CHECK_EDGE_W].top + 13;
w->widgets[WIDX_PATH_CHECK_EDGE_NW].top = GBBT(propertiesAnchor, 3) + 7 * 1;
2018-06-22 23:21:44 +02:00
w->widgets[WIDX_PATH_CHECK_EDGE_NW].bottom = w->widgets[WIDX_PATH_CHECK_EDGE_NW].top + 13;
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(w, WIDX_PATH_CHECK_SLOPED, tileElement->AsPath()->IsSloped());
WidgetSetCheckboxValue(w, WIDX_PATH_CHECK_BROKEN, tileElement->AsPath()->IsBroken());
WidgetSetCheckboxValue(
w, WIDX_PATH_CHECK_EDGE_NE, tileElement->AsPath()->GetEdges() & (1 << ((0 - get_current_rotation()) & 3)));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_PATH_CHECK_EDGE_SE, tileElement->AsPath()->GetEdges() & (1 << ((1 - get_current_rotation()) & 3)));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_PATH_CHECK_EDGE_SW, tileElement->AsPath()->GetEdges() & (1 << ((2 - get_current_rotation()) & 3)));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_PATH_CHECK_EDGE_NW, tileElement->AsPath()->GetEdges() & (1 << ((3 - get_current_rotation()) & 3)));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_PATH_CHECK_EDGE_E, tileElement->AsPath()->GetCorners() & (1 << ((0 - get_current_rotation()) & 3)));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_PATH_CHECK_EDGE_S, tileElement->AsPath()->GetCorners() & (1 << ((1 - get_current_rotation()) & 3)));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_PATH_CHECK_EDGE_W, tileElement->AsPath()->GetCorners() & (1 << ((2 - get_current_rotation()) & 3)));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_PATH_CHECK_EDGE_N, tileElement->AsPath()->GetCorners() & (1 << ((3 - get_current_rotation()) & 3)));
2018-06-22 23:21:44 +02:00
break;
case TILE_INSPECTOR_PAGE_TRACK:
w->widgets[WIDX_TRACK_CHECK_APPLY_TO_ALL].top = GBBT(propertiesAnchor, 0);
w->widgets[WIDX_TRACK_CHECK_APPLY_TO_ALL].bottom = GBBB(propertiesAnchor, 0);
w->widgets[WIDX_TRACK_SPINNER_HEIGHT].top = GBBT(propertiesAnchor, 1) + 3;
w->widgets[WIDX_TRACK_SPINNER_HEIGHT].bottom = GBBB(propertiesAnchor, 1) - 3;
w->widgets[WIDX_TRACK_SPINNER_HEIGHT_INCREASE].top = GBBT(propertiesAnchor, 1) + 4;
w->widgets[WIDX_TRACK_SPINNER_HEIGHT_INCREASE].bottom = GBBB(propertiesAnchor, 1) - 4;
w->widgets[WIDX_TRACK_SPINNER_HEIGHT_DECREASE].top = GBBT(propertiesAnchor, 1) + 4;
w->widgets[WIDX_TRACK_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 1) - 4;
w->widgets[WIDX_TRACK_CHECK_CHAIN_LIFT].top = GBBT(propertiesAnchor, 2);
w->widgets[WIDX_TRACK_CHECK_CHAIN_LIFT].bottom = GBBB(propertiesAnchor, 2);
w->widgets[WIDX_TRACK_CHECK_BLOCK_BRAKE_CLOSED].top = GBBT(propertiesAnchor, 3);
w->widgets[WIDX_TRACK_CHECK_BLOCK_BRAKE_CLOSED].bottom = GBBB(propertiesAnchor, 3);
w->widgets[WIDX_TRACK_CHECK_IS_INDESTRUCTIBLE].top = GBBT(propertiesAnchor, 4);
w->widgets[WIDX_TRACK_CHECK_IS_INDESTRUCTIBLE].bottom = GBBB(propertiesAnchor, 4);
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(w, WIDX_TRACK_CHECK_APPLY_TO_ALL, windowTileInspectorApplyToAll);
WidgetSetCheckboxValue(w, WIDX_TRACK_CHECK_CHAIN_LIFT, tileElement->AsTrack()->HasChain());
WidgetSetCheckboxValue(w, WIDX_TRACK_CHECK_BLOCK_BRAKE_CLOSED, tileElement->AsTrack()->BlockBrakeClosed());
WidgetSetCheckboxValue(w, WIDX_TRACK_CHECK_IS_INDESTRUCTIBLE, tileElement->AsTrack()->IsIndestructible());
2018-06-22 23:21:44 +02:00
break;
case TILE_INSPECTOR_PAGE_SCENERY:
{
// Raise / Lower
w->widgets[WIDX_SCENERY_SPINNER_HEIGHT].top = GBBT(propertiesAnchor, 0) + 3;
w->widgets[WIDX_SCENERY_SPINNER_HEIGHT].bottom = GBBB(propertiesAnchor, 0) - 3;
w->widgets[WIDX_SCENERY_SPINNER_HEIGHT_INCREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_SCENERY_SPINNER_HEIGHT_INCREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_SCENERY_SPINNER_HEIGHT_DECREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_SCENERY_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
// Quadrant checkboxes
w->widgets[WIDX_SCENERY_CHECK_QUARTER_N].top = GBBT(propertiesAnchor, 1) - 5 + 7 * 0;
w->widgets[WIDX_SCENERY_CHECK_QUARTER_N].bottom = w->widgets[WIDX_SCENERY_CHECK_QUARTER_N].top + 13;
w->widgets[WIDX_SCENERY_CHECK_QUARTER_E].top = GBBT(propertiesAnchor, 1) - 5 + 7 * 1;
w->widgets[WIDX_SCENERY_CHECK_QUARTER_E].bottom = w->widgets[WIDX_SCENERY_CHECK_QUARTER_E].top + 13;
w->widgets[WIDX_SCENERY_CHECK_QUARTER_S].top = GBBT(propertiesAnchor, 1) - 5 + 7 * 2;
w->widgets[WIDX_SCENERY_CHECK_QUARTER_S].bottom = w->widgets[WIDX_SCENERY_CHECK_QUARTER_S].top + 13;
w->widgets[WIDX_SCENERY_CHECK_QUARTER_W].top = GBBT(propertiesAnchor, 1) - 5 + 7 * 1;
w->widgets[WIDX_SCENERY_CHECK_QUARTER_W].bottom = w->widgets[WIDX_SCENERY_CHECK_QUARTER_W].top + 13;
// This gets the relative rotation, by subtracting the camera's rotation, and wrapping it between 0-3 inclusive
bool N = tileElement->AsSmallScenery()->GetSceneryQuadrant() == ((0 - get_current_rotation()) & 3);
bool E = tileElement->AsSmallScenery()->GetSceneryQuadrant() == ((1 - get_current_rotation()) & 3);
bool S = tileElement->AsSmallScenery()->GetSceneryQuadrant() == ((2 - get_current_rotation()) & 3);
bool W = tileElement->AsSmallScenery()->GetSceneryQuadrant() == ((3 - get_current_rotation()) & 3);
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(w, WIDX_SCENERY_CHECK_QUARTER_N, N);
WidgetSetCheckboxValue(w, WIDX_SCENERY_CHECK_QUARTER_E, E);
WidgetSetCheckboxValue(w, WIDX_SCENERY_CHECK_QUARTER_S, S);
WidgetSetCheckboxValue(w, WIDX_SCENERY_CHECK_QUARTER_W, W);
2018-06-22 23:21:44 +02:00
// Collision checkboxes
w->widgets[WIDX_SCENERY_CHECK_COLLISION_N].top = GBBT(propertiesAnchor, 2) + 5 + 7 * 0;
w->widgets[WIDX_SCENERY_CHECK_COLLISION_N].bottom = w->widgets[WIDX_SCENERY_CHECK_COLLISION_N].top + 13;
w->widgets[WIDX_SCENERY_CHECK_COLLISION_E].top = GBBT(propertiesAnchor, 2) + 5 + 7 * 1;
w->widgets[WIDX_SCENERY_CHECK_COLLISION_E].bottom = w->widgets[WIDX_SCENERY_CHECK_COLLISION_E].top + 13;
w->widgets[WIDX_SCENERY_CHECK_COLLISION_S].top = GBBT(propertiesAnchor, 2) + 5 + 7 * 2;
w->widgets[WIDX_SCENERY_CHECK_COLLISION_S].bottom = w->widgets[WIDX_SCENERY_CHECK_COLLISION_S].top + 13;
w->widgets[WIDX_SCENERY_CHECK_COLLISION_W].top = GBBT(propertiesAnchor, 2) + 5 + 7 * 1;
w->widgets[WIDX_SCENERY_CHECK_COLLISION_W].bottom = w->widgets[WIDX_SCENERY_CHECK_COLLISION_W].top + 13;
auto occupiedQuadrants = tileElement->GetOccupiedQuadrants();
N = (occupiedQuadrants & (1 << ((2 - get_current_rotation()) & 3))) != 0;
E = (occupiedQuadrants & (1 << ((3 - get_current_rotation()) & 3))) != 0;
S = (occupiedQuadrants & (1 << ((0 - get_current_rotation()) & 3))) != 0;
W = (occupiedQuadrants & (1 << ((1 - get_current_rotation()) & 3))) != 0;
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(w, WIDX_SCENERY_CHECK_COLLISION_N, N);
WidgetSetCheckboxValue(w, WIDX_SCENERY_CHECK_COLLISION_E, E);
WidgetSetCheckboxValue(w, WIDX_SCENERY_CHECK_COLLISION_S, S);
WidgetSetCheckboxValue(w, WIDX_SCENERY_CHECK_COLLISION_W, W);
2018-06-22 23:21:44 +02:00
break;
}
case TILE_INSPECTOR_PAGE_ENTRANCE:
w->widgets[WIDX_ENTRANCE_SPINNER_HEIGHT].top = GBBT(propertiesAnchor, 0) + 3;
w->widgets[WIDX_ENTRANCE_SPINNER_HEIGHT].bottom = GBBB(propertiesAnchor, 0) - 3;
w->widgets[WIDX_ENTRANCE_SPINNER_HEIGHT_INCREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_ENTRANCE_SPINNER_HEIGHT_INCREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_ENTRANCE_SPINNER_HEIGHT_DECREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_ENTRANCE_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_ENTRANCE_BUTTON_MAKE_USABLE].top = GBBT(propertiesAnchor, 1);
w->widgets[WIDX_ENTRANCE_BUTTON_MAKE_USABLE].bottom = GBBB(propertiesAnchor, 1);
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(
2018-09-26 15:44:09 +02:00
w, WIDX_ENTRANCE_BUTTON_MAKE_USABLE,
tileElement->AsEntrance()->GetEntranceType() != ENTRANCE_TYPE_PARK_ENTRANCE);
2018-06-22 23:21:44 +02:00
break;
case TILE_INSPECTOR_PAGE_WALL:
{
w->widgets[WIDX_WALL_SPINNER_HEIGHT].top = GBBT(propertiesAnchor, 0) + 3;
w->widgets[WIDX_WALL_SPINNER_HEIGHT].bottom = GBBB(propertiesAnchor, 0) - 3;
w->widgets[WIDX_WALL_SPINNER_HEIGHT_INCREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_WALL_SPINNER_HEIGHT_INCREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_WALL_SPINNER_HEIGHT_DECREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_WALL_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_WALL_DROPDOWN_SLOPE].top = GBBT(propertiesAnchor, 1) + 3;
w->widgets[WIDX_WALL_DROPDOWN_SLOPE].bottom = GBBB(propertiesAnchor, 1) - 3;
w->widgets[WIDX_WALL_DROPDOWN_SLOPE].text = WallSlopeStringIds[tileElement->AsWall()->GetSlope()];
2018-06-22 23:21:44 +02:00
w->widgets[WIDX_WALL_DROPDOWN_SLOPE_BUTTON].top = GBBT(propertiesAnchor, 1) + 4;
w->widgets[WIDX_WALL_DROPDOWN_SLOPE_BUTTON].bottom = GBBB(propertiesAnchor, 1) - 4;
w->widgets[WIDX_WALL_SPINNER_ANIMATION_FRAME].top = GBBT(propertiesAnchor, 2) + 3;
w->widgets[WIDX_WALL_SPINNER_ANIMATION_FRAME].bottom = GBBB(propertiesAnchor, 2) - 3;
w->widgets[WIDX_WALL_SPINNER_ANIMATION_FRAME_INCREASE].top = GBBT(propertiesAnchor, 2) + 4;
w->widgets[WIDX_WALL_SPINNER_ANIMATION_FRAME_INCREASE].bottom = GBBB(propertiesAnchor, 2) - 4;
w->widgets[WIDX_WALL_SPINNER_ANIMATION_FRAME_DECREASE].top = GBBT(propertiesAnchor, 2) + 4;
w->widgets[WIDX_WALL_SPINNER_ANIMATION_FRAME_DECREASE].bottom = GBBB(propertiesAnchor, 2) - 4;
const auto wallType = tileElement->AsWall()->GetEntryIndex();
2018-06-22 23:21:44 +02:00
const rct_wall_scenery_entry wallEntry = get_wall_entry(wallType)->wall;
const bool canBeSloped = !(wallEntry.flags & WALL_SCENERY_CANT_BUILD_ON_SLOPE);
const bool hasAnimation = wallEntry.flags & WALL_SCENERY_IS_DOOR;
2018-06-22 23:21:44 +02:00
// Wall slope dropdown
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(w, WIDX_WALL_DROPDOWN_SLOPE, canBeSloped);
2018-06-22 23:21:44 +02:00
widget_invalidate(w, WIDX_WALL_DROPDOWN_SLOPE);
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(w, WIDX_WALL_DROPDOWN_SLOPE_BUTTON, canBeSloped);
2018-06-22 23:21:44 +02:00
widget_invalidate(w, WIDX_WALL_DROPDOWN_SLOPE_BUTTON);
// Wall animation frame spinner
2020-11-03 22:29:22 +01:00
WidgetSetEnabled(w, WIDX_WALL_SPINNER_ANIMATION_FRAME, hasAnimation);
WidgetSetEnabled(w, WIDX_WALL_SPINNER_ANIMATION_FRAME_INCREASE, hasAnimation);
WidgetSetEnabled(w, WIDX_WALL_SPINNER_ANIMATION_FRAME_DECREASE, hasAnimation);
2018-06-22 23:21:44 +02:00
break;
}
case TILE_INSPECTOR_PAGE_LARGE_SCENERY:
w->widgets[WIDX_LARGE_SCENERY_SPINNER_HEIGHT].top = GBBT(propertiesAnchor, 0) + 3;
w->widgets[WIDX_LARGE_SCENERY_SPINNER_HEIGHT].bottom = GBBB(propertiesAnchor, 0) - 3;
w->widgets[WIDX_LARGE_SCENERY_SPINNER_HEIGHT_INCREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_LARGE_SCENERY_SPINNER_HEIGHT_INCREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_LARGE_SCENERY_SPINNER_HEIGHT_DECREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_LARGE_SCENERY_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
break;
case TILE_INSPECTOR_PAGE_BANNER:
w->widgets[WIDX_BANNER_SPINNER_HEIGHT].top = GBBT(propertiesAnchor, 0) + 3;
w->widgets[WIDX_BANNER_SPINNER_HEIGHT].bottom = GBBB(propertiesAnchor, 0) - 3;
w->widgets[WIDX_BANNER_SPINNER_HEIGHT_INCREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_BANNER_SPINNER_HEIGHT_INCREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_BANNER_SPINNER_HEIGHT_DECREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_BANNER_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_BANNER_CHECK_BLOCK_NE].top = GBBT(propertiesAnchor, 1);
w->widgets[WIDX_BANNER_CHECK_BLOCK_NE].bottom = GBBB(propertiesAnchor, 1);
w->widgets[WIDX_BANNER_CHECK_BLOCK_SE].top = GBBT(propertiesAnchor, 2);
w->widgets[WIDX_BANNER_CHECK_BLOCK_SE].bottom = GBBB(propertiesAnchor, 2);
w->widgets[WIDX_BANNER_CHECK_BLOCK_SW].top = GBBT(propertiesAnchor, 2);
w->widgets[WIDX_BANNER_CHECK_BLOCK_SW].bottom = GBBB(propertiesAnchor, 2);
w->widgets[WIDX_BANNER_CHECK_BLOCK_NW].top = GBBT(propertiesAnchor, 1);
w->widgets[WIDX_BANNER_CHECK_BLOCK_NW].bottom = GBBB(propertiesAnchor, 1);
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_BANNER_CHECK_BLOCK_NE,
2018-09-26 14:52:16 +02:00
!(tileElement->AsBanner()->GetAllowedEdges() & (1 << ((0 - get_current_rotation()) & 3))));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_BANNER_CHECK_BLOCK_SE,
2018-09-26 14:52:16 +02:00
!(tileElement->AsBanner()->GetAllowedEdges() & (1 << ((1 - get_current_rotation()) & 3))));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_BANNER_CHECK_BLOCK_SW,
2018-09-26 14:52:16 +02:00
!(tileElement->AsBanner()->GetAllowedEdges() & (1 << ((2 - get_current_rotation()) & 3))));
2020-11-03 22:29:22 +01:00
WidgetSetCheckboxValue(
w, WIDX_BANNER_CHECK_BLOCK_NW,
2018-09-26 14:52:16 +02:00
!(tileElement->AsBanner()->GetAllowedEdges() & (1 << ((3 - get_current_rotation()) & 3))));
2018-06-22 23:21:44 +02:00
break;
case TILE_INSPECTOR_PAGE_CORRUPT:
w->widgets[WIDX_CORRUPT_SPINNER_HEIGHT].top = GBBT(propertiesAnchor, 0) + 3;
w->widgets[WIDX_CORRUPT_SPINNER_HEIGHT].bottom = GBBB(propertiesAnchor, 0) - 3;
w->widgets[WIDX_CORRUPT_SPINNER_HEIGHT_INCREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_CORRUPT_SPINNER_HEIGHT_INCREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_CORRUPT_SPINNER_HEIGHT_DECREASE].top = GBBT(propertiesAnchor, 0) + 4;
w->widgets[WIDX_CORRUPT_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_CORRUPT_BUTTON_CLAMP].top = GBBT(propertiesAnchor, 1);
w->widgets[WIDX_CORRUPT_BUTTON_CLAMP].bottom = GBBB(propertiesAnchor, 1);
break;
}
}
2018-06-22 23:21:44 +02:00
static void window_tile_inspector_paint(rct_window* w, rct_drawpixelinfo* dpi)
{
WindowDrawWidgets(w, dpi);
// Set medium font size
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
// Draw column headers
2018-06-22 23:21:44 +02:00
rct_widget* widget;
if ((widget = &w->widgets[WIDX_COLUMN_TYPE])->type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
DrawTextEllipsised(
dpi, { w->windowPos.x + widget->left + 1, w->windowPos.y + widget->top + 1 }, widget->width(),
STR_TILE_INSPECTOR_ELEMENT_TYPE, {}, w->colours[1]);
}
if ((widget = &w->widgets[WIDX_COLUMN_BASEHEIGHT])->type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
DrawTextEllipsised(
dpi, { w->windowPos.x + widget->left + 1, w->windowPos.y + widget->top + 1 }, widget->width(),
STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT, {}, w->colours[1]);
}
if ((widget = &w->widgets[WIDX_COLUMN_CLEARANCEHEIGHT])->type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
DrawTextEllipsised(
dpi, { w->windowPos.x + widget->left + 1, w->windowPos.y + widget->top + 1 }, widget->width(),
STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT, {}, w->colours[1]);
}
if ((widget = &w->widgets[WIDX_COLUMN_GHOSTFLAG])->type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
DrawTextEllipsised(
dpi, { w->windowPos.x + widget->left + 1, w->windowPos.y + widget->top + 1 }, widget->width(),
STR_TILE_INSPECTOR_FLAG_GHOST_SHORT, {}, w->colours[1]);
}
if ((widget = &w->widgets[WIDX_COLUMN_LASTFLAG])->type != WindowWidgetType::Empty)
2018-06-22 23:21:44 +02:00
{
DrawTextEllipsised(
dpi, { w->windowPos.x + widget->left + 1, w->windowPos.y + widget->top + 1 }, widget->width(),
STR_TILE_INSPECTOR_FLAG_LAST_SHORT, {}, w->colours[1]);
}
ScreenCoordsXY screenCoords(w->windowPos.x, w->windowPos.y);
// Draw coordinates
gfx_draw_string(dpi, "X:", COLOUR_WHITE, screenCoords + ScreenCoordsXY(5, 24));
gfx_draw_string(dpi, "Y:", COLOUR_WHITE, screenCoords + ScreenCoordsXY(74, 24));
2018-06-22 23:21:44 +02:00
if (windowTileInspectorTileSelected)
{
2019-06-18 21:47:30 +02:00
auto tileCoords = TileCoordsXY{ windowTileInspectorToolMap };
auto ft = Formatter();
ft.Add<int32_t>(tileCoords.x);
DrawTextBasic(dpi, screenCoords + ScreenCoordsXY{ 43, 24 }, STR_FORMAT_INTEGER, ft, COLOUR_WHITE, TextAlignment::RIGHT);
ft = Formatter();
ft.Add<int32_t>(tileCoords.y);
DrawTextBasic(
dpi, screenCoords + ScreenCoordsXY{ 113, 24 }, STR_FORMAT_INTEGER, ft, COLOUR_WHITE, TextAlignment::RIGHT);
}
2018-06-22 23:21:44 +02:00
else
{
gfx_draw_string(dpi, "-", COLOUR_WHITE, screenCoords + ScreenCoordsXY(43 - 7, 24));
gfx_draw_string(dpi, "-", COLOUR_WHITE, screenCoords + ScreenCoordsXY(113, 24));
}
2018-06-22 23:21:44 +02:00
if (windowTileInspectorSelectedIndex != -1)
{
// X and Y of first element in detail box
screenCoords = w->windowPos
+ ScreenCoordsXY{ w->widgets[WIDX_GROUPBOX_DETAILS].left + 7, w->widgets[WIDX_GROUPBOX_DETAILS].top + 14 };
// Get map element
2018-11-01 13:53:50 +01:00
TileElement* const tileElement = window_tile_inspector_get_selected_element(w);
2018-06-22 23:21:44 +02:00
switch (w->page)
{
case TILE_INSPECTOR_PAGE_SURFACE:
{
// Details
// Terrain texture name
rct_string_id terrainNameId = STR_EMPTY;
auto surfaceStyle = tileElement->AsSurface()->GetSurfaceStyleObject();
if (surfaceStyle != nullptr)
{
terrainNameId = surfaceStyle->NameStringId;
}
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SURFACE_TERAIN, &terrainNameId, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Edge texture name
rct_string_id terrainEdgeNameId = STR_EMPTY;
auto edgeStyle = tileElement->AsSurface()->GetEdgeStyleObject();
if (edgeStyle != nullptr)
{
terrainEdgeNameId = edgeStyle->NameStringId;
}
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_SURFACE_EDGE, &terrainEdgeNameId, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 11 });
2018-06-22 23:21:44 +02:00
// Land ownership
rct_string_id landOwnership;
2018-09-14 14:54:12 +02:00
if (tileElement->AsSurface()->GetOwnership() & OWNERSHIP_OWNED)
2018-06-22 23:21:44 +02:00
landOwnership = STR_LAND_OWNED;
2018-09-14 14:54:12 +02:00
else if (tileElement->AsSurface()->GetOwnership() & OWNERSHIP_AVAILABLE)
2018-06-22 23:21:44 +02:00
landOwnership = STR_LAND_SALE;
2018-09-14 14:54:12 +02:00
else if (tileElement->AsSurface()->GetOwnership() & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED)
2018-06-22 23:21:44 +02:00
landOwnership = STR_CONSTRUCTION_RIGHTS_OWNED;
2018-09-14 14:54:12 +02:00
else if (tileElement->AsSurface()->GetOwnership() & OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE)
2018-06-22 23:21:44 +02:00
landOwnership = STR_CONSTRUCTION_RIGHTS_SALE;
else
landOwnership = STR_TILE_INSPECTOR_LAND_NOT_OWNED_AND_NOT_AVAILABLE;
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_SURFACE_OWNERSHIP, &landOwnership, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 22 });
2018-06-22 23:21:44 +02:00
// Water level
2018-09-15 10:56:35 +02:00
uint32_t waterLevel = tileElement->AsSurface()->GetWaterHeight();
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_SURFACE_WATER_LEVEL, &waterLevel, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 33 });
2018-06-22 23:21:44 +02:00
// Properties
// Raise / lower label
screenCoords = w->windowPos
+ ScreenCoordsXY{ w->widgets[WIDX_GROUPBOX_DETAILS].left + 7, w->widgets[WIDX_SURFACE_SPINNER_HEIGHT].top };
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Current base height
screenCoords.x = w->windowPos.x + w->widgets[WIDX_SURFACE_SPINNER_HEIGHT].left + 3;
2018-06-22 23:21:44 +02:00
int32_t baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Raised corners
screenCoords = w->windowPos
+ ScreenCoordsXY{ w->widgets[WIDX_GROUPBOX_DETAILS].left + 7, w->widgets[WIDX_SURFACE_CHECK_CORNER_E].top };
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SURFACE_CORNERS, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
break;
}
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_PATH:
{
// Details
// Path name
2020-03-04 18:43:09 +01:00
rct_string_id pathNameId = tileElement->AsPath()->GetSurfaceEntry()->string_idx;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_PATH_NAME, &pathNameId, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Path addition
if (tileElement->AsPath()->HasAddition())
2018-06-22 23:21:44 +02:00
{
const auto pathAdditionType = tileElement->AsPath()->GetAdditionEntryIndex();
const auto* sceneryElement = get_footpath_item_entry(pathAdditionType);
rct_string_id additionNameId = sceneryElement != nullptr
? sceneryElement->name
: static_cast<rct_string_id>(STR_UNKNOWN_OBJECT_TYPE);
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_PATH_ADDITIONS, &additionNameId, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 11 });
2018-06-22 23:21:44 +02:00
}
else
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_PATH_ADDITIONS_NONE, nullptr, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 11 });
2018-06-22 23:21:44 +02:00
// Properties
// Raise / lower label
screenCoords = w->windowPos
+ ScreenCoordsXY{ w->widgets[WIDX_GROUPBOX_DETAILS].left + 7, w->widgets[WIDX_PATH_SPINNER_HEIGHT].top };
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Current base height
screenCoords.x = w->windowPos.x + w->widgets[WIDX_PATH_SPINNER_HEIGHT].left + 3;
2018-06-22 23:21:44 +02:00
int32_t baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Path connections
screenCoords = w->windowPos
+ ScreenCoordsXY{ w->widgets[WIDX_GROUPBOX_DETAILS].left + 7, w->widgets[WIDX_PATH_CHECK_EDGE_W].top };
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_PATH_CONNECTED_EDGES, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
break;
}
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_TRACK:
2017-12-04 20:09:38 +01:00
{
2018-06-22 23:21:44 +02:00
// Details
// Ride
2019-01-08 11:25:12 +01:00
auto trackElement = tileElement->AsTrack();
int16_t rideId = trackElement->GetRideIndex();
auto ride = get_ride(rideId);
if (ride != nullptr)
{
auto rideType = RideTypeDescriptors[ride->type].Naming.Name;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_TRACK_RIDE_TYPE, &rideType, COLOUR_WHITE, screenCoords);
}
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_TRACK_RIDE_ID, &rideId, COLOUR_WHITE, screenCoords + ScreenCoordsXY{ 0, 11 });
if (ride != nullptr)
{
auto ft = Formatter();
ride->FormatNameTo(ft);
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_TRACK_RIDE_NAME, ft.Data(), COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 22 });
}
2018-06-22 23:21:44 +02:00
// Track
2019-01-08 11:25:12 +01:00
int16_t trackType = trackElement->GetTrackType();
int16_t sequenceNumber = trackElement->GetSequenceIndex();
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_TRACK_PIECE_ID, &trackType, COLOUR_WHITE, screenCoords + ScreenCoordsXY{ 0, 33 });
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_TRACK_SEQUENCE, &sequenceNumber, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 44 });
if (trackElement->IsStation())
2019-01-08 11:25:12 +01:00
{
int16_t stationIndex = trackElement->GetStationIndex();
auto ft = Formatter();
ft.Add<rct_string_id>(STR_COMMA16);
ft.Add<int16_t>(stationIndex);
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_STATION_INDEX, ft.Data(), COLOUR_WHITE, screenCoords + ScreenCoordsXY{ 0, 55 });
}
else
{
const char* stationNone = "-";
auto ft = Formatter();
ft.Add<rct_string_id>(STR_STRING);
ft.Add<char*>(stationNone);
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_STATION_INDEX, ft.Data(), COLOUR_WHITE, screenCoords + ScreenCoordsXY{ 0, 55 });
2019-01-08 11:25:12 +01:00
}
2018-06-22 23:21:44 +02:00
rct_string_id colourScheme = ColourSchemeNames[trackElement->GetColourScheme()];
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_COLOUR_SCHEME, &colourScheme, COLOUR_WHITE, screenCoords + ScreenCoordsXY{ 0, 66 });
2018-06-22 23:21:44 +02:00
// Properties
// Raise / lower label
screenCoords.y = w->windowPos.y + w->widgets[WIDX_TRACK_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Current base height
screenCoords.x = w->windowPos.x + w->widgets[WIDX_TRACK_SPINNER_HEIGHT].left + 3;
2018-06-22 23:21:44 +02:00
int32_t baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
break;
}
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_SCENERY:
{
// Details
// Age
int16_t age = tileElement->AsSmallScenery()->GetAge();
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SCENERY_AGE, &age, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Quadrant value
const rct_scenery_entry* sceneryEntry = get_small_scenery_entry(tileElement->AsSmallScenery()->GetEntryIndex());
2018-06-22 23:21:44 +02:00
if (!(scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_FULL_TILE)))
{
int16_t quadrant = tileElement->AsSmallScenery()->GetSceneryQuadrant();
2018-06-22 23:21:44 +02:00
static rct_string_id quadrant_string_idx[] = { STR_TILE_INSPECTOR_SCENERY_QUADRANT_SW,
STR_TILE_INSPECTOR_SCENERY_QUADRANT_NW,
STR_TILE_INSPECTOR_SCENERY_QUADRANT_NE,
STR_TILE_INSPECTOR_SCENERY_QUADRANT_SE };
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_SCENERY_QUADRANT, &quadrant_string_idx[quadrant], COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 11 });
2018-06-22 23:21:44 +02:00
}
2018-06-22 23:21:44 +02:00
// Scenery ID
int16_t idx = tileElement->AsSmallScenery()->GetEntryIndex();
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_SCENERY_ENTRY_IDX, &idx, COLOUR_WHITE, screenCoords + ScreenCoordsXY{ 0, 22 });
2018-06-22 23:21:44 +02:00
// Properties
// Raise / Lower
screenCoords.y = w->windowPos.y + w->widgets[WIDX_SCENERY_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Current base height
screenCoords.x = w->windowPos.x + w->widgets[WIDX_SCENERY_SPINNER_HEIGHT].left + 3;
2018-06-22 23:21:44 +02:00
int32_t baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Quarter tile
screenCoords = w->windowPos
+ ScreenCoordsXY{ w->widgets[WIDX_GROUPBOX_DETAILS].left + 7,
w->widgets[WIDX_SCENERY_CHECK_QUARTER_E].top };
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SCENERY_QUADRANT_LABEL, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Collision
screenCoords.y = w->windowPos.y + w->widgets[WIDX_SCENERY_CHECK_COLLISION_E].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_COLLISSION, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
break;
}
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_ENTRANCE:
2018-05-18 15:18:40 +02:00
{
2018-06-22 23:21:44 +02:00
// Details
// Entrance type
2018-09-26 12:13:44 +02:00
rct_string_id entranceType = EntranceTypeStringIds[tileElement->AsEntrance()->GetEntranceType()];
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRANCE_TYPE, &entranceType, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
2018-09-26 12:13:44 +02:00
if (tileElement->AsEntrance()->GetEntranceType() == ENTRANCE_TYPE_PARK_ENTRANCE)
2018-05-18 15:18:40 +02:00
{
2018-06-22 23:21:44 +02:00
// TODO: Make this work with Left/Right park entrance parts
2019-06-18 21:47:30 +02:00
int16_t parkEntranceIndex = park_entrance_get_index(
{ windowTileInspectorToolMap, tileElement->GetBaseZ() });
2018-05-18 15:18:40 +02:00
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRANCE_ENTRANCE_ID, &parkEntranceIndex, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 11 });
}
2018-05-18 15:18:40 +02:00
else
{
int16_t rideEntranceIndex = tileElement->AsEntrance()->GetStationIndex();
2018-09-26 12:13:44 +02:00
if (tileElement->AsEntrance()->GetEntranceType() == ENTRANCE_TYPE_RIDE_ENTRANCE)
2018-06-22 23:21:44 +02:00
{
// Ride entrance ID
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRANCE_ENTRANCE_ID, &rideEntranceIndex, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 11 });
2018-06-22 23:21:44 +02:00
}
else
{
// Ride exit ID
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRANCE_EXIT_ID, &rideEntranceIndex, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 11 });
2018-06-22 23:21:44 +02:00
}
}
2018-09-26 12:13:44 +02:00
if (tileElement->AsEntrance()->GetEntranceType() == ENTRANCE_TYPE_PARK_ENTRANCE)
2018-06-22 23:21:44 +02:00
{
// Entrance part
rct_string_id entrancePart = ParkEntrancePartStringIds[tileElement->AsEntrance()->GetSequenceIndex()];
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRANCE_PART, &entrancePart, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 22 });
2018-06-22 23:21:44 +02:00
}
else
{
// Ride ID
2018-09-26 12:30:27 +02:00
int16_t rideId = tileElement->AsEntrance()->GetRideIndex();
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRANCE_RIDE_ID, &rideId, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 22 });
2019-01-08 11:25:12 +01:00
// Station index
int16_t stationIndex = tileElement->AsEntrance()->GetStationIndex();
auto ft = Formatter();
ft.Add<rct_string_id>(STR_COMMA16);
ft.Add<int16_t>(stationIndex);
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_STATION_INDEX, ft.Data(), COLOUR_WHITE, screenCoords + ScreenCoordsXY{ 0, 33 });
2018-06-22 23:21:44 +02:00
}
2018-06-22 23:21:44 +02:00
// Properties
// Raise / Lower
screenCoords.y = w->windowPos.y + w->widgets[WIDX_ENTRANCE_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Current base height
screenCoords.x = w->windowPos.x + w->widgets[WIDX_ENTRANCE_SPINNER_HEIGHT].left + 3;
auto ft = Formatter();
ft.Add<int32_t>(tileElement->base_height);
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, ft.Data(), COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
break;
}
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_WALL:
{
// Details
// Type
int16_t wallType = tileElement->AsWall()->GetEntryIndex();
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_WALL_TYPE, &wallType, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Banner info
rct_wall_scenery_entry wallEntry = get_wall_entry(wallType)->wall;
if (wallEntry.flags & WALL_SCENERY_IS_BANNER)
{
2019-07-25 18:51:22 +02:00
auto banner = tileElement->AsWall()->GetBanner();
2019-07-21 18:40:52 +02:00
if (banner != nullptr && !banner->IsNull())
2019-07-25 18:51:22 +02:00
{
Formatter ft;
banner->FormatTextTo(ft);
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, ft.Data(), COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 11 });
2019-07-25 18:51:22 +02:00
}
2018-06-22 23:21:44 +02:00
}
else
{
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_NONE, nullptr, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 11 });
2018-06-22 23:21:44 +02:00
}
2018-06-22 23:21:44 +02:00
// Properties
// Raise / lower label
screenCoords.y = w->windowPos.y + w->widgets[WIDX_WALL_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Current base height
screenCoords.x = w->windowPos.x + w->widgets[WIDX_WALL_SPINNER_HEIGHT].left + 3;
2018-06-22 23:21:44 +02:00
int32_t baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Slope label
screenCoords = w->windowPos
+ ScreenCoordsXY{ w->widgets[WIDX_GROUPBOX_DETAILS].left + 7, w->widgets[WIDX_WALL_DROPDOWN_SLOPE].top };
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_WALL_SLOPE, nullptr, COLOUR_WHITE, screenCoords);
// Animation frame label
screenCoords.y = w->windowPos.y + w->widgets[WIDX_WALL_SPINNER_ANIMATION_FRAME].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_WALL_ANIMATION_FRAME, nullptr, COLOUR_WHITE, screenCoords);
// Current animation frame
uint8_t colour = COLOUR_WHITE;
2020-11-03 22:29:22 +01:00
if (WidgetIsDisabled(w, WIDX_WALL_SPINNER_ANIMATION_FRAME))
{
colour = w->colours[0] | COLOUR_FLAG_INSET;
}
screenCoords.x = w->windowPos.x + w->widgets[WIDX_WALL_SPINNER_ANIMATION_FRAME].left + 3;
int32_t animationFrame = tileElement->AsWall()->GetAnimationFrame();
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &animationFrame, colour, screenCoords);
2018-06-22 23:21:44 +02:00
break;
}
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_LARGE_SCENERY:
{
// Details
// Type
2018-09-14 12:12:22 +02:00
auto sceneryElement = tileElement->AsLargeScenery();
int16_t largeSceneryType = sceneryElement->GetEntryIndex();
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_LARGE_SCENERY_TYPE, &largeSceneryType, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Part ID
2018-09-14 12:12:22 +02:00
int16_t pieceID = sceneryElement->GetSequenceIndex();
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_LARGE_SCENERY_PIECE_ID, &pieceID, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 11 });
2018-06-22 23:21:44 +02:00
// Banner info
2018-09-14 12:12:22 +02:00
rct_scenery_entry* largeSceneryEntry = get_large_scenery_entry(largeSceneryType);
if (largeSceneryEntry->large_scenery.scrolling_mode != SCROLLING_MODE_NONE)
2018-06-22 23:21:44 +02:00
{
2019-07-25 18:51:22 +02:00
auto banner = sceneryElement->GetBanner();
2019-07-21 18:40:52 +02:00
if (banner != nullptr && !banner->IsNull())
2019-07-25 18:51:22 +02:00
{
Formatter ft;
banner->FormatTextTo(ft);
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, ft.Data(), COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 22 });
2019-07-25 18:51:22 +02:00
}
2018-06-22 23:21:44 +02:00
}
else
{
gfx_draw_string_left(
dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_NONE, nullptr, COLOUR_WHITE,
screenCoords + ScreenCoordsXY{ 0, 22 });
2018-06-22 23:21:44 +02:00
}
2018-06-22 23:21:44 +02:00
// Properties
// Raise / lower label
screenCoords.y = w->windowPos.y + w->widgets[WIDX_LARGE_SCENERY_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Current base height
screenCoords.x = w->windowPos.x + w->widgets[WIDX_LARGE_SCENERY_SPINNER_HEIGHT].left + 3;
2018-06-22 23:21:44 +02:00
int32_t baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
break;
}
2018-06-22 23:21:44 +02:00
case TILE_INSPECTOR_PAGE_BANNER:
{
// Details
// Banner info
2019-07-25 18:51:22 +02:00
auto banner = tileElement->AsBanner()->GetBanner();
2019-07-21 18:40:52 +02:00
if (banner != nullptr && !banner->IsNull())
2018-06-22 23:21:44 +02:00
{
Formatter ft;
banner->FormatTextTo(ft);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, ft.Data(), COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
}
2018-06-22 23:21:44 +02:00
// Properties
// Raise / lower label
screenCoords.y = w->windowPos.y + w->widgets[WIDX_BANNER_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Current base height
screenCoords.x = w->windowPos.x + w->widgets[WIDX_BANNER_SPINNER_HEIGHT].left + 3;
2018-06-22 23:21:44 +02:00
int32_t baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Blocked paths
screenCoords.y += 28;
screenCoords.x = w->windowPos.x + w->widgets[WIDX_GROUPBOX_DETAILS].left + 7;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BANNER_BLOCKED_PATHS, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
break;
}
case TILE_INSPECTOR_PAGE_CORRUPT:
{
// Properties
// Raise / lower label
screenCoords.y = w->windowPos.y + w->widgets[WIDX_CORRUPT_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
// Current base height
screenCoords.x = w->windowPos.x + w->widgets[WIDX_CORRUPT_SPINNER_HEIGHT].left + 3;
2018-06-22 23:21:44 +02:00
int32_t baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_WHITE, screenCoords);
2018-06-22 23:21:44 +02:00
break;
}
} // switch page
}
}
static void window_tile_inspector_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex)
{
const int32_t listWidth = w->widgets[WIDX_LIST].width();
gfx_fill_rect(
dpi, { { dpi->x, dpi->y }, { dpi->x + dpi->width - 1, dpi->y + dpi->height - 1 } },
ColourMapA[w->colours[1]].mid_light);
ScreenCoordsXY screenCoords{};
screenCoords.y = SCROLLABLE_ROW_HEIGHT * (windowTileInspectorElementCount - 1);
int32_t i = 0;
char buffer[256];
if (!windowTileInspectorTileSelected)
return;
const TileElement* tileElement = map_get_first_element_at(windowTileInspectorToolMap);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
2018-06-22 23:21:44 +02:00
do
{
if (tileElement == nullptr)
break;
const bool selectedRow = i == windowTileInspectorSelectedIndex;
2018-05-22 21:54:09 +02:00
const bool hoveredRow = i == windowTileInspectorHighlightedIndex;
int32_t type = tileElement->GetType();
2018-05-22 21:54:09 +02:00
const char* typeName = "";
auto fillRectangle = ScreenRect{ { 0, screenCoords.y }, { listWidth, screenCoords.y + SCROLLABLE_ROW_HEIGHT - 1 } };
2018-05-22 21:54:09 +02:00
if (selectedRow)
{
gfx_fill_rect(dpi, fillRectangle, ColourMapA[w->colours[1]].mid_dark);
}
2018-05-22 21:54:09 +02:00
else if (hoveredRow)
{
gfx_fill_rect(dpi, fillRectangle, ColourMapA[w->colours[1]].mid_dark | 0x1000000);
2018-05-22 21:54:09 +02:00
}
else if (((windowTileInspectorElementCount - i) & 1) == 0)
{
// Zebra stripes
gfx_fill_rect(dpi, fillRectangle, ColourMapA[w->colours[1]].light | 0x1000000);
2018-05-22 21:54:09 +02:00
}
2018-06-22 23:21:44 +02:00
switch (type)
{
case TILE_ELEMENT_TYPE_SURFACE:
typeName = language_get_string(STR_TILE_INSPECTOR_SURFACE);
break;
case TILE_ELEMENT_TYPE_PATH:
2018-10-03 10:57:29 +02:00
typeName = tileElement->AsPath()->IsQueue() ? language_get_string(STR_QUEUE_LINE_MAP_TIP)
: language_get_string(STR_FOOTPATH_MAP_TIP);
2018-06-22 23:21:44 +02:00
break;
case TILE_ELEMENT_TYPE_TRACK:
typeName = language_get_string(STR_RIDE_COMPONENT_TRACK_CAPITALISED);
break;
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
snprintf(
buffer, sizeof(buffer), "%s (%s)", language_get_string(STR_OBJECT_SELECTION_SMALL_SCENERY),
language_get_string(get_small_scenery_entry(tileElement->AsSmallScenery()->GetEntryIndex())->name));
2018-06-22 23:21:44 +02:00
typeName = buffer;
break;
case TILE_ELEMENT_TYPE_ENTRANCE:
typeName = language_get_string(STR_RIDE_CONSTRUCTION_ENTRANCE);
break;
case TILE_ELEMENT_TYPE_WALL:
snprintf(
buffer, sizeof(buffer), "%s (%s)", language_get_string(STR_TILE_INSPECTOR_WALL),
language_get_string(tileElement->AsWall()->GetEntry()->name));
2018-06-22 23:21:44 +02:00
typeName = buffer;
break;
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
typeName = language_get_string(STR_OBJECT_SELECTION_LARGE_SCENERY);
break;
case TILE_ELEMENT_TYPE_BANNER:
snprintf(
buffer, sizeof(buffer), "%s (%d)", language_get_string(STR_BANNER_WINDOW_TITLE),
2018-09-26 14:07:04 +02:00
tileElement->AsBanner()->GetIndex());
2018-06-22 23:21:44 +02:00
typeName = buffer;
break;
case TILE_ELEMENT_TYPE_CORRUPT:
// fall-through
default:
snprintf(buffer, sizeof(buffer), "%s (%d)", language_get_string(STR_UNKNOWN_OBJECT_TYPE), type);
typeName = buffer;
}
const int32_t baseHeight = tileElement->base_height;
const int32_t clearanceHeight = tileElement->clearance_height;
2019-02-26 09:13:21 +01:00
const bool ghost = tileElement->IsGhost();
2019-02-26 11:09:58 +01:00
const bool last = tileElement->IsLastForTile();
2018-05-22 21:54:09 +02:00
const rct_string_id stringFormat = (selectedRow || hoveredRow) ? STR_WHITE_STRING : STR_WINDOW_COLOUR_2_STRINGID;
// Undo relative scroll offset, but keep the 3 pixel padding
screenCoords.x = -w->widgets[WIDX_LIST].left;
auto ft = Formatter();
ft.Add<rct_string_id>(STR_STRING);
ft.Add<char*>(typeName);
DrawTextEllipsised(
dpi, screenCoords + ScreenCoordsXY{ COL_X_TYPE + 3, 0 }, COL_X_BH, stringFormat, ft, COLOUR_BLACK); // 3px padding
// Base height
ft = Formatter();
ft.Add<rct_string_id>(STR_FORMAT_INTEGER);
ft.Add<int32_t>(baseHeight);
gfx_draw_string_left(dpi, stringFormat, ft.Data(), COLOUR_BLACK, screenCoords + ScreenCoordsXY{ COL_X_BH, 0 });
// Clearance height
ft = Formatter();
ft.Add<rct_string_id>(STR_FORMAT_INTEGER);
ft.Add<int32_t>(clearanceHeight);
gfx_draw_string_left(dpi, stringFormat, ft.Data(), COLOUR_BLACK, screenCoords + ScreenCoordsXY{ COL_X_CH, 0 });
// Checkmarks for ghost and last for tile
ft = Formatter();
ft.Add<rct_string_id>(STR_STRING);
ft.Add<char*>(CheckBoxMarkString);
if (ghost)
{
gfx_draw_string_left(dpi, stringFormat, ft.Data(), COLOUR_BLACK, screenCoords + ScreenCoordsXY{ COL_X_GF, 0 });
}
if (last)
{
gfx_draw_string_left(dpi, stringFormat, ft.Data(), COLOUR_BLACK, screenCoords + ScreenCoordsXY{ COL_X_LF, 0 });
}
screenCoords.y -= SCROLLABLE_ROW_HEIGHT;
i++;
} while (!(tileElement++)->IsLastForTile());
}