From aa9f44eaec14f7acbe731dbe8f469f464d94c459 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 1 Nov 2015 21:51:10 +0000 Subject: [PATCH] Fix flicker/render errors of bridge/tunnels in viewport map mode. Fix bridges not being rendered when the region to be repainted did not intersect with either of the bridge ends. Fix flicker due to non-deterministic ordering of the two bridge/tunnel ends (if the tile heights of the two ends are different). --- src/viewport.cpp | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/viewport.cpp b/src/viewport.cpp index d478c7f753..95574a3df0 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1545,8 +1545,17 @@ static void ViewportMapStoreBridgeTunnel(const ViewPort * const vp, const TileIn /* It's a new one, add it to the list */ tbtm = tbtmv->Append(); - tbtm->from_tile = tile; - tbtm->to_tile = GetOtherTunnelBridgeEnd(tile); + TileIndex other_end = GetOtherTunnelBridgeEnd(tile); + + /* ensure deterministic ordering, to avoid render flicker */ + if (other_end > tile) { + tbtm->from_tile = other_end; + tbtm->to_tile = tile; + } else { + tbtm->from_tile = tile; + tbtm->to_tile = other_end; + } + if (vp->map_type == VPMT_OWNER && _settings_client.gui.use_owner_colour_for_tunnelbridge && o < MAX_COMPANIES) { const uint8 colour = _legend_land_owners[_company_to_list_pos[o]].colour; tbtm->colour = tile_is_tunnel ? _darken_colour[colour] : _lighten_colour[colour]; @@ -2083,6 +2092,31 @@ static inline uint32 ViewportMapGetColourOwner(const TileIndex tile, TileType t, return colour; } +static inline void ViewportMapStoreBridgeAboveTile(const ViewPort * const vp, const TileIndex tile) +{ + /* No need to bother for hidden things */ + if (!_settings_client.gui.show_bridges_on_map) return; + + /* Check existing stored bridges */ + TunnelBridgeToMap *tbtm = _vd.tunnel_bridge_to_map.Begin(); + TunnelBridgeToMap *tbtm_end = _vd.tunnel_bridge_to_map.End(); + for (; tbtm != tbtm_end; ++tbtm) { + if (!IsBridge(tbtm->from_tile)) continue; + + TileIndex from = tbtm->from_tile; + TileIndex to = tbtm->to_tile; + if (TileX(from) == TileX(to) && TileX(from) == TileX(tile)) { + if (TileY(from) > TileY(to)) std::swap(from, to); + if (TileY(from) <= TileY(tile) && TileY(tile) <= TileY(to)) return; /* already covered */ + } else if (TileY(from) == TileY(to) && TileY(from) == TileY(tile)) { + if (TileX(from) > TileX(to)) std::swap(from, to); + if (TileX(from) <= TileX(tile) && TileX(tile) <= TileX(to)) return; /* already covered */ + } + } + + ViewportMapStoreBridgeTunnel(vp, GetSouthernBridgeEnd(tile)); +} + static inline TileIndex ViewportMapGetMostSignificantTileType(const ViewPort * const vp, const TileIndex from_tile, TileType * const tile_type) { if (vp->zoom <= ZOOM_LVL_OUT_128X || !_settings_client.gui.viewport_map_scan_surroundings) { @@ -2090,6 +2124,7 @@ static inline TileIndex ViewportMapGetMostSignificantTileType(const ViewPort * c /* Store bridges and tunnels. */ if (ttype != MP_TUNNELBRIDGE) { *tile_type = ttype; + if (IsBridgeAbove(from_tile)) ViewportMapStoreBridgeAboveTile(vp, from_tile); } else { ViewportMapStoreBridgeTunnel(vp, from_tile); switch (GetTunnelBridgeTransportType(from_tile)) { @@ -2116,6 +2151,9 @@ static inline TileIndex ViewportMapGetMostSignificantTileType(const ViewPort * c importance = tile_importance; result = tile; } + if (ttype != MP_TUNNELBRIDGE && IsBridgeAbove(tile)) { + ViewportMapStoreBridgeAboveTile(vp, tile); + } } /* Store bridges and tunnels. */