OpenRCT2/src/windows/tile_inspector.c

1118 lines
44 KiB
C
Raw Normal View History

#pragma region Copyright (c) 2014-2016 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 "../input.h"
#include "../localisation/localisation.h"
2016-01-30 15:00:41 +01:00
#include "../interface/themes.h"
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../interface/viewport.h"
#include "../world/scenery.h"
#include "../world/map.h"
#include "../world/footpath.h"
#include "../sprites.h"
2016-07-27 00:02:10 +02:00
#include "../ride/ride_data.h"
static const rct_string_id TerrainTypes[] = {
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 const rct_string_id TerrainEdgeTypes[] = {
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,
};
static const rct_string_id EntranceTypes[] = {
STR_TILE_INSPECTOR_ENTRANCE_TYPE_RIDE_ENTRANCE,
STR_TILE_INSPECTOR_ENTRANCE_TYPE_RIDE_EXIT,
STR_TILE_INSPECTOR_ENTRANCE_TYPE_PARK_ENTRANC,
};
enum WINDOW_TILE_INSPECTOR_PAGES {
PAGE_DEFAULT,
PAGE_SURFACE,
PAGE_PATH,
PAGE_TRACK,
PAGE_SCENERY,
PAGE_ENTRANCE,
PAGE_FENCE,
PAGE_LARGE_SCENERY,
PAGE_BANNER,
PAGE_CORRUPT
};
enum WINDOW_TILE_INSPECTOR_WIDGET_IDX {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_LIST,
WIDX_CORRUPT,
WIDX_REMOVE,
WIDX_MOVE_DOWN,
WIDX_MOVE_UP,
WIDX_ROTATE,
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_BUTTON_REMOVE_FENCES = PAGE_WIDGETS,
WIDX_SURFACE_BUTTON_RESTORE_FENCES,
// Path
WIDX_PATH_SPINNER_HEIGHT = PAGE_WIDGETS,
WIDX_PATH_SPINNER_HEIGHT_INCREASE,
WIDX_PATH_SPINNER_HEIGHT_DECREASE,
WIDX_PATH_CHECK_EDGE_NE, // Note: This is NOT named after the actual 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,
WIDX_PATH_CHECK_EDGE_SW,
WIDX_PATH_CHECK_EDGE_W,
WIDX_PATH_CHECK_EDGE_NW,
WIDX_PATH_CHECK_EDGE_N,
// Track
// Scenery
// Entrance
// Fence
// Large
// Banner
// Corrupt
};
#define WW 400
#define WH 220
#define MIN_WW WW
#define MAX_WW WW
#define MIN_WH 200
#define MAX_WH 800
2016-05-30 00:35:50 +02:00
#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
#define PADDING_BOTTOM 15
#define GROUPBOX_PADDING 6
#define LIST_ITEM_HEIGHT 11
2016-05-30 00:35:50 +02:00
// 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 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 */ \
/* 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_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BY, BY + 11, STR_UP, STR_MOVE_SELECTED_ELEMENT_UP_TIP }, /* Move down */ \
{ WWT_CLOSEBOX, 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 */ \
/* Column headers */ \
{ WWT_13, 1, COL_X_TYPE, COL_X_BH - 1, 42, 42 + 13, STR_NONE, STR_NONE }, /* Type */ \
{ WWT_13, 1, COL_X_BH, COL_X_CH - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_BASE_HEIGHT }, /* Base height */ \
{ WWT_13, 1, COL_X_CH, COL_X_GF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_CLEARANCE_HEIGHT }, /* Clearance height */ \
{ WWT_13, 1, COL_X_GF, COL_X_BF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_GHOST }, /* Ghost flag */ \
{ WWT_13, 1, COL_X_BF, COL_X_LF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_BROKEN }, /* Broken flag */ \
{ WWT_13, 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 */
rct_widget window_tile_inspector_widgets[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WIDGETS_END },
};
// Calculates the .left, .right, .top and .bottom for buttons in a group box
#define GBBL(col) (12 + col * 115)
#define GBBR(col) (GBBL(col) + 110)
#define GBBT(GROUPTOP, row) ((GROUPTOP) + 14 + row * 21)
#define GBBB(GROUPTOP, row) (GBBT((GROUPTOP), row) + 17)
#define GBB(GROUPTOP, col, row) GBBL(col), GBBR(col), GBBT((GROUPTOP), row), GBBB((GROUPTOP), row)
2016-05-30 00:35:50 +02:00
// Same, but for spinners and their increase/decrease buttons
#define GBS(GBT, col, row) GBBL(col), GBBR(col), GBBT(GBT, row) + 3, GBBB(GBT, row) - 3
#define GBSI(GBT, col, row) GBBR(col) - 11, GBBR(col) - 1, GBBT(GBT, row) + 4, GBBT(GBT, row) + 8
#define GBSD(GBT, col, row) GBBR(col) - 11, GBBR(col) - 1, GBBB(GBT, row) - 8, GBBB(GBT, row) - 4
// Checkbox - given topleft corner
#define CHK(x, y) x, x + 13, y, y + 13
// 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 + 1 * 21) // Surface group box properties top
#define SUR_GBDB (SUR_GBPT + GROUPBOX_PADDING) // Surface group box details bottom
#define SUR_GBDT (SUR_GBDB + 20 + 3 * 11) // Surface group box details top
rct_widget window_tile_inspector_widgets_surface[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WWT_CLOSEBOX, 1, GBB(WH - SUR_GBPT, 0, 0), STR_TILE_INSPECTOR_SURFACE_REMOVE_FENCES, STR_NONE }, // WIDX_SURFACE_BUTTON_REMOVE_FENCES
{ WWT_CLOSEBOX, 1, GBB(WH - SUR_GBPT, 1, 0), STR_TILE_INSPECTOR_SURFACE_RESTORE_FENCES, STR_NONE }, // WIDX_SURFACE_BUTTON_RESTORE_FENCES
{ WIDGETS_END },
};
#define PAT_GBPB PADDING_BOTTOM // Path group box properties bottom
2016-05-30 00:35:50 +02:00
#define PAT_GBPT (PAT_GBPB + 16 + 3 * 21) // Path group box properties top
#define PAT_GBDB (PAT_GBPT + GROUPBOX_PADDING) // Path group box info bottom
2016-05-30 00:35:50 +02:00
#define PAT_GBDT (PAT_GBDB + 20 + 1 * 11) // Path group box info top
rct_widget window_tile_inspector_widgets_path[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WWT_SPINNER, 1, GBS(WH - PAT_GBPT, 1, 0), STR_NONE, STR_NONE }, // WIDX_PATH_SPINNER_HEIGHT
{ WWT_DROPDOWN_BUTTON, 1, GBSI(WH - PAT_GBPT, 1, 0), STR_NUMERIC_UP, STR_NONE }, // WIDX_PATH_SPINNER_HEIGHT_INCREASE
{ WWT_DROPDOWN_BUTTON, 1, GBSD(WH - PAT_GBPT, 1, 0), STR_NUMERIC_DOWN, STR_NONE }, // WIDX_PATH_SPINNER_HEIGHT_DECREASE
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 3, GBBT(WH - PAT_GBPT, 1) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_NE
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 4, GBBT(WH - PAT_GBPT, 1) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_E
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 3, GBBT(WH - PAT_GBPT, 1) + 7 * 3), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_SE
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 2, GBBT(WH - PAT_GBPT, 1) + 7 * 4), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_S
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - PAT_GBPT, 1) + 7 * 3), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_SW
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 0, GBBT(WH - PAT_GBPT, 1) + 7 * 2), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_W
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 1, GBBT(WH - PAT_GBPT, 1) + 7 * 1), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_NW
{ WWT_CHECKBOX, 1, CHK(GBBL(1) + 14 * 2, GBBT(WH - PAT_GBPT, 1) + 7 * 0), STR_NONE, STR_NONE }, // WIDX_PATH_CHECK_EDGE_N
{ WIDGETS_END },
};
#define TRA_GBPB PADDING_BOTTOM // Path group box properties bottom
#define TRA_GBPT (TRA_GBPB + 16 + 0 * 21) // Path group box properties top
#define TRA_GBDB (TRA_GBPT + GROUPBOX_PADDING) // Path group box info bottom
#define TRA_GBDT (TRA_GBDB + 20 + 0 * 11) // Path group box info top
rct_widget window_tile_inspector_widgets_track[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WIDGETS_END },
};
#define SCE_GBPB PADDING_BOTTOM // Path group box properties bottom
#define SCE_GBPT (SCE_GBPB + 16 + 0 * 21) // Path group box properties top
#define SCE_GBDB (SCE_GBPT + GROUPBOX_PADDING) // Path group box info bottom
#define SCE_GBDT (SCE_GBDB + 20 + 0 * 11) // Path group box info top
rct_widget window_tile_inspector_widgets_scenery[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WIDGETS_END },
};
#define ENT_GBPB PADDING_BOTTOM // Path group box properties bottom
#define ENT_GBPT (ENT_GBPB + 16 + 0 * 21) // Path group box properties top
#define ENT_GBDB (ENT_GBPT + GROUPBOX_PADDING) // Path group box info bottom
#define ENT_GBDT (ENT_GBDB + 20 + 0 * 11) // Path group box info top
rct_widget window_tile_inspector_widgets_entrance[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WIDGETS_END },
};
#define FEN_GBPB PADDING_BOTTOM // Path group box properties bottom
#define FEN_GBPT (FEN_GBPB + 16 + 0 * 21) // Path group box properties top
#define FEN_GBDB (FEN_GBPT + GROUPBOX_PADDING) // Path group box info bottom
#define FEN_GBDT (FEN_GBDB + 20 + 0 * 11) // Path group box info top
rct_widget window_tile_inspector_widgets_fence[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WIDGETS_END },
};
#define LAR_GBPB PADDING_BOTTOM // Path group box properties bottom
#define LAR_GBPT (LAR_GBPB + 16 + 0 * 21) // Path group box properties top
#define LAR_GBDB (LAR_GBPT + GROUPBOX_PADDING) // Path group box info bottom
#define LAR_GBDT (LAR_GBDB + 20 + 0 * 11) // Path group box info top
rct_widget window_tile_inspector_widgets_large_scenery[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WIDGETS_END },
};
#define BAN_GBPB PADDING_BOTTOM // Path group box properties bottom
#define BAN_GBPT (BAN_GBPB + 16 + 0 * 21) // Path group box properties top
#define BAN_GBDB (BAN_GBPT + GROUPBOX_PADDING) // Path group box info bottom
#define BAN_GBDT (BAN_GBDB + 20 + 0 * 11) // Path group box info top
rct_widget window_tile_inspector_widgets_banner[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WIDGETS_END },
};
#define COR_GBPB PADDING_BOTTOM // Path group box properties bottom
#define COR_GBPT (COR_GBPB + 16 + 0 * 21) // Path group box properties top
#define COR_GBDB (COR_GBPT + GROUPBOX_PADDING) // Path group box info bottom
#define COR_GBDT (COR_GBDB + 20 + 0 * 11) // Path group box info top
rct_widget window_tile_inspector_widgets_corrupt[] = {
MAIN_TILE_INSPECTOR_WIDGETS,
{ WIDGETS_END },
};
rct_widget *tile_inspector_widgets[] = {
window_tile_inspector_widgets,
window_tile_inspector_widgets_surface,
window_tile_inspector_widgets_path,
window_tile_inspector_widgets_track,
window_tile_inspector_widgets_scenery,
window_tile_inspector_widgets_entrance,
window_tile_inspector_widgets_fence,
window_tile_inspector_widgets_large_scenery,
window_tile_inspector_widgets_banner,
window_tile_inspector_widgets_corrupt,
};
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_idx;
} page_group_box_settings[] = {
{ 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 },
{ FEN_GBDT, FEN_GBDB, FEN_GBPT, FEN_GBPB, STR_TILE_INSPECTOR_GROUPBOX_FENCE_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 window_tile_inspector_highlighted_index = -1;
static int window_tile_inspector_tile_x;
static int window_tile_inspector_tile_y;
static int window_tile_inspector_item_count;
static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex);
static void window_tile_inspector_resize(rct_window *w);
static void window_tile_inspector_update(rct_window *w);
static void window_tile_inspector_tool_update(rct_window* w, int widgetIndex, int x, int y);
static void window_tile_inspector_tool_down(rct_window* w, int widgetIndex, int x, int y);
static void window_tile_inspector_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height);
static void window_tile_inspector_scrollmousedown(rct_window *w, int scrollIndex, int x, int y);
static void window_tile_inspector_scrollmouseover(rct_window *w, int scrollIndex, int x, int 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, int scrollIndex);
static void window_tile_inspector_auto_set_buttons(rct_window *w);
static rct_window_event_list window_tile_inspector_events = {
NULL,
window_tile_inspector_mouseup,
window_tile_inspector_resize,
NULL,
NULL,
NULL,
window_tile_inspector_update,
NULL,
NULL,
window_tile_inspector_tool_update,
window_tile_inspector_tool_down,
NULL,
NULL,
NULL,
NULL,
window_tile_inspector_scrollgetsize,
window_tile_inspector_scrollmousedown,
NULL,
window_tile_inspector_scrollmouseover,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
window_tile_inspector_invalidate,
window_tile_inspector_paint,
window_tile_inspector_scrollpaint
};
static uint64 window_tile_inspector_page_enabled_widgets[] = {
(1UL << WIDX_CLOSE),
(1UL << WIDX_CLOSE) | (1UL << WIDX_REMOVE) | (1UL << WIDX_SURFACE_BUTTON_REMOVE_FENCES) | (1UL << WIDX_SURFACE_BUTTON_RESTORE_FENCES),
(1UL << WIDX_CLOSE) | (1UL << WIDX_REMOVE) | (1UL << WIDX_ROTATE) | (1UL << WIDX_PATH_SPINNER_HEIGHT_INCREASE) | (1UL << WIDX_PATH_SPINNER_HEIGHT_DECREASE) | (1UL << WIDX_PATH_CHECK_EDGE_N) | (1UL << WIDX_PATH_CHECK_EDGE_NE) | (1UL << WIDX_PATH_CHECK_EDGE_E) | (1UL << WIDX_PATH_CHECK_EDGE_SE) | (1UL << WIDX_PATH_CHECK_EDGE_S) | (1UL << WIDX_PATH_CHECK_EDGE_SW) | (1UL << WIDX_PATH_CHECK_EDGE_W) | (1UL << WIDX_PATH_CHECK_EDGE_NW),
2016-05-30 00:35:50 +02:00
(1UL << WIDX_CLOSE) | (1UL << WIDX_REMOVE) | (1UL << WIDX_ROTATE),
(1UL << WIDX_CLOSE) | (1UL << WIDX_REMOVE) | (1UL << WIDX_ROTATE),
(1UL << WIDX_CLOSE) | (1UL << WIDX_REMOVE) | (1UL << WIDX_ROTATE),
(1UL << WIDX_CLOSE) | (1UL << WIDX_REMOVE) | (1UL << WIDX_ROTATE),
(1UL << WIDX_CLOSE) | (1UL << WIDX_REMOVE),
2016-05-30 00:35:50 +02:00
(1UL << WIDX_CLOSE) | (1UL << WIDX_REMOVE) | (1UL << WIDX_ROTATE),
(1UL << WIDX_CLOSE) | (1UL << WIDX_REMOVE),
};
static uint64 window_tile_inspector_page_disabled_widgets[] = {
(1 << WIDX_CORRUPT) | (1 << WIDX_MOVE_UP) | (1 << WIDX_MOVE_DOWN) | (1 << WIDX_REMOVE) | (1 << WIDX_ROTATE),
0,
0,
0,
0,
0,
0,
2016-05-30 00:35:50 +02:00
(1UL << WIDX_ROTATE),
0,
2016-05-30 00:35:50 +02:00
(1UL << WIDX_ROTATE),
};
void 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 != NULL)
return;
window = window_create(
0,
29,
WW,
WH,
&window_tile_inspector_events,
WC_TILE_INSPECTOR,
2015-06-13 23:16:14 +02:00
WF_RESIZABLE
);
window->page = PAGE_DEFAULT;
window->widgets = window_tile_inspector_widgets;
window->enabled_widgets = window_tile_inspector_page_enabled_widgets[window->page];
window->disabled_widgets = window_tile_inspector_page_disabled_widgets[window->page];
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;
window_tile_inspector_tile_x = -1;
window_tile_inspector_tile_y = -1;
2015-06-13 17:05:56 +02:00
tool_set(window, WIDX_BACKGROUND, 12);
}
2016-04-17 11:58:13 +02:00
static void corrupt_element() {
rct_map_element* mapElement;
mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
while (!map_element_is_last_for_tile(mapElement++));
mapElement--;
mapElement = map_element_insert(window_tile_inspector_tile_x, window_tile_inspector_tile_y, mapElement->base_height, 0);
2016-02-26 20:49:01 +01:00
assert(mapElement != NULL);
mapElement->type = (8 << 2);
map_invalidate_tile_full(window_tile_inspector_tile_x << 5, window_tile_inspector_tile_y << 5);
}
2016-04-17 11:58:13 +02:00
static void remove_element(int index)
{
assert(index < window_tile_inspector_item_count);
rct_map_element *mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
mapElement += index;
map_element_remove(mapElement);
window_tile_inspector_item_count--;
map_invalidate_tile_full(window_tile_inspector_tile_x << 5, window_tile_inspector_tile_y << 5);
}
2016-04-17 11:58:13 +02:00
static void rotate_element(int index)
{
uint8 new_rotation;
assert(index < window_tile_inspector_item_count);
rct_map_element *mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
mapElement += index;
switch (map_element_get_type(mapElement))
{
case MAP_ELEMENT_TYPE_PATH: // Only sloped paths have a direction
2016-05-30 00:35:50 +02:00
if (footpath_element_is_sloped(mapElement)) {
new_rotation = (footpath_element_get_slope_direction(mapElement) + 1) & 3;
mapElement->properties.path.type &= ~3;
mapElement->properties.path.type |= new_rotation;
}
2016-05-30 00:35:50 +02:00
break;
case MAP_ELEMENT_TYPE_TRACK:
case MAP_ELEMENT_TYPE_SCENERY:
case MAP_ELEMENT_TYPE_ENTRANCE:
case MAP_ELEMENT_TYPE_FENCE:
new_rotation = (mapElement->type + 1) & 0x3;
mapElement->type &= ~0x3;
mapElement->type |= new_rotation;
break;
case MAP_ELEMENT_TYPE_SCENERY_MULTIPLE:
case MAP_ELEMENT_TYPE_BANNER:
case MAP_ELEMENT_TYPE_CORRUPT:
default:
// Not rotating - button should be disabled
break;
}
map_invalidate_tile_full(window_tile_inspector_tile_x << 5, window_tile_inspector_tile_y << 5);
}
// Swap element with its parent
2016-04-17 11:58:13 +02:00
static void swap_elements(sint16 first, sint16 second)
{
rct_map_element *mapElement;
rct_map_element *firstElement = NULL;
rct_map_element *secondElement = NULL;
mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
// swap_elements shouldn't be called when there is only one element on the tile
assert(!map_element_is_last_for_tile(mapElement));
// Search for the elements
sint16 i = 0;
do {
if (i == first) firstElement = mapElement;
if (i == second) secondElement = mapElement;
i++;
// Check if both elements have been found
if (firstElement != NULL && secondElement != NULL)
break;
} while (!map_element_is_last_for_tile(mapElement++));
// Swap their memory
rct_map_element temp = *firstElement;
*firstElement = *secondElement;
*secondElement = temp;
// Swap the 'last map element for tile' flag if either one of them was last
if (map_element_is_last_for_tile(firstElement) || map_element_is_last_for_tile(secondElement)) {
firstElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE;
secondElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE;
}
map_invalidate_tile_full(window_tile_inspector_tile_x << 5, window_tile_inspector_tile_y << 5);
}
static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex)
{
switch (widgetIndex) {
case WIDX_CLOSE:
tool_cancel();
window_close(w);
break;
case WIDX_CORRUPT:
corrupt_element();
w->scrolls[0].v_top = 0;
w->selected_list_item = window_tile_inspector_item_count++;
window_tile_inspector_auto_set_buttons(w);
widget_invalidate(w, WIDX_LIST);
break;
case WIDX_REMOVE:
remove_element(w->selected_list_item);
w->selected_list_item = -1;
window_tile_inspector_auto_set_buttons(w);
widget_invalidate(w, WIDX_LIST);
break;
case WIDX_ROTATE:
rotate_element(w->selected_list_item);
break;
case WIDX_MOVE_DOWN:
swap_elements(w->selected_list_item, w->selected_list_item + 1);
w->selected_list_item++;
window_tile_inspector_auto_set_buttons(w);
widget_invalidate(w, WIDX_LIST);
break;
case WIDX_MOVE_UP:
swap_elements(w->selected_list_item - 1, w->selected_list_item);
w->selected_list_item--;
window_tile_inspector_auto_set_buttons(w);
widget_invalidate(w, WIDX_LIST);
break;
}
rct_map_element *mapElement;
// Page widgets
switch (w->page) {
case PAGE_SURFACE:
2016-05-30 00:35:50 +02:00
// Get surface element
mapElement = map_get_surface_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
switch (widgetIndex) {
case WIDX_SURFACE_BUTTON_REMOVE_FENCES:
mapElement->properties.surface.ownership &= ~0xF;
map_invalidate_tile_full(window_tile_inspector_tile_x << 5, window_tile_inspector_tile_y << 5);
break;
case WIDX_SURFACE_BUTTON_RESTORE_FENCES:
update_park_fences(window_tile_inspector_tile_x << 5, window_tile_inspector_tile_y << 5);
2016-05-30 00:35:50 +02:00
map_invalidate_tile_full(window_tile_inspector_tile_x << 5, window_tile_inspector_tile_y << 5);
break;
} // switch widgetindex
break;
case PAGE_PATH:
// Get path element
mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
mapElement += w->selected_list_item;
switch (widgetIndex) {
case WIDX_PATH_SPINNER_HEIGHT_INCREASE:
2016-05-30 00:35:50 +02:00
mapElement->base_height++;
mapElement->clearance_height++;
map_invalidate_tile_full(window_tile_inspector_tile_x << 5, window_tile_inspector_tile_y << 5);
break;
case WIDX_PATH_SPINNER_HEIGHT_DECREASE:
2016-05-30 00:35:50 +02:00
mapElement->base_height--;
mapElement->clearance_height--;
map_invalidate_tile_full(window_tile_inspector_tile_x << 5, window_tile_inspector_tile_y << 5);
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:
widget_set_checkbox_value(w, widgetIndex, !widget_is_pressed(w, widgetIndex));
mapElement->properties.path.edges ^= (1 << (4 + (((widgetIndex - WIDX_PATH_CHECK_EDGE_E) / 2 - get_current_rotation() + 4) % 4))) & 0xF0;
printf("%d\n", (widgetIndex - WIDX_PATH_CHECK_EDGE_E) / 2);
2016-05-30 00:35:50 +02:00
map_invalidate_tile_full(window_tile_inspector_tile_x << 5, window_tile_inspector_tile_y << 5);
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:
widget_set_checkbox_value(w, widgetIndex, !widget_is_pressed(w, widgetIndex));
mapElement->properties.path.edges ^= (1 << (((widgetIndex - WIDX_PATH_CHECK_EDGE_NE) / 2 - get_current_rotation() + 4) % 4)) & 0x0F;
2016-05-30 00:35:50 +02:00
map_invalidate_tile_full(window_tile_inspector_tile_x << 5, window_tile_inspector_tile_y << 5);
break;
} // switch widgetindex
break;
2016-05-30 00:35:50 +02:00
case PAGE_TRACK:
case PAGE_SCENERY:
case PAGE_ENTRANCE:
case PAGE_FENCE:
case PAGE_LARGE_SCENERY:
case PAGE_BANNER:
case PAGE_CORRUPT:
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_update(rct_window *w)
{
// Check if the mouse is hovering over the list
2016-05-30 00:35:50 +02:00
if (!widget_is_highlighted(w, WIDX_LIST)) {
window_tile_inspector_highlighted_index = -1;
widget_invalidate(w, WIDX_LIST);
}
if(gCurrentToolWidget.window_classification != WC_TILE_INSPECTOR)
window_close(w);
}
static void window_tile_inspector_tool_update(rct_window* w, int widgetIndex, int x, int y)
{
int direction;
short mapX, mapY;
map_invalidate_selection_rect();
2016-05-14 01:54:13 +02:00
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
2015-07-13 22:43:54 +02:00
mapX = x;
mapY = y;
screen_pos_to_map_pos(&mapX, &mapY, &direction);
if (mapX == (short)0x8000) {
return;
}
2016-05-14 01:54:13 +02:00
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
gMapSelectPositionA.x = mapX;
gMapSelectPositionA.y = mapY;
gMapSelectPositionB.x = mapX;
gMapSelectPositionB.y = mapY;
gMapSelectType = MAP_SELECT_TYPE_FULL;
map_invalidate_selection_rect();
}
static void window_tile_inspector_tool_down(rct_window* w, int widgetIndex, int x, int y)
{
int direction;
short mapX, mapY;
2015-07-13 22:43:54 +02:00
mapX = x;
mapY = y;
screen_pos_to_map_pos(&mapX, &mapY, &direction);
2015-07-13 22:43:54 +02:00
if (mapX == (short)0x8000) {
return;
}
2015-07-13 22:43:54 +02:00
window_tile_inspector_tile_x = mapX >> 5;
window_tile_inspector_tile_y = mapY >> 5;
rct_map_element *element = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
int numItems = 0;
do {
numItems++;
} while (!map_element_is_last_for_tile(element++));
window_tile_inspector_item_count = numItems;
// Set default page
w->page = PAGE_DEFAULT;
w->widgets = tile_inspector_widgets[w->page];
w->enabled_widgets = window_tile_inspector_page_enabled_widgets[w->page];
w->disabled_widgets = window_tile_inspector_page_disabled_widgets[w->page];
// Enable 'insert corrupt element' button
w->enabled_widgets |= (1 << WIDX_CORRUPT);
w->disabled_widgets &= ~(1ULL << WIDX_CORRUPT);
// undo selection and buttons affecting it
w->selected_list_item = -1;
w->disabled_widgets |= (1ULL << WIDX_MOVE_UP) | (1ULL << WIDX_MOVE_DOWN) | (1ULL << WIDX_REMOVE) | (1 << WIDX_ROTATE);
w->enabled_widgets &= ~((1ULL << WIDX_MOVE_UP) | (1ULL << WIDX_MOVE_DOWN) | (1ULL << WIDX_REMOVE) | (1 << WIDX_ROTATE));
w->scrolls[0].v_top = 0;
window_invalidate(w);
}
static void window_tile_inspector_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height)
{
*width = WW - 30;
*height = window_tile_inspector_item_count * LIST_ITEM_HEIGHT;
}
static void window_tile_inspector_auto_set_buttons(rct_window *w)
{
// Remove button
if (w->selected_list_item == -1) { // Check if anything is selected
2016-04-17 12:21:45 +02:00
w->disabled_widgets |= (1ULL << WIDX_REMOVE);
w->enabled_widgets &= ~((1ULL << WIDX_REMOVE));
2016-05-30 00:35:50 +02:00
}
else { // Nothing is selected
2016-04-17 12:21:45 +02:00
w->disabled_widgets &= ~((1ULL << WIDX_REMOVE));
w->enabled_widgets |= (1ULL << WIDX_REMOVE);
}
widget_invalidate(w, WIDX_REMOVE);
// Move Up button
if (w->selected_list_item <= 0) { // Top element in list, or -1
w->disabled_widgets |= (1ULL << WIDX_MOVE_UP);
w->enabled_widgets &= ~(1ULL << WIDX_MOVE_UP);
2016-05-30 00:35:50 +02:00
}
else { // Not the top element in the list
w->enabled_widgets |= (1ULL << WIDX_MOVE_UP);
w->disabled_widgets &= ~(1ULL << WIDX_MOVE_UP);
}
widget_invalidate(w, WIDX_MOVE_UP);
// Move Down button
if (w->selected_list_item == window_tile_inspector_item_count - 1 || w->selected_list_item == -1) { // Bottom element in list, or -1
w->disabled_widgets |= (1ULL << WIDX_MOVE_DOWN);
w->enabled_widgets &= ~(1ULL << WIDX_MOVE_DOWN);
2016-05-30 00:35:50 +02:00
}
else { // Not the bottom element in the list
w->enabled_widgets |= (1ULL << WIDX_MOVE_DOWN);
w->disabled_widgets &= ~(1ULL << WIDX_MOVE_DOWN);
}
widget_invalidate(w, WIDX_MOVE_DOWN);
}
static void window_tile_inspector_scrollmousedown(rct_window *w, int scrollIndex, int x, int y)
{
// Because the list items are displayed in reverse order, subtract the number from the amount of elements
sint16 index = window_tile_inspector_item_count - (y - 1) / LIST_ITEM_HEIGHT - 1;
if (index < 0 || index >= window_tile_inspector_item_count) {
w->selected_list_item = -1;
w->page = 0;
}
else {
w->selected_list_item = index;
// Pick widget layout
rct_map_element *mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
mapElement += index;
w->page = (min(map_element_get_type(mapElement), MAP_ELEMENT_TYPE_CORRUPT) >> 2) + 1;
}
w->widgets = tile_inspector_widgets[w->page];
w->enabled_widgets = window_tile_inspector_page_enabled_widgets[w->page];
w->disabled_widgets = window_tile_inspector_page_disabled_widgets[w->page];
// Enable/disable buttons
window_tile_inspector_auto_set_buttons(w);
window_invalidate(w);
}
static void window_tile_inspector_scrollmouseover(rct_window *w, int scrollIndex, int x, int y)
{
sint16 index = window_tile_inspector_item_count - (y - 1) / LIST_ITEM_HEIGHT - 1;
if (index < 0 || index >= window_tile_inspector_item_count)
window_tile_inspector_highlighted_index = -1;
else
window_tile_inspector_highlighted_index = index;
widget_invalidate(w, WIDX_LIST);
}
static void window_tile_inspector_invalidate(rct_window *w)
{
2016-01-30 15:00:41 +01:00
colour_scheme_update(w);
w->widgets[WIDX_BACKGROUND].bottom = w->height - 1;
if (w->page == 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 = page_group_box_settings[w->page - 1].string_idx;
w->widgets[WIDX_GROUPBOX_DETAILS].top = w->height - page_group_box_settings[w->page - 1].details_top_offset;
w->widgets[WIDX_GROUPBOX_DETAILS].bottom = w->height - page_group_box_settings[w->page - 1].details_bottom_offset;
w->widgets[WIDX_GROUPBOX_PROPERTIES].top = w->height - page_group_box_settings[w->page - 1].properties_top_offset;
w->widgets[WIDX_GROUPBOX_PROPERTIES].bottom = w->height - page_group_box_settings[w->page - 1].properties_bottom_offset;
w->widgets[WIDX_LIST].bottom = w->widgets[WIDX_GROUPBOX_DETAILS].top - GROUPBOX_PADDING;
}
// Using a switch, because I don't think giving each page their own callbacks is
// needed here, as only the mouseup and invalidate functions would be different.
int anchor;
rct_map_element *mapElement;
switch (w->page) {
case PAGE_SURFACE:
anchor = w->widgets[WIDX_GROUPBOX_PROPERTIES].top;
w->widgets[WIDX_SURFACE_BUTTON_REMOVE_FENCES].top = GBBT(anchor, 0);
w->widgets[WIDX_SURFACE_BUTTON_REMOVE_FENCES].bottom = GBBB(anchor, 0);
w->widgets[WIDX_SURFACE_BUTTON_RESTORE_FENCES].top = GBBT(anchor, 0);
w->widgets[WIDX_SURFACE_BUTTON_RESTORE_FENCES].bottom = GBBB(anchor, 0);
break;
case PAGE_PATH:
anchor = w->widgets[WIDX_GROUPBOX_PROPERTIES].top;
mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
mapElement += w->selected_list_item;
w->widgets[WIDX_PATH_SPINNER_HEIGHT].top = GBBT(anchor, 0) + 3;
w->widgets[WIDX_PATH_SPINNER_HEIGHT].bottom = GBBB(anchor, 0) - 3;
w->widgets[WIDX_PATH_SPINNER_HEIGHT_INCREASE].top = GBBT(anchor, 0) + 4;
w->widgets[WIDX_PATH_SPINNER_HEIGHT_INCREASE].bottom = GBBT(anchor, 0) + 8;
w->widgets[WIDX_PATH_SPINNER_HEIGHT_DECREASE].top = GBBB(anchor, 0) - 8;
w->widgets[WIDX_PATH_SPINNER_HEIGHT_DECREASE].bottom = GBBB(anchor, 0) - 4;
w->widgets[WIDX_PATH_CHECK_EDGE_N].top = GBBT(anchor, 1) + 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(anchor, 1) + 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(anchor, 1) + 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(anchor, 1) + 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(anchor, 1) + 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(anchor, 1) + 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(anchor, 1) + 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(anchor, 1) + 7 * 1;
w->widgets[WIDX_PATH_CHECK_EDGE_NW].bottom = w->widgets[WIDX_PATH_CHECK_EDGE_NW].top + 13;
static uint8 edge_flags[] = { 1 << 0, 1 << 1, 1 << 2, 1 << 3 };
static uint8 corner_flags[] = { 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_NE, mapElement->properties.path.edges & edge_flags[(0 + 4 - get_current_rotation()) % 4]);
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_SE, mapElement->properties.path.edges & edge_flags[(1 + 4 - get_current_rotation()) % 4]);
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_SW, mapElement->properties.path.edges & edge_flags[(2 + 4 - get_current_rotation()) % 4]);
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_NW, mapElement->properties.path.edges & edge_flags[(3 + 4 - get_current_rotation()) % 4]);
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_E, mapElement->properties.path.edges & corner_flags[(0 + 4 - get_current_rotation()) % 4]);
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_S, mapElement->properties.path.edges & corner_flags[(1 + 4 - get_current_rotation()) % 4]);
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_W, mapElement->properties.path.edges & corner_flags[(2 + 4 - get_current_rotation()) % 4]);
widget_set_checkbox_value(w, WIDX_PATH_CHECK_EDGE_N, mapElement->properties.path.edges & corner_flags[(3 + 4 - get_current_rotation()) % 4]);
break;
case PAGE_TRACK:
break;
case PAGE_SCENERY:
break;
case PAGE_ENTRANCE:
break;
case PAGE_FENCE:
break;
case PAGE_LARGE_SCENERY:
break;
case PAGE_BANNER:
break;
case PAGE_CORRUPT:
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) {
2016-05-15 23:03:53 +02:00
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);
}
2016-05-30 00:35:50 +02:00
if ((widget = &w->widgets[WIDX_COLUMN_BASEHEIGHT])->type != WWT_EMPTY) {
2016-05-15 23:03:53 +02:00
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);
}
2016-05-30 00:35:50 +02:00
if ((widget = &w->widgets[WIDX_COLUMN_CLEARANCEHEIGHT])->type != WWT_EMPTY) {
2016-05-15 23:03:53 +02:00
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);
}
2016-05-30 00:35:50 +02:00
if ((widget = &w->widgets[WIDX_COLUMN_GHOSTFLAG])->type != WWT_EMPTY) {
2016-05-15 23:03:53 +02:00
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);
}
2016-05-30 00:35:50 +02:00
if ((widget = &w->widgets[WIDX_COLUMN_BROKENFLAG])->type != WWT_EMPTY) {
2016-05-15 23:03:53 +02:00
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);
}
2016-05-30 00:35:50 +02:00
if ((widget = &w->widgets[WIDX_COLUMN_LASTFLAG])->type != WWT_EMPTY) {
2016-05-15 23:03:53 +02:00
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
2016-04-17 12:21:45 +02:00
int x = w->x + w->widgets[WIDX_LIST].left;
int y = w->y + w->height - 13;
if (window_tile_inspector_tile_x == -1) { // No tile selected
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_CHOOSE_MSG, NULL, 12, x, y);
2016-05-30 00:35:50 +02:00
}
else {
2016-04-17 12:21:45 +02:00
char buffer[256];
snprintf(
buffer, 256,
"X: %d, Y: %d",
window_tile_inspector_tile_x,
window_tile_inspector_tile_y
);
gfx_draw_string(dpi, buffer, 12, x, y);
}
if (w->selected_list_item != -1) {
// Get map element
rct_map_element *mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
mapElement += w->selected_list_item;
switch (map_element_get_type(mapElement)) {
case MAP_ELEMENT_TYPE_SURFACE: {
x = w->x + w->widgets[WIDX_GROUPBOX_DETAILS].left + 7;
y = w->y + w->widgets[WIDX_GROUPBOX_DETAILS].top + 14;
rct_string_id terrain_name_id = TerrainTypes[map_element_get_terrain(mapElement)];
rct_string_id terrain_edge_name_id = TerrainEdgeTypes[map_element_get_terrain_edge(mapElement)];
int water_level = mapElement->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SURFACE_TERAIN, &terrain_name_id, 12, x, y);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SURFACE_EDGE, &terrain_edge_name_id, 12, x, y + 11);
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_SURFACE_WATER_LEVEL, &water_level, 12, x, y + 22);
break;
}
2016-05-30 00:35:50 +02:00
case MAP_ELEMENT_TYPE_PATH: {
x = w->x + w->widgets[WIDX_GROUPBOX_DETAILS].left + 7;
y = w->y + w->widgets[WIDX_GROUPBOX_DETAILS].top + 14;
2016-05-30 00:35:50 +02:00
if (footpath_element_has_path_scenery(mapElement)) {
const uint8 pathAdditionType = footpath_element_get_path_scenery_index(mapElement);
rct_string_id addition_name_id = get_footpath_item_entry(pathAdditionType)->name;
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_PATH_ADDITIONS, &addition_name_id, 12, x, y);
}
else
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_PATH_ADDITIONS_NONE, NULL, 12, x, y);
// 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_RAISE_LOWER, NULL, 12, x, y);
// Current base height
x = w->x + w->widgets[WIDX_PATH_SPINNER_HEIGHT].left + 3;
int base_height = mapElement->base_height;
gfx_draw_string_left(dpi, 5182, &base_height, 12, 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_CONECTED_EDGES, NULL, 12, x, y);
2016-05-30 00:35:50 +02:00
break;
}
}
}
}
static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex)
{
int x = 3;
int y = LIST_ITEM_HEIGHT * (window_tile_inspector_item_count - 1);
int i = 0;
char buffer[256];
if (window_tile_inspector_tile_x == -1)
return;
rct_map_element *element = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
do {
int type = map_element_get_type(element);
char *type_name;
int base_height = element->base_height;
int clearance_height = element->clearance_height;
// Fill colour for current list element
const int list_width = 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, list_width, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].darker | 0x1000000);
else if (i == window_tile_inspector_highlighted_index) // Hovering
gfx_fill_rect(dpi, 0, y, list_width, 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, list_width, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000);
switch (type) {
case MAP_ELEMENT_TYPE_SURFACE:
type_name = "Surface";
break;
case MAP_ELEMENT_TYPE_PATH:
{
const uint8 pathType = footpath_element_get_type(element);
const uint8 pathHasScenery = footpath_element_has_path_scenery(element);
const uint8 pathAdditionType = footpath_element_get_path_scenery_index(element);
if (footpath_element_is_queue(element)) {
snprintf(
buffer, sizeof(buffer), "Queue (%s)%s%s for (%d)",
language_get_string(get_footpath_entry(pathType)->string_idx), // Path name
pathHasScenery ? " with " : "", // Adds " with " when there is something on the path
pathHasScenery ? language_get_string(get_footpath_item_entry(pathAdditionType)->name) : "", // Path addition name
element->properties.path.ride_index // Ride index for queue
);
2016-05-30 00:35:50 +02:00
}
else {
snprintf(
buffer, sizeof(buffer), "Path (%s)%s%s",
language_get_string(get_footpath_entry(pathType)->string_idx), // Path name
pathHasScenery ? " with " : "", // Adds " with " when there is something on the path
pathHasScenery ? language_get_string(get_footpath_item_entry(pathAdditionType)->name) : "" // Path addition name
);
}
}
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_TRACK:
snprintf(
buffer, sizeof(buffer),
"Track (%s)",
language_get_string(STR_RIDE_NAME_SPIRAL_ROLLER_COASTER + get_ride(element->properties.track.ride_index)->type)
);
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_SCENERY:
snprintf(
buffer, sizeof(buffer),
"Scenery (%s)",
language_get_string(get_small_scenery_entry(element->properties.scenery.type)->name)
);
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_ENTRANCE:
snprintf(
buffer, sizeof(buffer),
"Entrance (%s)",
language_get_string(EntranceTypes[element->properties.entrance.type])
);
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_FENCE:
snprintf(
buffer, sizeof(buffer),
"Fence (%s)",
language_get_string(get_wall_entry(element->properties.scenery.type)->name)
);
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_SCENERY_MULTIPLE:
type_name = "Scenery multiple";
break;
case MAP_ELEMENT_TYPE_BANNER:
snprintf(
buffer, sizeof(buffer),
"Banner (%d)",
element->properties.banner.index
);
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_CORRUPT:
// fall-through
default:
snprintf(buffer, sizeof(buffer), "Unknown (type %d)", type);
type_name = buffer;
}
// Undo relative scroll offset, but keep the 3 pixel padding
x = -w->widgets[WIDX_LIST].left;
2016-01-01 20:35:08 +01:00
const bool ghost = (element->flags & MAP_ELEMENT_FLAG_GHOST) != 0;
const bool broken = (element->flags & MAP_ELEMENT_FLAG_BROKEN) != 0;
const bool last = (element->flags & MAP_ELEMENT_FLAG_LAST_TILE) != 0;
gfx_draw_string(dpi, type_name, 12, x + COL_X_TYPE + 3, y); // 3px padding
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &base_height, 12, x + COL_X_BH, y);
gfx_draw_string_left(dpi, STR_FORMAT_INTEGER, &clearance_height, 12, x + COL_X_CH, y);
2016-01-01 20:35:08 +01:00
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 (!map_element_is_last_for_tile(element++));
}