From 3b49f892facc3bf4aaf7f0d2b765afc384dd1219 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 18 Sep 2020 18:58:16 +0100 Subject: [PATCH] Redraw connecting link graph overlay links when moving station sign Add test console command --- src/console_cmds.cpp | 21 +++++++++++++ src/linkgraph/linkgraph_gui.cpp | 24 +++++++++++++++ src/linkgraph/linkgraph_gui.h | 1 + src/station_cmd.cpp | 4 +++ src/viewport.cpp | 53 +++++++++++++++++++++++++++++++-- src/viewport_func.h | 3 ++ 6 files changed, 104 insertions(+), 2 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 26708be71d..507ae6de8a 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -2282,6 +2282,26 @@ DEF_CONSOLE_CMD(ConViewportMarkDirty) return true; } + +DEF_CONSOLE_CMD(ConViewportMarkStationOverlayDirty) +{ + if (argc != 2) { + IConsoleHelp("Debug: Mark main viewport link graph overlay station links. Usage: 'viewport_mark_dirty_st_overlay '"); + return true; + } + + if (_game_mode != GM_NORMAL && _game_mode != GM_EDITOR) { + return true; + } + + const Station *st = Station::GetIfValid(atoi(argv[1])); + if (st == nullptr) return true; + MarkAllViewportOverlayStationLinksDirty(st); + + return true; +} + + DEF_CONSOLE_CMD(ConDoDisaster) { if (argc == 0) { @@ -2679,6 +2699,7 @@ void IConsoleStdLibRegister() IConsoleCmdRegister("show_industry_window", ConShowIndustryWindow, nullptr, true); IConsoleCmdRegister("viewport_debug", ConViewportDebug, nullptr, true); IConsoleCmdRegister("viewport_mark_dirty", ConViewportMarkDirty, nullptr, true); + IConsoleCmdRegister("viewport_mark_dirty_st_overlay", ConViewportMarkStationOverlayDirty, nullptr, true); /* NewGRF development stuff */ IConsoleCmdRegister("reload_newgrfs", ConNewGRFReload, ConHookNewGRFDeveloperTool); diff --git a/src/linkgraph/linkgraph_gui.cpp b/src/linkgraph/linkgraph_gui.cpp index 278b4a6d87..f1d4b9e0ba 100644 --- a/src/linkgraph/linkgraph_gui.cpp +++ b/src/linkgraph/linkgraph_gui.cpp @@ -16,6 +16,7 @@ #include "../viewport_func.h" #include "../smallmap_gui.h" #include "../zoom_func.h" +#include "../landscape.h" #include "../core/geometry_func.hpp" #include "../widgets/link_graph_legend_widget.h" @@ -81,6 +82,29 @@ bool LinkGraphOverlay::CacheStillValid() const } } +void LinkGraphOverlay::MarkStationViewportLinksDirty(const Station *st) +{ + if (this->window->viewport) { + Viewport *vp = this->window->viewport; + const Point pt = RemapCoords2(TileX(st->xy) * TILE_SIZE, TileY(st->xy) * TILE_SIZE); + const int padding = ScaleByZoom(3 * this->scale, vp->zoom); + MarkViewportDirty(vp, pt.x - padding, pt.y - padding, pt.x + padding, pt.y - padding); + + const int block_radius = ScaleByZoom(10, vp->zoom); + for (LinkList::iterator i(this->cached_links.begin()); i != this->cached_links.end(); ++i) { + if (i->from_id == st->index) { + const Station *stb = Station::GetIfValid(i->to_id); + if (stb == nullptr) continue; + MarkViewportLineDirty(vp, pt, RemapCoords2(TileX(stb->xy) * TILE_SIZE, TileY(stb->xy) * TILE_SIZE), block_radius); + } else if (i->to_id == st->index) { + const Station *sta = Station::GetIfValid(i->from_id); + if (sta == nullptr) continue; + MarkViewportLineDirty(vp, RemapCoords2(TileX(sta->xy) * TILE_SIZE, TileY(sta->xy) * TILE_SIZE), pt, block_radius); + } + } + } +} + /** * Rebuild the cache and recalculate which links and stations to be shown. */ diff --git a/src/linkgraph/linkgraph_gui.h b/src/linkgraph/linkgraph_gui.h index 5d42565da9..c6e9f1621c 100644 --- a/src/linkgraph/linkgraph_gui.h +++ b/src/linkgraph/linkgraph_gui.h @@ -69,6 +69,7 @@ public: void RebuildCache(bool incremental = false); bool CacheStillValid() const; + void MarkStationViewportLinksDirty(const Station *st); void Draw(const DrawPixelInfo *dpi); void SetCargoMask(CargoTypes cargo_mask); void SetCompanyMask(uint32 company_mask); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 726dccd7cf..cbf533cdec 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -433,11 +433,15 @@ void Station::MoveSign(TileIndex new_xy) { if (this->xy == new_xy) return; + MarkAllViewportOverlayStationLinksDirty(this); + _station_kdtree.Remove(this->index); this->BaseStation::MoveSign(new_xy); _station_kdtree.Insert(this->index); + + MarkAllViewportOverlayStationLinksDirty(this); } /** Update the virtual coords needed to draw the station sign for all stations. */ diff --git a/src/viewport.cpp b/src/viewport.cpp index 8d74dc5f85..6d5ac2ac00 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -259,7 +259,6 @@ struct ViewportDrawer { Point foundation_offset[FOUNDATION_PART_END]; ///< Pixel offset for ground sprites on the foundations. }; -static void MarkViewportDirty(Viewport * const vp, int left, int top, int right, int bottom); static void MarkRouteStepDirty(RouteStepsMap::const_iterator cit); static void MarkRouteStepDirty(const TileIndex tile, uint order_nr); @@ -3375,7 +3374,7 @@ void UpdateActiveScrollingViewport(Window *w) * @param bottom Bottom edge of area to repaint * @ingroup dirty */ -static void MarkViewportDirty(Viewport * const vp, int left, int top, int right, int bottom) +void MarkViewportDirty(Viewport * const vp, int left, int top, int right, int bottom) { /* Rounding wrt. zoom-out level */ right += (1 << vp->zoom) - 1; @@ -3479,6 +3478,22 @@ void MarkAllViewportMapsDirty(int left, int top, int right, int bottom) } } +/** + * Mark all viewport overlays for a specific station dirty (in need of repaint). + * @param st Station + * @ingroup dirty + */ +void MarkAllViewportOverlayStationLinksDirty(const Station *st) +{ + Window *w; + FOR_ALL_WINDOWS_FROM_BACK(w) { + Viewport *vp = w->viewport; + if (vp != nullptr && vp->overlay != nullptr) { + vp->overlay->MarkStationViewportLinksDirty(st); + } + } +} + void ConstrainAllViewportsZoom() { Window *w; @@ -3522,6 +3537,40 @@ void MarkTileGroundDirtyByTile(TileIndex tile, const ZoomLevel mark_dirty_if_zoo MarkAllViewportsDirty(top.x - TILE_PIXELS * ZOOM_LVL_BASE, top.y - TILE_HEIGHT * ZOOM_LVL_BASE, top.x + TILE_PIXELS * ZOOM_LVL_BASE, bot.y); } +void MarkViewportLineDirty(Viewport * const vp, const Point from_pt, const Point to_pt, const int block_radius) +{ + int x1 = from_pt.x / block_radius; + int y1 = from_pt.y / block_radius; + const int x2 = to_pt.x / block_radius; + const int y2 = to_pt.y / block_radius; + + /* http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#Simplification */ + const int dx = abs(x2 - x1); + const int dy = abs(y2 - y1); + const int sx = (x1 < x2) ? 1 : -1; + const int sy = (y1 < y2) ? 1 : -1; + int err = dx - dy; + for (;;) { + MarkViewportDirty( + vp, + (x1 - 2) * block_radius, + (y1 - 2) * block_radius, + (x1 + 2) * block_radius, + (y1 + 2) * block_radius + ); + if (x1 == x2 && y1 == y2) break; + const int e2 = 2 * err; + if (e2 > -dy) { + err -= dy; + x1 += sx; + } + if (e2 < dx) { + err += dx; + y1 += sy; + } + } +} + void MarkTileLineDirty(const TileIndex from_tile, const TileIndex to_tile) { assert(from_tile != INVALID_TILE); diff --git a/src/viewport_func.h b/src/viewport_func.h index 0189c21b45..53d81edc42 100644 --- a/src/viewport_func.h +++ b/src/viewport_func.h @@ -33,9 +33,12 @@ Point GetTileBelowCursor(); void UpdateViewportPosition(Window *w); void UpdateViewportSizeZoom(Viewport *vp); +void MarkViewportDirty(Viewport * const vp, int left, int top, int right, int bottom); void MarkAllViewportsDirty(int left, int top, int right, int bottom, const ZoomLevel mark_dirty_if_zoomlevel_is_below = ZOOM_LVL_END); void MarkAllViewportMapsDirty(int left, int top, int right, int bottom); +void MarkAllViewportOverlayStationLinksDirty(const Station *st); void MarkAllRouteStepsDirty(const Vehicle *veh); +void MarkViewportLineDirty(Viewport * const vp, const Point from_pt, const Point to_pt, const int block_radius); void MarkTileLineDirty(const TileIndex from_tile, const TileIndex to_tile); void MarkAllRoutePathsDirty(const Vehicle *veh); void CheckMarkDirtyFocusedRoutePaths(const Vehicle *veh);