1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-24 07:14:31 +01:00
Files
OpenRCT2/src/openrct2-ui/windows/TileInspector.cpp
Hielke Morsink 55979a3fff Remove and replace C typedefs
`typedef struct/union/enum name { ... } name_again;` is not needed whe compiling C++, moving the name at the back to be in front of the object and removing `typedef` makes it usable the very same way.
This also replaces typedefs with the using keyword. They have better readability, especially for function pointer types, and would allow more flexibility when used with templates.
2018-02-14 09:42:26 +01:00

2086 lines
105 KiB
C++

#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#include <openrct2-ui/windows/Window.h>
#include <openrct2/common.h>
#include <openrct2/core/Guard.hpp>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Util.hpp>
#include <openrct2/Game.h>
#include <openrct2/Input.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/localisation/Localisation.h>
#include <openrct2/localisation/StringIds.h>
#include <openrct2/ride/RideData.h>
#include <openrct2/ride/Track.h>
#include <openrct2/sprites.h>
#include <openrct2-ui/interface/Dropdown.h>
#include <openrct2/windows/tile_inspector.h>
#include <openrct2/world/Footpath.h>
#include <openrct2/world/LargeScenery.h>
#include <openrct2/world/Scenery.h>
#include <openrct2/world/SmallScenery.h>
#include <openrct2/world/TileInspector.h>
static constexpr const rct_string_id TerrainTypeStringIds[] = {
STR_TILE_INSPECTOR_TERRAIN_GRASS,
STR_TILE_INSPECTOR_TERRAIN_SAND,
STR_TILE_INSPECTOR_TERRAIN_DIRT,
STR_TILE_INSPECTOR_TERRAIN_ROCK,
STR_TILE_INSPECTOR_TERRAIN_MARTIAN,
STR_TILE_INSPECTOR_TERRAIN_CHECKERBOARD,
STR_TILE_INSPECTOR_TERRAIN_GRASS_CLUMPS,
STR_TILE_INSPECTOR_TERRAIN_ICE,
STR_TILE_INSPECTOR_TERRAIN_GRID_RED,
STR_TILE_INSPECTOR_TERRAIN_GRID_YELLOW,
STR_TILE_INSPECTOR_TERRAIN_GRID_BLUE,
STR_TILE_INSPECTOR_TERRAIN_GRID_GREEN,
STR_TILE_INSPECTOR_TERRAIN_SAND_DARK,
STR_TILE_INSPECTOR_TERRAIN_SAND_LIGHT,
STR_TILE_INSPECTOR_TERRAIN_CHECKERBOARD_INVERTED,
STR_TILE_INSPECTOR_TERRAIN_UNDERGROUND_VIEW,
};
static constexpr const rct_string_id TerrainEdgeTypeStringIds[] = {
STR_TILE_INSPECTOR_TERRAIN_EDGE_ROCK,
STR_TILE_INSPECTOR_TERRAIN_EDGE_WOOD_RED,
STR_TILE_INSPECTOR_TERRAIN_EDGE_WOOD_BLACK,
STR_TILE_INSPECTOR_TERRAIN_EDGE_ICE,
STR_TILE_INSPECTOR_TERRAIN_EDGE_BRICK,
STR_TILE_INSPECTOR_TERRAIN_EDGE_IRON,
STR_TILE_INSPECTOR_TERRAIN_EDGE_GREY,
STR_TILE_INSPECTOR_TERRAIN_EDGE_YELLOW,
STR_TILE_INSPECTOR_TERRAIN_EDGE_RED,
STR_TILE_INSPECTOR_TERRAIN_EDGE_PURPLE,
STR_TILE_INSPECTOR_TERRAIN_EDGE_GREEN,
STR_TILE_INSPECTOR_TERRAIN_EDGE_STONE_BROWN,
STR_TILE_INSPECTOR_TERRAIN_EDGE_STONE_GREY,
STR_TILE_INSPECTOR_TERRAIN_EDGE_SKYSCRAPER_A,
STR_TILE_INSPECTOR_TERRAIN_EDGE_SKYSCRAPER_B,
};
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
};
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_DOWN,
WIDX_BUTTON_MOVE_UP,
WIDX_BUTTON_ROTATE,
WIDX_BUTTON_SORT,
WIDX_BUTTON_COPY,
WIDX_BUTTON_PASTE,
WIDX_COLUMN_TYPE,
WIDX_COLUMN_BASEHEIGHT,
WIDX_COLUMN_CLEARANCEHEIGHT,
WIDX_COLUMN_GHOSTFLAG,
WIDX_COLUMN_BROKENFLAG,
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_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,
// 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,
// 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,
};
// Window sizes
#define WW 400
#define WH 280
#define MIN_WW WW
#define MAX_WW WW
#define MIN_WH 240
#define MAX_WH 800
// Button space for top buttons
#define BW (WW - 5) // Button's right side
#define BX (BW - 23) // Button's left side
#define BY 17 // Button's Top
#define BH (BY + 23) // Button's Bottom
#define BS 24
// Column offsets for the table headers
#define COL_X_TYPE 3 // Type
#define COL_X_BH (COL_X_TYPE + 300) // Base height
#define COL_X_CH (COL_X_BH + 20) // Clearance height
#define COL_X_GF (COL_X_CH + 20) // Ghost flag
#define COL_X_BF (COL_X_GF + 12) // Broken flag
#define COL_X_LF (COL_X_BF + 12) // Last for tile flag
#define PADDING_BOTTOM 15
#define GROUPBOX_PADDING 6
#define HORIZONTAL_GROUPBOX_PADDING 5
#define VERTICAL_GROUPBOX_PADDING 4
#define LIST_ITEM_HEIGHT 11
#define BUTTONW 130
#define 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
// Spinners and dropdowns use the buttons as a reference
#define GBS(GBT, col, row) GBBL(col), GBBR(col), GBBT(GBT, row) + 3, GBBB(GBT, row) - 3 // Group box spinner / dropdown field
#define GBSI(GBT, col, row) GBBR(col) - 11, GBBR(col) - 1, GBBT(GBT, row) + 4, GBBT(GBT, row) + 8 // Group box spinner increase
#define GBSD(GBT, col, row) GBBR(col) - 11, GBBR(col) - 1, GBBB(GBT, row) - 8, GBBB(GBT, row) - 4 // Group box spinner decrease
#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 \
{ WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0xFFFFFFFF, STR_NONE }, /* panel / background */ \
{ WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_TILE_INSPECTOR_TITLE, STR_WINDOW_TITLE_TIP }, /* title bar */ \
{ WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, /* close x button */ \
{ WWT_SCROLL, 1, 3, WW - 4, 57, WH - PADDING_BOTTOM, 2, STR_NONE }, /* Element list */ \
{ WWT_SPINNER, 1, 20, 61, 23, 34, STR_NONE, STR_NONE }, /* Spinner for X */ \
{ WWT_BUTTON, 1, 51, 60, 24, 28, STR_NUMERIC_UP, STR_NONE }, /* increase X */ \
{ WWT_BUTTON, 1, 51, 60, 29, 33, STR_NUMERIC_DOWN, STR_NONE }, /* decrease X */ \
{ WWT_SPINNER, 1, 77, 118, 23, 34, STR_NONE, STR_NONE }, /* Spinner for Y */ \
{ WWT_BUTTON, 1, 108, 117, 24, 28, STR_NUMERIC_UP, STR_NONE }, /* increase Y */ \
{ WWT_BUTTON, 1, 108, 117, 29, 33, STR_NUMERIC_DOWN, STR_NONE }, /* decrease Y */ \
/* Buttons */ \
{ WWT_FLATBTN, 1, BX, BW, BY, BH, SPR_MAP, STR_INSERT_CORRUPT_TIP }, /* Insert corrupt button */ \
{ WWT_FLATBTN, 1, BX - BS * 1, BW - BS * 1, BY, BH, SPR_DEMOLISH, STR_REMOVE_SELECTED_ELEMENT_TIP }, /* Remove button */ \
{ WWT_BUTTON, 1, BX - BS * 2, BW - BS * 2, BY, BY + 11, STR_UP, STR_MOVE_SELECTED_ELEMENT_UP_TIP }, /* Move down */ \
{ WWT_BUTTON, 1, BX - BS * 2, BW - BS * 2, BH - 11, BH, STR_DOWN, STR_MOVE_SELECTED_ELEMENT_DOWN_TIP }, /* Move up */ \
{ WWT_FLATBTN, 1, BX - BS * 3, BW - BS * 3, BY, BH, SPR_ROTATE_ARROW, STR_ROTATE_SELECTED_ELEMENT_TIP }, /* Rotate button */ \
{ WWT_FLATBTN, 1, BX - BS * 4, BW - BS * 4, BY, BH, SPR_G2_SORT, STR_TILE_INSPECTOR_SORT_TIP }, /* Sort button */ \
{ WWT_FLATBTN, 1, BX - BS * 5, BW - BS * 5, BY, BH, SPR_G2_COPY, STR_TILE_INSPECTOR_COPY_TIP }, /* Copy button */ \
{ WWT_FLATBTN, 1, BX - BS * 6, BW - BS * 6, BY, BH, SPR_G2_PASTE, STR_TILE_INSPECTOR_PASTE_TIP }, /* Paste button */ \
/* Column headers */ \
{ WWT_TABLE_HEADER, 1, COL_X_TYPE, COL_X_BH - 1, 42, 42 + 13, STR_NONE, STR_NONE }, /* Type */ \
{ WWT_TABLE_HEADER, 1, COL_X_BH, COL_X_CH - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_BASE_HEIGHT }, /* Base height */ \
{ WWT_TABLE_HEADER, 1, COL_X_CH, COL_X_GF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_CLEARANCE_HEIGHT }, /* Clearance height */ \
{ WWT_TABLE_HEADER, 1, COL_X_GF, COL_X_BF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_GHOST }, /* Ghost flag */ \
{ WWT_TABLE_HEADER, 1, COL_X_BF, COL_X_LF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_BROKEN }, /* Broken flag */ \
{ WWT_TABLE_HEADER, 1, COL_X_LF, WW - 3, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_LAST }, /* Last of tile flag */ \
{ WWT_GROUPBOX, 1, 6, WW - 6, -1, -1, STR_NONE, STR_NONE }, /* Details group box */ \
{ WWT_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
#define SUR_GBPB PADDING_BOTTOM // Surface group box properties bottom
#define SUR_GBPT (SUR_GBPB + 16 + 4 * 21) // Surface group box properties top
#define SUR_GBDB (SUR_GBPT + GROUPBOX_PADDING) // Surface group box details bottom
#define SUR_GBDT (SUR_GBDB + 20 + 4 * 11) // Surface group box details top
static rct_widget SurfaceWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WWT_SPINNER, 1, GBS(WH - SUR_GBPT, 1, 0), STR_NONE, STR_NONE }, // WIDX_SURFACE_SPINNER_HEIGHT
{ WWT_BUTTON, 1, GBSI(WH - SUR_GBPT, 1, 0), STR_NUMERIC_UP, STR_NONE }, // WIDX_SURFACE_SPINNER_HEIGHT_INCREASE
{ WWT_BUTTON, 1, GBSD(WH - SUR_GBPT, 1, 0), STR_NUMERIC_DOWN, STR_NONE }, // WIDX_SURFACE_SPINNER_HEIGHT_DECREASE
{ WWT_BUTTON, 1, GBB(WH - SUR_GBPT, 0, 1), STR_TILE_INSPECTOR_SURFACE_REMOVE_FENCES, STR_NONE }, // WIDX_SURFACE_BUTTON_REMOVE_FENCES
{ WWT_BUTTON, 1, GBB(WH - SUR_GBPT, 1, 1), STR_TILE_INSPECTOR_SURFACE_RESTORE_FENCES, STR_NONE }, // WIDX_SURFACE_BUTTON_RESTORE_FENCES
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SUR_GBPT, 2) + 7 * 0), STR_NONE, STR_NONE }, // WIDX_SURFACE_CHECK_CORNER_N
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 2, GBBT(WH - SUR_GBPT, 2) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_SURFACE_CHECK_CORNER_E
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SUR_GBPT, 2) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_SURFACE_CHECK_CORNER_S
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 0, GBBT(WH - SUR_GBPT, 2) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_SURFACE_CHECK_CORNER_W
{ WWT_CHECKBOX, 1, GBBF(WH - SUR_GBPT, 0, 4), STR_TILE_INSPECTOR_SURFACE_DIAGONAL, STR_NONE }, // WIDX_SURFACE_CHECK_DIAGONAL
{ WIDGETS_END },
};
#define PAT_GBPB PADDING_BOTTOM // Path group box properties bottom
#define PAT_GBPT (PAT_GBPB + 16 + 4 * 21) // Path group box properties top
#define PAT_GBDB (PAT_GBPT + GROUPBOX_PADDING) // Path group box info bottom
#define PAT_GBDT (PAT_GBDB + 20 + 2 * 11) // Path group box info top
static rct_widget PathWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WWT_SPINNER, 1, GBS(WH - PAT_GBPT, 1, 0), STR_NONE, STR_NONE }, // WIDX_PATH_SPINNER_HEIGHT
{ WWT_BUTTON, 1, GBSI(WH - PAT_GBPT, 1, 0), STR_NUMERIC_UP, STR_NONE }, // WIDX_PATH_SPINNER_HEIGHT_INCREASE
{ WWT_BUTTON, 1, GBSD(WH - PAT_GBPT, 1, 0), STR_NUMERIC_DOWN, STR_NONE }, // WIDX_PATH_SPINNER_HEIGHT_DECREASE
{ WWT_CHECKBOX, 1, GBBF(WH - PAT_GBPT, 0, 1), STR_TILE_INSPECTOR_PATH_SLOPED, STR_NONE }, // WIDX_PATH_CHECK_SLOPED
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 3, GBBT(WH - PAT_GBPT, 2) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_NE
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 4, GBBT(WH - PAT_GBPT, 2) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_E
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 3, GBBT(WH - PAT_GBPT, 2) + 7 * 3), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_SE
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 2, GBBT(WH - PAT_GBPT, 2) + 7 * 4), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_S
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - PAT_GBPT, 2) + 7 * 3), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_SW
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 0, GBBT(WH - PAT_GBPT, 2) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_W
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - PAT_GBPT, 2) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_NW
{ WWT_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 },
};
#define TRA_GBPB PADDING_BOTTOM // Track group box properties bottom
#define TRA_GBPT (TRA_GBPB + 16 + 3 * 21) // Track group box properties top
#define TRA_GBDB (TRA_GBPT + GROUPBOX_PADDING) // Track group box info bottom
#define TRA_GBDT (TRA_GBDB + 20 + 5 * 11) // Track group box info top
static rct_widget TrackWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WWT_CHECKBOX, 1, GBBF(WH - TRA_GBPT, 0, 0), STR_TILE_INSPECTOR_TRACK_ENTIRE_TRACK_PIECE, STR_NONE }, // WIDX_TRACK_CHECK_APPLY_TO_ALL
{ WWT_SPINNER, 1, GBS(WH - TRA_GBPT, 1, 1), STR_NONE, STR_NONE }, // WIDX_TRACK_SPINNER_HEIGHT
{ WWT_BUTTON, 1, GBSI(WH - TRA_GBPT, 1, 1), STR_NUMERIC_UP, STR_NONE }, // WIDX_TRACK_SPINNER_HEIGHT_INCREASE
{ WWT_BUTTON, 1, GBSD(WH - TRA_GBPT, 1, 1), STR_NUMERIC_DOWN, STR_NONE }, // WIDX_TRACK_SPINNER_HEIGHT_DECREASE
{ WWT_CHECKBOX, 1, GBBF(WH - TRA_GBPT, 0, 2), STR_TILE_INSPECTOR_TRACK_CHAIN_LIFT, STR_NONE }, // WIDX_TRACK_CHECK_CHAIN_LIFT
{ WIDGETS_END },
};
#define SCE_GBPB PADDING_BOTTOM // Scenery group box properties bottom
#define SCE_GBPT (SCE_GBPB + 16 + 4 * 21) // Scenery group box properties top
#define SCE_GBDB (SCE_GBPT + GROUPBOX_PADDING) // Scenery group box info bottom
#define SCE_GBDT (SCE_GBDB + 20 + 3 * 11) // Scenery group box info top
static rct_widget SceneryWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WWT_SPINNER, 1, GBS(WH - SCE_GBPT, 1, 0), STR_NONE, STR_NONE }, // WIDX_SCENERY_SPINNER_HEIGHT
{ WWT_BUTTON, 1, GBSI(WH - SCE_GBPT, 1, 0), STR_NUMERIC_UP, STR_NONE }, // WIDX_SCENERY_SPINNER_HEIGHT_INCREASE
{ WWT_BUTTON, 1, GBSD(WH - SCE_GBPT, 1, 0), STR_NUMERIC_DOWN, STR_NONE }, // WIDX_SCENERY_SPINNER_HEIGHT_DECREASE
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SCE_GBPT, 1) + 7 * 0), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_QUARTER_N
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 2, GBBT(WH - SCE_GBPT, 1) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_QUARTER_E
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SCE_GBPT, 1) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_QUARTER_S
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 0, GBBT(WH - SCE_GBPT, 1) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_QUARTER_W
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SCE_GBPT, 2) + 7 * 0), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_COLLISION_N
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 2, GBBT(WH - SCE_GBPT, 2) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_COLLISION_E
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - SCE_GBPT, 2) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_SCENERY_CHECK_COLLISION_S
{ WWT_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 },
};
#define ENT_GBPB PADDING_BOTTOM // Entrance group box properties bottom
#define ENT_GBPT (ENT_GBPB + 16 + 2 * 21) // Entrance group box properties top
#define ENT_GBDB (ENT_GBPT + GROUPBOX_PADDING) // Entrance group box info bottom
#define ENT_GBDT (ENT_GBDB + 20 + 3 * 11) // Entrance group box info top
static rct_widget EntranceWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WWT_SPINNER, 1, GBS(WH - ENT_GBPT, 1, 0), STR_NONE, STR_NONE }, // WIDX_ENTRANCE_SPINNER_HEIGHT
{ WWT_BUTTON, 1, GBSI(WH - ENT_GBPT, 1, 0), STR_NUMERIC_UP, STR_NONE }, // WIDX_ENTRANCE_SPINNER_HEIGHT_INCREASE
{ WWT_BUTTON, 1, GBSD(WH - ENT_GBPT, 1, 0), STR_NUMERIC_DOWN, STR_NONE }, // WIDX_ENTRANCE_SPINNER_HEIGHT_DECREASE
{ WWT_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 },
};
#define WALL_GBPB PADDING_BOTTOM // Wall group box properties bottom
#define WALL_GBPT (WALL_GBPB + 16 + 2 * 21) // Wall group box properties top
#define WALL_GBDB (WALL_GBPT + GROUPBOX_PADDING) // Wall group box info bottom
#define WALL_GBDT (WALL_GBDB + 20 + 2 * 11) // Wall group box info top
static rct_widget WallWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WWT_SPINNER, 1, GBS(WH - WALL_GBPT, 1, 0), STR_NONE, STR_NONE }, // WIDX_WALL_SPINNER_HEIGHT
{ WWT_BUTTON, 1, GBSI(WH - WALL_GBPT, 1, 0), STR_NUMERIC_UP, STR_NONE }, // WIDX_WALL_SPINNER_HEIGHT_INCREASE
{ WWT_BUTTON, 1, GBSD(WH - WALL_GBPT, 1, 0), STR_NUMERIC_DOWN, STR_NONE }, // WIDX_WALL_SPINNER_HEIGHT_DECREASE
{ WWT_DROPDOWN, 1, GBS(WH - WALL_GBPT, 1, 1), STR_NONE, STR_NONE }, // WIDX_WALL_DROPDOWN_SLOPE
{ WWT_BUTTON, 1, GBDB(WH - WALL_GBPT, 1, 1), STR_DROPDOWN_GLYPH, STR_NONE }, // WIDX_WALL_DROPDOWN_SLOPE_BUTTON
{ WIDGETS_END },
};
#define LAR_GBPB PADDING_BOTTOM // Large scenery group box properties bottom
#define LAR_GBPT (LAR_GBPB + 16 + 1 * 21) // Large scenery group box properties top
#define LAR_GBDB (LAR_GBPT + GROUPBOX_PADDING) // Large scenery group box info bottom
#define LAR_GBDT (LAR_GBDB + 20 + 3 * 11) // Large scenery group box info top
static rct_widget LargeSceneryWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WWT_SPINNER, 1, GBS(WH - LAR_GBPT, 1, 0), STR_NONE, STR_NONE }, // WIDX_LARGE_SCENERY_SPINNER_HEIGHT
{ WWT_BUTTON, 1, GBSI(WH - LAR_GBPT, 1, 0), STR_NUMERIC_UP, STR_NONE }, // WIDX_LARGE_SCENERY_SPINNER_HEIGHT_INCREASE
{ WWT_BUTTON, 1, GBSD(WH - LAR_GBPT, 1, 0), STR_NUMERIC_DOWN, STR_NONE }, // WIDX_LARGE_SCENERY_SPINNER_HEIGHT_DECREASE
{ WIDGETS_END },
};
#define BAN_GBPB PADDING_BOTTOM // Banner group box properties bottom
#define BAN_GBPT (BAN_GBPB + 16 + 3 * 21) // Banner group box properties top
#define BAN_GBDB (BAN_GBPT + GROUPBOX_PADDING) // Banner group box info bottom
#define BAN_GBDT (BAN_GBDB + 20 + 1 * 11) // Banner group box info top
static rct_widget BannerWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WWT_SPINNER, 1, GBS(WH - BAN_GBPT, 1, 0), STR_NONE, STR_NONE }, // WIDX_BANNER_SPINNER_HEIGHT
{ WWT_BUTTON, 1, GBSI(WH - BAN_GBPT, 1, 0), STR_NUMERIC_UP, STR_NONE }, // WIDX_BANNER_SPINNER_HEIGHT_INCREASE
{ WWT_BUTTON, 1, GBSD(WH - BAN_GBPT, 1, 0), STR_NUMERIC_DOWN, STR_NONE }, // WIDX_BANNER_SPINNER_HEIGHT_DECREASE
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 3, GBBT(WH - BAN_GBPT, 1) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_BANNER_CHECK_BLOCK_NE
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 3, GBBT(WH - BAN_GBPT, 1) + 7 * 3), STR_NONE, STR_NONE }, // WIDX_BANNER_CHECK_BLOCK_SE
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - BAN_GBPT, 1) + 7 * 3), STR_NONE, STR_NONE }, // WIDX_BANNER_CHECK_BLOCK_SW
{ WWT_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 },
};
#define COR_GBPB PADDING_BOTTOM // Corrupt element group box properties bottom
#define COR_GBPT (COR_GBPB + 16 + 2 * 21) // Corrupt element group box properties top
#define COR_GBDB (COR_GBPT + GROUPBOX_PADDING) // Corrupt element group box info bottom
#define COR_GBDT (COR_GBDB + 20 + 0 * 11) // Corrupt element group box info top
static rct_widget CorruptWidgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WWT_SPINNER, 1, GBS(WH - COR_GBPT, 1, 0), STR_NONE, STR_NONE }, // WIDX_CORRUPT_SPINNER_HEIGHT
{ WWT_BUTTON, 1, GBSI(WH - COR_GBPT, 1, 0), STR_NUMERIC_UP, STR_NONE }, // WIDX_CORRUPT_SPINNER_HEIGHT_INCREASE
{ WWT_BUTTON, 1, GBSD(WH - COR_GBPT, 1, 0), STR_NUMERIC_DOWN, STR_NONE }, // WIDX_CORRUPT_SPINNER_HEIGHT_DECREASE
{ WWT_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
sint16 details_top_offset, details_bottom_offset;
sint16 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 }
};
static sint16 windowTileInspectorHighlightedIndex = -1;
static bool windowTileInspectorTileSelected = false;
static sint32 windowTileInspectorToolMouseX = 0;
static sint32 windowTileInspectorToolMouseY = 0;
static sint32 windowTileInspectorToolMapX = 0;
static sint32 windowTileInspectorToolMapY = 0;
static bool windowTileInspectorApplyToAll = false;
static bool windowTileInspectorElementCopied = false;
static rct_tile_element tileInspectorCopiedElement;
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, sint32 dropdownIndex);
static void window_tile_inspector_tool_update(rct_window* w, rct_widgetindex widgetIndex, sint32 x, sint32 y);
static void window_tile_inspector_update_selected_tile(rct_window *w, sint32 x, sint32 y);
static void window_tile_inspector_tool_down(rct_window* w, rct_widgetindex widgetIndex, sint32 x, sint32 y);
static void window_tile_inspector_tool_drag(rct_window* w, rct_widgetindex widgetIndex, sint32 x, sint32 y);
static void window_tile_inspector_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height);
static void window_tile_inspector_scrollmousedown(rct_window *w, sint32 scrollIndex, sint32 x, sint32 y);
static void window_tile_inspector_scrollmouseover(rct_window *w, sint32 scrollIndex, sint32 x, sint32 y);
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, sint32 scrollIndex);
static rct_window_event_list TileInspectorWindowEvents = {
nullptr,
window_tile_inspector_mouseup,
window_tile_inspector_resize,
window_tile_inspector_mousedown,
window_tile_inspector_dropdown,
nullptr,
window_tile_inspector_update,
nullptr,
nullptr,
window_tile_inspector_tool_update,
window_tile_inspector_tool_down,
window_tile_inspector_tool_drag,
nullptr,
nullptr,
nullptr,
window_tile_inspector_scrollgetsize,
window_tile_inspector_scrollmousedown,
nullptr,
window_tile_inspector_scrollmouseover,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
window_tile_inspector_invalidate,
window_tile_inspector_paint,
window_tile_inspector_scrollpaint
};
static uint64 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_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_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_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_COPY) | (1ULL << WIDX_LARGE_SCENERY_SPINNER_HEIGHT) | (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) | (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) | (1ULL << WIDX_CORRUPT_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_CORRUPT_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_CORRUPT_BUTTON_CLAMP),
};
static uint64 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),
};
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);
if (window != nullptr)
return window;
window = window_create(
0,
29,
WW,
WH,
&TileInspectorWindowEvents,
WC_TILE_INSPECTOR,
WF_RESIZABLE
);
window_tile_inspector_set_page(window, TILE_INSPECTOR_PAGE_DEFAULT);
window_init_scroll_widgets(window);
window->min_width = MIN_WW;
window->min_height = MIN_WH;
window->max_width = MAX_WW;
window->max_height = MAX_WH;
window->selected_list_item = -1;
windowTileInspectorTileSelected = false;
tool_set(window, WIDX_BACKGROUND, TOOL_CROSSHAIR);
window_tile_inspector_auto_set_buttons(window);
return window;
}
void window_tile_inspector_clear_clipboard()
{
windowTileInspectorElementCopied = false;
}
static rct_tile_element* window_tile_inspector_get_selected_element(rct_window *w)
{
openrct2_assert(w->selected_list_item >= 0 && w->selected_list_item < windowTileInspectorElementCount,
"Selected list item out of range");
return map_get_first_element_at(windowTileInspectorTileX, windowTileInspectorTileY) + w->selected_list_item;
}
static void window_tile_inspector_select_element_from_list(rct_window *w, sint32 index)
{
sint32 page;
if (index < 0 || index >= windowTileInspectorElementCount) {
w->selected_list_item = -1;
page = 0;
}
else {
w->selected_list_item = index;
// Get type of selected map element to select the correct page
rct_tile_element *const tileElement = window_tile_inspector_get_selected_element(w);
page = (Math::Min<uint32>(tile_element_get_type(tileElement), TILE_ELEMENT_TYPE_CORRUPT) >> 2) + 1;
}
window_tile_inspector_set_page(w, (TILE_INSPECTOR_PAGE)page);
// Enable/disable buttons
window_tile_inspector_auto_set_buttons(w);
window_invalidate(w);
}
static void window_tile_inspector_load_tile(rct_window* w)
{
rct_tile_element *element = map_get_first_element_at(windowTileInspectorTileX, windowTileInspectorTileY);
sint32 numItems = 0;
do {
numItems++;
} while (!tile_element_is_last_for_tile(element++));
windowTileInspectorElementCount = numItems;
// Set default page
window_tile_inspector_set_page(w, TILE_INSPECTOR_PAGE_DEFAULT);
// undo selection and buttons affecting it
w->selected_list_item = -1;
window_tile_inspector_auto_set_buttons(w);
w->scrolls[0].v_top = 0;
window_invalidate(w);
}
static void window_tile_inspector_insert_corrupt_element(sint32 elementIndex)
{
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount,
"elementIndex out of range");
game_do_command(
TILE_INSPECTOR_ANY_INSERT_CORRUPT,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
0,
0
);
}
static void window_tile_inspector_remove_element(sint32 elementIndex)
{
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount,
"elementIndex out of range");
game_do_command(
TILE_INSPECTOR_ANY_REMOVE,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
0,
0
);
}
static void window_tile_inspector_rotate_element(sint32 elementIndex)
{
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount,
"elementIndex out of range");
game_do_command(
TILE_INSPECTOR_ANY_ROTATE,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
0,
0
);
}
// Swap element with its parent
static void window_tile_inspector_swap_elements(sint16 first, sint16 second)
{
openrct2_assert(first >= 0 && first < windowTileInspectorElementCount,
"first out of range");
openrct2_assert(second >= 0 && second < windowTileInspectorElementCount,
"second out of range");
game_do_command(
TILE_INSPECTOR_ANY_SWAP,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
first,
GAME_COMMAND_MODIFY_TILE,
second,
0
);
}
static void window_tile_inspector_sort_elements()
{
openrct2_assert(windowTileInspectorTileSelected, "No tile selected");
game_do_command(
TILE_INSPECTOR_ANY_SORT,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
0,
GAME_COMMAND_MODIFY_TILE,
0,
0
);
}
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;
}
static void window_tile_inspector_paste_element(rct_window *w)
{
// Construct the data to send using the surface's properties
sint32 data[2];
memcpy(&data[0], &tileInspectorCopiedElement, 8);
assert_struct_size(data, sizeof(tileInspectorCopiedElement));
game_do_command(
TILE_INSPECTOR_ANY_PASTE,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
data[0],
GAME_COMMAND_MODIFY_TILE,
data[1],
0
);
}
static void window_tile_inspector_base_height_offset(sint16 elementIndex, sint8 heightOffset)
{
game_do_command(
TILE_INSPECTOR_ANY_BASE_HEIGHT_OFFSET,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
heightOffset,
0
);
}
static void window_tile_inspector_surface_show_park_fences(bool showFences)
{
game_do_command(
TILE_INSPECTOR_SURFACE_SHOW_PARK_FENCES,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
showFences,
GAME_COMMAND_MODIFY_TILE,
0,
0
);
}
static void window_tile_inspector_surface_toggle_corner(sint32 cornerIndex)
{
game_do_command(
TILE_INSPECTOR_SURFACE_TOGGLE_CORNER,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
cornerIndex,
GAME_COMMAND_MODIFY_TILE,
0,
0
);
}
static void window_tile_inspector_surface_toggle_diagonal()
{
game_do_command(
TILE_INSPECTOR_SURFACE_TOGGLE_DIAGONAL,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
0,
GAME_COMMAND_MODIFY_TILE,
0,
0
);
}
static void window_tile_inspector_path_set_sloped(sint32 elementIndex, bool sloped)
{
game_do_command(
TILE_INSPECTOR_PATH_SET_SLOPE,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
sloped,
0
);
}
static void window_tile_inspector_path_toggle_edge(sint32 elementIndex, sint32 cornerIndex)
{
openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount,
"elementIndex out of range");
openrct2_assert(cornerIndex >= 0 && cornerIndex < 8, "cornerIndex out of range");
game_do_command(
TILE_INSPECTOR_PATH_TOGGLE_EDGE,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
cornerIndex,
0
);
}
static void window_tile_inspector_entrance_make_usable(sint32 elementIndex)
{
Guard::ArgumentInRange(elementIndex, 0, windowTileInspectorElementCount - 1);
game_do_command(
TILE_INSPECTOR_ENTRANCE_MAKE_USABLE,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
0,
0
);
}
static void window_tile_inspector_wall_set_slope(sint32 elementIndex, sint32 slopeValue)
{
// Make sure only the correct bits are set
openrct2_assert((slopeValue & 0xC0) == slopeValue, "slopeValue doesn't match its mask");
game_do_command(
TILE_INSPECTOR_WALL_SET_SLOPE,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
slopeValue,
0
);
}
static void window_tile_inspector_track_block_height_offset(sint32 elementIndex, sint8 heightOffset)
{
game_do_command(
TILE_INSPECTOR_TRACK_BASE_HEIGHT_OFFSET,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
heightOffset,
0
);
}
static void window_tile_inspector_track_block_set_lift(sint32 elementIndex, bool entireTrackBlock, bool chain)
{
game_do_command(
TILE_INSPECTOR_TRACK_SET_CHAIN,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
entireTrackBlock,
chain
);
}
static void window_tile_inspector_quarter_tile_set(sint32 elementIndex, const sint32 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");
game_do_command(
TILE_INSPECTOR_SCENERY_SET_QUARTER_LOCATION,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
(quarterIndex - get_current_rotation()) & 3,
0
);
}
static void window_tile_inspector_toggle_quadrant_collosion(sint32 elementIndex, const sint32 quadrantIndex)
{
game_do_command(
TILE_INSPECTOR_SCENERY_SET_QUARTER_COLLISION,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
(quadrantIndex + 2 - get_current_rotation()) & 3,
0
);
}
static void window_tile_inspector_banner_toggle_block(sint32 elementIndex, sint32 edgeIndex)
{
openrct2_assert(edgeIndex >= 0 && edgeIndex < 4, "edgeIndex out of range");
// Make edgeIndex abstract
edgeIndex = (edgeIndex - get_current_rotation()) & 3;
game_do_command(
TILE_INSPECTOR_BANNER_TOGGLE_BLOCKING_EDGE,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
edgeIndex,
0
);
}
static void window_tile_inspector_clamp_corrupt(sint32 elementIndex)
{
game_do_command(
TILE_INSPECTOR_CORRUPT_CLAMP,
GAME_COMMAND_FLAG_APPLY,
windowTileInspectorTileX | (windowTileInspectorTileY << 8),
elementIndex,
GAME_COMMAND_MODIFY_TILE,
0,
0
);
}
static void window_tile_inspector_mouseup(rct_window *w, rct_widgetindex widgetIndex)
{
switch (widgetIndex) {
case WIDX_CLOSE:
tool_cancel();
window_close(w);
break;
case WIDX_SPINNER_X_INCREASE:
windowTileInspectorTileX = Math::Min<uint32>(windowTileInspectorTileX + 1, 255);
window_tile_inspector_load_tile(w);
window_tile_inspector_auto_set_buttons(w);
break;
case WIDX_SPINNER_X_DECREASE:
windowTileInspectorTileX = Math::Max<uint32>(windowTileInspectorTileX - 1, 0);
window_tile_inspector_load_tile(w);
window_tile_inspector_auto_set_buttons(w);
break;
case WIDX_SPINNER_Y_INCREASE:
windowTileInspectorTileY = Math::Min<uint32>(windowTileInspectorTileY + 1, 255);
window_tile_inspector_load_tile(w);
window_tile_inspector_auto_set_buttons(w);
break;
case WIDX_SPINNER_Y_DECREASE:
windowTileInspectorTileY = Math::Max<uint32>(windowTileInspectorTileY - 1, 0);
window_tile_inspector_load_tile(w);
window_tile_inspector_auto_set_buttons(w);
break;
case WIDX_BUTTON_CORRUPT:
window_tile_inspector_insert_corrupt_element(w->selected_list_item);
break;
case WIDX_BUTTON_REMOVE: {
sint32 nextItemToSelect = w->selected_list_item - 1;
window_tile_inspector_remove_element(w->selected_list_item);
window_tile_inspector_select_element_from_list(w, nextItemToSelect);
break;
}
case WIDX_BUTTON_ROTATE:
window_tile_inspector_rotate_element(w->selected_list_item);
break;
case WIDX_BUTTON_SORT:
window_tile_inspector_sort_elements();
break;
case WIDX_BUTTON_COPY:
window_tile_inspector_copy_element(w);
window_tile_inspector_auto_set_buttons(w);
window_invalidate(w);
break;
case WIDX_BUTTON_PASTE:
window_tile_inspector_paste_element(w);
break;
case WIDX_BUTTON_MOVE_DOWN:
window_tile_inspector_swap_elements(w->selected_list_item, w->selected_list_item + 1);
break;
case WIDX_BUTTON_MOVE_UP:
window_tile_inspector_swap_elements(w->selected_list_item - 1, w->selected_list_item);
break;
}
// Only element-specific widgets from now on
if (w->page == TILE_INSPECTOR_PAGE_DEFAULT) {
return;
}
// Get the selected map element
rct_tile_element *const tileElement = window_tile_inspector_get_selected_element(w);
// Page widgets
switch (w->page) {
case TILE_INSPECTOR_PAGE_SURFACE:
switch (widgetIndex) {
case WIDX_SURFACE_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, 1);
break;
case WIDX_SURFACE_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, -1);
break;
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;
case TILE_INSPECTOR_PAGE_PATH:
switch (widgetIndex) {
case WIDX_PATH_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, 1);
break;
case WIDX_PATH_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, -1);
break;
case WIDX_PATH_CHECK_SLOPED:
window_tile_inspector_path_set_sloped(w->selected_list_item, !footpath_element_is_sloped(tileElement));
break;
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 sint32 eswn = (widgetIndex - WIDX_PATH_CHECK_EDGE_E) / 2;
// Transform to world orientation
const sint32 index = (4 + eswn - get_current_rotation()) & 3;
window_tile_inspector_path_toggle_edge(w->selected_list_item, 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 sint32 neseswnw = (widgetIndex - WIDX_PATH_CHECK_EDGE_NE) / 2;
// Transform to world orientation
const sint32 index = (4 + neseswnw - get_current_rotation()) & 3;
window_tile_inspector_path_toggle_edge(w->selected_list_item, index);
break;
}
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_TRACK:
switch (widgetIndex) {
case WIDX_TRACK_CHECK_APPLY_TO_ALL:
windowTileInspectorApplyToAll ^= 1;
widget_invalidate(w, widgetIndex);
break;
case WIDX_TRACK_SPINNER_HEIGHT_INCREASE:
if (widget_is_pressed(w, WIDX_TRACK_CHECK_APPLY_TO_ALL)) {
window_tile_inspector_track_block_height_offset(w->selected_list_item, 1);
}
else {
window_tile_inspector_base_height_offset(w->selected_list_item, 1);
}
break;
case WIDX_TRACK_SPINNER_HEIGHT_DECREASE:
if (widget_is_pressed(w, WIDX_TRACK_CHECK_APPLY_TO_ALL)) {
window_tile_inspector_track_block_height_offset(w->selected_list_item, -1);
}
else {
window_tile_inspector_base_height_offset(w->selected_list_item, -1);
}
break;
case WIDX_TRACK_CHECK_CHAIN_LIFT:
{
bool entireTrackBlock = widget_is_pressed(w, WIDX_TRACK_CHECK_APPLY_TO_ALL);
bool newLift = !track_element_is_lift_hill(tileElement);
window_tile_inspector_track_block_set_lift(w->selected_list_item, entireTrackBlock, newLift);
break;
}
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_SCENERY:
switch (widgetIndex) {
case WIDX_SCENERY_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, 1);
break;
case WIDX_SCENERY_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, -1);
break;
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(w->selected_list_item, 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(w->selected_list_item, widgetIndex - WIDX_SCENERY_CHECK_COLLISION_N);
break;
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_ENTRANCE:
switch (widgetIndex) {
case WIDX_ENTRANCE_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, 1);
break;
case WIDX_ENTRANCE_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, -1);
break;
case WIDX_ENTRANCE_BUTTON_MAKE_USABLE:
window_tile_inspector_entrance_make_usable(w->selected_list_item);
break;
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_WALL:
switch (widgetIndex) {
case WIDX_WALL_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, 1);
break;
case WIDX_WALL_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, -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(w->selected_list_item, 1);
break;
case WIDX_LARGE_SCENERY_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, -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(w->selected_list_item, 1);
break;
case WIDX_BANNER_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, -1);
break;
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(w->selected_list_item, widgetIndex - WIDX_BANNER_CHECK_BLOCK_NE);
break;
} // switch widget index
break;
case TILE_INSPECTOR_PAGE_CORRUPT:
switch (widgetIndex) {
case WIDX_CORRUPT_SPINNER_HEIGHT_INCREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, 1);
break;
case WIDX_CORRUPT_SPINNER_HEIGHT_DECREASE:
window_tile_inspector_base_height_offset(w->selected_list_item, -1);
break;
case WIDX_CORRUPT_BUTTON_CLAMP:
window_tile_inspector_clamp_corrupt(w->selected_list_item);
break;
} // switch widget index
break;
} // switch page
}
static void window_tile_inspector_resize(rct_window *w)
{
w->min_width = WW;
w->min_height = MIN_WH;
if (w->width < w->min_width) {
window_invalidate(w);
w->width = w->min_width;
}
if (w->height < w->min_height) {
window_invalidate(w);
w->height = w->min_height;
}
}
static void window_tile_inspector_mousedown(rct_window *w, rct_widgetindex widgetIndex, rct_widget* widget)
{
switch (w->page) {
case TILE_INSPECTOR_PAGE_WALL:
switch (widgetIndex) {
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;
window_dropdown_show_text_custom_width(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1],
0,
DROPDOWN_FLAG_STAY_OPEN,
3,
widget->right - widget->left - 3
);
// Set current value as checked
rct_tile_element *const tileElement = window_tile_inspector_get_selected_element(w);
dropdown_set_checked((tileElement->type & 0xC0) >> 6, true);
break;
}
break;
}
}
static void window_tile_inspector_update(rct_window *w)
{
// Check if the mouse is hovering over the list
if (!widget_is_highlighted(w, WIDX_LIST)) {
windowTileInspectorHighlightedIndex = -1;
widget_invalidate(w, WIDX_LIST);
}
if (gCurrentToolWidget.window_classification != WC_TILE_INSPECTOR)
window_close(w);
}
static void window_tile_inspector_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex)
{
if (dropdownIndex == -1) {
return;
}
// Get selected element
rct_tile_element *const tileElement = window_tile_inspector_get_selected_element(w);
switch (w->page) {
case TILE_INSPECTOR_PAGE_WALL:
openrct2_assert(tile_element_get_type(tileElement) == TILE_ELEMENT_TYPE_WALL, "Element is not a wall");
switch (widgetIndex) {
case WIDX_WALL_DROPDOWN_SLOPE_BUTTON:
window_tile_inspector_wall_set_slope(w->selected_list_item, dropdownIndex << 6);
break;
}
break;
}
}
static void window_tile_inspector_tool_update(rct_window* w, rct_widgetindex widgetIndex, sint32 x, sint32 y)
{
map_invalidate_selection_rect();
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
sint16 mapX = x;
sint16 mapY = y;
sint32 direction;
screen_pos_to_map_pos(&mapX, &mapY, &direction);
if (mapX != LOCATION_NULL) {
gMapSelectPositionA.x = gMapSelectPositionB.x = mapX;
gMapSelectPositionA.y = gMapSelectPositionB.y = mapY;
}
else if (windowTileInspectorTileSelected){
gMapSelectPositionA.x = gMapSelectPositionB.x = windowTileInspectorTileX << 5;
gMapSelectPositionA.y = gMapSelectPositionB.y = windowTileInspectorTileY << 5;
}
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, sint32 x, sint32 y)
{
// Mouse hasn't moved
if (x == windowTileInspectorToolMouseX && y == windowTileInspectorToolMouseY) {
return;
}
windowTileInspectorToolMouseX = x;
windowTileInspectorToolMouseY = y;
sint16 mapX = x;
sint16 mapY = y;
sint32 direction;
screen_pos_to_map_pos(&mapX, &mapY, &direction);
if (mapX == LOCATION_NULL) {
return;
}
// Tile is already selected
if (windowTileInspectorTileSelected && mapX == windowTileInspectorToolMapX && mapY == windowTileInspectorToolMapY) {
return;
}
windowTileInspectorTileSelected = true;
windowTileInspectorToolMapX = mapX;
windowTileInspectorToolMapY = mapY;
windowTileInspectorTileX = mapX >> 5;
windowTileInspectorTileY = mapY >> 5;
window_tile_inspector_load_tile(w);
window_tile_inspector_auto_set_buttons(w);
}
static void window_tile_inspector_tool_down(rct_window* w, rct_widgetindex widgetIndex, sint32 x, sint32 y)
{
window_tile_inspector_update_selected_tile(w, x, y);
}
static void window_tile_inspector_tool_drag(rct_window* w, rct_widgetindex widgetIndex, sint32 x, sint32 y)
{
window_tile_inspector_update_selected_tile(w, x, y);
}
static void window_tile_inspector_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height)
{
*width = WW - 30;
*height = windowTileInspectorElementCount * LIST_ITEM_HEIGHT;
}
void window_tile_inspector_set_page(rct_window *w, const TILE_INSPECTOR_PAGE page)
{
w->page = page;
w->widgets = PageWidgets[page];
w->enabled_widgets = PageEnabledWidgets[page];
w->disabled_widgets = PageDisabledWidgets[page];
}
void window_tile_inspector_auto_set_buttons(rct_window *w)
{
// X and Y spinners
widget_set_enabled(w, WIDX_SPINNER_X_INCREASE, (windowTileInspectorTileSelected && (windowTileInspectorTileX < 255)));
widget_set_enabled(w, WIDX_SPINNER_X_DECREASE, (windowTileInspectorTileSelected && (windowTileInspectorTileX > 0)));
widget_set_enabled(w, WIDX_SPINNER_Y_INCREASE, (windowTileInspectorTileSelected && (windowTileInspectorTileY < 255)));
widget_set_enabled(w, WIDX_SPINNER_Y_DECREASE, (windowTileInspectorTileSelected && (windowTileInspectorTileY > 0)));
// Sort buttons
widget_set_enabled(w, WIDX_BUTTON_SORT, (windowTileInspectorTileSelected && windowTileInspectorElementCount > 1));
// Move Up button
widget_set_enabled(w, WIDX_BUTTON_MOVE_UP, (w->selected_list_item > 0));
widget_invalidate(w, WIDX_BUTTON_MOVE_UP);
// Move Down button
widget_set_enabled(w, WIDX_BUTTON_MOVE_DOWN, (w->selected_list_item != -1 && w->selected_list_item < windowTileInspectorElementCount - 1));
widget_invalidate(w, WIDX_BUTTON_MOVE_DOWN);
// Copy button
widget_set_enabled(w, WIDX_BUTTON_COPY, w->selected_list_item >= 0);
widget_invalidate(w, WIDX_BUTTON_COPY);
// Paste button
widget_set_enabled(w, WIDX_BUTTON_PASTE, windowTileInspectorTileSelected && windowTileInspectorElementCopied);
widget_invalidate(w, WIDX_BUTTON_PASTE);
// Page widgets
switch (w->page) {
case TILE_INSPECTOR_PAGE_WALL: {
const rct_tile_element *const tileElement = window_tile_inspector_get_selected_element(w);
const uint8 wallType = tileElement->properties.wall.type;
const rct_wall_scenery_entry wallEntry = get_wall_entry(wallType)->wall;
const bool canBeSloped = !(wallEntry.flags & WALL_SCENERY_CANT_BUILD_ON_SLOPE);
// Wall slope dropdown
widget_set_enabled(w, WIDX_WALL_DROPDOWN_SLOPE, canBeSloped);
widget_invalidate(w, WIDX_WALL_DROPDOWN_SLOPE);
widget_set_enabled(w, WIDX_WALL_DROPDOWN_SLOPE_BUTTON, canBeSloped);
widget_invalidate(w, WIDX_WALL_DROPDOWN_SLOPE_BUTTON);
break;
}
} // switch page
}
static void window_tile_inspector_scrollmousedown(rct_window *w, sint32 scrollIndex, sint32 x, sint32 y)
{
// Because the list items are displayed in reverse order, subtract the calculated index from the amount of elements
const sint16 index = windowTileInspectorElementCount - (y - 1) / LIST_ITEM_HEIGHT - 1;
window_tile_inspector_select_element_from_list(w, index);
}
static void window_tile_inspector_scrollmouseover(rct_window *w, sint32 scrollIndex, sint32 x, sint32 y)
{
sint16 index = windowTileInspectorElementCount - (y - 1) / LIST_ITEM_HEIGHT - 1;
if (index < 0 || index >= windowTileInspectorElementCount)
windowTileInspectorHighlightedIndex = -1;
else
windowTileInspectorHighlightedIndex = index;
widget_invalidate(w, WIDX_LIST);
}
static void window_tile_inspector_invalidate(rct_window *w)
{
w->widgets[WIDX_BACKGROUND].bottom = w->height - 1;
if (w->page == TILE_INSPECTOR_PAGE_DEFAULT) {
w->widgets[WIDX_GROUPBOX_DETAILS].type = WWT_EMPTY;
w->widgets[WIDX_GROUPBOX_PROPERTIES].type = WWT_EMPTY;
w->widgets[WIDX_LIST].bottom = w->height - PADDING_BOTTOM;
}
else {
w->widgets[WIDX_GROUPBOX_DETAILS].type = WWT_GROUPBOX;
w->widgets[WIDX_GROUPBOX_PROPERTIES].type = WWT_GROUPBOX;
w->widgets[WIDX_GROUPBOX_DETAILS].image = 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;
}
// Only page-specific widgets related to the map element will be
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 sint32 propertiesAnchor = w->widgets[WIDX_GROUPBOX_PROPERTIES].top;
rct_tile_element *const tileElement = window_tile_inspector_get_selected_element(w);
switch (w->page) {
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 = GBBT(propertiesAnchor, 0) + 8;
w->widgets[WIDX_SURFACE_SPINNER_HEIGHT_DECREASE].top = GBBB(propertiesAnchor, 0) - 8;
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;
widget_set_checkbox_value(w, WIDX_SURFACE_CHECK_CORNER_N, tileElement->properties.surface.slope & (1 << ((2 - get_current_rotation()) & 3)));
widget_set_checkbox_value(w, WIDX_SURFACE_CHECK_CORNER_E, tileElement->properties.surface.slope & (1 << ((3 - get_current_rotation()) & 3)));
widget_set_checkbox_value(w, WIDX_SURFACE_CHECK_CORNER_S, tileElement->properties.surface.slope & (1 << ((0 - get_current_rotation()) & 3)));
widget_set_checkbox_value(w, WIDX_SURFACE_CHECK_CORNER_W, tileElement->properties.surface.slope & (1 << ((1 - get_current_rotation()) & 3)));
widget_set_checkbox_value(w, WIDX_SURFACE_CHECK_DIAGONAL, tileElement->properties.surface.slope & TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT);
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 = GBBT(propertiesAnchor, 0) + 8;
w->widgets[WIDX_PATH_SPINNER_HEIGHT_DECREASE].top = GBBB(propertiesAnchor, 0) - 8;
w->widgets[WIDX_PATH_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
w->widgets[WIDX_PATH_CHECK_SLOPED].top = GBBT(propertiesAnchor, 1) + 2;
w->widgets[WIDX_PATH_CHECK_SLOPED].bottom = GBBT(propertiesAnchor, 1) + 15;
w->widgets[WIDX_PATH_CHECK_EDGE_N].top = GBBT(propertiesAnchor, 2) + 7 * 0;
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, 2) + 7 * 1;
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, 2) + 7 * 2;
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, 2) + 7 * 3;
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, 2) + 7 * 4;
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, 2) + 7 * 3;
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, 2) + 7 * 2;
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, 2) + 7 * 1;
w->widgets[WIDX_PATH_CHECK_EDGE_NW].bottom = w->widgets[WIDX_PATH_CHECK_EDGE_NW].top + 13;
widget_set_checkbox_value(w, WIDX_PATH_CHECK_SLOPED, footpath_element_is_sloped(tileElement));
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_NE, tileElement->properties.path.edges & (1 << ((0 - get_current_rotation()) & 3)));
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_SE, tileElement->properties.path.edges & (1 << ((1 - get_current_rotation()) & 3)));
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_SW, tileElement->properties.path.edges & (1 << ((2 - get_current_rotation()) & 3)));
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_NW, tileElement->properties.path.edges & (1 << ((3 - get_current_rotation()) & 3)));
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_E, tileElement->properties.path.edges & (1 << (4 + ((0 - get_current_rotation()) & 3))));
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_S, tileElement->properties.path.edges & (1 << (4 + ((1 - get_current_rotation()) & 3))));
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_W, tileElement->properties.path.edges & (1 << (4 + ((2 - get_current_rotation()) & 3))));
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_N, tileElement->properties.path.edges & (1 << (4 + ((3 - get_current_rotation()) & 3))));
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 = GBBT(propertiesAnchor, 1) + 8;
w->widgets[WIDX_TRACK_SPINNER_HEIGHT_DECREASE].top = GBBB(propertiesAnchor, 1) - 8;
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);
widget_set_checkbox_value(w, WIDX_TRACK_CHECK_APPLY_TO_ALL, windowTileInspectorApplyToAll);
widget_set_checkbox_value(w, WIDX_TRACK_CHECK_CHAIN_LIFT, track_element_is_lift_hill(tileElement));
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 = GBBT(propertiesAnchor, 0) + 8;
w->widgets[WIDX_SCENERY_SPINNER_HEIGHT_DECREASE].top = GBBB(propertiesAnchor, 0) - 8;
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->type & TILE_ELEMENT_QUADRANT_MASK) == ((0 - get_current_rotation()) & 3) << 6;
bool E = (tileElement->type & TILE_ELEMENT_QUADRANT_MASK) == ((1 - get_current_rotation()) & 3) << 6;
bool S = (tileElement->type & TILE_ELEMENT_QUADRANT_MASK) == ((2 - get_current_rotation()) & 3) << 6;
bool W = (tileElement->type & TILE_ELEMENT_QUADRANT_MASK) == ((3 - get_current_rotation()) & 3) << 6;
widget_set_checkbox_value(w, WIDX_SCENERY_CHECK_QUARTER_N, N);
widget_set_checkbox_value(w, WIDX_SCENERY_CHECK_QUARTER_E, E);
widget_set_checkbox_value(w, WIDX_SCENERY_CHECK_QUARTER_S, S);
widget_set_checkbox_value(w, WIDX_SCENERY_CHECK_QUARTER_W, W);
// 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;
N = (tileElement->flags & (1 << ((2 - get_current_rotation()) & 3))) != 0;
E = (tileElement->flags & (1 << ((3 - get_current_rotation()) & 3))) != 0;
S = (tileElement->flags & (1 << ((0 - get_current_rotation()) & 3))) != 0;
W = (tileElement->flags & (1 << ((1 - get_current_rotation()) & 3))) != 0;
widget_set_checkbox_value(w, WIDX_SCENERY_CHECK_COLLISION_N, N);
widget_set_checkbox_value(w, WIDX_SCENERY_CHECK_COLLISION_E, E);
widget_set_checkbox_value(w, WIDX_SCENERY_CHECK_COLLISION_S, S);
widget_set_checkbox_value(w, WIDX_SCENERY_CHECK_COLLISION_W, W);
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 = GBBT(propertiesAnchor, 0) + 8;
w->widgets[WIDX_ENTRANCE_SPINNER_HEIGHT_DECREASE].top = GBBB(propertiesAnchor, 0) - 8;
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);
widget_set_enabled(w, WIDX_ENTRANCE_BUTTON_MAKE_USABLE, tileElement->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE);
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 = GBBT(propertiesAnchor, 0) + 8;
w->widgets[WIDX_WALL_SPINNER_HEIGHT_DECREASE].top = GBBB(propertiesAnchor, 0) - 8;
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->type & 0xC0) >> 6];
w->widgets[WIDX_WALL_DROPDOWN_SLOPE_BUTTON].top = GBBT(propertiesAnchor, 1) + 4;
w->widgets[WIDX_WALL_DROPDOWN_SLOPE_BUTTON].bottom = GBBB(propertiesAnchor, 1) - 4;
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 = GBBT(propertiesAnchor, 0) + 8;
w->widgets[WIDX_LARGE_SCENERY_SPINNER_HEIGHT_DECREASE].top = GBBB(propertiesAnchor, 0) - 8;
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 = GBBT(propertiesAnchor, 0) + 8;
w->widgets[WIDX_BANNER_SPINNER_HEIGHT_DECREASE].top = GBBB(propertiesAnchor, 0) - 8;
w->widgets[WIDX_BANNER_SPINNER_HEIGHT_DECREASE].bottom = GBBB(propertiesAnchor, 0) - 4;
widget_set_checkbox_value(w, WIDX_BANNER_CHECK_BLOCK_NE, !(tileElement->properties.banner.flags & (1 << ((0 - get_current_rotation()) & 3))));
widget_set_checkbox_value(w, WIDX_BANNER_CHECK_BLOCK_SE, !(tileElement->properties.banner.flags & (1 << ((1 - get_current_rotation()) & 3))));
widget_set_checkbox_value(w, WIDX_BANNER_CHECK_BLOCK_SW, !(tileElement->properties.banner.flags & (1 << ((2 - get_current_rotation()) & 3))));
widget_set_checkbox_value(w, WIDX_BANNER_CHECK_BLOCK_NW, !(tileElement->properties.banner.flags & (1 << ((3 - get_current_rotation()) & 3))));
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 = GBBT(propertiesAnchor, 0) + 8;
w->widgets[WIDX_CORRUPT_SPINNER_HEIGHT_DECREASE].top = GBBB(propertiesAnchor, 0) - 8;
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;
}
}
static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
window_draw_widgets(w, dpi);
// Set medium font size
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
// Draw column headers
rct_widget *widget;
if ((widget = &w->widgets[WIDX_COLUMN_TYPE])->type != WWT_EMPTY) {
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_ELEMENT_TYPE, gCommonFormatArgs, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
if ((widget = &w->widgets[WIDX_COLUMN_BASEHEIGHT])->type != WWT_EMPTY) {
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT, gCommonFormatArgs, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
if ((widget = &w->widgets[WIDX_COLUMN_CLEARANCEHEIGHT])->type != WWT_EMPTY) {
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT, gCommonFormatArgs, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
if ((widget = &w->widgets[WIDX_COLUMN_GHOSTFLAG])->type != WWT_EMPTY) {
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_FLAG_GHOST_SHORT, gCommonFormatArgs, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
if ((widget = &w->widgets[WIDX_COLUMN_BROKENFLAG])->type != WWT_EMPTY) {
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_FLAG_BROKEN_SHORT, gCommonFormatArgs, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
if ((widget = &w->widgets[WIDX_COLUMN_LASTFLAG])->type != WWT_EMPTY) {
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_FLAG_LAST_SHORT, gCommonFormatArgs, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
// Draw coordinates
gfx_draw_string(dpi, (char *)"X:", COLOUR_DARK_GREEN, w->x + 6, w->y + 24);
gfx_draw_string(dpi, (char *)"Y:", COLOUR_DARK_GREEN, w->x + 64, w->y + 24);
if (windowTileInspectorTileSelected) {
gfx_draw_string_right(dpi, STR_FORMAT_INTEGER, &windowTileInspectorTileX, COLOUR_DARK_GREEN, w->x + 48, w->y + 24);
gfx_draw_string_right(dpi, STR_FORMAT_INTEGER, &windowTileInspectorTileY, COLOUR_DARK_GREEN, w->x + 105, w->y + 24);
}
else {
gfx_draw_string(dpi, (char *)"-", COLOUR_DARK_GREEN, w->x + 48 - 7, w->y + 24);
gfx_draw_string(dpi, (char *)"-", COLOUR_DARK_GREEN, w->x + 105 - 7, w->y + 24);
}
if (w->selected_list_item != -1) {
// X and Y of first element in detail box
sint32 x = w->x + w->widgets[WIDX_GROUPBOX_DETAILS].left + 7;
sint32 y = w->y + w->widgets[WIDX_GROUPBOX_DETAILS].top + 14;
// Get map element
rct_tile_element *const tileElement = window_tile_inspector_get_selected_element(w);
switch (w->page) {
case TILE_INSPECTOR_PAGE_SURFACE: {
// Details
// Terrain texture name
rct_string_id terrainNameId = TerrainTypeStringIds[tile_element_get_terrain(tileElement)];
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SURFACE_TERAIN, &terrainNameId, COLOUR_DARK_GREEN, x, y);
// Edge texture name
sint32 idx = tile_element_get_terrain_edge(tileElement);
openrct2_assert((uint32)idx < Util::CountOf(TerrainEdgeTypeStringIds), "Tried accessing invalid entry %d in terrainEdgeTypeStringIds", idx);
rct_string_id terrainEdgeNameId = TerrainEdgeTypeStringIds[tile_element_get_terrain_edge(tileElement)];
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SURFACE_EDGE, &terrainEdgeNameId, COLOUR_DARK_GREEN, x, y + 11);
// Land ownership
rct_string_id landOwnership;
if (tileElement->properties.surface.ownership & OWNERSHIP_OWNED) landOwnership = STR_LAND_OWNED;
else if (tileElement->properties.surface.ownership & OWNERSHIP_AVAILABLE) landOwnership = STR_LAND_SALE;
else if (tileElement->properties.surface.ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED) landOwnership = STR_CONSTRUCTION_RIGHTS_OWNED;
else if (tileElement->properties.surface.ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE) 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_DARK_GREEN, x, y + 22);
// Water level
sint32 waterLevel = map_get_water_height(tileElement);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SURFACE_WATER_LEVEL, &waterLevel, COLOUR_DARK_GREEN, x, y + 33);
// Properties
// Raise / lower label
x = w->x + w->widgets[WIDX_GROUPBOX_DETAILS].left + 7;
y = w->y + w->widgets[WIDX_SURFACE_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_DARK_GREEN, x, y);
// Current base height
x = w->x + w->widgets[WIDX_SURFACE_SPINNER_HEIGHT].left + 3;
sint32 baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_DARK_GREEN, x, y);
// Raised corners
x = w->x + w->widgets[WIDX_GROUPBOX_DETAILS].left + 7;
y = w->y + w->widgets[WIDX_SURFACE_CHECK_CORNER_E].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SURFACE_CORNERS, nullptr, COLOUR_DARK_GREEN, x, y);
break;
}
case TILE_INSPECTOR_PAGE_PATH: {
// Details
// Path name
rct_string_id pathNameId = get_footpath_entry(footpath_element_get_type(tileElement))->string_idx;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_PATH_NAME, &pathNameId, COLOUR_DARK_GREEN, x, y);
// Path addition
if (footpath_element_has_path_scenery(tileElement)) {
const uint8 pathAdditionType = footpath_element_get_path_scenery_index(tileElement);
rct_string_id additionNameId = get_footpath_item_entry(pathAdditionType)->name;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_PATH_ADDITIONS, &additionNameId, COLOUR_DARK_GREEN, x, y + 11);
}
else
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_PATH_ADDITIONS_NONE, nullptr, COLOUR_DARK_GREEN, x, y + 11);
// Properties
// Raise / lower label
x = w->x + w->widgets[WIDX_GROUPBOX_DETAILS].left + 7;
y = w->y + w->widgets[WIDX_PATH_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_DARK_GREEN, x, y);
// Current base height
x = w->x + w->widgets[WIDX_PATH_SPINNER_HEIGHT].left + 3;
sint32 baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_DARK_GREEN, x, y);
// Path connections
x = w->x + w->widgets[WIDX_GROUPBOX_DETAILS].left + 7;
y = w->y + w->widgets[WIDX_PATH_CHECK_EDGE_W].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_PATH_CONNECTED_EDGES, nullptr, COLOUR_DARK_GREEN, x, y);
break;
}
case TILE_INSPECTOR_PAGE_TRACK: {
// Details
// Ride
sint16 rideId = track_element_get_ride_index(tileElement);
Ride *ride = get_ride(rideId);
rct_string_id rideType = RideNaming[ride->type].name;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_TRACK_RIDE_TYPE, &rideType, COLOUR_DARK_GREEN, x, y);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_TRACK_RIDE_ID, &rideId, COLOUR_DARK_GREEN, x, y + 11);
set_format_arg(0, rct_string_id, ride->name);
set_format_arg(0 + sizeof(rct_string_id), uint32, ride->name_arguments);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_TRACK_RIDE_NAME, gCommonFormatArgs, COLOUR_DARK_GREEN, x, y + 22);
// Track
sint16 trackType = track_element_get_type(tileElement);
sint16 sequenceNumber = tile_element_get_track_sequence(tileElement);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_TRACK_PIECE_ID, &trackType, COLOUR_DARK_GREEN, x, y + 33);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_TRACK_SEQUENCE, &sequenceNumber, COLOUR_DARK_GREEN, x, y + 44);
// Properties
// Raise / lower label
y = w->y + w->widgets[WIDX_TRACK_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_DARK_GREEN, x, y);
// Current base height
x = w->x + w->widgets[WIDX_TRACK_SPINNER_HEIGHT].left + 3;
sint32 baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_DARK_GREEN, x, y);
break;
}
case TILE_INSPECTOR_PAGE_SCENERY: {
// Details
// Age
sint16 age = tileElement->properties.scenery.age;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SCENERY_AGE, &age, COLOUR_DARK_GREEN, x, y);
// Quadrant value
const rct_scenery_entry * sceneryEntry = get_small_scenery_entry(tileElement->properties.scenery.type);
if (!(scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_FULL_TILE)))
{
sint16 quadrant = (tileElement->type & TILE_ELEMENT_QUADRANT_MASK) >> 6;
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_DARK_GREEN, x, y + 11);
}
// Scenery ID
sint16 idx = tileElement->properties.scenery.type;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SCENERY_ENTRY_IDX, &idx, COLOUR_DARK_GREEN, x, y + 22);
// Properties
// Raise / Lower
y = w->y + w->widgets[WIDX_SCENERY_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_DARK_GREEN, x, y);
// Current base height
x = w->x + w->widgets[WIDX_SCENERY_SPINNER_HEIGHT].left + 3;
sint32 baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_DARK_GREEN, x, y);
// Quarter tile
x = w->x + w->widgets[WIDX_GROUPBOX_DETAILS].left + 7;
y = w->y + w->widgets[WIDX_SCENERY_CHECK_QUARTER_E].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SCENERY_QUADRANT_LABEL, nullptr, COLOUR_DARK_GREEN, x, y);
// Collision
y = w->y + w->widgets[WIDX_SCENERY_CHECK_COLLISION_E].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_COLLISSION, nullptr, COLOUR_DARK_GREEN, x, y);
break;
}
case TILE_INSPECTOR_PAGE_ENTRANCE: {
// Details
// Entrance type
rct_string_id entranceType = EntranceTypeStringIds[tileElement->properties.entrance.type];
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRANCE_TYPE, &entranceType, COLOUR_DARK_GREEN, x, y);
if (tileElement->properties.entrance.type == ENTRANCE_TYPE_PARK_ENTRANCE) {
// Park entrance ID
sint32 middleX = windowTileInspectorTileX << 5;
sint32 middleY = windowTileInspectorTileY << 5;
// TODO: Make this work with Left/Right park entrance parts
sint16 parkEntranceIndex = park_entrance_get_index(middleX, middleY, tileElement->base_height * 8);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRANCE_ENTRANCE_ID, &parkEntranceIndex, COLOUR_DARK_GREEN, x, y + 11);
}
else {
sint16 rideEntranceIndex = (tileElement->properties.entrance.index & 0x30) >> 4;
if (tileElement->properties.entrance.type == ENTRANCE_TYPE_RIDE_ENTRANCE) {
// Ride entrance ID
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRANCE_ENTRANCE_ID, &rideEntranceIndex, COLOUR_DARK_GREEN, x, y + 11);
}
else {
// Ride exit ID
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRANCE_EXIT_ID, &rideEntranceIndex, COLOUR_DARK_GREEN, x, y + 11);
}
}
if (tileElement->properties.entrance.type == ENTRANCE_TYPE_PARK_ENTRANCE) {
// Entrance part
rct_string_id entrancePart = ParkEntrancePartStringIds[tileElement->properties.entrance.index & 0x0F];
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRANCE_PART, &entrancePart, COLOUR_DARK_GREEN, x, y + 22);
}
else {
// Ride ID
sint16 rideId = tileElement->properties.entrance.ride_index;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRANCE_RIDE_ID, &rideId, COLOUR_DARK_GREEN, x, y + 22);
}
// Properties
// Raise / Lower
y = w->y + w->widgets[WIDX_ENTRANCE_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_DARK_GREEN, x, y);
// Current base height
x = w->x + w->widgets[WIDX_ENTRANCE_SPINNER_HEIGHT].left + 3;
sint32 baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_DARK_GREEN, x, y);
break;
}
case TILE_INSPECTOR_PAGE_WALL: {
// Details
// Type
sint16 wallType = tileElement->properties.wall.type;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_WALL_TYPE, &wallType, COLOUR_DARK_GREEN, x, y);
// Banner info
rct_wall_scenery_entry wallEntry = get_wall_entry(wallType)->wall;
if (wallEntry.flags & WALL_SCENERY_IS_BANNER) {
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, &gBanners[tileElement->properties.wall.banner_index].string_idx, COLOUR_DARK_GREEN, x, y + 11);
}
else {
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_NONE, nullptr, COLOUR_DARK_GREEN, x, y + 11);
}
// Properties
// Raise / lower label
y = w->y + w->widgets[WIDX_WALL_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_DARK_GREEN, x, y);
// Current base height
x = w->x + w->widgets[WIDX_WALL_SPINNER_HEIGHT].left + 3;
sint32 baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_DARK_GREEN, x, y);
// Slope label
x = w->x + w->widgets[WIDX_GROUPBOX_DETAILS].left + 7;
y = w->y + w->widgets[WIDX_WALL_DROPDOWN_SLOPE].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_WALL_SLOPE, nullptr, COLOUR_DARK_GREEN, x, y);
break;
}
case TILE_INSPECTOR_PAGE_LARGE_SCENERY:
{
// Details
// Type
sint16 largeSceneryType = scenery_large_get_type(tileElement);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_LARGE_SCENERY_TYPE, &largeSceneryType, COLOUR_DARK_GREEN, x, y);
// Part ID
sint16 pieceID = scenery_large_get_sequence(tileElement);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_LARGE_SCENERY_PIECE_ID, &pieceID, COLOUR_DARK_GREEN, x, y + 11);
// Banner info
rct_scenery_entry *largeSceneryEntry = get_large_scenery_entry(scenery_large_get_type(tileElement));
if (largeSceneryEntry->large_scenery.scrolling_mode != 0xFF)
{
const sint32 bannerIndex = scenery_large_get_banner_id(tileElement);
//window_sign_open(bannerIndex);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, &gBanners[bannerIndex].string_idx, COLOUR_DARK_GREEN, x, y + 22);
}
else {
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_NONE, nullptr, COLOUR_DARK_GREEN, x, y + 22);
}
// Properties
// Raise / lower label
y = w->y + w->widgets[WIDX_LARGE_SCENERY_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_DARK_GREEN, x, y);
// Current base height
x = w->x + w->widgets[WIDX_LARGE_SCENERY_SPINNER_HEIGHT].left + 3;
sint32 baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_DARK_GREEN, x, y);
break;
}
case TILE_INSPECTOR_PAGE_BANNER:
{
// Details
// Banner info
const uint8 bannerIndex = tileElement->properties.banner.index;
if (gBanners[bannerIndex].flags & BANNER_FLAG_NO_ENTRY) {
rct_string_id noEntryStringIdx = STR_NO_ENTRY;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, &noEntryStringIdx, COLOUR_DARK_GREEN, x, y);
}
else {
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_ENTRY_BANNER_TEXT, &gBanners[bannerIndex].string_idx, COLOUR_DARK_GREEN, x, y);
}
// Properties
// Raise / lower label
y = w->y + w->widgets[WIDX_BANNER_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_DARK_GREEN, x, y);
// Current base height
x = w->x + w->widgets[WIDX_BANNER_SPINNER_HEIGHT].left + 3;
sint32 baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_DARK_GREEN, x, y);
// Blocked paths
y += 28;
x = w->x + w->widgets[WIDX_GROUPBOX_DETAILS].left + 7;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BANNER_BLOCKED_PATHS, nullptr, COLOUR_DARK_GREEN, x, y);
break;
}
case TILE_INSPECTOR_PAGE_CORRUPT:
{
// Properties
// Raise / lower label
y = w->y + w->widgets[WIDX_CORRUPT_SPINNER_HEIGHT].top;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_FULL, nullptr, COLOUR_DARK_GREEN, x, y);
// Current base height
x = w->x + w->widgets[WIDX_CORRUPT_SPINNER_HEIGHT].left + 3;
sint32 baseHeight = tileElement->base_height;
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_DARK_GREEN, x, y);
break;
}
} // switch page
}
}
static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex)
{
sint32 y = LIST_ITEM_HEIGHT * (windowTileInspectorElementCount - 1);
sint32 i = 0;
char buffer[256];
if (!windowTileInspectorTileSelected)
return;
rct_tile_element *tileElement = map_get_first_element_at(windowTileInspectorTileX, windowTileInspectorTileY);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
do {
sint32 type = tile_element_get_type(tileElement);
const char * typeName = "";
sint32 baseHeight = tileElement->base_height;
sint32 clearanceHeight = tileElement->clearance_height;
// Fill colour for current list element
const sint32 listWidth = w->widgets[WIDX_LIST].right - w->widgets[WIDX_LIST].left;
if (i == w->selected_list_item) // Currently selected element
gfx_fill_rect(dpi, 0, y, listWidth, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].darker | 0x1000000);
else if (i == windowTileInspectorHighlightedIndex) // Hovering
gfx_fill_rect(dpi, 0, y, listWidth, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].mid_dark | 0x1000000);
else if ((i & 1) != 0) // odd / even check
gfx_fill_rect(dpi, 0, y, listWidth, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000);
switch (type) {
case TILE_ELEMENT_TYPE_SURFACE:
typeName = language_get_string(STR_TILE_INSPECTOR_SURFACE);
break;
case TILE_ELEMENT_TYPE_PATH:
typeName = footpath_element_is_queue(tileElement) ? language_get_string(STR_QUEUE_LINE_MAP_TIP) : language_get_string(STR_FOOTPATH_MAP_TIP);
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->properties.scenery.type)->name)
);
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(get_wall_entry(tileElement->properties.scenery.type)->name)
);
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),
tileElement->properties.banner.index
);
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;
}
// Undo relative scroll offset, but keep the 3 pixel padding
sint32 x = -w->widgets[WIDX_LIST].left;
const bool ghost = (tileElement->flags & TILE_ELEMENT_FLAG_GHOST) != 0;
const bool broken = (tileElement->flags & TILE_ELEMENT_FLAG_BROKEN) != 0;
const bool last = (tileElement->flags & TILE_ELEMENT_FLAG_LAST_TILE) != 0;
gfx_clip_string(buffer, w->widgets[WIDX_COLUMN_TYPE].right - w->widgets[WIDX_COLUMN_TYPE].left - COL_X_TYPE);
gfx_draw_string(dpi, (char *)typeName, COLOUR_DARK_GREEN, x + COL_X_TYPE + 3, y); // 3px padding
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &baseHeight, COLOUR_DARK_GREEN, x + COL_X_BH, y);
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &clearanceHeight, COLOUR_DARK_GREEN, x + COL_X_CH, y);
if (ghost) gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1], x + COL_X_GF, y);
if (broken) gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1], x + COL_X_BF, y);
if (last) gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1], x + COL_X_LF, y);
y -= LIST_ITEM_HEIGHT;
i++;
} while (!tile_element_is_last_for_tile(tileElement++));
}