From fa57b6aea07f357ecc8dc90f7872fbbca8188c31 Mon Sep 17 00:00:00 2001 From: Duncan Date: Sat, 18 Sep 2021 20:34:38 +0100 Subject: [PATCH] Remove focus union and replace with typed focus (#15426) * Remove focus union and replace with typed focus This if for the NSF to allow for CoordsXYZ * Remove legacy structures * Rework viewport_create to deduplicate logic * Simplify yet further * Apply review comments * Remove intermediate --- src/openrct2-ui/interface/Window.cpp | 6 +- src/openrct2-ui/scripting/CustomWindow.cpp | 8 +- src/openrct2-ui/windows/Banner.cpp | 3 +- src/openrct2-ui/windows/EditorMain.cpp | 3 +- src/openrct2-ui/windows/Guest.cpp | 21 +--- src/openrct2-ui/windows/Main.cpp | 3 +- src/openrct2-ui/windows/Park.cpp | 34 +---- src/openrct2-ui/windows/Player.cpp | 8 +- src/openrct2-ui/windows/Ride.cpp | 68 +++------- src/openrct2-ui/windows/ScenarioSelect.cpp | 1 - src/openrct2-ui/windows/Sign.cpp | 7 +- src/openrct2-ui/windows/Staff.cpp | 25 +--- .../windows/TitleCommandEditor.cpp | 6 +- src/openrct2-ui/windows/Viewport.cpp | 3 +- src/openrct2/interface/Viewport.cpp | 117 +++++++++--------- src/openrct2/interface/Viewport.h | 6 +- src/openrct2/interface/Window.h | 66 ++++------ src/openrct2/interface/Window_internal.cpp | 22 +--- src/openrct2/interface/Window_internal.h | 3 +- 19 files changed, 140 insertions(+), 270 deletions(-) diff --git a/src/openrct2-ui/interface/Window.cpp b/src/openrct2-ui/interface/Window.cpp index bf11d1c644..14aee560f7 100644 --- a/src/openrct2-ui/interface/Window.cpp +++ b/src/openrct2-ui/interface/Window.cpp @@ -274,11 +274,7 @@ rct_window* WindowCreate( w->min_height = height; w->max_height = height; - w->viewport_focus_coordinates.var_480 = 0; - w->viewport_focus_coordinates.x = 0; - w->viewport_focus_coordinates.y = 0; - w->viewport_focus_coordinates.z = 0; - w->viewport_focus_coordinates.rotation = 0; + w->focus2 = 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 5573233436..4e01689373 100644 --- a/src/openrct2-ui/scripting/CustomWindow.cpp +++ b/src/openrct2-ui/scripting/CustomWindow.cpp @@ -786,12 +786,8 @@ namespace OpenRCT2::Ui::Windows auto wheight = viewportWidget->height() - 1; if (viewport == nullptr) { - auto mapX = 0; - auto mapY = 0; - auto mapZ = 0; - viewport_create( - this, { left, top }, wwidth, wheight, 0, { mapX, mapY, mapZ }, VIEWPORT_FOCUS_TYPE_COORDINATE, - SPRITE_INDEX_NULL); + const auto focus = Focus2(CoordsXYZ(0, 0, 0)); + viewport_create(this, { left, top }, wwidth, wheight, focus); flags |= WF_NO_SCROLLING; Invalidate(); } diff --git a/src/openrct2-ui/windows/Banner.cpp b/src/openrct2-ui/windows/Banner.cpp index 2ec3a3e9a6..3959bc29de 100644 --- a/src/openrct2-ui/windows/Banner.cpp +++ b/src/openrct2-ui/windows/Banner.cpp @@ -79,9 +79,10 @@ 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, 0, _bannerViewPos, 0, SPRITE_INDEX_NULL); + (viewportWidget->width()) - 1, (viewportWidget->height()) - 1, focus); 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 d38822ea9a..121b8e4ac3 100644 --- a/src/openrct2-ui/windows/EditorMain.cpp +++ b/src/openrct2-ui/windows/EditorMain.cpp @@ -40,7 +40,8 @@ rct_window* window_editor_main_open() &window_editor_main_events, WC_MAIN_WINDOW, WF_STICK_TO_BACK); window->widgets = window_editor_main_widgets; - viewport_create(window, window->windowPos, window->width, window->height, 0, { 0x0FFF, 0x0FFF, 0 }, 0x1, SPRITE_INDEX_NULL); + const auto focus = Focus2(CoordsXYZ(0x0FFF, 0x0FFF, 0)); + viewport_create(window, window->windowPos, window->width, window->height, focus); window->viewport->flags |= 0x0400; gCurrentRotation = 0; diff --git a/src/openrct2-ui/windows/Guest.cpp b/src/openrct2-ui/windows/Guest.cpp index 3d0d2565a9..d96bcf206d 100644 --- a/src/openrct2-ui/windows/Guest.cpp +++ b/src/openrct2-ui/windows/Guest.cpp @@ -398,7 +398,6 @@ rct_window* window_guest_open(Peep* peep) window->enabled_widgets = window_guest_page_enabled_widgets[0]; window->number = peep->sprite_index; window->page = 0; - window->viewport_focus_coordinates.y = 0; window->frame_no = 0; window->list_information_type = 0; window->picked_peep_frame = 0; @@ -410,8 +409,6 @@ rct_window* window_guest_open(Peep* peep) window->max_height = 450; window->no_list_items = 0; window->selected_list_item = -1; - - window->viewport_focus_coordinates.y = -1; } window->page = 0; @@ -730,16 +727,12 @@ void window_guest_viewport_init(rct_window* w) return; } - auto focus = viewport_update_smart_guest_follow(w, peep); + viewport_update_smart_guest_follow(w, peep); bool reCreateViewport = false; uint16_t origViewportFlags{}; if (w->viewport != nullptr) { - // Check all combos, for now skipping y and rot - if (focus.coordinate.x == w->viewport_focus_coordinates.x - && (focus.coordinate.y & VIEWPORT_FOCUS_Y_MASK) == w->viewport_focus_coordinates.y - && focus.coordinate.z == w->viewport_focus_coordinates.z - && focus.coordinate.rotation == w->viewport_focus_coordinates.rotation) + if (w->focus2.has_value()) return; origViewportFlags = w->viewport->flags; @@ -750,11 +743,6 @@ void window_guest_viewport_init(rct_window* w) window_event_invalidate_call(w); - w->viewport_focus_coordinates.x = focus.coordinate.x; - w->viewport_focus_coordinates.y = focus.coordinate.y; - w->viewport_focus_coordinates.z = focus.coordinate.z; - w->viewport_focus_coordinates.rotation = focus.coordinate.rotation; - if (peep->State != PeepState::Picked && w->viewport == nullptr) { auto view_widget = &w->widgets[WIDX_VIEWPORT]; @@ -762,10 +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, 0, - { focus.coordinate.x, focus.coordinate.y & VIEWPORT_FOCUS_Y_MASK, focus.coordinate.z }, - focus.sprite.type & VIEWPORT_FOCUS_TYPE_MASK, focus.sprite.sprite_id); + viewport_create(w, screenPos, width, height, w->focus2.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 4013b9f1ae..347f2cc49f 100644 --- a/src/openrct2-ui/windows/Main.cpp +++ b/src/openrct2-ui/windows/Main.cpp @@ -41,7 +41,8 @@ rct_window* window_main_open() WF_STICK_TO_BACK); window->widgets = window_main_widgets; - viewport_create(window, window->windowPos, window->width, window->height, 0, { 0x0FFF, 0x0FFF, 0 }, 0x1, SPRITE_INDEX_NULL); + const auto focus = Focus2(CoordsXYZ(0x0FFF, 0x0FFF, 0)); + viewport_create(window, window->windowPos, window->width, window->height, focus); 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 4ac9087e87..6b477ad3b4 100644 --- a/src/openrct2-ui/windows/Park.cpp +++ b/src/openrct2-ui/windows/Park.cpp @@ -415,7 +415,6 @@ static rct_window* window_park_open() w->enabled_widgets = window_park_page_enabled_widgets[WINDOW_PARK_PAGE_ENTRANCE]; w->number = 0; w->page = WINDOW_PARK_PAGE_ENTRANCE; - w->viewport_focus_coordinates.y = 0; w->frame_no = 0; w->list_information_type = std::numeric_limits::max(); w->numberOfStaff = -1; @@ -459,8 +458,6 @@ rct_window* window_park_entrance_open() if (window == nullptr) { window = window_park_open(); - window->viewport_focus_coordinates.y = -1; - window->viewport_focus_coordinates.x = -1; } window->page = WINDOW_PARK_PAGE_ENTRANCE; @@ -738,22 +735,16 @@ static void window_park_entrance_paint(rct_window* w, rct_drawpixelinfo* dpi) */ static void window_park_init_viewport(rct_window* w) { - int32_t x, y, z, r, xy, zr, viewportFlags; - x = y = z = r = xy = zr = 0; + int32_t viewportFlags; if (w->page != WINDOW_PARK_PAGE_ENTRANCE) return; + std::optional focus = std::nullopt; if (!gParkEntrances.empty()) { const auto& entrance = gParkEntrances[0]; - x = entrance.x + 16; - y = entrance.y + 16; - z = entrance.z + 32; - r = get_current_rotation(); - - xy = IMAGE_TYPE_TRANSPARENT | (y << 16) | x; - zr = (z << 16) | (r << 8); + focus = Focus2(CoordsXYZ{ entrance.x + 16, entrance.y + 16, entrance.z + 32 }); } if (w->viewport == nullptr) @@ -769,13 +760,9 @@ static void window_park_init_viewport(rct_window* w) // Call invalidate event window_event_invalidate_call(w); - w->viewport_focus_coordinates.x = x; - w->viewport_focus_coordinates.y = y; - w->viewport_focus_sprite.type |= VIEWPORT_FOCUS_TYPE_COORDINATE; - w->viewport_focus_coordinates.z = z; - w->viewport_focus_coordinates.rotation = r; + w->focus2 = focus; - if (zr != 0xFFFF) + if (focus.has_value()) { // Create viewport if (w->viewport == nullptr) @@ -783,8 +770,7 @@ static void window_park_init_viewport(rct_window* w) rct_widget* viewportWidget = &window_park_entrance_widgets[WIDX_VIEWPORT]; viewport_create( w, w->windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 }, - viewportWidget->width() - 1, viewportWidget->height() - 1, 0, { x, y, z }, - w->viewport_focus_sprite.type & VIEWPORT_FOCUS_TYPE_MASK, SPRITE_INDEX_NULL); + viewportWidget->width() - 1, viewportWidget->height() - 1, focus.value()); w->flags |= (1 << 2); w->Invalidate(); } @@ -811,8 +797,6 @@ rct_window* window_park_rating_open() if (window == nullptr) { window = window_park_open(); - window->viewport_focus_coordinates.x = -1; - window->viewport_focus_coordinates.y = -1; } if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) @@ -947,8 +931,6 @@ rct_window* window_park_guests_open() if (window == nullptr) { window = window_park_open(); - window->viewport_focus_coordinates.x = -1; - window->viewport_focus_coordinates.y = -1; } if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) @@ -1356,8 +1338,6 @@ rct_window* window_park_objective_open() if (window == nullptr) { window = window_park_open(); - window->viewport_focus_coordinates.x = -1; - window->viewport_focus_coordinates.y = -1; } if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) @@ -1549,8 +1529,6 @@ rct_window* window_park_awards_open() if (window == nullptr) { window = window_park_open(); - window->viewport_focus_coordinates.x = -1; - window->viewport_focus_coordinates.y = -1; } if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) diff --git a/src/openrct2-ui/windows/Player.cpp b/src/openrct2-ui/windows/Player.cpp index bbbff05b0b..fab5a3df40 100644 --- a/src/openrct2-ui/windows/Player.cpp +++ b/src/openrct2-ui/windows/Player.cpp @@ -155,7 +155,6 @@ rct_window* window_player_open(uint8_t id) window = WindowCreateAutoPos(240, 170, &window_player_overview_events, WC_PLAYER, WF_RESIZABLE); window->number = id; window->page = 0; - window->viewport_focus_coordinates.y = 0; window->frame_no = 0; window->list_information_type = 0; window->picked_peep_frame = 0; @@ -164,10 +163,9 @@ rct_window* window_player_open(uint8_t id) window->min_height = 134; window->max_width = 500; window->max_height = 450; + window->no_list_items = 0; window->selected_list_item = -1; - - window->viewport_focus_coordinates.y = -1; } window->page = 0; @@ -549,8 +547,8 @@ static void window_player_set_page(rct_window* w, int32_t page) { if (w->viewport == nullptr) { - viewport_create( - w, w->windowPos, w->width, w->height, 0, TileCoordsXYZ(128, 128, 0).ToCoordsXYZ(), 1, SPRITE_INDEX_NULL); + const auto focus = Focus2(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); window_player_update_viewport(w, false); diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index a4249d37c9..0805b3d36d 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -1591,42 +1591,29 @@ static void window_ride_init_viewport(rct_window* w) if (ride == nullptr) return; - int32_t viewSelectionIndex = w->viewport_focus_coordinates.var_480 - 1; + int32_t viewSelectionIndex = w->ride.view - 1; - union - { - sprite_focus sprite; - coordinate_focus coordinate; - } focus; - - focus.coordinate.x = 0; - focus.coordinate.y = 0; - focus.coordinate.z = 0; - focus.sprite.sprite_id = SPRITE_INDEX_NULL; - focus.coordinate.zoom = 0; - focus.coordinate.rotation = get_current_rotation(); - focus.coordinate.width = 0; - focus.coordinate.height = 0; + std::optional focus; if (viewSelectionIndex >= 0 && viewSelectionIndex < ride->num_vehicles && ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) { - focus.sprite.sprite_id = ride->vehicles[viewSelectionIndex]; + uint16_t vehId = ride->vehicles[viewSelectionIndex]; rct_ride_entry* ride_entry = ride->GetRideEntry(); if (ride_entry && ride_entry->tab_vehicle != 0) { - Vehicle* vehicle = GetEntity(focus.sprite.sprite_id); + Vehicle* vehicle = GetEntity(vehId); if (vehicle == nullptr) { - focus.sprite.sprite_id = SPRITE_INDEX_NULL; + vehId = SPRITE_INDEX_NULL; } else if (vehicle->next_vehicle_on_train != SPRITE_INDEX_NULL) { - focus.sprite.sprite_id = vehicle->next_vehicle_on_train; + vehId = vehicle->next_vehicle_on_train; } } - if (focus.sprite.sprite_id != SPRITE_INDEX_NULL) + if (vehId != SPRITE_INDEX_NULL) { - focus.sprite.type |= VIEWPORT_FOCUS_TYPE_SPRITE; + focus = Focus2(vehId); } } else if (viewSelectionIndex >= ride->num_vehicles && viewSelectionIndex < (ride->num_vehicles + ride->num_stations)) @@ -1634,41 +1621,28 @@ static void window_ride_init_viewport(rct_window* w) auto stationIndex = GetStationIndexFromViewSelection(*w); if (stationIndex) { - auto location = ride->stations[*stationIndex].GetStart(); - focus.coordinate.x = location.x; - focus.coordinate.y = location.y; - focus.coordinate.z = location.z; - focus.sprite.type |= VIEWPORT_FOCUS_TYPE_COORDINATE; + const auto location = ride->stations[*stationIndex].GetStart(); + focus = Focus2(location); } } else { if (viewSelectionIndex > 0) { - w->viewport_focus_coordinates.var_480 = 0; + w->ride.view = 0; } if (w->number < ride_overall_views.size()) { const auto& view = ride_overall_views[w->number]; - focus.coordinate.x = view.x; - focus.coordinate.y = view.y; - focus.coordinate.z = view.z; - focus.coordinate.zoom = view.zoom; - focus.sprite.type |= VIEWPORT_FOCUS_TYPE_COORDINATE; + CoordsXYZ loc = { view.x, view.y, view.z }; + focus = Focus2(loc, view.zoom); } } - focus.coordinate.var_480 = w->viewport_focus_coordinates.var_480; uint16_t viewport_flags = 0; - if (w->viewport != nullptr) { - if (focus.coordinate.x == w->viewport_focus_coordinates.x - && (focus.coordinate.y & VIEWPORT_FOCUS_Y_MASK) == w->viewport_focus_coordinates.y - && focus.coordinate.z == w->viewport_focus_coordinates.z - && focus.coordinate.rotation == w->viewport_focus_coordinates.rotation - && focus.coordinate.zoom == w->viewport_focus_coordinates.zoom && focus.coordinate.width == w->width - && focus.coordinate.height == w->height) + if (focus == w->focus2) { return; } @@ -1682,13 +1656,7 @@ static void window_ride_init_viewport(rct_window* w) window_event_invalidate_call(w); - w->viewport_focus_coordinates.x = focus.coordinate.x; - w->viewport_focus_coordinates.y = focus.coordinate.y; - w->viewport_focus_coordinates.z = focus.coordinate.z; - w->viewport_focus_coordinates.rotation = focus.coordinate.rotation; - w->viewport_focus_coordinates.zoom = focus.coordinate.zoom; - w->viewport_focus_coordinates.width = w->width; - w->viewport_focus_coordinates.height = w->height; + w->focus2 = focus; // rct2: 0x006aec9c only used here so brought it into the function if (!w->viewport && !ride->overall_view.IsNull()) @@ -1698,10 +1666,8 @@ static void window_ride_init_viewport(rct_window* w) auto screenPos = w->windowPos + ScreenCoordsXY{ view_widget->left + 1, view_widget->top + 1 }; int32_t width = view_widget->width() - 1; int32_t height = view_widget->height() - 1; - viewport_create( - w, screenPos, width, height, focus.coordinate.zoom, - { focus.coordinate.x, focus.coordinate.y & VIEWPORT_FOCUS_Y_MASK, focus.coordinate.z }, - focus.sprite.type & VIEWPORT_FOCUS_TYPE_MASK, focus.sprite.sprite_id); + + viewport_create(w, screenPos, width, height, w->focus2.value()); w->flags |= WF_NO_SCROLLING; w->Invalidate(); diff --git a/src/openrct2-ui/windows/ScenarioSelect.cpp b/src/openrct2-ui/windows/ScenarioSelect.cpp index 99f14c0f87..19f24afbf1 100644 --- a/src/openrct2-ui/windows/ScenarioSelect.cpp +++ b/src/openrct2-ui/windows/ScenarioSelect.cpp @@ -196,7 +196,6 @@ rct_window* window_scenarioselect_open(std::function cal initialise_list_items(window); WindowInitScrollWidgets(window); - window->viewport_focus_coordinates.var_480 = -1; window->highlighted_scenario = nullptr; return window; diff --git a/src/openrct2-ui/windows/Sign.cpp b/src/openrct2-ui/windows/Sign.cpp index f9e62a7477..bddfd0dd20 100644 --- a/src/openrct2-ui/windows/Sign.cpp +++ b/src/openrct2-ui/windows/Sign.cpp @@ -127,10 +127,10 @@ 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, 0, { signViewPosition, viewZ }, 0, SPRITE_INDEX_NULL); + viewportWidget.height() - 1, focus); viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; Invalidate(); @@ -300,9 +300,10 @@ 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, 0, signViewPos, 0, SPRITE_INDEX_NULL); + viewportWidget->height() - 1, focus); 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 4545948c59..2a691c0fab 100644 --- a/src/openrct2-ui/windows/Staff.cpp +++ b/src/openrct2-ui/windows/Staff.cpp @@ -267,7 +267,6 @@ rct_window* window_staff_open(Peep* peep) w->number = peep->sprite_index; w->page = 0; - w->viewport_focus_coordinates.y = 0; w->frame_no = 0; w->highlighted_item = 0; @@ -1347,9 +1346,7 @@ void window_staff_viewport_init(rct_window* w) if (w->page != WINDOW_STAFF_OVERVIEW) return; - sprite_focus focus = {}; - - focus.sprite_id = w->number; + std::optional focus; const auto peep = GetStaff(w); if (peep == nullptr) @@ -1357,23 +1354,16 @@ void window_staff_viewport_init(rct_window* w) return; } - if (peep->State == PeepState::Picked) + if (peep->State != PeepState::Picked) { - focus.sprite_id = SPRITE_INDEX_NULL; - } - else - { - focus.type |= VIEWPORT_FOCUS_TYPE_SPRITE | VIEWPORT_FOCUS_TYPE_COORDINATE; - focus.rotation = get_current_rotation(); + focus = Focus2(peep->sprite_index); } uint16_t viewport_flags; if (w->viewport) { - // Check all combos, for now skipping y and rot - if (focus.sprite_id == w->viewport_focus_sprite.sprite_id && focus.type == w->viewport_focus_sprite.type - && focus.rotation == w->viewport_focus_sprite.rotation) + if (focus == w->focus2) return; viewport_flags = w->viewport->flags; @@ -1388,9 +1378,7 @@ void window_staff_viewport_init(rct_window* w) window_event_invalidate_call(w); - w->viewport_focus_sprite.sprite_id = focus.sprite_id; - w->viewport_focus_sprite.type = focus.type; - w->viewport_focus_sprite.rotation = focus.rotation; + w->focus2 = focus; if (peep->State != PeepState::Picked) { @@ -1402,8 +1390,7 @@ void window_staff_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, 0, { 0, 0, 0 }, focus.type & VIEWPORT_FOCUS_TYPE_MASK, focus.sprite_id); + viewport_create(w, screenPos, width, height, focus.value()); w->flags |= WF_NO_SCROLLING; w->Invalidate(); } diff --git a/src/openrct2-ui/windows/TitleCommandEditor.cpp b/src/openrct2-ui/windows/TitleCommandEditor.cpp index 718964cefd..4b15b97904 100644 --- a/src/openrct2-ui/windows/TitleCommandEditor.cpp +++ b/src/openrct2-ui/windows/TitleCommandEditor.cpp @@ -227,9 +227,10 @@ 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 }); viewport_create( window, window->windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 }, - viewportWidget->width() - 1, viewportWidget->height() - 1, 0, { 0, 0, 0 }, 0, SPRITE_INDEX_NULL); + viewportWidget->width() - 1, viewportWidget->height() - 1, focus); _window_title_command_editor_index = index; _window_title_command_editor_insert = insert; @@ -476,7 +477,8 @@ static void window_title_command_editor_dropdown(rct_window* w, rct_widgetindex _command.SpriteIndex = SPRITE_INDEX_NULL; _command.SpriteName[0] = '\0'; window_unfollow_sprite(w); - w->viewport->flags &= ~VIEWPORT_FOCUS_TYPE_SPRITE; + // This is incorrect + w->viewport->flags &= ~VIEWPORT_FLAG_GRIDLINES; break; case TitleScript::Speed: _command.Speed = 1; diff --git a/src/openrct2-ui/windows/Viewport.cpp b/src/openrct2-ui/windows/Viewport.cpp index 821ede093a..abcd712170 100644 --- a/src/openrct2-ui/windows/Viewport.cpp +++ b/src/openrct2-ui/windows/Viewport.cpp @@ -76,7 +76,8 @@ public: enabled_widgets = (1ULL << WIDX_CLOSE) | (1ULL << WIDX_ZOOM_IN) | (1ULL << WIDX_ZOOM_OUT) | (1ULL << WIDX_LOCATE); // Create viewport - viewport_create(this, windowPos, width, height, 0, TileCoordsXYZ(128, 128, 0).ToCoordsXYZ(), 1, SPRITE_INDEX_NULL); + const auto focus = Focus2(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ()); + viewport_create(this, windowPos, width, height, focus); if (viewport == nullptr) { Close(); diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 57f4134d93..65e093703f 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -117,6 +117,30 @@ std::optional centre_2d_coordinates(const CoordsXYZ& loc, rct_vi return { screenCoord }; } +CoordsXYZ Focus2::GetPos() const +{ + return std::visit( + [](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) + return arg; + else if constexpr (std::is_same_v) + { + auto* centreEntity = GetEntity(arg); + if (centreEntity != nullptr) + { + return CoordsXYZ{ centreEntity->x, centreEntity->y, centreEntity->z }; + } + else + { + log_error("Invalid entity for focus."); + return CoordsXYZ{}; + } + } + }, + data); +} + /** * Viewport will look at sprite or at coordinates as specified in flags 0b_1X * for sprite 0b_0X for coordinates @@ -134,9 +158,7 @@ std::optional centre_2d_coordinates(const CoordsXYZ& loc, rct_vi * 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, int32_t zoom, CoordsXYZ centrePos, - char flags, uint16_t sprite) +void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus2& focus) { rct_viewport* viewport = nullptr; if (_viewports.size() >= MAX_VIEWPORT_COUNT) @@ -151,11 +173,7 @@ void viewport_create( viewport->pos = screenCoords; viewport->width = width; viewport->height = height; - - if (!(flags & VIEWPORT_FOCUS_TYPE_COORDINATE)) - { - zoom = 0; - } + const auto zoom = focus.zoom; viewport->view_width = width << zoom; viewport->view_height = height << zoom; @@ -166,24 +184,16 @@ void viewport_create( viewport->flags |= VIEWPORT_FLAG_GRIDLINES; w->viewport = viewport; - if (flags & VIEWPORT_FOCUS_TYPE_SPRITE) - { - w->viewport_target_sprite = sprite; - auto* centreEntity = GetEntity(sprite); - if (centreEntity != nullptr) - { - centrePos = { centreEntity->x, centreEntity->y, centreEntity->z }; - } - else - { - log_error("Invalid entity for viewport."); - return; - } - } - else - { - w->viewport_target_sprite = SPRITE_INDEX_NULL; - } + CoordsXYZ centrePos = focus.GetPos(); + w->viewport_target_sprite = std::visit( + [](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) + return SPRITE_INDEX_NULL; + else if constexpr (std::is_same_v) + return arg; + }, + focus.data); auto centreLoc = centre_2d_coordinates(centrePos, viewport); if (!centreLoc.has_value()) @@ -692,24 +702,23 @@ 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->viewport_focus_sprite.sprite_id = window->viewport_smart_follow_sprite; + window->focus2 = Focus2(window->viewport_smart_follow_sprite); window->viewport_target_sprite = window->viewport_smart_follow_sprite; break; } } -viewport_focus viewport_update_smart_guest_follow(rct_window* window, const Guest* peep) +void viewport_update_smart_guest_follow(rct_window* window, const Guest* peep) { - viewport_focus focus{}; - focus.type = VIEWPORT_FOCUS_TYPE_SPRITE; - focus.sprite.sprite_id = peep->sprite_index; + Focus2 focus = Focus2(peep->sprite_index); + window->viewport_target_sprite = peep->sprite_index; if (peep->State == PeepState::Picked) { - focus.sprite.sprite_id = SPRITE_INDEX_NULL; window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; window->viewport_target_sprite = SPRITE_INDEX_NULL; - return focus; + window->focus2 = std::nullopt; // No focus + return; } bool overallFocus = true; @@ -725,8 +734,9 @@ viewport_focus viewport_update_smart_guest_follow(rct_window* window, const Gues const auto car = train->GetCar(peep->CurrentCar); if (car != nullptr) { - focus.sprite.sprite_id = car->sprite_index; + focus = Focus2(car->sprite_index); overallFocus = false; + window->viewport_target_sprite = car->sprite_index; } } } @@ -738,51 +748,36 @@ viewport_focus viewport_update_smart_guest_follow(rct_window* window, const Gues if (ride != nullptr) { auto xy = ride->overall_view.ToTileCentre(); - focus.type = VIEWPORT_FOCUS_TYPE_COORDINATE; - focus.coordinate.x = xy.x; - focus.coordinate.y = xy.y; - focus.coordinate.z = tile_element_height(xy) + (4 * COORDS_Z_STEP); - focus.sprite.type |= VIEWPORT_FOCUS_TYPE_COORDINATE; + CoordsXYZ coordFocus; + coordFocus.x = xy.x; + coordFocus.y = xy.y; + coordFocus.z = tile_element_height(xy) + (4 * COORDS_Z_STEP); + focus = Focus2(coordFocus); + window->viewport_target_sprite = SPRITE_INDEX_NULL; } } - else - { - focus.sprite.type |= VIEWPORT_FOCUS_TYPE_SPRITE | VIEWPORT_FOCUS_TYPE_COORDINATE; - focus.sprite.pad_486 &= 0xFFFF; - } - focus.coordinate.rotation = get_current_rotation(); - window->viewport_focus_sprite = focus.sprite; - window->viewport_target_sprite = window->viewport_focus_sprite.sprite_id; - return focus; + window->focus2 = focus; } void viewport_update_smart_staff_follow(rct_window* window, const Staff* peep) { - sprite_focus focus = {}; - - focus.sprite_id = window->viewport_smart_follow_sprite; - if (peep->State == PeepState::Picked) { window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; window->viewport_target_sprite = SPRITE_INDEX_NULL; + window->focus2 = std::nullopt; return; } - focus.type |= VIEWPORT_FOCUS_TYPE_SPRITE | VIEWPORT_FOCUS_TYPE_COORDINATE; - - window->viewport_focus_sprite = focus; - window->viewport_target_sprite = window->viewport_focus_sprite.sprite_id; + window->focus2 = Focus2(window->viewport_smart_follow_sprite); + window->viewport_target_sprite = window->viewport_smart_follow_sprite; } void viewport_update_smart_vehicle_follow(rct_window* window) { - sprite_focus focus = {}; - focus.sprite_id = window->viewport_smart_follow_sprite; - - window->viewport_focus_sprite = focus; - window->viewport_target_sprite = window->viewport_focus_sprite.sprite_id; + window->focus2 = Focus2(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 09091e511b..d9b22283ac 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -104,15 +104,13 @@ 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, int32_t zoom, CoordsXYZ centrePos, - char flags, uint16_t sprite); +void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus2& 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); void viewport_update_sprite_follow(rct_window* window); void viewport_update_smart_sprite_follow(rct_window* window); -viewport_focus viewport_update_smart_guest_follow(rct_window* window, const Guest* peep); +void viewport_update_smart_guest_follow(rct_window* window, const Guest* peep); void viewport_update_smart_staff_follow(rct_window* window, const Staff* peep); void viewport_update_smart_vehicle_follow(rct_window* window); void viewport_render( diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index 2eb24fb286..929a0b9141 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -20,6 +20,7 @@ #include #include #include +#include struct rct_drawpixelinfo; struct rct_window; @@ -194,51 +195,34 @@ struct rct_scroll constexpr auto WINDOW_SCROLL_UNDEFINED = std::numeric_limits::max(); -/** - * Viewport focus structure. - * size: 0xA - * Use sprite.type to work out type. - */ -struct coordinate_focus +struct Focus2 { - int16_t var_480; - int16_t x; // 0x482 - int16_t y; // 0x484 & VIEWPORT_FOCUS_Y_MASK - int16_t z; // 0x486 - uint8_t rotation; // 0x488 - uint8_t zoom; // 0x489 - int16_t width; - int16_t height; -}; + using CoordinateFocus = CoordsXYZ; + using EntityFocus = uint16_t; -// Type is viewport_target_sprite_id & 0x80000000 != 0 -struct sprite_focus -{ - int16_t var_480; - uint16_t sprite_id; // 0x482 - uint8_t pad_484; - uint8_t type; // 0x485 & VIEWPORT_FOCUS_TYPE_MASK - uint16_t pad_486; - uint8_t rotation; // 0x488 - uint8_t zoom; // 0x489 -}; + uint8_t zoom = 0; + std::variant data; -#define VIEWPORT_FOCUS_TYPE_MASK 0xC0 -enum VIEWPORT_FOCUS_TYPE : uint8_t -{ - VIEWPORT_FOCUS_TYPE_COORDINATE = (1 << 6), - VIEWPORT_FOCUS_TYPE_SPRITE = (1 << 7) -}; -#define VIEWPORT_FOCUS_Y_MASK 0x3FFF - -struct viewport_focus -{ - VIEWPORT_FOCUS_TYPE type{}; - union + template constexpr explicit Focus2(T newValue, uint8_t newZoom = 0) { - sprite_focus sprite; - coordinate_focus coordinate; - }; + data = newValue; + zoom = newZoom; + } + + CoordsXYZ GetPos() const; + + constexpr bool operator==(const Focus2& other) const + { + if (zoom != other.zoom) + { + return false; + } + return data == other.data; + } + constexpr bool operator!=(const Focus2& other) const + { + return !(*this == other); + } }; struct rct_window_event_list diff --git a/src/openrct2/interface/Window_internal.cpp b/src/openrct2/interface/Window_internal.cpp index 3db47f0186..576212edc7 100644 --- a/src/openrct2/interface/Window_internal.cpp +++ b/src/openrct2/interface/Window_internal.cpp @@ -12,28 +12,10 @@ void rct_window::SetLocation(const CoordsXYZ& coords) void rct_window::ScrollToViewport() { - // In original checked to make sure x and y were not -1 as well. - if (viewport == nullptr || viewport_focus_coordinates.y == -1) + if (viewport == nullptr || !focus2.has_value()) return; - CoordsXYZ newCoords = {}; - if (viewport_focus_sprite.type & VIEWPORT_FOCUS_TYPE_SPRITE) - { - auto* sprite = GetEntity(viewport_focus_sprite.sprite_id); - if (sprite == nullptr) - { - return; - } - newCoords.x = sprite->x; - newCoords.y = sprite->y; - newCoords.z = sprite->z; - } - else - { - newCoords.x = viewport_focus_coordinates.x; - newCoords.y = viewport_focus_coordinates.y & VIEWPORT_FOCUS_Y_MASK; - newCoords.z = viewport_focus_coordinates.z; - } + CoordsXYZ newCoords = focus2.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 ed63206e35..b699aa0b06 100644 --- a/src/openrct2/interface/Window_internal.h +++ b/src/openrct2/interface/Window_internal.h @@ -55,10 +55,9 @@ 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; union { - coordinate_focus viewport_focus_coordinates; - sprite_focus viewport_focus_sprite; campaign_variables campaign; new_ride_variables new_ride; news_variables news;