diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index a025a57d68..a3b0387632 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -4299,6 +4299,10 @@ STR_5987 :Unable to create folder STR_5988 :{SMALLFONT}{BLACK}No remaining land rights for sale STR_5989 :{SMALLFONT}{BLACK}No remaining construction rights for sale STR_5990 :{SMALLFONT}{BLACK}No remaining land rights or construction rights for sale +STR_5991 :Can't paste element... +STR_5992 :The map elements limit has been reached +STR_5993 :{SMALLFONT}{BLACK}Copy selected element +STR_5994 :{SMALLFONT}{BLACK}Paste copied element ############# # Scenarios # diff --git a/resources/g2/78.png b/resources/g2/78.png new file mode 100644 index 0000000000..7e0f3d7906 Binary files /dev/null and b/resources/g2/78.png differ diff --git a/resources/g2/79.png b/resources/g2/79.png new file mode 100644 index 0000000000..a69189ee3e Binary files /dev/null and b/resources/g2/79.png differ diff --git a/src/editor.c b/src/editor.c index 7fb215d73b..9cc88281dd 100644 --- a/src/editor.c +++ b/src/editor.c @@ -113,6 +113,7 @@ void editor_load() mainWindow->flags &= ~WF_SCROLLING_TO_LOCATION; load_palette(); gfx_invalidate_screen(); + window_tile_inspector_clear_clipboard(); gScreenAge = 0; safe_strcpy(gScenarioName, language_get_string(STR_MY_NEW_SCENARIO), 64); @@ -197,6 +198,7 @@ void trackdesigner_load() mainWindow->flags &= ~WF_SCROLLING_TO_LOCATION; load_palette(); gfx_invalidate_screen(); + window_tile_inspector_clear_clipboard(); } /** @@ -237,6 +239,7 @@ void trackmanager_load() mainWindow->flags &= ~WF_SCROLLING_TO_LOCATION; load_palette(); gfx_invalidate_screen(); + window_tile_inspector_clear_clipboard(); } /** @@ -484,6 +487,7 @@ static void editor_finalise_main_view() gWindowUpdateTicks = 0; load_palette(); gfx_invalidate_screen(); + window_tile_inspector_clear_clipboard(); } /** diff --git a/src/game.c b/src/game.c index 2736cdbf09..8c6647bd65 100644 --- a/src/game.c +++ b/src/game.c @@ -909,6 +909,7 @@ void game_load_init() load_palette(); gfx_invalidate_screen(); + window_tile_inspector_clear_clipboard(); window_update_all(); gGameSpeed = 1; diff --git a/src/interface/window.h b/src/interface/window.h index 1b0cae79bc..ad3f8fe329 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -709,6 +709,7 @@ void window_themes_open(); void window_title_editor_open(int tab); void window_title_command_editor_open(int command, bool insert); void window_tile_inspector_open(); +void window_tile_inspector_clear_clipboard(); void window_text_input_open(rct_window* call_w, int call_widget, rct_string_id title, rct_string_id description, rct_string_id existing_text, uintptr_t existing_args, int maxLength); void window_text_input_raw_open(rct_window* call_w, int call_widget, rct_string_id title, rct_string_id description, utf8string existing_text, int maxLength); rct_window *window_mapgen_open(); diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index f82c024184..170ac486b6 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -3639,6 +3639,10 @@ enum { STR_NO_LAND_RIGHTS_FOR_SALE_TIP = 5988, STR_NO_CONSTRUCTION_RIGHTS_FOR_SALE_TIP = 5989, STR_NO_LAND_OR_CONSTRUCTION_RIGHTS_FOR_SALE_TIP = 5990, + STR_CANT_PASTE = 5991, + STR_MAP_ELEMENT_LIMIT_REACHED = 5992, + STR_TILE_INSPECTOR_COPY_TIP = 5993, + STR_TILE_INSPECTOR_PASTE_TIP = 5994, // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 diff --git a/src/peep/peep.c b/src/peep/peep.c index aac9218e0e..c6294d8c44 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -8080,11 +8080,10 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m } uint8 entranceIndex = 0; - while (1){ + for (entranceIndex = 0; entranceIndex < 4; entranceIndex++) { if (gParkEntranceX[entranceIndex] == (x & 0xFFE0) && gParkEntranceY[entranceIndex] == (y & 0xFFE0)) break; - entranceIndex++; } sint16 z = gParkEntranceZ[entranceIndex] / 8; diff --git a/src/scenario.c b/src/scenario.c index 8f53bbd549..ced4aef136 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -305,8 +305,8 @@ void scenario_begin() gParkFlags |= PARK_FLAGS_18; load_palette(); - gfx_invalidate_screen(); + window_tile_inspector_clear_clipboard(); gScreenAge = 0; gGameSpeed = 1; } diff --git a/src/sprites.h b/src/sprites.h index f3bfab5013..fd90623303 100644 --- a/src/sprites.h +++ b/src/sprites.h @@ -744,6 +744,8 @@ enum { SPR_G2_MENU_MULTIPLAYER = SPR_G2_BEGIN + 60, SPR_G2_SORT = SPR_G2_BEGIN + 77, + SPR_G2_COPY = SPR_G2_BEGIN + 78, + SPR_G2_PASTE = SPR_G2_BEGIN + 79, }; #endif diff --git a/src/title.c b/src/title.c index 4a3b194b2b..9e968b1764 100644 --- a/src/title.c +++ b/src/title.c @@ -220,6 +220,7 @@ static int title_load_park(const char *path) news_item_init_queue(); load_palette(); gfx_invalidate_screen(); + window_tile_inspector_clear_clipboard(); gScreenAge = 0; gGameSpeed = 1; return 1; diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index d279a29be1..60de76d74d 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -15,6 +15,7 @@ #pragma endregion #include "dropdown.h" +#include "error.h" #include "../input.h" #include "../interface/themes.h" #include "../interface/viewport.h" @@ -103,6 +104,8 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { 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, @@ -259,6 +262,8 @@ enum WINDOW_TILE_INSPECTOR_WIDGET_IDX { { 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 */ \ { 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_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 */ \ @@ -453,6 +458,8 @@ static unsigned int windowTileInspectorTileY; static bool windowTileInspectorTileSelected = false; static int windowTileInspectorElementCount = 0; static bool windowTileInspectorApplyToAll = false; +static bool windowTileInspectorElementCopied = false; +static rct_map_element tileInspectorCopiedElement; static rct_map_element* window_tile_inspector_get_selected_element(rct_window *w); static void window_tile_inspector_load_tile(rct_window* w); @@ -461,6 +468,8 @@ static void window_tile_inspector_swap_elements(sint16 first, sint16 second); static void window_tile_inspector_remove_element(int index); static void window_tile_inspector_rotate_element(int index); static void window_tile_inspector_sort_elements(rct_window *w); +static void window_tile_inspector_copy_element(rct_window *w); +static void window_tile_inspector_paste_element(rct_window *w); static void window_tile_inspector_surface_toggle_corner(rct_map_element *mapElement, int cornerIndex); static void window_tile_inspector_track_block_height_offset(rct_map_element *mapElement, uint8 offset); static void window_tile_inspector_track_block_set_lift(rct_map_element *mapElement, bool chain); @@ -515,19 +524,19 @@ static rct_window_event_list windowTileInspectorEvents = { static uint64 windowTileInspectorEnabledWidgets[] = { (1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT), - (1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_ROTATE) | (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_PATH_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_PATH_SPINNER_HEIGHT_DECREASE) | (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_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_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_ENTRANCE_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_ENTRANCE_SPINNER_HEIGHT_DECREASE), - (1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_ROTATE) | (1ULL << WIDX_FENCE_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_FENCE_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_FENCE_DROPDOWN_SLOPE) | (1ULL << WIDX_FENCE_DROPDOWN_SLOPE_BUTTON), - (1ULL << WIDX_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (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_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_CORRUPT_SPINNER_HEIGHT) | (1ULL << WIDX_CORRUPT_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_CORRUPT_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_CORRUPT_BUTTON_CLAMP), + (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_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_CLOSE) | (1ULL << WIDX_BUTTON_CORRUPT) | (1ULL << WIDX_BUTTON_REMOVE) | (1ULL << WIDX_BUTTON_ROTATE) | (1ULL << WIDX_BUTTON_COPY) | (1ULL << WIDX_FENCE_SPINNER_HEIGHT_INCREASE) | (1ULL << WIDX_FENCE_SPINNER_HEIGHT_DECREASE) | (1ULL << WIDX_FENCE_DROPDOWN_SLOPE) | (1ULL << WIDX_FENCE_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 windowTileInspectorDisabledWidgets[] = { - (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_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, @@ -539,7 +548,8 @@ static uint64 windowTileInspectorDisabledWidgets[] = { (1ULL << WIDX_BUTTON_ROTATE), }; -void window_tile_inspector_open() { +void window_tile_inspector_open() +{ rct_window* window; // Check if window is already open @@ -571,12 +581,19 @@ void window_tile_inspector_open() { window_tile_inspector_auto_set_buttons(window); } -static rct_map_element* window_tile_inspector_get_selected_element(rct_window *w) { +void window_tile_inspector_clear_clipboard() +{ + windowTileInspectorElementCopied = false; +} + +static rct_map_element* window_tile_inspector_get_selected_element(rct_window *w) +{ assert(w->selected_list_item >= 0 && w->selected_list_item < windowTileInspectorElementCount); return map_get_first_element_at(windowTileInspectorTileX, windowTileInspectorTileY) + w->selected_list_item; } -static void window_tile_inspector_load_tile(rct_window* w) { +static void window_tile_inspector_load_tile(rct_window* w) +{ rct_map_element *element = map_get_first_element_at(windowTileInspectorTileX, windowTileInspectorTileY); int numItems = 0; do { @@ -596,7 +613,8 @@ static void window_tile_inspector_load_tile(rct_window* w) { window_invalidate(w); } -static void window_tile_inspector_insert_corrupt_element(rct_window *w) { +static void window_tile_inspector_insert_corrupt_element(rct_window *w) +{ // Create new corrupt element rct_map_element *curruptElement = map_element_insert(windowTileInspectorTileX, windowTileInspectorTileY, -1, 0); // Ugly hack: -1 guarantees this to be placed first windowTileInspectorElementCount++; @@ -616,7 +634,8 @@ static void window_tile_inspector_insert_corrupt_element(rct_window *w) { map_invalidate_tile_full(windowTileInspectorTileX << 5, windowTileInspectorTileY << 5); } -static void window_tile_inspector_remove_element(int index) { +static void window_tile_inspector_remove_element(int index) +{ assert(index < windowTileInspectorElementCount); rct_map_element *const mapElement = map_get_first_element_at(windowTileInspectorTileX, windowTileInspectorTileY) + index; map_element_remove(mapElement); @@ -624,7 +643,8 @@ static void window_tile_inspector_remove_element(int index) { map_invalidate_tile_full(windowTileInspectorTileX << 5, windowTileInspectorTileY << 5); } -static void window_tile_inspector_rotate_element(int index) { +static void window_tile_inspector_rotate_element(int index) +{ uint8 newRotation, pathEdges, pathCorners; assert(index < windowTileInspectorElementCount); @@ -662,7 +682,8 @@ static void window_tile_inspector_rotate_element(int index) { } // Swap element with its parent -static void window_tile_inspector_swap_elements(sint16 first, sint16 second) { +static void window_tile_inspector_swap_elements(sint16 first, sint16 second) +{ rct_map_element *mapElement = map_get_first_element_at(windowTileInspectorTileX, windowTileInspectorTileY); rct_map_element *const firstElement = mapElement + first; rct_map_element *const secondElement = mapElement + second; @@ -690,7 +711,8 @@ static void window_tile_inspector_swap_elements(sint16 first, sint16 second) { map_invalidate_tile_full(windowTileInspectorTileX << 5, windowTileInspectorTileY << 5); } -static void window_tile_inspector_sort_elements(rct_window *w) { +static void window_tile_inspector_sort_elements(rct_window *w) +{ const rct_map_element *const firstElement = map_get_first_element_at(windowTileInspectorTileX, windowTileInspectorTileY); // Bubble sort @@ -709,7 +731,37 @@ static void window_tile_inspector_sort_elements(rct_window *w) { } } -static void window_tile_inspector_surface_toggle_corner(rct_map_element *mapElement, int cornerIndex) { +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) +{ + rct_map_element *const pastedElement = map_element_insert(windowTileInspectorTileX, windowTileInspectorTileY, tileInspectorCopiedElement.base_height, 0); + if (pastedElement == NULL) { + // map_element_insert displays an error message on failure + window_error_open(STR_CANT_PASTE, STR_MAP_ELEMENT_LIMIT_REACHED); + return; + } + + windowTileInspectorElementCount++; + bool lastForTile = map_element_is_last_for_tile(pastedElement); + *pastedElement = tileInspectorCopiedElement; + pastedElement->flags &= ~MAP_ELEMENT_FLAG_LAST_TILE; + if (lastForTile) { + pastedElement->flags |= MAP_ELEMENT_FLAG_LAST_TILE; + } + + // Make pasted element selected + const rct_map_element *mapElement = map_get_first_element_at(windowTileInspectorTileX, windowTileInspectorTileY); + w->selected_list_item = (sint16)(pastedElement - mapElement); +} + +static void window_tile_inspector_surface_toggle_corner(rct_map_element *mapElement, int cornerIndex) +{ const uint8 originalSlope = mapElement->properties.surface.slope; const bool diagonal = (originalSlope & 0x10) >> 4; @@ -742,7 +794,8 @@ static void window_tile_inspector_surface_toggle_corner(rct_map_element *mapElem // Copied from track.c (track_remove), and modified for raising/lowering // Not sure if this should be in this file, track.c, or maybe another one -static void window_tile_inspector_track_block_height_offset(rct_map_element *mapElement, uint8 offset) { +static void window_tile_inspector_track_block_height_offset(rct_map_element *mapElement, uint8 offset) +{ uint8 type = mapElement->properties.track.type; sint16 originX = windowTileInspectorTileX << 5; sint16 originY = windowTileInspectorTileY << 5; @@ -843,7 +896,8 @@ static void window_tile_inspector_track_block_height_offset(rct_map_element *map // Sets chainlift for entire block // Basically a copy of the above function, with just two different lines... should probably be combined somehow -static void window_tile_inspector_track_block_set_lift(rct_map_element *mapElement, bool chain) { +static void window_tile_inspector_track_block_set_lift(rct_map_element *mapElement, bool chain) +{ uint8 type = mapElement->properties.track.type; sint16 originX = windowTileInspectorTileX << 5; sint16 originY = windowTileInspectorTileY << 5; @@ -942,7 +996,8 @@ static void window_tile_inspector_track_block_set_lift(rct_map_element *mapEleme } } -static void window_tile_inspector_quarter_tile_set(rct_map_element *const mapElement, const int index) { +static void window_tile_inspector_quarter_tile_set(rct_map_element *const mapElement, const int index) +{ // index is widget index relative to WIDX_SCENERY_CHECK_QUARTER_N, so a value from 0-3 assert(index >= 0 && index < 4); @@ -959,7 +1014,8 @@ static void window_tile_inspector_quarter_tile_set(rct_map_element *const mapEle map_invalidate_tile_full(windowTileInspectorTileX << 5, windowTileInspectorTileY << 5); } -static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) { +static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) +{ switch (widgetIndex) { case WIDX_CLOSE: tool_cancel(); @@ -1009,6 +1065,17 @@ static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) { w->selected_list_item = -1; window_invalidate(w); break; + case WIDX_BUTTON_COPY: + window_tile_inspector_copy_element(w); + map_invalidate_tile_full(windowTileInspectorTileX << 5, windowTileInspectorTileY << 5); + window_tile_inspector_auto_set_buttons(w); + window_invalidate(w); + break; + case WIDX_BUTTON_PASTE: + window_tile_inspector_paste_element(w); + map_invalidate_tile_full(windowTileInspectorTileX << 5, windowTileInspectorTileY << 5); + widget_invalidate(w, WIDX_LIST); + break; case WIDX_BUTTON_MOVE_DOWN: window_tile_inspector_swap_elements(w->selected_list_item, w->selected_list_item + 1); w->selected_list_item++; @@ -1287,7 +1354,8 @@ static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) { } // switch page } -static void window_tile_inspector_resize(rct_window *w) { +static void window_tile_inspector_resize(rct_window *w) +{ w->min_width = WW; w->min_height = MIN_WH; if (w->width < w->min_width) { @@ -1300,7 +1368,8 @@ static void window_tile_inspector_resize(rct_window *w) { } } -static void window_tile_inspector_mousedown(int widgetIndex, rct_window *w, rct_widget* widget) { +static void window_tile_inspector_mousedown(int widgetIndex, rct_window *w, rct_widget* widget) +{ switch (w->page) { case PAGE_FENCE: switch (widgetIndex) { @@ -1334,7 +1403,8 @@ static void window_tile_inspector_mousedown(int widgetIndex, rct_window *w, rct_ } } -static void window_tile_inspector_update(rct_window *w) { +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; @@ -1345,7 +1415,8 @@ static void window_tile_inspector_update(rct_window *w) { window_close(w); } -static void window_tile_inspector_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { +static void window_tile_inspector_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) +{ if (dropdownIndex == -1) { return; } @@ -1373,7 +1444,8 @@ static void window_tile_inspector_dropdown(rct_window *w, int widgetIndex, int d } } -static void window_tile_inspector_tool_update(rct_window* w, int widgetIndex, int x, int y) { +static void window_tile_inspector_tool_update(rct_window* w, int widgetIndex, int x, int y) +{ map_invalidate_selection_rect(); gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; @@ -1398,7 +1470,8 @@ static void window_tile_inspector_tool_update(rct_window* w, int widgetIndex, in map_invalidate_selection_rect(); } -static void window_tile_inspector_tool_down(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) +{ short mapX = x; short mapY = y; int direction; @@ -1415,19 +1488,22 @@ static void window_tile_inspector_tool_down(rct_window* w, int widgetIndex, int window_tile_inspector_auto_set_buttons(w); } -static void window_tile_inspector_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) { +static void window_tile_inspector_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) +{ *width = WW - 30; *height = windowTileInspectorElementCount * LIST_ITEM_HEIGHT; } -static void window_tile_inspector_set_page(rct_window *w, const int page) { +static void window_tile_inspector_set_page(rct_window *w, const int page) +{ w->page = page; w->widgets = tileInspectorWidgets[page]; w->enabled_widgets = windowTileInspectorEnabledWidgets[page]; w->disabled_widgets = windowTileInspectorDisabledWidgets[page]; } -static void window_tile_inspector_auto_set_buttons(rct_window *w) { +static 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))); @@ -1445,6 +1521,14 @@ static void window_tile_inspector_auto_set_buttons(rct_window *w) { 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 PAGE_FENCE: { @@ -1452,6 +1536,7 @@ static void window_tile_inspector_auto_set_buttons(rct_window *w) { const uint8 fenceType = mapElement->properties.fence.type; const rct_wall_scenery_entry wallEntry = get_wall_entry(fenceType)->wall; const bool canBeSloped = !(wallEntry.flags & WALL_SCENERY_CANT_BUILD_ON_SLOPE); + // Fence slope dropdown widget_set_enabled(w, WIDX_FENCE_DROPDOWN_SLOPE, canBeSloped); widget_invalidate(w, WIDX_FENCE_DROPDOWN_SLOPE); widget_set_enabled(w, WIDX_FENCE_DROPDOWN_SLOPE_BUTTON, canBeSloped); @@ -1461,7 +1546,8 @@ static void window_tile_inspector_auto_set_buttons(rct_window *w) { } // switch page } -static void window_tile_inspector_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) { +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 calculated index from the amount of elements const sint16 index = windowTileInspectorElementCount - (y - 1) / LIST_ITEM_HEIGHT - 1; int page; @@ -1484,7 +1570,8 @@ static void window_tile_inspector_scrollmousedown(rct_window *w, int scrollIndex window_invalidate(w); } -static void window_tile_inspector_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) { +static void window_tile_inspector_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) +{ sint16 index = windowTileInspectorElementCount - (y - 1) / LIST_ITEM_HEIGHT - 1; if (index < 0 || index >= windowTileInspectorElementCount) windowTileInspectorHighlightedIndex = -1; @@ -1494,7 +1581,8 @@ static void window_tile_inspector_scrollmouseover(rct_window *w, int scrollIndex widget_invalidate(w, WIDX_LIST); } -static void window_tile_inspector_invalidate(rct_window *w) { +static void window_tile_inspector_invalidate(rct_window *w) +{ colour_scheme_update(w); w->widgets[WIDX_BACKGROUND].bottom = w->height - 1; @@ -1700,7 +1788,8 @@ 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_paint(rct_window *w, rct_drawpixelinfo *dpi) +{ window_draw_widgets(w, dpi); // Set medium font size @@ -2059,7 +2148,8 @@ 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_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) +{ int x = 3; int y = LIST_ITEM_HEIGHT * (windowTileInspectorElementCount - 1); int i = 0;