From 7549982f12e37fa692e7e24b86108f87150d9e67 Mon Sep 17 00:00:00 2001 From: rubidium Date: Sat, 12 May 2012 07:19:47 +0000 Subject: [PATCH] (svn r24225) [1.2] -Backport from trunk: - Fix: Conflicting strategies for resizing the main toolbar and statusbar after resizing the main window [FS#5136] (r24089) - Fix: Significantly reduce the area that is redrawn for text effects [FS#5103] (r24068) - Fix: Do not redraw up to 25% of the map when making a new vehicle visible for the first time (r24067) - Fix: Do not redraw the text effect when nothing changed (r24066) --- src/texteff.cpp | 5 +++-- src/vehicle.cpp | 16 ++++++++++------ src/viewport.cpp | 33 +++++++++++++++++++++++---------- src/viewport_type.h | 2 +- src/window.cpp | 23 +++++++++++++---------- src/window_func.h | 2 +- 6 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/texteff.cpp b/src/texteff.cpp index 32062fc1b8..981453c10d 100644 --- a/src/texteff.cpp +++ b/src/texteff.cpp @@ -65,6 +65,7 @@ void UpdateTextEffect(TextEffectID te_id, StringID msg) { /* Update details */ TextEffect *te = _text_effects.Get(te_id); + if (msg == te->string_id && GetDParam(0) == te->params_1) return; te->string_id = msg; te->params_1 = GetDParam(0); @@ -88,9 +89,9 @@ void MoveAllTextEffects() continue; } - te->MarkDirty(); + te->MarkDirty(ZOOM_LVL_OUT_8X); te->top -= ZOOM_LVL_BASE; - te->MarkDirty(); + te->MarkDirty(ZOOM_LVL_OUT_8X); } } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index c6abc3f25c..4851a4529e 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1416,12 +1416,16 @@ void VehicleUpdateViewport(Vehicle *v, bool dirty) v->coord.bottom = pt.y + spr->height + 2 * ZOOM_LVL_BASE; if (dirty) { - MarkAllViewportsDirty( - min(old_coord.left, v->coord.left), - min(old_coord.top, v->coord.top), - max(old_coord.right, v->coord.right) + 1 * ZOOM_LVL_BASE, - max(old_coord.bottom, v->coord.bottom) + 1 * ZOOM_LVL_BASE - ); + if (old_coord.left == INVALID_COORD) { + MarkSingleVehicleDirty(v); + } else { + MarkAllViewportsDirty( + min(old_coord.left, v->coord.left), + min(old_coord.top, v->coord.top), + max(old_coord.right, v->coord.right) + 1 * ZOOM_LVL_BASE, + max(old_coord.bottom, v->coord.bottom) + 1 * ZOOM_LVL_BASE + ); + } } } diff --git a/src/viewport.cpp b/src/viewport.cpp index 2f134056f8..e7191cc10a 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -143,6 +143,8 @@ struct ViewportDrawer { Point foundation_offset[FOUNDATION_PART_END]; ///< Pixel offset for ground sprites on the foundations. }; +static void MarkViewportDirty(const ViewPort *vp, int left, int top, int right, int bottom); + static ViewportDrawer _vd; TileHighlightData _thd; @@ -1242,20 +1244,31 @@ void ViewportSign::UpdatePosition(int center, int top, StringID str) /** * Mark the sign dirty in all viewports. + * @param maxzoom Maximum %ZoomLevel at which the text is visible. * * @ingroup dirty */ -void ViewportSign::MarkDirty() const +void ViewportSign::MarkDirty(ZoomLevel maxzoom) const { - /* We use ZOOM_LVL_MAX here, as every viewport can have another zoom, - * and there is no way for us to know which is the biggest. So make the - * biggest area dirty, and we are safe for sure. - * We also add 1 to make sure the whole thing is redrawn. */ - MarkAllViewportsDirty( - this->center - ScaleByZoom(this->width_normal / 2 + 1, ZOOM_LVL_MAX), - this->top - ScaleByZoom(1, ZOOM_LVL_MAX), - this->center + ScaleByZoom(this->width_normal / 2 + 1, ZOOM_LVL_MAX), - this->top + ScaleByZoom(VPSM_TOP + FONT_HEIGHT_NORMAL + VPSM_BOTTOM + 1, ZOOM_LVL_MAX)); + Rect zoomlevels[ZOOM_LVL_COUNT]; + + for (ZoomLevel zoom = ZOOM_LVL_BEGIN; zoom != ZOOM_LVL_END; zoom++) { + /* FIXME: This doesn't switch to width_small when appropriate. */ + zoomlevels[zoom].left = this->center - ScaleByZoom(this->width_normal / 2 + 1, zoom); + zoomlevels[zoom].top = this->top - ScaleByZoom(1, zoom); + zoomlevels[zoom].right = this->center + ScaleByZoom(this->width_normal / 2 + 1, zoom); + zoomlevels[zoom].bottom = this->top + ScaleByZoom(VPSM_TOP + FONT_HEIGHT_NORMAL + VPSM_BOTTOM + 1, zoom); + } + + Window *w; + FOR_ALL_WINDOWS_FROM_BACK(w) { + ViewPort *vp = w->viewport; + if (vp != NULL && vp->zoom <= maxzoom) { + assert(vp->width != 0); + Rect &zl = zoomlevels[vp->zoom]; + MarkViewportDirty(vp, zl.left, zl.top, zl.right, zl.bottom); + } + } } static void ViewportDrawTileSprites(const TileSpriteToDrawVector *tstdv) diff --git a/src/viewport_type.h b/src/viewport_type.h index cd8ebaea6d..2c29c83b3d 100644 --- a/src/viewport_type.h +++ b/src/viewport_type.h @@ -48,7 +48,7 @@ struct ViewportSign { uint16 width_small; ///< The width when zoomed out (small font) void UpdatePosition(int center, int top, StringID str); - void MarkDirty() const; + void MarkDirty(ZoomLevel maxzoom = ZOOM_LVL_MAX) const; }; /** diff --git a/src/window.cpp b/src/window.cpp index a1a2899252..2ea83c9ff1 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1753,16 +1753,19 @@ static void EnsureVisibleCaption(Window *w, int nx, int ny) * @param w Window to resize * @param delta_x Delta x-size of changed window (positive if larger, etc.) * @param delta_y Delta y-size of changed window + * @param clamp_to_screen Whether to make sure the whole window stays visible */ -void ResizeWindow(Window *w, int delta_x, int delta_y) +void ResizeWindow(Window *w, int delta_x, int delta_y, bool clamp_to_screen) { if (delta_x != 0 || delta_y != 0) { - /* Determine the new right/bottom position. If that is outside of the bounds of - * the resolution clamp it in such a manner that it stays within the bounds. */ - int new_right = w->left + w->width + delta_x; - int new_bottom = w->top + w->height + delta_y; - if (new_right >= (int)_cur_resolution.width) delta_x -= Ceil(new_right - _cur_resolution.width, max(1U, w->nested_root->resize_x)); - if (new_bottom >= (int)_cur_resolution.height) delta_y -= Ceil(new_bottom - _cur_resolution.height, max(1U, w->nested_root->resize_y)); + if (clamp_to_screen) { + /* Determine the new right/bottom position. If that is outside of the bounds of + * the resolution clamp it in such a manner that it stays within the bounds. */ + int new_right = w->left + w->width + delta_x; + int new_bottom = w->top + w->height + delta_y; + if (new_right >= (int)_cur_resolution.width) delta_x -= Ceil(new_right - _cur_resolution.width, max(1U, w->nested_root->resize_x)); + if (new_bottom >= (int)_cur_resolution.height) delta_y -= Ceil(new_bottom - _cur_resolution.height, max(1U, w->nested_root->resize_y)); + } w->SetDirty(); @@ -2988,7 +2991,7 @@ void RelocateAllWindows(int neww, int newh) continue; case WC_MAIN_TOOLBAR: - ResizeWindow(w, min(neww, *_preferred_toolbar_size) - w->width, 0); + ResizeWindow(w, min(neww, *_preferred_toolbar_size) - w->width, 0, false); top = w->top; left = PositionMainToolbar(w); // changes toolbar orientation @@ -3000,14 +3003,14 @@ void RelocateAllWindows(int neww, int newh) break; case WC_STATUS_BAR: - ResizeWindow(w, min(neww, *_preferred_statusbar_size) - w->width, 0); + ResizeWindow(w, min(neww, *_preferred_statusbar_size) - w->width, 0, false); top = newh - w->height; left = PositionStatusbar(w); break; case WC_SEND_NETWORK_MSG: - ResizeWindow(w, Clamp(neww, 320, 640) - w->width, 0); + ResizeWindow(w, Clamp(neww, 320, 640) - w->width, 0, false); top = newh - w->height - FindWindowById(WC_STATUS_BAR, 0)->height; left = PositionNetworkChatWindow(w); break; diff --git a/src/window_func.h b/src/window_func.h index d430c0ccd1..704885b9a8 100644 --- a/src/window_func.h +++ b/src/window_func.h @@ -19,7 +19,7 @@ Window *FindWindowById(WindowClass cls, WindowNumber number); Window *FindWindowByClass(WindowClass cls); void ChangeWindowOwner(Owner old_owner, Owner new_owner); -void ResizeWindow(Window *w, int x, int y); +void ResizeWindow(Window *w, int x, int y, bool clamp_to_screen = true); int PositionMainToolbar(Window *w); int PositionStatusbar(Window *w); int PositionNewsMessage(Window *w);