diff --git a/src/openrct2-ui/windows/Banner.cpp b/src/openrct2-ui/windows/Banner.cpp index fd4480a5e1..44467e0d20 100644 --- a/src/openrct2-ui/windows/Banner.cpp +++ b/src/openrct2-ui/windows/Banner.cpp @@ -153,7 +153,7 @@ rct_window* window_banner_open(rct_windownumber number) viewportWidget = &window_banner_widgets[WIDX_VIEWPORT]; viewport_create( w, w->x + viewportWidget->left + 1, w->y + viewportWidget->top + 1, (viewportWidget->right - viewportWidget->left) - 2, - (viewportWidget->bottom - viewportWidget->top) - 2, 0, view_x, view_y, view_z, 0, -1); + (viewportWidget->bottom - viewportWidget->top) - 2, 0, view_x, view_y, view_z, 0, SPRITE_INDEX_NULL); w->viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; window_invalidate(w); @@ -345,7 +345,7 @@ static void window_banner_viewport_rotate(rct_window* w) rct_widget* viewportWidget = &window_banner_widgets[WIDX_VIEWPORT]; viewport_create( w, w->x + viewportWidget->left + 1, w->y + viewportWidget->top + 1, (viewportWidget->right - viewportWidget->left) - 1, - (viewportWidget->bottom - viewportWidget->top) - 1, 0, view_x, view_y, view_z, 0, -1); + (viewportWidget->bottom - viewportWidget->top) - 1, 0, view_x, view_y, view_z, 0, SPRITE_INDEX_NULL); w->viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; window_invalidate(w); diff --git a/src/openrct2-ui/windows/EditorMain.cpp b/src/openrct2-ui/windows/EditorMain.cpp index 06c52ef9e1..ee97ea15ce 100644 --- a/src/openrct2-ui/windows/EditorMain.cpp +++ b/src/openrct2-ui/windows/EditorMain.cpp @@ -13,6 +13,7 @@ #include #include #include +#include static void window_editor_main_paint(rct_window* w, rct_drawpixelinfo* dpi); @@ -65,7 +66,7 @@ rct_window* window_editor_main_open() WC_MAIN_WINDOW, WF_STICK_TO_BACK); window->widgets = window_editor_main_widgets; - viewport_create(window, window->x, window->y, window->width, window->height, 0, 0x0FFF, 0x0FFF, 0, 0x1, -1); + viewport_create(window, window->x, window->y, window->width, window->height, 0, 0x0FFF, 0x0FFF, 0, 0x1, SPRITE_INDEX_NULL); window->viewport->flags |= 0x0400; gCurrentRotation = 0; diff --git a/src/openrct2-ui/windows/Guest.cpp b/src/openrct2-ui/windows/Guest.cpp index a188c6417b..8eaa297c2f 100644 --- a/src/openrct2-ui/windows/Guest.cpp +++ b/src/openrct2-ui/windows/Guest.cpp @@ -701,98 +701,38 @@ void window_guest_viewport_init(rct_window* w) if (w->page != WINDOW_GUEST_OVERVIEW) return; - union + auto peep = GET_PEEP(w->number); + if (peep != nullptr) { - sprite_focus sprite; - coordinate_focus coordinate; - } focus = {}; // The focus will be either a sprite or a coordinate. - - focus.sprite.sprite_id = w->number; - - Peep* peep = GET_PEEP(w->number); - - if (peep->state == PEEP_STATE_PICKED) - { - focus.sprite.sprite_id = SPRITE_INDEX_NULL; - } - else - { - uint8_t final_check = 1; - if (peep->state == PEEP_STATE_ON_RIDE || peep->state == PEEP_STATE_ENTERING_RIDE - || (peep->state == PEEP_STATE_LEAVING_RIDE && peep->x == LOCATION_NULL)) + auto focus = viewport_update_smart_guest_follow(w, peep); + bool reCreateViewport = false; + uint16_t origViewportFlags{}; + if (w->viewport != nullptr) { - Ride* ride = get_ride(peep->current_ride); - if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) - { - rct_vehicle* train = GET_VEHICLE(ride->vehicles[peep->current_train]); - int32_t car = peep->current_car; + // 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) + return; - for (; car != 0; car--) - { - train = GET_VEHICLE(train->next_vehicle_on_train); - } + origViewportFlags = w->viewport->flags; - focus.sprite.sprite_id = train->sprite_index; - final_check = 0; - } + reCreateViewport = true; + w->viewport->width = 0; + w->viewport = nullptr; } - if (peep->x == LOCATION_NULL && final_check) + + 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 != PEEP_STATE_PICKED && w->viewport == nullptr) { - Ride* ride = get_ride(peep->current_ride); - int32_t x = ride->overall_view.x * 32 + 16; - int32_t y = ride->overall_view.y * 32 + 16; - int32_t height = tile_element_height(x, y); - height += 32; - focus.coordinate.x = x; - focus.coordinate.y = y; - focus.coordinate.z = height; - focus.sprite.type |= VIEWPORT_FOCUS_TYPE_COORDINATE; - } - else - { - focus.sprite.type |= VIEWPORT_FOCUS_TYPE_SPRITE | VIEWPORT_FOCUS_TYPE_COORDINATE; - focus.sprite.pad_486 &= 0xFFFF; - } - focus.coordinate.rotation = get_current_rotation(); - } - - uint16_t viewport_flags; - - if (w->viewport) - { - // 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) - return; - - viewport_flags = w->viewport->flags; - w->viewport->width = 0; - w->viewport = nullptr; - } - else - { - viewport_flags = 0; - if (gConfigGeneral.always_show_gridlines) - { - viewport_flags |= VIEWPORT_FLAG_GRIDLINES; - } - } - - 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 != PEEP_STATE_PICKED) - { - if (!(w->viewport)) - { - rct_widget* view_widget = &w->widgets[WIDX_VIEWPORT]; - + auto view_widget = &w->widgets[WIDX_VIEWPORT]; int32_t x = view_widget->left + 1 + w->x; int32_t y = view_widget->top + 1 + w->y; int32_t width = view_widget->right - view_widget->left - 1; @@ -801,15 +741,15 @@ void window_guest_viewport_init(rct_window* w) viewport_create( w, x, y, 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); - + if (w->viewport != nullptr && reCreateViewport) + { + w->viewport->flags = origViewportFlags; + } w->flags |= WF_NO_SCROLLING; window_invalidate(w); } + window_invalidate(w); } - - if (w->viewport) - w->viewport->flags = viewport_flags; - window_invalidate(w); } /** diff --git a/src/openrct2-ui/windows/Main.cpp b/src/openrct2-ui/windows/Main.cpp index 69f1d7b7b1..9464562608 100644 --- a/src/openrct2-ui/windows/Main.cpp +++ b/src/openrct2-ui/windows/Main.cpp @@ -13,6 +13,7 @@ #include #include #include +#include // clang-format off static rct_widget window_main_widgets[] = { @@ -67,7 +68,7 @@ rct_window* window_main_open() WF_STICK_TO_BACK); window->widgets = window_main_widgets; - viewport_create(window, window->x, window->y, window->width, window->height, 0, 0x0FFF, 0x0FFF, 0, 0x1, -1); + viewport_create(window, window->x, window->y, window->width, window->height, 0, 0x0FFF, 0x0FFF, 0, 0x1, SPRITE_INDEX_NULL); 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 1ee15965fc..ebd224fc6d 100644 --- a/src/openrct2-ui/windows/Park.cpp +++ b/src/openrct2-ui/windows/Park.cpp @@ -923,7 +923,7 @@ static void window_park_init_viewport(rct_window* w) viewport_create( w, w->x + viewportWidget->left + 1, w->y + viewportWidget->top + 1, (viewportWidget->right - viewportWidget->left) - 1, (viewportWidget->bottom - viewportWidget->top) - 1, 0, x, y, - z, w->viewport_focus_sprite.type & VIEWPORT_FOCUS_TYPE_MASK, -1); + z, w->viewport_focus_sprite.type & VIEWPORT_FOCUS_TYPE_MASK, SPRITE_INDEX_NULL); w->flags |= (1 << 2); window_invalidate(w); } diff --git a/src/openrct2-ui/windows/Player.cpp b/src/openrct2-ui/windows/Player.cpp index d2cfcda983..88316cbdff 100644 --- a/src/openrct2-ui/windows/Player.cpp +++ b/src/openrct2-ui/windows/Player.cpp @@ -565,7 +565,7 @@ static void window_player_set_page(rct_window* w, int32_t page) { if (w->viewport == nullptr) { - viewport_create(w, w->x, w->y, w->width, w->height, 0, 128 * 32, 128 * 32, 0, 1, -1); + viewport_create(w, w->x, w->y, w->width, w->height, 0, 128 * 32, 128 * 32, 0, 1, SPRITE_INDEX_NULL); w->flags |= WF_NO_SCROLLING; window_event_invalidate_call(w); window_player_update_viewport(w, false); diff --git a/src/openrct2-ui/windows/Sign.cpp b/src/openrct2-ui/windows/Sign.cpp index fecbc6f98a..5c02229952 100644 --- a/src/openrct2-ui/windows/Sign.cpp +++ b/src/openrct2-ui/windows/Sign.cpp @@ -188,7 +188,7 @@ rct_window* window_sign_open(rct_windownumber number) viewportWidget = &window_sign_widgets[WIDX_VIEWPORT]; viewport_create( w, w->x + viewportWidget->left + 1, w->y + viewportWidget->top + 1, (viewportWidget->right - viewportWidget->left) - 1, - (viewportWidget->bottom - viewportWidget->top) - 1, 0, view_x, view_y, view_z, 0, -1); + (viewportWidget->bottom - viewportWidget->top) - 1, 0, view_x, view_y, view_z, 0, SPRITE_INDEX_NULL); w->viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; window_invalidate(w); @@ -381,7 +381,7 @@ static void window_sign_viewport_rotate(rct_window* w) rct_widget* viewportWidget = &window_sign_widgets[WIDX_VIEWPORT]; viewport_create( w, w->x + viewportWidget->left + 1, w->y + viewportWidget->top + 1, (viewportWidget->right - viewportWidget->left) - 1, - (viewportWidget->bottom - viewportWidget->top) - 1, 0, view_x, view_y, view_z, 0, -1); + (viewportWidget->bottom - viewportWidget->top) - 1, 0, view_x, view_y, view_z, 0, SPRITE_INDEX_NULL); w->viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; window_invalidate(w); @@ -445,7 +445,7 @@ rct_window* window_sign_small_open(rct_windownumber number) viewportWidget = &window_sign_widgets[WIDX_VIEWPORT]; viewport_create( w, w->x + viewportWidget->left + 1, w->y + viewportWidget->top + 1, (viewportWidget->right - viewportWidget->left) - 1, - (viewportWidget->bottom - viewportWidget->top) - 1, 0, view_x, view_y, view_z, 0, -1); + (viewportWidget->bottom - viewportWidget->top) - 1, 0, view_x, view_y, view_z, 0, SPRITE_INDEX_NULL); w->viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; w->flags |= WF_NO_SCROLLING; diff --git a/src/openrct2-ui/windows/TitleCommandEditor.cpp b/src/openrct2-ui/windows/TitleCommandEditor.cpp index b78bb9f9e7..4acf7ec8d3 100644 --- a/src/openrct2-ui/windows/TitleCommandEditor.cpp +++ b/src/openrct2-ui/windows/TitleCommandEditor.cpp @@ -251,7 +251,8 @@ void window_title_command_editor_open(TitleSequence* sequence, int32_t index, bo rct_widget* const viewportWidget = &window_title_command_editor_widgets[WIDX_VIEWPORT]; viewport_create( window, window->x + viewportWidget->left + 1, window->y + viewportWidget->top + 1, - viewportWidget->right - viewportWidget->left - 1, viewportWidget->bottom - viewportWidget->top - 1, 0, 0, 0, 0, 0, -1); + viewportWidget->right - viewportWidget->left - 1, viewportWidget->bottom - viewportWidget->top - 1, 0, 0, 0, 0, 0, + SPRITE_INDEX_NULL); _window_title_command_editor_index = index; _window_title_command_editor_insert = insert; diff --git a/src/openrct2-ui/windows/Viewport.cpp b/src/openrct2-ui/windows/Viewport.cpp index 7014050bbf..dd6d7c96dc 100644 --- a/src/openrct2-ui/windows/Viewport.cpp +++ b/src/openrct2-ui/windows/Viewport.cpp @@ -94,7 +94,7 @@ rct_window* window_viewport_open() w->number = _viewportNumber++; // Create viewport - viewport_create(w, w->x, w->y, w->width, w->height, 0, 128 * 32, 128 * 32, 0, 1, -1); + viewport_create(w, w->x, w->y, w->width, w->height, 0, 128 * 32, 128 * 32, 0, 1, SPRITE_INDEX_NULL); rct_window* mainWindow = window_get_main(); if (mainWindow != nullptr) { diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index ba56de8399..1ad01f0276 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -145,7 +145,7 @@ void centre_2d_coordinates(int32_t x, int32_t y, int32_t z, int32_t* out_x, int3 */ 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, int16_t sprite) + int32_t centre_z, char flags, uint16_t sprite) { rct_viewport* viewport = nullptr; for (int32_t i = 0; i < MAX_VIEWPORT_COUNT; i++) @@ -686,55 +686,53 @@ void viewport_update_smart_sprite_follow(rct_window* window) } } -void viewport_update_smart_guest_follow(rct_window* window, Peep* peep) +viewport_focus viewport_update_smart_guest_follow(rct_window* window, Peep* peep) { - union - { - sprite_focus sprite; - coordinate_focus coordinate; - } focus = {}; // The focus will be either a sprite or a coordinate. - - focus.sprite.sprite_id = window->viewport_smart_follow_sprite; + viewport_focus focus{}; + focus.type = VIEWPORT_FOCUS_TYPE_SPRITE; + focus.sprite.sprite_id = peep->sprite_index; if (peep->state == PEEP_STATE_PICKED) { - // focus.sprite.sprite_id = SPRITE_INDEX_NULL; + focus.sprite.sprite_id = SPRITE_INDEX_NULL; window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; window->viewport_target_sprite = SPRITE_INDEX_NULL; - return; + return focus; } else { - uint8_t final_check = 1; + bool overallFocus = true; if (peep->state == PEEP_STATE_ON_RIDE || peep->state == PEEP_STATE_ENTERING_RIDE || (peep->state == PEEP_STATE_LEAVING_RIDE && peep->x == LOCATION_NULL)) { Ride* ride = get_ride(peep->current_ride); if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) { - rct_vehicle* train = GET_VEHICLE(ride->vehicles[peep->current_train]); - int32_t car = peep->current_car; - - for (; car != 0; car--) + auto train = GET_VEHICLE(ride->vehicles[peep->current_train]); + if (train != nullptr) { - train = GET_VEHICLE(train->next_vehicle_on_train); + auto car = train->GetCar(peep->current_car); + if (car != nullptr) + { + focus.sprite.sprite_id = car->sprite_index; + overallFocus = false; + } } - - focus.sprite.sprite_id = train->sprite_index; - final_check = 0; } } - if (peep->x == LOCATION_NULL && final_check) + if (peep->x == LOCATION_NULL && overallFocus) { - Ride* ride = get_ride(peep->current_ride); - int32_t x = ride->overall_view.x * 32 + 16; - int32_t y = ride->overall_view.y * 32 + 16; - int32_t height = tile_element_height(x, y); - height += 32; - focus.coordinate.x = x; - focus.coordinate.y = y; - focus.coordinate.z = height; - focus.sprite.type |= VIEWPORT_FOCUS_TYPE_COORDINATE; + auto ride = get_ride(peep->current_ride); + if (ride != nullptr) + { + auto x = (int32_t)ride->overall_view.x * 32 + 16; + auto y = (int32_t)ride->overall_view.y * 32 + 16; + focus.type = VIEWPORT_FOCUS_TYPE_COORDINATE; + focus.coordinate.x = x; + focus.coordinate.y = y; + focus.coordinate.z = tile_element_height(x, y) + 32; + focus.sprite.type |= VIEWPORT_FOCUS_TYPE_COORDINATE; + } } else { @@ -746,6 +744,7 @@ void viewport_update_smart_guest_follow(rct_window* window, Peep* peep) window->viewport_focus_sprite = focus.sprite; window->viewport_target_sprite = window->viewport_focus_sprite.sprite_id; + return focus; } void viewport_update_smart_staff_follow(rct_window* window, Peep* peep) diff --git a/src/openrct2/interface/Viewport.h b/src/openrct2/interface/Viewport.h index 58c4054c59..a348556d8e 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -122,11 +122,11 @@ 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); 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, int16_t sprite); + int32_t centre_z, char flags, uint16_t sprite); void viewport_update_position(rct_window* window); void viewport_update_sprite_follow(rct_window* window); void viewport_update_smart_sprite_follow(rct_window* window); -void viewport_update_smart_guest_follow(rct_window* window, Peep* peep); +viewport_focus viewport_update_smart_guest_follow(rct_window* window, Peep* peep); void viewport_update_smart_staff_follow(rct_window* window, Peep* 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 bc109a6920..98d0600802 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -148,13 +148,23 @@ struct sprite_focus }; #define VIEWPORT_FOCUS_TYPE_MASK 0xC0 -enum +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 + { + sprite_focus sprite; + coordinate_focus coordinate; + }; +}; + struct rct_window_event_list { void (*close)(struct rct_window*); diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 259a319396..97aeb55a96 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -10002,3 +10002,13 @@ const rct_vehicle* rct_vehicle::GetHead() const { return ((rct_vehicle*)this)->GetHead(); } + +const rct_vehicle* rct_vehicle::GetCar(size_t carIndex) const +{ + auto car = this; + for (; carIndex != 0; carIndex--) + { + car = GET_VEHICLE(car->next_vehicle_on_train); + } + return car; +} diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h index e82ab5a15e..f1b91d0f05 100644 --- a/src/openrct2/ride/Vehicle.h +++ b/src/openrct2/ride/Vehicle.h @@ -233,6 +233,7 @@ struct rct_vehicle : rct_sprite_common } rct_vehicle* GetHead(); const rct_vehicle* GetHead() const; + const rct_vehicle* GetCar(size_t carIndex) const; }; struct train_ref diff --git a/src/openrct2/world/Sprite.cpp b/src/openrct2/world/Sprite.cpp index 92f8b5e7ca..faf327f4e1 100644 --- a/src/openrct2/world/Sprite.cpp +++ b/src/openrct2/world/Sprite.cpp @@ -80,6 +80,10 @@ rct_sprite* try_get_sprite(size_t spriteIndex) rct_sprite* get_sprite(size_t sprite_idx) { + if (sprite_idx == SPRITE_INDEX_NULL) + { + return nullptr; + } openrct2_assert(sprite_idx < MAX_SPRITES, "Tried getting sprite %u", sprite_idx); return &_spriteList[sprite_idx]; }