diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 491bed7d59..034e8b4df3 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,5 +1,6 @@ 0.0.8 (in development) ------------------------------------------------------------------------ +- Improved: Mouse can now be dragged to select scenery when saving track designs - Fix: [#3178, #5456] Paths with non-ASCII characters not handled properly on macOS. - Fix: [#3681] Steel Twister rollercoaster always shows all track designs - Fix: Track components added by OpenRCT2 are now usable in older scenarios. diff --git a/src/openrct2/ride/track_design.h b/src/openrct2/ride/track_design.h index e81389fea0..acaacdd581 100644 --- a/src/openrct2/ride/track_design.h +++ b/src/openrct2/ride/track_design.h @@ -232,7 +232,7 @@ void track_design_save_init(); void track_design_save_reset_scenery(); bool track_design_save_contains_map_element(rct_map_element *mapElement); void track_design_save_select_nearby_scenery(sint32 rideIndex); -void track_design_save_toggle_map_element(sint32 interactionType, sint32 x, sint32 y, rct_map_element *mapElement); +void track_design_save_select_map_element(sint32 interactionType, sint32 x, sint32 y, rct_map_element *mapElement, bool collect); bool track_design_save(uint8 rideIndex); bool track_design_save_to_file(const utf8 *path); diff --git a/src/openrct2/ride/track_design_save.c b/src/openrct2/ride/track_design_save.c index 6f90ad78a4..0170968fc5 100644 --- a/src/openrct2/ride/track_design_save.c +++ b/src/openrct2/ride/track_design_save.c @@ -31,6 +31,7 @@ #include "TrackDesignRepository.h" #define TRACK_MAX_SAVED_MAP_ELEMENTS 1500 +#define TRACK_NEARBY_SCENERY_DISTANCE 1 bool gTrackDesignSaveMode = false; uint8 gTrackDesignSaveRideIndex = 255; @@ -75,16 +76,20 @@ void track_design_save_init() * * rct2: 0x006D2B07 */ -void track_design_save_toggle_map_element(sint32 interactionType, sint32 x, sint32 y, rct_map_element *mapElement) +void track_design_save_select_map_element(sint32 interactionType, sint32 x, sint32 y, rct_map_element *mapElement, bool collect) { if (track_design_save_contains_map_element(mapElement)) { - track_design_save_remove_map_element(interactionType, x, y, mapElement); + if (!collect) { + track_design_save_remove_map_element(interactionType, x, y, mapElement); + } } else { - if (!track_design_save_add_map_element(interactionType, x, y, mapElement)) { - window_error_open( - STR_SAVE_TRACK_SCENERY_UNABLE_TO_SELECT_ADDITIONAL_ITEM_OF_SCENERY, - STR_SAVE_TRACK_SCENERY_TOO_MANY_ITEMS_SELECTED - ); + if (collect) { + if (!track_design_save_add_map_element(interactionType, x, y, mapElement)) { + window_error_open( + STR_SAVE_TRACK_SCENERY_UNABLE_TO_SELECT_ADDITIONAL_ITEM_OF_SCENERY, + STR_SAVE_TRACK_SCENERY_TOO_MANY_ITEMS_SELECTED + ); + } } } } @@ -593,8 +598,8 @@ static void track_design_save_select_nearby_scenery_for_tile(sint32 rideIndex, s { rct_map_element *mapElement; - for (sint32 y = cy - 1; y <= cy + 1; y++) { - for (sint32 x = cx - 1; x <= cx + 1; x++) { + for (sint32 y = cy - TRACK_NEARBY_SCENERY_DISTANCE; y <= cy + TRACK_NEARBY_SCENERY_DISTANCE; y++) { + for (sint32 x = cx - TRACK_NEARBY_SCENERY_DISTANCE; x <= cx + TRACK_NEARBY_SCENERY_DISTANCE; x++) { mapElement = map_get_first_element_at(x, y); do { sint32 interactionType = VIEWPORT_INTERACTION_ITEM_NONE; diff --git a/src/openrct2/windows/ride.c b/src/openrct2/windows/ride.c index 90c77d8b33..fd922195c2 100644 --- a/src/openrct2/windows/ride.c +++ b/src/openrct2/windows/ride.c @@ -584,6 +584,7 @@ static void window_ride_measurements_mousedown(rct_widgetindex widgetIndex, rct_ static void window_ride_measurements_dropdown(rct_window *w, rct_widgetindex widgetIndex, sint32 dropdownIndex); static void window_ride_measurements_update(rct_window *w); static void window_ride_measurements_tooldown(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y); +static void window_ride_measurements_tooldrag(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y); static void window_ride_measurements_toolabort(rct_window *w, rct_widgetindex widgetIndex); static void window_ride_measurements_invalidate(rct_window *w); static void window_ride_measurements_paint(rct_window *w, rct_drawpixelinfo *dpi); @@ -820,7 +821,7 @@ static rct_window_event_list window_ride_measurements_events = { NULL, NULL, window_ride_measurements_tooldown, - NULL, + window_ride_measurements_tooldrag, NULL, window_ride_measurements_toolabort, NULL, @@ -951,6 +952,9 @@ static rct_window_event_list *window_ride_page_events[] = { #pragma endregion static uint8 _rideType; +static bool _collectTrackDesignScenery = false; +static sint32 _lastSceneryX = 0; +static sint32 _lastSceneryY = 0; static void set_operating_setting(sint32 rideNumber, uint8 setting, uint8 value); @@ -5091,13 +5095,40 @@ static void window_ride_measurements_tooldown(rct_window *w, rct_widgetindex wid sint16 mapX, mapY; sint32 interactionType; + _lastSceneryX = x; + _lastSceneryY = y; + _collectTrackDesignScenery = true; // Default to true in case user does not select anything valid + get_map_coordinates_from_pos(x, y, 0xFCCF, &mapX, &mapY, &interactionType, &mapElement, NULL); switch (interactionType) { case VIEWPORT_INTERACTION_ITEM_SCENERY: case VIEWPORT_INTERACTION_ITEM_LARGE_SCENERY: case VIEWPORT_INTERACTION_ITEM_WALL: case VIEWPORT_INTERACTION_ITEM_FOOTPATH: - track_design_save_toggle_map_element(interactionType, mapX, mapY, mapElement); + _collectTrackDesignScenery = !track_design_save_contains_map_element(mapElement); + track_design_save_select_map_element(interactionType, mapX, mapY, mapElement, _collectTrackDesignScenery); + break; + } +} + +static void window_ride_measurements_tooldrag(rct_window *w, rct_widgetindex widgetIndex, sint32 x, sint32 y) +{ + if (x == _lastSceneryX && y == _lastSceneryY) + return; + _lastSceneryX = x; + _lastSceneryY = y; + + rct_map_element *mapElement; + sint16 mapX, mapY; + sint32 interactionType; + + get_map_coordinates_from_pos(x, y, 0xFCCF, &mapX, &mapY, &interactionType, &mapElement, NULL); + switch (interactionType) { + case VIEWPORT_INTERACTION_ITEM_SCENERY: + case VIEWPORT_INTERACTION_ITEM_LARGE_SCENERY: + case VIEWPORT_INTERACTION_ITEM_WALL: + case VIEWPORT_INTERACTION_ITEM_FOOTPATH: + track_design_save_select_map_element(interactionType, mapX, mapY, mapElement, _collectTrackDesignScenery); break; } }