diff --git a/src/intro_gui.cpp b/src/intro_gui.cpp index 06be8a8530..c76118fc21 100644 --- a/src/intro_gui.cpp +++ b/src/intro_gui.cpp @@ -251,7 +251,8 @@ struct SelectGameWindow : public Window { /* Update the viewport position. */ mw->viewport->dest_scrollpos_x = mw->viewport->scrollpos_x = pos.x; mw->viewport->dest_scrollpos_y = mw->viewport->scrollpos_y = pos.y; - UpdateViewportPosition(mw); + UpdateNextViewportPosition(mw); + ApplyNextViewportPosition(mw); mw->SetDirty(); // Required during panning, otherwise logo graphics disappears /* If there is only one command, we just executed it and don't need to do any more */ diff --git a/src/viewport.cpp b/src/viewport.cpp index be9584635f..529d4fbfee 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -4023,10 +4023,10 @@ static inline void ClampViewportToMap(const Viewport *vp, int *scroll_x, int *sc } /** - * Update the viewport position being displayed. + * Update the next viewport position being displayed. * @param w %Window owning the viewport. */ -void UpdateViewportPosition(Window *w) +void UpdateNextViewportPosition(Window *w) { const Viewport *vp = w->viewport; @@ -4034,9 +4034,9 @@ void UpdateViewportPosition(Window *w) const Vehicle *veh = Vehicle::Get(w->viewport->follow_vehicle); Point pt = MapXYZToViewport(vp, veh->x_pos, veh->y_pos, veh->z_pos); - w->viewport->scrollpos_x = pt.x; - w->viewport->scrollpos_y = pt.y; - SetViewportPosition(w, pt.x, pt.y, false); + w->viewport->next_scrollpos_x = pt.x; + w->viewport->next_scrollpos_y = pt.y; + w->viewport->force_update_overlay_pending = false; } else { /* Ensure the destination location is within the map */ ClampViewportToMap(vp, &w->viewport->dest_scrollpos_x, &w->viewport->dest_scrollpos_y); @@ -4044,29 +4044,40 @@ void UpdateViewportPosition(Window *w) int delta_x = w->viewport->dest_scrollpos_x - w->viewport->scrollpos_x; int delta_y = w->viewport->dest_scrollpos_y - w->viewport->scrollpos_y; + w->viewport->next_scrollpos_x = w->viewport->scrollpos_x; + w->viewport->next_scrollpos_y = w->viewport->scrollpos_y; + bool update_overlay = false; if (delta_x != 0 || delta_y != 0) { if (_settings_client.gui.smooth_scroll) { int max_scroll = ScaleByMapSize1D(512 * ZOOM_LVL_BASE); /* Not at our desired position yet... */ - w->viewport->scrollpos_x += Clamp(DivAwayFromZero(delta_x, 4), -max_scroll, max_scroll); - w->viewport->scrollpos_y += Clamp(DivAwayFromZero(delta_y, 4), -max_scroll, max_scroll); + w->viewport->next_scrollpos_x += Clamp(DivAwayFromZero(delta_x, 4), -max_scroll, max_scroll); + w->viewport->next_scrollpos_y += Clamp(DivAwayFromZero(delta_y, 4), -max_scroll, max_scroll); } else { - w->viewport->scrollpos_x = w->viewport->dest_scrollpos_x; - w->viewport->scrollpos_y = w->viewport->dest_scrollpos_y; + w->viewport->next_scrollpos_x = w->viewport->dest_scrollpos_x; + w->viewport->next_scrollpos_y = w->viewport->dest_scrollpos_y; } - update_overlay = (w->viewport->scrollpos_x == w->viewport->dest_scrollpos_x && - w->viewport->scrollpos_y == w->viewport->dest_scrollpos_y); + update_overlay = (w->viewport->next_scrollpos_x == w->viewport->dest_scrollpos_x && + w->viewport->next_scrollpos_y == w->viewport->dest_scrollpos_y); } + w->viewport->force_update_overlay_pending = update_overlay; - ClampViewportToMap(vp, &w->viewport->scrollpos_x, &w->viewport->scrollpos_y); + ClampViewportToMap(vp, &w->viewport->next_scrollpos_x, &w->viewport->next_scrollpos_y); if (_scrolling_viewport == w) UpdateActiveScrollingViewport(w); - - SetViewportPosition(w, w->viewport->scrollpos_x, w->viewport->scrollpos_y, update_overlay); } } +/** + * Apply the next viewport position being displayed. + * @param w %Window owning the viewport. + */ +void ApplyNextViewportPosition(Window *w) +{ + SetViewportPosition(w, w->viewport->next_scrollpos_x, w->viewport->next_scrollpos_y, w->viewport->force_update_overlay_pending); +} + void UpdateViewportSizeZoom(Viewport *vp) { vp->dirty_blocks_per_column = CeilDiv(vp->height, vp->GetDirtyBlockHeight()); diff --git a/src/viewport_func.h b/src/viewport_func.h index 598eedf39b..fb93160f1a 100644 --- a/src/viewport_func.h +++ b/src/viewport_func.h @@ -33,7 +33,8 @@ void InitializeWindowViewport(Window *w, int x, int y, int width, int height, ui Viewport *IsPtInWindowViewport(const Window *w, int x, int y); Point TranslateXYToTileCoord(const Viewport *vp, int x, int y, bool clamp_to_map = true); Point GetTileBelowCursor(); -void UpdateViewportPosition(Window *w); +void UpdateNextViewportPosition(Window *w); +void ApplyNextViewportPosition(Window *w); void UpdateViewportSizeZoom(Viewport *vp); void MarkViewportDirty(Viewport * const vp, int left, int top, int right, int bottom, ViewportMarkDirtyFlags flags); diff --git a/src/window.cpp b/src/window.cpp index aecb230139..bf85fe90b6 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -3365,11 +3365,16 @@ void UpdateWindows() } } + for (Window *w : Window::Iterate()) { + /* Update viewport only if window is not shaded. */ + if (w->viewport != nullptr && !w->IsShaded()) UpdateNextViewportPosition(w); + } + DrawDirtyBlocks(); for (Window *w : Window::Iterate()) { /* Update viewport only if window is not shaded. */ - if (w->viewport != nullptr && !w->IsShaded()) UpdateViewportPosition(w); + if (w->viewport != nullptr && !w->IsShaded()) ApplyNextViewportPosition(w); } ViewportDoDrawProcessAllPending(); NetworkDrawChatMessage(); diff --git a/src/window_gui.h b/src/window_gui.h index 4356295dc9..d75202fde5 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -211,7 +211,7 @@ static const int WHITE_BORDER_DURATION = 3; ///< The initial timeout value for W * A viewport is either following a vehicle (its id in then in #follow_vehicle), or it aims to display a specific * location #dest_scrollpos_x, #dest_scrollpos_y (#follow_vehicle is then #INVALID_VEHICLE). * The actual location being shown is #scrollpos_x, #scrollpos_y. - * @see InitializeViewport(), UpdateViewportPosition(), UpdateViewportCoordinates(). + * @see InitializeViewport(), UpdateNextViewportPosition(), ApplyNextViewportPosition(), UpdateViewportCoordinates(). */ struct ViewportData : Viewport { VehicleID follow_vehicle; ///< VehicleID to follow if following a vehicle, #INVALID_VEHICLE otherwise. @@ -219,6 +219,9 @@ struct ViewportData : Viewport { int32 scrollpos_y; ///< Currently shown y coordinate (virtual screen coordinate of topleft corner of the viewport). int32 dest_scrollpos_x; ///< Current destination x coordinate to display (virtual screen coordinate of topleft corner of the viewport). int32 dest_scrollpos_y; ///< Current destination y coordinate to display (virtual screen coordinate of topleft corner of the viewport). + int32 next_scrollpos_x; ///< Next x coordinate to display (virtual screen coordinate of topleft corner of the viewport). + int32 next_scrollpos_y; ///< Next y coordinate to display (virtual screen coordinate of topleft corner of the viewport). + bool force_update_overlay_pending; ///< Forced overlay update is pending (see SetViewportPosition) }; struct QueryString;