diff --git a/src/misc.cpp b/src/misc.cpp index 90558cdd9b..ed1976ae17 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -30,6 +30,7 @@ #include "linkgraph/linkgraphschedule.h" #include "tracerestrict.h" #include "programmable_signals.h" +#include "viewport_func.h" #include "safeguards.h" @@ -61,6 +62,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 192cc57205..fd47523746 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -66,6 +66,7 @@ #include "viewport_sprite_sorter.h" #include "programmable_signals.h" #include "smallmap_gui.h" +#include "viewport_func.h" #include "linkgraph/linkgraphschedule.h" #include "tracerestrict.h" @@ -319,6 +320,8 @@ static void ShutdownGame() FioCloseAll(); UninitFreeType(); + + ViewportMapClearTunnelCache(); } /** diff --git a/src/smallmap_gui.h b/src/smallmap_gui.h index 9589ca3aea..faa750a713 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 322769e102..5835457078 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -41,6 +41,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" @@ -881,6 +882,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 cfb43dff97..73df1f98c0 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -175,7 +175,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; @@ -1538,7 +1539,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) { @@ -1558,12 +1559,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--; + } + } } /** @@ -2101,8 +2112,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; @@ -2280,6 +2291,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) @@ -2336,21 +2376,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); } } } @@ -2448,7 +2498,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 */