diff --git a/src/openrct2-ui/windows/Player.cpp b/src/openrct2-ui/windows/Player.cpp index 45aae78737..177618bdb6 100644 --- a/src/openrct2-ui/windows/Player.cpp +++ b/src/openrct2-ui/windows/Player.cpp @@ -648,24 +648,26 @@ static void window_player_update_viewport(rct_window* w, bool scroll) LocationXYZ16 coord = network_get_player_last_action_coord(playerIndex); if (coord.x != 0 || coord.y != 0 || coord.z != 0) { - int32_t viewX, viewY; - centre_2d_coordinates(coord.x, coord.y, coord.z, &viewX, &viewY, viewport); - + auto centreLoc = centre_2d_coordinates({ coord.x, coord.y, coord.z }, viewport); + if (!centreLoc) + { + return; + } // Don't scroll if the view was originally undefined if (w->var_492 == -1) { scroll = false; } - if (!scroll || w->saved_view_x != viewX || w->saved_view_y != viewY) + if (!scroll || w->saved_view_x != centreLoc->x || w->saved_view_y != centreLoc->y) { w->flags |= WF_SCROLLING_TO_LOCATION; - w->saved_view_x = viewX; - w->saved_view_y = viewY; + w->saved_view_x = centreLoc->x; + w->saved_view_y = centreLoc->y; if (!scroll) { - w->viewport->view_x = viewX; - w->viewport->view_y = viewY; + w->viewport->view_x = centreLoc->x; + w->viewport->view_y = centreLoc->y; } widget_invalidate(w, WIDX_VIEWPORT); } diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 06f28f32e4..770f1dc86b 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -102,7 +102,6 @@ void viewport_init_all() textinput_cancel(); } -// TODO: Return ScreenCoords, takein CoordsXYZ /** * Converts between 3d point of a sprite to 2d coordinates for centring on that * sprite @@ -113,26 +112,21 @@ void viewport_init_all() * out_x : ax * out_y : bx */ -void centre_2d_coordinates(int32_t x, int32_t y, int32_t z, int32_t* out_x, int32_t* out_y, rct_viewport* viewport) +std::optional centre_2d_coordinates(CoordsXYZ loc, rct_viewport* viewport) { - int32_t start_x = x; - - CoordsXYZ coord_3d = { x, y, z }; - - auto coord_2d = translate_3d_to_2d_with_z(get_current_rotation(), coord_3d); + auto screenCoord = translate_3d_to_2d_with_z(get_current_rotation(), loc); // If the start location was invalid // propagate the invalid location to the output. // This fixes a bug that caused the game to enter an infinite loop. - if (start_x == LOCATION_NULL) + if (loc.x == LOCATION_NULL) { - *out_x = LOCATION_NULL; - *out_y = 0; - return; + return std::nullopt; } - *out_x = coord_2d.x - viewport->view_width / 2; - *out_y = coord_2d.y - viewport->view_height / 2; + screenCoord.x -= viewport->view_width / 2; + screenCoord.y -= viewport->view_height / 2; + return { screenCoord }; } /** @@ -203,13 +197,16 @@ void viewport_create( w->viewport_target_sprite = SPRITE_INDEX_NULL; } - int32_t view_x, view_y; - centre_2d_coordinates(centre_x, centre_y, centre_z, &view_x, &view_y, viewport); - - w->saved_view_x = view_x; - w->saved_view_y = view_y; - viewport->view_x = view_x; - viewport->view_y = view_y; + auto centreLoc = centre_2d_coordinates({ centre_x, centre_y, centre_z }, viewport); + if (!centreLoc) + { + log_error("Invalid location for viewport."); + return; + } + w->saved_view_x = centreLoc->x; + w->saved_view_y = centreLoc->y; + viewport->view_x = centreLoc->x; + viewport->view_y = centreLoc->y; } /** @@ -592,11 +589,12 @@ void viewport_update_position(rct_window* window) if (at_map_edge) { - int32_t _2d_x, _2d_y; - centre_2d_coordinates(mapCoord.x, mapCoord.y, 0, &_2d_x, &_2d_y, viewport); - - window->saved_view_x = _2d_x; - window->saved_view_y = _2d_y; + auto centreLoc = centre_2d_coordinates({ mapCoord, 0 }, viewport); + if (centreLoc) + { + window->saved_view_x = centreLoc->x; + window->saved_view_y = centreLoc->y; + } } x = window->saved_view_x; @@ -651,12 +649,13 @@ void viewport_update_sprite_follow(rct_window* window) viewport_set_underground_flag(underground, window, window->viewport); - int32_t centre_x, centre_y; - centre_2d_coordinates(sprite->generic.x, sprite->generic.y, sprite->generic.z, ¢re_x, ¢re_y, window->viewport); - - window->saved_view_x = centre_x; - window->saved_view_y = centre_y; - viewport_move(centre_x, centre_y, window, window->viewport); + auto centreLoc = centre_2d_coordinates({ sprite->generic.x, sprite->generic.y, sprite->generic.z }, window->viewport); + if (centreLoc) + { + window->saved_view_x = centreLoc->x; + window->saved_view_y = centreLoc->y; + viewport_move(centreLoc->x, centreLoc->y, window, window->viewport); + } } } diff --git a/src/openrct2/interface/Viewport.h b/src/openrct2/interface/Viewport.h index 02ed412c7f..5ffb26f117 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -10,6 +10,7 @@ #ifndef _VIEWPORT_H_ #define _VIEWPORT_H_ +#include "../core/Optional.hpp" #include "../world/Location.hpp" #include "Window.h" @@ -120,7 +121,7 @@ extern paint_entry* gNextFreePaintStruct; extern uint8_t gCurrentRotation; void viewport_init_all(); -void centre_2d_coordinates(int32_t x, int32_t y, int32_t z, int32_t* out_x, int32_t* out_y, rct_viewport* viewport); +std::optional centre_2d_coordinates(CoordsXYZ loc, rct_viewport* viewport); void viewport_create( rct_window* w, int32_t x, int32_t y, int32_t width, int32_t height, int32_t zoom, int32_t centre_x, int32_t centre_y, int32_t centre_z, char flags, uint16_t sprite); diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index 4ad02c5ee2..552ba4bedc 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -935,13 +935,15 @@ void window_rotate_camera(rct_window* w, int32_t direction) gCurrentRotation = (get_current_rotation() + direction) & 3; - int32_t new_x, new_y; - centre_2d_coordinates(coords.x, coords.y, z, &new_x, &new_y, viewport); + auto centreLoc = centre_2d_coordinates({ coords, z }, viewport); - w->saved_view_x = new_x; - w->saved_view_y = new_y; - viewport->view_x = new_x; - viewport->view_y = new_y; + if (centreLoc) + { + w->saved_view_x = centreLoc->x; + w->saved_view_y = centreLoc->y; + viewport->view_x = centreLoc->x; + viewport->view_y = centreLoc->y; + } w->Invalidate(); @@ -960,25 +962,35 @@ void window_viewport_get_map_coords_by_cursor( get_map_coordinates_from_pos(mouse_x, mouse_y, VIEWPORT_INTERACTION_MASK_NONE, map_x, map_y, nullptr, nullptr, nullptr); // Get viewport coordinates centring around the tile. - int32_t base_height = tile_element_height({ *map_x, *map_y }); - int32_t dest_x, dest_y; - centre_2d_coordinates(*map_x, *map_y, base_height, &dest_x, &dest_y, w->viewport); + int32_t z = tile_element_height({ *map_x, *map_y }); + + auto centreLoc = centre_2d_coordinates({ *map_x, *map_y, z }, w->viewport); + if (!centreLoc) + { + log_error("Invalid location."); + return; + } // Rebase mouse position onto centre of window, and compensate for zoom level. int32_t rebased_x = ((w->width >> 1) - mouse_x) * (1 << w->viewport->zoom), rebased_y = ((w->height >> 1) - mouse_y) * (1 << w->viewport->zoom); // Compute cursor offset relative to tile. - *offset_x = (w->saved_view_x - (dest_x + rebased_x)) * (1 << w->viewport->zoom); - *offset_y = (w->saved_view_y - (dest_y + rebased_y)) * (1 << w->viewport->zoom); + *offset_x = (w->saved_view_x - (centreLoc->x + rebased_x)) * (1 << w->viewport->zoom); + *offset_y = (w->saved_view_y - (centreLoc->y + rebased_y)) * (1 << w->viewport->zoom); } void window_viewport_centre_tile_around_cursor(rct_window* w, int16_t map_x, int16_t map_y, int16_t offset_x, int16_t offset_y) { // Get viewport coordinates centring around the tile. - int32_t dest_x, dest_y; - int32_t base_height = tile_element_height({ map_x, map_y }); - centre_2d_coordinates(map_x, map_y, base_height, &dest_x, &dest_y, w->viewport); + int32_t z = tile_element_height({ map_x, map_y }); + auto centreLoc = centre_2d_coordinates({ map_x, map_y, z }, w->viewport); + + if (!centreLoc) + { + log_error("Invalid location."); + return; + } // Get mouse position to offset against. int32_t mouse_x, mouse_y; @@ -989,8 +1001,8 @@ void window_viewport_centre_tile_around_cursor(rct_window* w, int16_t map_x, int rebased_y = ((w->height >> 1) - mouse_y) * (1 << w->viewport->zoom); // Apply offset to the viewport. - w->saved_view_x = dest_x + rebased_x + (offset_x / (1 << w->viewport->zoom)); - w->saved_view_y = dest_y + rebased_y + (offset_y / (1 << w->viewport->zoom)); + w->saved_view_x = centreLoc->x + rebased_x + (offset_x / (1 << w->viewport->zoom)); + w->saved_view_y = centreLoc->y + rebased_y + (offset_y / (1 << w->viewport->zoom)); } void window_zoom_set(rct_window* w, int32_t zoomLevel, bool atCursor)