diff --git a/src/bridge_signal_map.h b/src/bridge_signal_map.h index b97070c91f..6fa63b9c90 100644 --- a/src/bridge_signal_map.h +++ b/src/bridge_signal_map.h @@ -79,4 +79,6 @@ static inline void ClearBridgeEntranceSimulatedSignals(TileIndex t) void ClearBridgeSimulatedSignalMapping(); +void MarkSingleBridgeSignalDirty(TileIndex tile, TileIndex bridge_start_tile); + #endif /* BRIDGE_SIGNAL_MAP_H */ diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 125b54ed98..af1357719a 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -2677,13 +2677,6 @@ static void GetSignalXY(TileIndex tile, uint pos, uint &x, uint &y) y = TileY(tile) * TILE_SIZE + SignalPositions[side][pos].y; } -static bool _signal_sprite_oversized = false; - -static const int SIGNAL_DIRTY_LEFT = 14 * ZOOM_LVL_BASE; -static const int SIGNAL_DIRTY_RIGHT = 14 * ZOOM_LVL_BASE; -static const int SIGNAL_DIRTY_TOP = 30 * ZOOM_LVL_BASE; -static const int SIGNAL_DIRTY_BOTTOM = 5 * ZOOM_LVL_BASE; - void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, SignalState condition, SignalOffsets image, uint pos, SignalType type, SignalVariant variant, bool show_restricted, bool exit_signal = false) { diff --git a/src/signal.cpp b/src/signal.cpp index 4f6a40dcd3..42e168a2b2 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -27,6 +27,7 @@ #include "safeguards.h" uint8 _extra_aspects = 0; +bool _signal_sprite_oversized = false; /// List of signals dependent upon this one typedef std::vector SignalDependencyList; @@ -1244,10 +1245,11 @@ static void RefreshBridgeOnExitAspectChange(TileIndex entrance, TileIndex exit) const TileIndexDiffC offset = TileIndexDiffCByDiagDir(GetTunnelBridgeDirection(entrance)); const TileIndexDiff diff = TileDiffXY(offset.x * simulated_wormhole_signals, offset.y * simulated_wormhole_signals); const uint signal_count = bridge_length / simulated_wormhole_signals; + if (signal_count == 0) return; TileIndex tile = entrance + ((int)signal_count * diff); const uint redraw_count = std::min(_extra_aspects, signal_count); for (uint i = 0; i < redraw_count; i++) { - MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE); + MarkSingleBridgeSignalDirty(tile, entrance); tile -= diff; } } diff --git a/src/signal_func.h b/src/signal_func.h index 368dd00ffc..ec9d1fb98e 100644 --- a/src/signal_func.h +++ b/src/signal_func.h @@ -20,6 +20,7 @@ #include "vehicle_type.h" extern uint8 _extra_aspects; +extern bool _signal_sprite_oversized; /** * Maps a trackdir to the bit that stores its status in the map arrays, in the diff --git a/src/signal_type.h b/src/signal_type.h index daa3fe608d..fb7ccae4f5 100644 --- a/src/signal_type.h +++ b/src/signal_type.h @@ -13,6 +13,7 @@ #include "core/enum_type.hpp" #include "track_type.h" #include "tile_type.h" +#include "zoom_type.h" /** Variant of the signal, i.e. how does the signal look? */ enum SignalVariant { @@ -63,4 +64,9 @@ enum SignalState { SIGNAL_STATE_MAX = SIGNAL_STATE_GREEN, }; +static const int SIGNAL_DIRTY_LEFT = 14 * ZOOM_LVL_BASE; +static const int SIGNAL_DIRTY_RIGHT = 14 * ZOOM_LVL_BASE; +static const int SIGNAL_DIRTY_TOP = 30 * ZOOM_LVL_BASE; +static const int SIGNAL_DIRTY_BOTTOM = 5 * ZOOM_LVL_BASE; + #endif /* SIGNAL_TYPE_H */ diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index c2a1897e18..93b4191d44 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -3396,7 +3396,7 @@ static void UpdateAspectFromBridgeMiddleSignalChange(TileIndex entrance, TileInd UpdateEntranceAspectFromMiddleSignalChange(entrance, signal_number); if (signal_number > 0) { for (int i = std::max(0, signal_number - _extra_aspects); i < signal_number; i++) { - MarkTileDirtyByTile(entrance + (diff * (i + 1)), VMDF_NOT_MAP_MODE); + MarkSingleBridgeSignalDirty(entrance + (diff * (i + 1)), entrance); } } } @@ -3409,7 +3409,7 @@ static void HandleLastTunnelBridgeSignals(TileIndex tile, TileIndex end, DiagDir if (signal_offset) { TileIndexDiff diff = TileOffsByDiagDir(dir) * GetTunnelBridgeSignalSimulationSpacing(tile); TileIndex last_signal_tile = end + (diff * signal_offset); - MarkTileDirtyByTile(last_signal_tile, VMDF_NOT_MAP_MODE); + MarkSingleBridgeSignalDirty(last_signal_tile, end); if (_extra_aspects > 0) UpdateAspectFromBridgeMiddleSignalChange(end, diff, signal_offset - 1); } MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE); @@ -5101,7 +5101,7 @@ static void HandleSignalBehindTrain(Train *v, int signal_number) if (IsTunnelBridgeSignalSimulationEntrance(tile)) SetTunnelBridgeEntranceSignalGreen(tile); } else if (IsBridge(v->tile) && signal_number >= 0) { SetBridgeEntranceSimulatedSignalState(v->tile, signal_number, SIGNAL_STATE_GREEN); - MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE); + MarkSingleBridgeSignalDirty(tile, v->tile); if (_extra_aspects > 0) UpdateAspectFromBridgeMiddleSignalChange(v->tile, TileOffsByDiagDir(GetTunnelBridgeDirection(v->tile)) * simulated_wormhole_signals, signal_number); } else if (IsTunnel(v->tile) && signal_number >= 0 && _extra_aspects > 0) { UpdateEntranceAspectFromMiddleSignalChange(v->tile, signal_number); @@ -5504,7 +5504,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) /* flip signal in front to red on bridges*/ if (distance == 0 && IsBridge(v->tile)) { SetBridgeEntranceSimulatedSignalState(v->tile, v->tunnel_bridge_signal_num, SIGNAL_STATE_RED); - MarkTileDirtyByTile(gp.new_tile, VMDF_NOT_MAP_MODE); + MarkSingleBridgeSignalDirty(gp.new_tile, v->tile); } } } diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 225256e619..839f713082 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1791,6 +1791,30 @@ static void DrawTunnelBridgeRampSignal(const TileInfo *ti) } } +static void GetBridgeSignalXY(TileIndex tile, DiagDirection bridge_direction, uint &position, uint &x, uint &y) +{ + bool side = (_settings_game.vehicle.road_side != 0) && _settings_game.construction.train_signal_side; + + static const Point SignalPositions[2][4] = { + { /* X X Y Y Signals on the left side */ + {11, 3}, { 4, 13}, { 3, 4}, {11, 13} + }, {/* X X Y Y Signals on the right side */ + {11, 13}, { 4, 3}, {13, 4}, { 3, 11} + } + }; + + switch (bridge_direction) { + default: NOT_REACHED(); + case DIAGDIR_NE: position = 0; break; + case DIAGDIR_SE: position = 2; break; + case DIAGDIR_SW: position = 1; break; + case DIAGDIR_NW: position = 3; break; + } + + x = TileX(tile) * TILE_SIZE + SignalPositions[side][position].x; + y = TileY(tile) * TILE_SIZE + SignalPositions[side][position].y; +} + /* Draws a signal on tunnel / bridge entrance tile. */ static void DrawBridgeSignalOnMiddlePart(const TileInfo *ti, TileIndex bridge_start_tile, TileIndex bridge_end_tile, uint z) { @@ -1803,29 +1827,9 @@ static void DrawBridgeSignalOnMiddlePart(const TileInfo *ti, TileIndex bridge_st while (bridge_signal_position <= bridge_section) { bridge_signal_position += simulated_wormhole_signals; if (bridge_signal_position == bridge_section) { - bool side = (_settings_game.vehicle.road_side != 0) && _settings_game.construction.train_signal_side; - static const Point SignalPositions[2][4] = { - { /* X X Y Y Signals on the left side */ - {11, 3}, { 4, 13}, { 3, 4}, {11, 13} - }, {/* X X Y Y Signals on the right side */ - {11, 13}, { 4, 3}, {13, 4}, { 3, 11} - } - }; - - uint position; - - switch (GetTunnelBridgeDirection(bridge_start_tile)) { - default: NOT_REACHED(); - case DIAGDIR_NE: position = 0; break; - case DIAGDIR_SE: position = 2; break; - case DIAGDIR_SW: position = 1; break; - case DIAGDIR_NW: position = 3; break; - } - - uint x = TileX(ti->tile) * TILE_SIZE + SignalPositions[side][position].x; - uint y = TileY(ti->tile) * TILE_SIZE + SignalPositions[side][position].y; - z += 5; + uint position, x, y; + GetBridgeSignalXY(ti->tile, GetTunnelBridgeDirection(bridge_start_tile), position, x, y); SignalVariant variant = IsTunnelBridgeSemaphore(bridge_start_tile) ? SIG_SEMAPHORE : SIG_ELECTRIC; SignalState state = GetBridgeEntranceSimulatedSignalState(bridge_start_tile, m2_position); @@ -1864,13 +1868,32 @@ static void DrawBridgeSignalOnMiddlePart(const TileInfo *ti, TileIndex bridge_st sprite.pal = PAL_NONE; } - AddSortableSpriteToDraw(sprite.sprite, sprite.pal, x, y, 1, 1, TILE_HEIGHT, z, false, 0, 0, BB_Z_SEPARATOR); + AddSortableSpriteToDraw(sprite.sprite, sprite.pal, x, y, 1, 1, TILE_HEIGHT, z + 5, false, 0, 0, BB_Z_SEPARATOR); break; } m2_position++; } } +void MarkSingleBridgeSignalDirty(TileIndex tile, TileIndex bridge_start_tile) +{ + if (_signal_sprite_oversized) { + MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE); + return; + } + + uint position, x, y; + GetBridgeSignalXY(tile, GetTunnelBridgeDirection(bridge_start_tile), position, x, y); + Point pt = RemapCoords(x, y, GetBridgePixelHeight(bridge_start_tile) + 5 - BRIDGE_Z_START); + MarkAllViewportsDirty( + pt.x - SIGNAL_DIRTY_LEFT, + pt.y - SIGNAL_DIRTY_TOP, + pt.x + SIGNAL_DIRTY_RIGHT, + pt.y + SIGNAL_DIRTY_BOTTOM, + VMDF_NOT_MAP_MODE + ); +} + /** * Draws a tunnel of bridge tile. * For tunnels, this is rather simple, as you only need to draw the entrance.