From a268350615182dbc3e6bcbf3e39a5f3cec03508f Mon Sep 17 00:00:00 2001 From: Duncan Date: Tue, 21 Sep 2021 10:06:04 +0100 Subject: [PATCH] Fix #15439: Ride viewport is partially grey The ride viewport does not work the same as other viewports due to the selection of views that it has. After refactoring the focus system to use a more streamlined approach the ride viewport lost its invalidation on resizing. If the ride window was to use the same viewport update code as say the guest window then the viewport focus still ends up incorrect due to it no longer centring the focus. Therefore the best approach was to lose the focus on resize and force a recalculation of it. Also renamed Focus2 to Focus as Focus2 was meant to just be fill in whilst removing the original focus structs. --- src/openrct2-ui/interface/Window.cpp | 2 +- src/openrct2-ui/scripting/CustomWindow.cpp | 3 +- src/openrct2-ui/windows/Banner.cpp | 3 +- src/openrct2-ui/windows/EditorMain.cpp | 3 +- src/openrct2-ui/windows/Guest.cpp | 4 +-- src/openrct2-ui/windows/Main.cpp | 3 +- src/openrct2-ui/windows/Park.cpp | 6 ++-- src/openrct2-ui/windows/Player.cpp | 2 +- src/openrct2-ui/windows/Ride.cpp | 16 +++++----- src/openrct2-ui/windows/Sign.cpp | 6 ++-- src/openrct2-ui/windows/Staff.cpp | 8 ++--- .../windows/TitleCommandEditor.cpp | 2 +- src/openrct2-ui/windows/Viewport.cpp | 3 +- src/openrct2/interface/Viewport.cpp | 30 +++++++++---------- src/openrct2/interface/Viewport.h | 2 +- src/openrct2/interface/Window.h | 8 ++--- src/openrct2/interface/Window_internal.cpp | 4 +-- src/openrct2/interface/Window_internal.h | 2 +- 18 files changed, 51 insertions(+), 56 deletions(-) diff --git a/src/openrct2-ui/interface/Window.cpp b/src/openrct2-ui/interface/Window.cpp index 14aee560f7..7ffc99deb4 100644 --- a/src/openrct2-ui/interface/Window.cpp +++ b/src/openrct2-ui/interface/Window.cpp @@ -274,7 +274,7 @@ rct_window* WindowCreate( w->min_height = height; w->max_height = height; - w->focus2 = std::nullopt; + w->focus = std::nullopt; w->page = 0; w->var_48C = 0; w->var_492 = 0; diff --git a/src/openrct2-ui/scripting/CustomWindow.cpp b/src/openrct2-ui/scripting/CustomWindow.cpp index 4e01689373..874427ef14 100644 --- a/src/openrct2-ui/scripting/CustomWindow.cpp +++ b/src/openrct2-ui/scripting/CustomWindow.cpp @@ -786,8 +786,7 @@ namespace OpenRCT2::Ui::Windows auto wheight = viewportWidget->height() - 1; if (viewport == nullptr) { - const auto focus = Focus2(CoordsXYZ(0, 0, 0)); - viewport_create(this, { left, top }, wwidth, wheight, focus); + viewport_create(this, { left, top }, wwidth, wheight, Focus(CoordsXYZ(0, 0, 0))); flags |= WF_NO_SCROLLING; Invalidate(); } diff --git a/src/openrct2-ui/windows/Banner.cpp b/src/openrct2-ui/windows/Banner.cpp index 3959bc29de..534f908b7e 100644 --- a/src/openrct2-ui/windows/Banner.cpp +++ b/src/openrct2-ui/windows/Banner.cpp @@ -79,10 +79,9 @@ private: void CreateViewport() { rct_widget* viewportWidget = &window_banner_widgets[WIDX_VIEWPORT]; - const auto focus = Focus2(_bannerViewPos); viewport_create( this, windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 }, - (viewportWidget->width()) - 1, (viewportWidget->height()) - 1, focus); + (viewportWidget->width()) - 1, (viewportWidget->height()) - 1, Focus(_bannerViewPos)); if (viewport != nullptr) viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; diff --git a/src/openrct2-ui/windows/EditorMain.cpp b/src/openrct2-ui/windows/EditorMain.cpp index 121b8e4ac3..d0186f17db 100644 --- a/src/openrct2-ui/windows/EditorMain.cpp +++ b/src/openrct2-ui/windows/EditorMain.cpp @@ -40,8 +40,7 @@ rct_window* window_editor_main_open() &window_editor_main_events, WC_MAIN_WINDOW, WF_STICK_TO_BACK); window->widgets = window_editor_main_widgets; - const auto focus = Focus2(CoordsXYZ(0x0FFF, 0x0FFF, 0)); - viewport_create(window, window->windowPos, window->width, window->height, focus); + viewport_create(window, window->windowPos, window->width, window->height, Focus(CoordsXYZ(0x0FFF, 0x0FFF, 0))); window->viewport->flags |= 0x0400; gCurrentRotation = 0; diff --git a/src/openrct2-ui/windows/Guest.cpp b/src/openrct2-ui/windows/Guest.cpp index d96bcf206d..db53bce639 100644 --- a/src/openrct2-ui/windows/Guest.cpp +++ b/src/openrct2-ui/windows/Guest.cpp @@ -732,7 +732,7 @@ void window_guest_viewport_init(rct_window* w) uint16_t origViewportFlags{}; if (w->viewport != nullptr) { - if (w->focus2.has_value()) + if (w->focus.has_value()) return; origViewportFlags = w->viewport->flags; @@ -750,7 +750,7 @@ void window_guest_viewport_init(rct_window* w) int32_t width = view_widget->width() - 1; int32_t height = view_widget->height() - 1; - viewport_create(w, screenPos, width, height, w->focus2.value()); + viewport_create(w, screenPos, width, height, w->focus.value()); if (w->viewport != nullptr && reCreateViewport) { w->viewport->flags = origViewportFlags; diff --git a/src/openrct2-ui/windows/Main.cpp b/src/openrct2-ui/windows/Main.cpp index 347f2cc49f..ed7bab0503 100644 --- a/src/openrct2-ui/windows/Main.cpp +++ b/src/openrct2-ui/windows/Main.cpp @@ -41,8 +41,7 @@ rct_window* window_main_open() WF_STICK_TO_BACK); window->widgets = window_main_widgets; - const auto focus = Focus2(CoordsXYZ(0x0FFF, 0x0FFF, 0)); - viewport_create(window, window->windowPos, window->width, window->height, focus); + viewport_create(window, window->windowPos, window->width, window->height, Focus(CoordsXYZ(0x0FFF, 0x0FFF, 0))); window->viewport->flags |= VIEWPORT_FLAG_SOUND_ON; gCurrentRotation = 0; gShowGridLinesRefCount = 0; diff --git a/src/openrct2-ui/windows/Park.cpp b/src/openrct2-ui/windows/Park.cpp index 6b477ad3b4..9f3bf92f0d 100644 --- a/src/openrct2-ui/windows/Park.cpp +++ b/src/openrct2-ui/windows/Park.cpp @@ -740,11 +740,11 @@ static void window_park_init_viewport(rct_window* w) if (w->page != WINDOW_PARK_PAGE_ENTRANCE) return; - std::optional focus = std::nullopt; + std::optional focus = std::nullopt; if (!gParkEntrances.empty()) { const auto& entrance = gParkEntrances[0]; - focus = Focus2(CoordsXYZ{ entrance.x + 16, entrance.y + 16, entrance.z + 32 }); + focus = Focus(CoordsXYZ{ entrance.x + 16, entrance.y + 16, entrance.z + 32 }); } if (w->viewport == nullptr) @@ -760,7 +760,7 @@ static void window_park_init_viewport(rct_window* w) // Call invalidate event window_event_invalidate_call(w); - w->focus2 = focus; + w->focus = focus; if (focus.has_value()) { diff --git a/src/openrct2-ui/windows/Player.cpp b/src/openrct2-ui/windows/Player.cpp index fab5a3df40..9a6c6352de 100644 --- a/src/openrct2-ui/windows/Player.cpp +++ b/src/openrct2-ui/windows/Player.cpp @@ -547,7 +547,7 @@ static void window_player_set_page(rct_window* w, int32_t page) { if (w->viewport == nullptr) { - const auto focus = Focus2(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ()); + const auto focus = Focus(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ()); viewport_create(w, w->windowPos, w->width, w->height, focus); w->flags |= WF_NO_SCROLLING; window_event_invalidate_call(w); diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index ec0286cbb8..1f2d68054b 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -1589,7 +1589,7 @@ static void window_ride_init_viewport(rct_window* w) int32_t viewSelectionIndex = w->ride.view - 1; - std::optional focus; + std::optional focus; if (viewSelectionIndex >= 0 && viewSelectionIndex < ride->num_vehicles && ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) { @@ -1609,7 +1609,7 @@ static void window_ride_init_viewport(rct_window* w) } if (vehId != SPRITE_INDEX_NULL) { - focus = Focus2(vehId); + focus = Focus(vehId); } } else if (viewSelectionIndex >= ride->num_vehicles && viewSelectionIndex < (ride->num_vehicles + ride->num_stations)) @@ -1618,7 +1618,7 @@ static void window_ride_init_viewport(rct_window* w) if (stationIndex) { const auto location = ride->stations[*stationIndex].GetStart(); - focus = Focus2(location); + focus = Focus(location); } } else @@ -1630,14 +1630,14 @@ static void window_ride_init_viewport(rct_window* w) if (w->number < ride_overall_views.size()) { const auto& view = ride_overall_views[w->number]; - focus = Focus2(view.loc, view.zoom); + focus = Focus(view.loc, view.zoom); } } uint16_t viewport_flags = 0; if (w->viewport != nullptr) { - if (focus == w->focus2) + if (focus == w->focus) { return; } @@ -1651,7 +1651,7 @@ static void window_ride_init_viewport(rct_window* w) window_event_invalidate_call(w); - w->focus2 = focus; + w->focus = focus; // rct2: 0x006aec9c only used here so brought it into the function if (!w->viewport && !ride->overall_view.IsNull()) @@ -1662,7 +1662,7 @@ static void window_ride_init_viewport(rct_window* w) int32_t width = view_widget->width() - 1; int32_t height = view_widget->height() - 1; - viewport_create(w, screenPos, width, height, w->focus2.value()); + viewport_create(w, screenPos, width, height, w->focus.value()); w->flags |= WF_NO_SCROLLING; w->Invalidate(); @@ -1796,6 +1796,8 @@ static void window_ride_main_resize(rct_window* w) w->flags |= WF_RESIZABLE; window_set_resize(w, 316, minHeight, 500, 450); + // Unlike with other windows, the focus needs to be recentred so it’s best to just reset it. + w->focus = std::nullopt; window_ride_init_viewport(w); } diff --git a/src/openrct2-ui/windows/Sign.cpp b/src/openrct2-ui/windows/Sign.cpp index bddfd0dd20..b111f95c9b 100644 --- a/src/openrct2-ui/windows/Sign.cpp +++ b/src/openrct2-ui/windows/Sign.cpp @@ -127,10 +127,9 @@ public: // Create viewport rct_widget& viewportWidget = window_sign_widgets[WIDX_VIEWPORT]; - const auto focus = Focus2(CoordsXYZ{ signViewPosition, viewZ }); viewport_create( this, windowPos + ScreenCoordsXY{ viewportWidget.left + 1, viewportWidget.top + 1 }, viewportWidget.width() - 1, - viewportWidget.height() - 1, focus); + viewportWidget.height() - 1, Focus(CoordsXYZ{ signViewPosition, viewZ })); viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; Invalidate(); @@ -300,10 +299,9 @@ public: // Create viewport rct_widget* viewportWidget = &window_sign_widgets[WIDX_VIEWPORT]; - const auto focus = Focus2(CoordsXYZ{ signViewPos }); viewport_create( this, windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 }, viewportWidget->width() - 1, - viewportWidget->height() - 1, focus); + viewportWidget->height() - 1, Focus(CoordsXYZ{ signViewPos })); if (viewport != nullptr) viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; Invalidate(); diff --git a/src/openrct2-ui/windows/Staff.cpp b/src/openrct2-ui/windows/Staff.cpp index 2a691c0fab..727e755429 100644 --- a/src/openrct2-ui/windows/Staff.cpp +++ b/src/openrct2-ui/windows/Staff.cpp @@ -1346,7 +1346,7 @@ void window_staff_viewport_init(rct_window* w) if (w->page != WINDOW_STAFF_OVERVIEW) return; - std::optional focus; + std::optional focus; const auto peep = GetStaff(w); if (peep == nullptr) @@ -1356,14 +1356,14 @@ void window_staff_viewport_init(rct_window* w) if (peep->State != PeepState::Picked) { - focus = Focus2(peep->sprite_index); + focus = Focus(peep->sprite_index); } uint16_t viewport_flags; if (w->viewport) { - if (focus == w->focus2) + if (focus == w->focus) return; viewport_flags = w->viewport->flags; @@ -1378,7 +1378,7 @@ void window_staff_viewport_init(rct_window* w) window_event_invalidate_call(w); - w->focus2 = focus; + w->focus = focus; if (peep->State != PeepState::Picked) { diff --git a/src/openrct2-ui/windows/TitleCommandEditor.cpp b/src/openrct2-ui/windows/TitleCommandEditor.cpp index 4b15b97904..b02e3fc1a3 100644 --- a/src/openrct2-ui/windows/TitleCommandEditor.cpp +++ b/src/openrct2-ui/windows/TitleCommandEditor.cpp @@ -227,7 +227,7 @@ void window_title_command_editor_open(TitleSequence* sequence, int32_t index, bo WindowInitScrollWidgets(window); rct_widget* const viewportWidget = &window_title_command_editor_widgets[WIDX_VIEWPORT]; - const auto focus = Focus2(CoordsXYZ{ 0, 0, 0 }); + const auto focus = Focus(CoordsXYZ{ 0, 0, 0 }); viewport_create( window, window->windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 }, viewportWidget->width() - 1, viewportWidget->height() - 1, focus); diff --git a/src/openrct2-ui/windows/Viewport.cpp b/src/openrct2-ui/windows/Viewport.cpp index abcd712170..66ee0f3a33 100644 --- a/src/openrct2-ui/windows/Viewport.cpp +++ b/src/openrct2-ui/windows/Viewport.cpp @@ -76,8 +76,7 @@ public: enabled_widgets = (1ULL << WIDX_CLOSE) | (1ULL << WIDX_ZOOM_IN) | (1ULL << WIDX_ZOOM_OUT) | (1ULL << WIDX_LOCATE); // Create viewport - const auto focus = Focus2(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ()); - viewport_create(this, windowPos, width, height, focus); + viewport_create(this, windowPos, width, height, Focus(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ())); if (viewport == nullptr) { Close(); diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 65e093703f..28cab048bd 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -117,14 +117,14 @@ std::optional centre_2d_coordinates(const CoordsXYZ& loc, rct_vi return { screenCoord }; } -CoordsXYZ Focus2::GetPos() const +CoordsXYZ Focus::GetPos() const { return std::visit( [](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) return arg; - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) { auto* centreEntity = GetEntity(arg); if (centreEntity != nullptr) @@ -158,7 +158,7 @@ CoordsXYZ Focus2::GetPos() const * flags: edx top most 2 bits 0b_X1 for zoom clear see below for 2nd bit. * w: esi */ -void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus2& focus) +void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus& focus) { rct_viewport* viewport = nullptr; if (_viewports.size() >= MAX_VIEWPORT_COUNT) @@ -188,9 +188,9 @@ void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t w->viewport_target_sprite = std::visit( [](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) return SPRITE_INDEX_NULL; - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return arg; }, focus.data); @@ -702,7 +702,7 @@ void viewport_update_smart_sprite_follow(rct_window* window) break; default: // All other types don't need any "smart" following; steam particle, duck, money effect, etc. - window->focus2 = Focus2(window->viewport_smart_follow_sprite); + window->focus = Focus(window->viewport_smart_follow_sprite); window->viewport_target_sprite = window->viewport_smart_follow_sprite; break; } @@ -710,14 +710,14 @@ void viewport_update_smart_sprite_follow(rct_window* window) void viewport_update_smart_guest_follow(rct_window* window, const Guest* peep) { - Focus2 focus = Focus2(peep->sprite_index); + Focus focus = Focus(peep->sprite_index); window->viewport_target_sprite = peep->sprite_index; if (peep->State == PeepState::Picked) { window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; window->viewport_target_sprite = SPRITE_INDEX_NULL; - window->focus2 = std::nullopt; // No focus + window->focus = std::nullopt; // No focus return; } @@ -734,7 +734,7 @@ void viewport_update_smart_guest_follow(rct_window* window, const Guest* peep) const auto car = train->GetCar(peep->CurrentCar); if (car != nullptr) { - focus = Focus2(car->sprite_index); + focus = Focus(car->sprite_index); overallFocus = false; window->viewport_target_sprite = car->sprite_index; } @@ -752,12 +752,12 @@ void viewport_update_smart_guest_follow(rct_window* window, const Guest* peep) coordFocus.x = xy.x; coordFocus.y = xy.y; coordFocus.z = tile_element_height(xy) + (4 * COORDS_Z_STEP); - focus = Focus2(coordFocus); + focus = Focus(coordFocus); window->viewport_target_sprite = SPRITE_INDEX_NULL; } } - window->focus2 = focus; + window->focus = focus; } void viewport_update_smart_staff_follow(rct_window* window, const Staff* peep) @@ -766,17 +766,17 @@ void viewport_update_smart_staff_follow(rct_window* window, const Staff* peep) { window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; window->viewport_target_sprite = SPRITE_INDEX_NULL; - window->focus2 = std::nullopt; + window->focus = std::nullopt; return; } - window->focus2 = Focus2(window->viewport_smart_follow_sprite); + window->focus = Focus(window->viewport_smart_follow_sprite); window->viewport_target_sprite = window->viewport_smart_follow_sprite; } void viewport_update_smart_vehicle_follow(rct_window* window) { - window->focus2 = Focus2(window->viewport_smart_follow_sprite); + window->focus = Focus(window->viewport_smart_follow_sprite); window->viewport_target_sprite = window->viewport_smart_follow_sprite; } diff --git a/src/openrct2/interface/Viewport.h b/src/openrct2/interface/Viewport.h index d9b22283ac..697eb65510 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -104,7 +104,7 @@ extern uint8_t gCurrentRotation; void viewport_init_all(); std::optional centre_2d_coordinates(const CoordsXYZ& loc, rct_viewport* viewport); -void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus2& focus); +void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus& focus); void viewport_remove(rct_viewport* viewport); void viewports_invalidate(int32_t left, int32_t top, int32_t right, int32_t bottom, int32_t maxZoom = -1); void viewport_update_position(rct_window* window); diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index 929a0b9141..f6fbbba70c 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -195,7 +195,7 @@ struct rct_scroll constexpr auto WINDOW_SCROLL_UNDEFINED = std::numeric_limits::max(); -struct Focus2 +struct Focus { using CoordinateFocus = CoordsXYZ; using EntityFocus = uint16_t; @@ -203,7 +203,7 @@ struct Focus2 uint8_t zoom = 0; std::variant data; - template constexpr explicit Focus2(T newValue, uint8_t newZoom = 0) + template constexpr explicit Focus(T newValue, uint8_t newZoom = 0) { data = newValue; zoom = newZoom; @@ -211,7 +211,7 @@ struct Focus2 CoordsXYZ GetPos() const; - constexpr bool operator==(const Focus2& other) const + constexpr bool operator==(const Focus& other) const { if (zoom != other.zoom) { @@ -219,7 +219,7 @@ struct Focus2 } return data == other.data; } - constexpr bool operator!=(const Focus2& other) const + constexpr bool operator!=(const Focus& other) const { return !(*this == other); } diff --git a/src/openrct2/interface/Window_internal.cpp b/src/openrct2/interface/Window_internal.cpp index 576212edc7..35aaa071db 100644 --- a/src/openrct2/interface/Window_internal.cpp +++ b/src/openrct2/interface/Window_internal.cpp @@ -12,10 +12,10 @@ void rct_window::SetLocation(const CoordsXYZ& coords) void rct_window::ScrollToViewport() { - if (viewport == nullptr || !focus2.has_value()) + if (viewport == nullptr || !focus.has_value()) return; - CoordsXYZ newCoords = focus2.value().GetPos(); + CoordsXYZ newCoords = focus.value().GetPos(); auto mainWindow = window_get_main(); if (mainWindow != nullptr) diff --git a/src/openrct2/interface/Window_internal.h b/src/openrct2/interface/Window_internal.h index b699aa0b06..56dab05199 100644 --- a/src/openrct2/interface/Window_internal.h +++ b/src/openrct2/interface/Window_internal.h @@ -55,7 +55,7 @@ struct rct_window uint32_t list_item_positions[1024]{}; uint16_t no_list_items{}; // 0 for no items int16_t selected_list_item{}; // -1 for none selected - std::optional focus2; + std::optional focus; union { campaign_variables campaign;