diff --git a/source.list b/source.list index 6849fb0ff4..4eb2265107 100644 --- a/source.list +++ b/source.list @@ -450,6 +450,7 @@ core/alloc_type.hpp core/backup_type.hpp core/bitmath_func.cpp core/bitmath_func.hpp +core/container_func.hpp core/endian_func.hpp core/endian_type.hpp core/enum_type.hpp diff --git a/src/core/container_func.hpp b/src/core/container_func.hpp new file mode 100644 index 0000000000..1b8e8ad847 --- /dev/null +++ b/src/core/container_func.hpp @@ -0,0 +1,35 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file container_func.hpp Functions related to use of containers. */ + +template unsigned int container_unordered_remove_if (C &container, UP predicate) { + unsigned int removecount = 0; + for (auto it = container.begin(); it != container.end();) { + if (predicate(*it)) { + removecount++; + if (std::next(it) != container.end()) { + *it = std::move(container.back()); + container.pop_back(); + } else { + container.pop_back(); + break; + } + } else { + ++it; + } + } + return removecount; +} + +template unsigned int container_unordered_remove(C &container, const V &value) { + return container_unordered_remove_if (container, [&](const typename C::value_type &v) { + return v == value; + }); +} diff --git a/src/viewport.cpp b/src/viewport.cpp index 0184438691..2ddbee3365 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -99,6 +99,7 @@ #include "depot_base.h" #include "tunnelbridge_map.h" #include "gui.h" +#include "core/container_func.hpp" #include #include @@ -225,6 +226,8 @@ static void MarkRouteStepDirty(const TileIndex tile, uint order_nr); static DrawPixelInfo _dpi_for_text; static ViewportDrawer _vd; +static std::vector _viewport_window_cache; + RouteStepsMap _vp_route_steps; RouteStepsMap _vp_route_steps_last_mark_dirty; uint _vp_route_step_width = 0; @@ -284,6 +287,7 @@ void DeleteWindowViewport(Window *w) { if (w->viewport == NULL) return; + container_unordered_remove(_viewport_window_cache, w->viewport); delete w->viewport->overlay; free(w->viewport); w->viewport = NULL; @@ -346,6 +350,7 @@ void InitializeWindowViewport(Window *w, int x, int y, w->viewport = vp; vp->virtual_left = 0; // pt.x; vp->virtual_top = 0; // pt.y; + _viewport_window_cache.push_back(vp); } static Point _vp_move_offs; @@ -1465,11 +1470,8 @@ void ViewportSign::MarkDirty(ZoomLevel maxzoom) const 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); + for (ViewPort *vp : _viewport_window_cache) { + if (vp->zoom <= maxzoom) { Rect &zl = zoomlevels[vp->zoom]; MarkViewportDirty(vp, zl.left, zl.top, zl.right, zl.bottom); } @@ -2862,31 +2864,21 @@ static void MarkViewportDirty(const ViewPort * const vp, int left, int top, int */ void MarkAllViewportsDirty(int left, int top, int right, int bottom, const ZoomLevel mark_dirty_if_zoomlevel_is_below) { - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { - const ViewPort * const vp = w->viewport; - if (vp != NULL) { - assert(vp->width != 0); - if (vp->zoom >= mark_dirty_if_zoomlevel_is_below) continue; - MarkViewportDirty(vp, left, top, right, bottom); - } + for (const ViewPort * const vp : _viewport_window_cache) { + if (vp->zoom >= mark_dirty_if_zoomlevel_is_below) continue; + MarkViewportDirty(vp, left, top, right, bottom); } } static void MarkRouteStepDirty(const TileIndex tile, uint order_nr) { assert(tile != INVALID_TILE); - Window *w; const Point pt = RemapCoords2(TileX(tile) * TILE_SIZE + TILE_SIZE / 2, TileY(tile) * TILE_SIZE + TILE_SIZE / 2); const int char_height = GetCharacterHeight(FS_SMALL) + 1; - FOR_ALL_WINDOWS_FROM_BACK(w) { - const ViewPort * const vp = w->viewport; - if (vp != NULL) { - assert(vp->width != 0); - const int half_width = ScaleByZoom((_vp_route_step_width / 2) + 1, vp->zoom); - const int height = ScaleByZoom(_vp_route_step_height_top + char_height * order_nr + _vp_route_step_height_bottom, vp->zoom); - MarkViewportDirty(vp, pt.x - half_width, pt.y - height, pt.x + half_width, pt.y); - } + for (const ViewPort * const vp : _viewport_window_cache) { + const int half_width = ScaleByZoom((_vp_route_step_width / 2) + 1, vp->zoom); + const int height = ScaleByZoom(_vp_route_step_height_top + char_height * order_nr + _vp_route_step_height_bottom, vp->zoom); + MarkViewportDirty(vp, pt.x - half_width, pt.y - height, pt.x + half_width, pt.y); } }