diff --git a/src/misc.cpp b/src/misc.cpp index d9d506993f..cd442bfd43 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -28,6 +28,7 @@ #include "core/pool_type.hpp" #include "game/game.hpp" #include "linkgraph/linkgraphschedule.h" +#include "viewport_func.h" #include "safeguards.h" @@ -59,6 +60,8 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin AllocateMap(size_x, size_y); + ViewportMapClearTunnelCache(); + _pause_mode = PM_UNPAUSED; _fast_forward = 0; _tick_counter = 0; diff --git a/src/openttd.cpp b/src/openttd.cpp index 29846a2102..c249c0fa55 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -64,6 +64,7 @@ #include "gfx_layout.h" #include "viewport_sprite_sorter.h" #include "smallmap_gui.h" +#include "viewport_func.h" #include "linkgraph/linkgraphschedule.h" @@ -312,6 +313,8 @@ static void ShutdownGame() FioCloseAll(); UninitFreeType(); + + ViewportMapClearTunnelCache(); } /** diff --git a/src/smallmap_gui.h b/src/smallmap_gui.h index efb9ae7c08..e1dca43ae3 100644 --- a/src/smallmap_gui.h +++ b/src/smallmap_gui.h @@ -44,7 +44,6 @@ void BuildLinkStatsLegend(); struct TunnelBridgeToMap { TileIndex from_tile; TileIndex to_tile; - uint8 colour; }; typedef SmallVector TunnelBridgeToMapVector; diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 16e9bbe1c8..deb7098a8f 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -40,6 +40,7 @@ #include "object_base.h" #include "water.h" #include "company_gui.h" +#include "viewport_func.h" #include "table/strings.h" #include "table/bridge_land.h" @@ -866,6 +867,8 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags) DoClearSquare(tile); DoClearSquare(endtile); } + ViewportMapInvalidateTunnelCacheByTile(tile); + ViewportMapInvalidateTunnelCacheByTile(endtile); } return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_TUNNEL] * len); } diff --git a/src/viewport.cpp b/src/viewport.cpp index 846a4f2fec..a8bd70d265 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -174,7 +174,8 @@ struct ViewportDrawer { ParentSpriteToDrawVector parent_sprites_to_draw; ParentSpriteToSortVector parent_sprites_to_sort; ///< Parent sprite pointer array used for sorting ChildScreenSpriteToDrawVector child_screen_sprites_to_draw; - TunnelBridgeToMapVector tunnel_bridge_to_map; + TunnelBridgeToMapVector tunnel_to_map; + TunnelBridgeToMapVector bridge_to_map; int *last_child; @@ -1535,7 +1536,7 @@ static void ViewportMapStoreBridgeTunnel(const ViewPort * const vp, const TileIn if (!_legend_land_owners[_company_to_list_pos[o]].show_on_map) return; /* Check if already stored */ - TunnelBridgeToMapVector * const tbtmv = &_vd.tunnel_bridge_to_map; + TunnelBridgeToMapVector * const tbtmv = tile_is_tunnel ? &_vd.tunnel_to_map : &_vd.bridge_to_map; TunnelBridgeToMap *tbtm = tbtmv->Begin(); const TunnelBridgeToMap * const tbtm_end = tbtmv->End(); while (tbtm != tbtm_end) { @@ -1555,12 +1556,22 @@ static void ViewportMapStoreBridgeTunnel(const ViewPort * const vp, const TileIn 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]; - } else - tbtm->colour = tile_is_tunnel ? PC_BLACK : PC_VERY_LIGHT_YELLOW; +void ViewportMapClearTunnelCache() +{ + _vd.tunnel_to_map.Clear(); +} + +void ViewportMapInvalidateTunnelCacheByTile(const TileIndex tile) +{ + TunnelBridgeToMapVector * const tbtmv = &_vd.tunnel_to_map; + for (TunnelBridgeToMap *tbtm = tbtmv->Begin(); tbtm != tbtmv->End(); tbtm++) { + if (tbtm->from_tile == tile || tbtm->to_tile == tile) { + tbtmv->Erase(tbtm); + tbtm--; + } + } } /** @@ -2098,8 +2109,8 @@ static inline void ViewportMapStoreBridgeAboveTile(const ViewPort * const vp, co 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(); + TunnelBridgeToMap *tbtm = _vd.bridge_to_map.Begin(); + TunnelBridgeToMap *tbtm_end = _vd.bridge_to_map.End(); for (; tbtm != tbtm_end; ++tbtm) { if (!IsBridge(tbtm->from_tile)) continue; @@ -2277,6 +2288,35 @@ static void ViewportMapDrawScrollingViewportBox(const ViewPort * const vp) uint32 *_vp_map_line; ///< Buffer for drawing the map of a viewport. +static void ViewportMapDrawBridgeTunnel(const ViewPort * const vp, const TunnelBridgeToMap * const tbtm, const int z, + const bool is_tunnel, const int w, const int h, Blitter * const blitter) +{ + extern LegendAndColour _legend_land_owners[NUM_NO_COMPANY_ENTRIES + MAX_COMPANIES + 1]; + extern uint _company_to_list_pos[MAX_COMPANIES]; + + TileIndex tile = tbtm->from_tile; + const Owner o = GetTileOwner(tile); + if (!_legend_land_owners[_company_to_list_pos[o]].show_on_map) return; + + uint8 colour; + if (vp->map_type == VPMT_OWNER && _settings_client.gui.use_owner_colour_for_tunnelbridge && o < MAX_COMPANIES) { + colour = _legend_land_owners[_company_to_list_pos[o]].colour; + colour = is_tunnel ? _darken_colour[colour] : _lighten_colour[colour]; + } else { + colour = is_tunnel ? PC_BLACK : PC_VERY_LIGHT_YELLOW; + } + + TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile)); + for (; tile != tbtm->to_tile; tile += delta) { // For each tile + const Point pt = RemapCoords(TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE, z); + const int x = UnScaleByZoomLower(pt.x - _vd.dpi.left, _vd.dpi.zoom); + if (IsInsideMM(x, 0, w)) { + const int y = UnScaleByZoomLower(pt.y - _vd.dpi.top, _vd.dpi.zoom); + if (IsInsideMM(y, 0, h)) blitter->SetPixel(_vd.dpi.dst_ptr, x, y, colour); + } + } +} + /** Draw the map on a viewport. */ template void ViewportMapDraw(const ViewPort * const vp) @@ -2333,21 +2373,31 @@ void ViewportMapDraw(const ViewPort * const vp) b += incr_b; } while (++j < h); - /* Render bridges and tunnels */ - if (_vd.tunnel_bridge_to_map.Length() != 0) { - const TunnelBridgeToMap * const tbtm_end = _vd.tunnel_bridge_to_map.End(); - for (const TunnelBridgeToMap *tbtm = _vd.tunnel_bridge_to_map.Begin(); tbtm != tbtm_end; tbtm++) { // For each bridge or tunnel - TileIndex tile = tbtm->from_tile; - const int z = (IsBridge(tile) ? GetBridgeHeight(tile) : GetTileZ(tile)) * TILE_HEIGHT; - TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile)); - for (; tile != tbtm->to_tile; tile += delta) { // For each tile - const Point pt = RemapCoords(TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE, z); - const int x = UnScaleByZoomLower(pt.x - _vd.dpi.left, _vd.dpi.zoom); - if (IsInsideMM(x, 0, w)) { - const int y = UnScaleByZoomLower(pt.y - _vd.dpi.top, _vd.dpi.zoom); - if (IsInsideMM(y, 0, h)) blitter->SetPixel(_vd.dpi.dst_ptr, x, y, tbtm->colour); - } - } + /* Render tunnels */ + if (_settings_client.gui.show_tunnels_on_map && _vd.tunnel_to_map.Length() != 0) { + const TunnelBridgeToMap * const tbtm_end = _vd.tunnel_to_map.End(); + for (const TunnelBridgeToMap *tbtm = _vd.tunnel_to_map.Begin(); tbtm != tbtm_end; tbtm++) { // For each tunnel + const int tunnel_z = GetTileZ(tbtm->from_tile) * TILE_HEIGHT; + const Point pt_from = RemapCoords(TileX(tbtm->from_tile) * TILE_SIZE, TileY(tbtm->from_tile) * TILE_SIZE, tunnel_z); + const Point pt_to = RemapCoords(TileX(tbtm->to_tile) * TILE_SIZE, TileY(tbtm->to_tile) * TILE_SIZE, tunnel_z); + + /* check if tunnel is wholly outside redrawing area */ + const int x_from = UnScaleByZoomLower(pt_from.x - _vd.dpi.left, _vd.dpi.zoom); + const int x_to = UnScaleByZoomLower(pt_to.x - _vd.dpi.left, _vd.dpi.zoom); + if ((x_from < 0 && x_to < 0) || (x_from > w && x_to > w)) continue; + const int y_from = UnScaleByZoomLower(pt_from.y - _vd.dpi.top, _vd.dpi.zoom); + const int y_to = UnScaleByZoomLower(pt_to.y - _vd.dpi.top, _vd.dpi.zoom); + if ((y_from < 0 && y_to < 0) || (y_from > h && y_to > h)) continue; + + ViewportMapDrawBridgeTunnel(vp, tbtm, tunnel_z, true, w, h, blitter); + } + } + + /* Render bridges */ + if (_settings_client.gui.show_bridges_on_map && _vd.bridge_to_map.Length() != 0) { + const TunnelBridgeToMap * const tbtm_end = _vd.bridge_to_map.End(); + for (const TunnelBridgeToMap *tbtm = _vd.bridge_to_map.Begin(); tbtm != tbtm_end; tbtm++) { // For each bridge + ViewportMapDrawBridgeTunnel(vp, tbtm, (GetBridgeHeight(tbtm->from_tile) - 1) * TILE_HEIGHT, false, w, h, blitter); } } } @@ -2445,7 +2495,7 @@ void ViewportDoDraw(const ViewPort *vp, int left, int top, int right, int bottom _cur_dpi = old_dpi; - _vd.tunnel_bridge_to_map.Clear(); + _vd.bridge_to_map.Clear(); _vd.string_sprites_to_draw.Clear(); _vd.tile_sprites_to_draw.Clear(); _vd.parent_sprites_to_draw.Clear(); diff --git a/src/viewport_func.h b/src/viewport_func.h index 47b2a2d16d..3ee230b7c5 100644 --- a/src/viewport_func.h +++ b/src/viewport_func.h @@ -94,4 +94,7 @@ Point GetViewportStationMiddle(const ViewPort *vp, const Station *st); void ShowTooltipForTile(Window *w, const TileIndex tile); +void ViewportMapClearTunnelCache(); +void ViewportMapInvalidateTunnelCacheByTile(const TileIndex tile); + #endif /* VIEWPORT_FUNC_H */