Add signal style flag for drawing on the opposite side

pull/400/head
Jonathan G Rennison 2 years ago
parent ff064e06b8
commit fcae909839

@ -512,6 +512,11 @@ item (FEAT_GLOBALVARS) {
The value is clamped to be less than or equal to the value set in the <span class="code">extra_aspects</span> property.
</td>
</tr>
<tr><td>style_opposite_side</td><td>0 or 1</td>
<td>
Set whether signals should be drawn on the opposite side of the track for the most recently defined style (defined using the <span class="code">define_style</span> property).
</td>
</tr>
<tr><td>no_default_style</td><td>0 or 1</td>
<td>
When enabled, custom signal graphics from this GRF are only used for custom signal styles, not the default style

@ -480,6 +480,13 @@
The Action 0 Id field is not used, the value is ignored.
</p>
<p>This is indicated by the feature name: <font face="monospace">action0_signals_style</font>, version 1</p>
<h4 id="signals_style_opposite_side">Set custom signal style signal drawn on opposite side (mappable property: signals_style_opposite_side)</h4>
<p>This applies to the most recent custom signal style defined using the <a href="#signals_define_style">signals_define_style</a> property.<br />
When enabled, signals using this style are drawn on the opposite side of the track.</p>
<p>The property length is 1 byte. 0 is disabled (default). 1 is enabled.<br />
The Action 0 Id field is not used, the value is ignored.
</p>
<p>This is indicated by the feature name: <font face="monospace">action0_signals_style</font>, version 1</p>
<h4 id="signals_no_default_style">Set whether custom signal sprites should not be used for the default signal style (mappable property: signals_no_default_style)</h4>
<p>This applies to <a href="#a3signals_custom_signal_sprites">Action 2/3 Signals (Feature 0E) custom signal sprites</a> for this GRF.<br />
When enabled, this GRF is not used for the default signal style, it is only used for custom signal styles defined with <a href="#signals_define_style">signals_define_style</a>.</p>

@ -4271,6 +4271,15 @@ static ChangeInfoResult SignalsChangeInfo(uint id, int numinfo, int prop, const
break;
}
case A0RPI_SIGNALS_STYLE_OPPOSITE_SIDE: {
if (MappedPropertyLengthMismatch(buf, 1, mapping_entry)) break;
uint8 value = buf->ReadByte();
if (_cur.grffile->current_new_signal_style != nullptr) {
SB(_cur.grffile->current_new_signal_style->style_flags, NSSF_OPPOSITE_SIDE, 1, (value != 0 ? 1 : 0));
}
break;
}
default:
ret = HandleAction0PropertyDefault(buf, prop);
break;

@ -99,6 +99,7 @@ extern const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = {
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_STYLE_LOOKAHEAD_EXTRA_ASPECTS, "signals_style_lookahead_extra_aspects"),
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_STYLE_SEMAPHORE_ENABLED, "signals_style_semaphore_enabled"),
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_STYLE_ELECTRIC_ENABLED, "signals_style_electric_enabled"),
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_STYLE_OPPOSITE_SIDE, "signals_style_opposite_side"),
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_USE_LAND_GROUND, "object_use_land_ground"),
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_EDGE_FOUNDATION_MODE, "object_edge_foundation_mode"),
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_FLOOD_RESISTANT, "object_flood_resistant"),

@ -43,6 +43,7 @@ enum Action0RemapPropertyIds {
A0RPI_SIGNALS_STYLE_LOOKAHEAD_EXTRA_ASPECTS,
A0RPI_SIGNALS_STYLE_SEMAPHORE_ENABLED,
A0RPI_SIGNALS_STYLE_ELECTRIC_ENABLED,
A0RPI_SIGNALS_STYLE_OPPOSITE_SIDE,
A0RPI_OBJECT_USE_LAND_GROUND,
A0RPI_OBJECT_EDGE_FOUNDATION_MODE,
A0RPI_OBJECT_FLOOD_RESISTANT,

@ -28,6 +28,7 @@ enum NewSignalStyleFlags {
NSSF_NO_ASPECT_INC = 0,
NSSF_ALWAYS_RESERVE_THROUGH = 1,
NSSF_LOOKAHEAD_ASPECTS_SET = 2,
NSSF_OPPOSITE_SIDE = 3,
};
struct NewSignalStyle {

@ -479,7 +479,7 @@ static inline Money SignalMaintenanceCost(uint32 num)
}
void MarkSingleSignalDirty(TileIndex tile, Trackdir td);
void MarkSingleSignalDirtyAtZ(TileIndex tile, Trackdir td, uint z);
void MarkSingleSignalDirtyAtZ(TileIndex tile, Trackdir td, bool opposite_side, uint z);
void DrawTrainDepotSprite(int x, int y, int image, RailType railtype);
int TicksToLeaveDepot(const Train *v);

@ -2763,7 +2763,7 @@ static uint GetSaveSlopeZ(uint x, uint y, Track track)
return GetSlopePixelZ(x, y);
}
static void GetSignalXY(TileIndex tile, uint pos, uint &x, uint &y)
static void GetSignalXY(TileIndex tile, uint pos, bool opposite, uint &x, uint &y)
{
bool side;
switch (_settings_game.construction.train_signal_side) {
@ -2771,6 +2771,7 @@ static void GetSignalXY(TileIndex tile, uint pos, uint &x, uint &y)
case 2: side = true; break; // right
default: side = _settings_game.vehicle.road_side != 0; break; // driving side
}
side ^= opposite;
static const Point SignalPositions[2][12] = {
{ // Signals on the left side
/* LEFT LEFT RIGHT RIGHT UPPER UPPER */
@ -2796,8 +2797,25 @@ void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, Sign
if (type == SIGTYPE_NO_ENTRY) pos ^= 1;
uint8 style = 0;
if (_num_new_signal_styles > 0) {
switch (context) {
case CSSC_TRACK:
style = GetSignalStyle(tile, track);
break;
case CSSC_TUNNEL_BRIDGE_ENTRANCE:
case CSSC_TUNNEL_BRIDGE_EXIT:
style = GetTunnelBridgeSignalStyle(tile);
break;
default:
break;
}
}
uint x, y;
GetSignalXY(tile, pos, x, y);
GetSignalXY(tile, pos, HasBit(_signal_opposite_side_style_mask, style), x, y);
uint8 aspect;
if (condition == SIGNAL_STATE_GREEN) {
@ -2824,23 +2842,6 @@ void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, Sign
aspect = 0;
}
uint8 style = 0;
if (_num_new_signal_styles > 0) {
switch (context) {
case CSSC_TRACK:
style = GetSignalStyle(tile, track);
break;
case CSSC_TUNNEL_BRIDGE_ENTRANCE:
case CSSC_TUNNEL_BRIDGE_EXIT:
style = GetTunnelBridgeSignalStyle(tile);
break;
default:
break;
}
}
const CustomSignalSpriteResult result = GetCustomSignalSprite(rti, tile, type, variant, aspect, context, style, prog);
SpriteID sprite = result.sprite.sprite;
PaletteID pal = PAL_NONE;
@ -2926,7 +2927,7 @@ static void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track trac
}
template <typename F>
void MarkSingleSignalDirtyIntl(TileIndex tile, Trackdir td, F get_z)
void MarkSingleSignalDirtyIntl(TileIndex tile, Trackdir td, bool opposite, F get_z)
{
static const uint8 trackdir_to_pos[TRACKDIR_END] = {
8, // TRACKDIR_X_NE
@ -2948,7 +2949,7 @@ void MarkSingleSignalDirtyIntl(TileIndex tile, Trackdir td, F get_z)
};
uint x, y;
GetSignalXY(tile, trackdir_to_pos[td], x, y);
GetSignalXY(tile, trackdir_to_pos[td], opposite, x, y);
Point pt = RemapCoords(x, y, get_z(x, y));
MarkAllViewportsDirty(
pt.x - SIGNAL_DIRTY_LEFT,
@ -2965,15 +2966,18 @@ void MarkSingleSignalDirty(TileIndex tile, Trackdir td)
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
return;
}
MarkSingleSignalDirtyIntl(tile, td, [td](uint x, uint y) -> uint {
bool opposite = false;
if (_signal_opposite_side_style_mask != 0) {
opposite = HasBit(_signal_opposite_side_style_mask, GetSignalStyleGeneric(tile, TrackdirToTrack(td)));
}
MarkSingleSignalDirtyIntl(tile, td, opposite, [td](uint x, uint y) -> uint {
return GetSaveSlopeZ(x, y, TrackdirToTrack(td));
});
}
void MarkSingleSignalDirtyAtZ(TileIndex tile, Trackdir td, uint z)
void MarkSingleSignalDirtyAtZ(TileIndex tile, Trackdir td, bool opposite_side, uint z)
{
MarkSingleSignalDirtyIntl(tile, td, [z](uint x, uint y) -> uint {
MarkSingleSignalDirtyIntl(tile, td, opposite_side, [z](uint x, uint y) -> uint {
return z;
});
}

@ -409,6 +409,18 @@ static inline uint8 GetSignalStyle(TileIndex t, Track track)
return GB(_me[t].m6, pos, 4);
}
static inline uint8 GetSignalStyleGeneric(TileIndex t, Track track)
{
switch (GetTileType(t)) {
case MP_RAILWAY:
return GetSignalStyle(t, track);
case MP_TUNNELBRIDGE:
return GetTunnelBridgeSignalStyle(t);
default:
return 0;
}
}
static inline void SetSignalStyle(TileIndex t, Track track, uint8 style)
{
assert_tile(GetRailTileType(t) == RAIL_TILE_SIGNALS, t);

@ -33,6 +33,7 @@ uint64 _aspect_cfg_hash = 0;
uint16 _non_aspect_inc_style_mask = 0;
uint16 _always_reserve_through_style_mask = 0;
uint16 _no_tunnel_bridge_style_mask = 0;
uint16 _signal_opposite_side_style_mask = 0;
bool _signal_sprite_oversized = false;
/// List of signals dependent upon this one
@ -1513,6 +1514,7 @@ static bool DetermineExtraAspectsVariable()
_non_aspect_inc_style_mask = 0;
_no_tunnel_bridge_style_mask = 0;
_always_reserve_through_style_mask = 0;
_signal_opposite_side_style_mask = 0;
if (_settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) {
@ -1536,6 +1538,9 @@ static bool DetermineExtraAspectsVariable()
} else {
_new_signal_styles[i].lookahead_extra_aspects = _new_signal_styles[i].grffile->new_signal_extra_aspects;
}
if (HasBit(_new_signal_styles[i].style_flags, NSSF_OPPOSITE_SIDE)) {
SetBit(_signal_opposite_side_style_mask, i + 1);
}
}
for (uint i = _num_new_signal_styles; i < MAX_NEW_SIGNAL_STYLES; i++) {
_new_signal_styles[i].lookahead_extra_aspects = new_extra_aspects;

@ -24,6 +24,7 @@ extern uint64 _aspect_cfg_hash;
extern uint16 _non_aspect_inc_style_mask;
extern uint16 _always_reserve_through_style_mask;
extern uint16 _no_tunnel_bridge_style_mask;
extern uint16 _signal_opposite_side_style_mask;
extern bool _signal_sprite_oversized;
/**

@ -1729,9 +1729,12 @@ static void DrawBridgeRoadBits(TileIndex head_tile, int x, int y, int z, int off
static void DrawTunnelBridgeRampSingleSignal(const TileInfo *ti, bool is_green, uint position, SignalType type, bool show_exit)
{
bool side = (_settings_game.vehicle.road_side != 0) &&_settings_game.construction.train_signal_side;
bool side = (_settings_game.vehicle.road_side != 0) && _settings_game.construction.train_signal_side;
DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
uint8 style = GetTunnelBridgeSignalStyle(ti->tile);
side ^= HasBit(_signal_opposite_side_style_mask, style);
static const Point SignalPositions[2][4] = {
{ /* X X Y Y Signals on the left side */
{13, 3}, { 2, 13}, { 3, 4}, {13, 14}
@ -1761,7 +1764,7 @@ static void DrawTunnelBridgeRampSingleSignal(const TileInfo *ti, bool is_green,
}
bool show_restricted = IsTunnelBridgeRestrictedSignal(ti->tile);
const TraceRestrictProgram *prog = show_restricted ? GetExistingTraceRestrictProgram(ti->tile, FindFirstTrack(GetAcrossTunnelBridgeTrackBits(ti->tile))) : nullptr;
const CustomSignalSpriteResult result = GetCustomSignalSprite(rti, ti->tile, type, variant, aspect, show_exit ? CSSC_TUNNEL_BRIDGE_EXIT : CSSC_TUNNEL_BRIDGE_ENTRANCE, GetTunnelBridgeSignalStyle(ti->tile), prog);
const CustomSignalSpriteResult result = GetCustomSignalSprite(rti, ti->tile, type, variant, aspect, show_exit ? CSSC_TUNNEL_BRIDGE_EXIT : CSSC_TUNNEL_BRIDGE_ENTRANCE, style, prog);
PalSpriteID sprite = result.sprite;
bool is_custom_sprite = (sprite.sprite != 0);
@ -1827,9 +1830,10 @@ static void DrawTunnelBridgeRampSignal(const TileInfo *ti)
}
}
static void GetBridgeSignalXY(TileIndex tile, DiagDirection bridge_direction, uint &position, uint &x, uint &y)
static void GetBridgeSignalXY(TileIndex tile, DiagDirection bridge_direction, bool opposite_side, uint &position, uint &x, uint &y)
{
bool side = (_settings_game.vehicle.road_side != 0) && _settings_game.construction.train_signal_side;
side ^= opposite_side;
static const Point SignalPositions[2][4] = {
{ /* X X Y Y Signals on the left side */
@ -1863,9 +1867,10 @@ 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) {
uint8 style = GetBridgeSignalStyle(bridge_start_tile);
uint position, x, y;
GetBridgeSignalXY(ti->tile, GetTunnelBridgeDirection(bridge_start_tile), position, x, y);
GetBridgeSignalXY(ti->tile, GetTunnelBridgeDirection(bridge_start_tile), HasBit(_signal_opposite_side_style_mask, style), position, x, y);
SignalVariant variant = IsTunnelBridgeSemaphore(bridge_start_tile) ? SIG_SEMAPHORE : SIG_ELECTRIC;
SignalState state = GetBridgeEntranceSimulatedSignalState(bridge_start_tile, m2_position);
@ -1889,7 +1894,7 @@ static void DrawBridgeSignalOnMiddlePart(const TileInfo *ti, TileIndex bridge_st
}
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(bridge_start_tile));
PalSpriteID sprite = GetCustomSignalSprite(rti, bridge_start_tile, SIGTYPE_NORMAL, variant, aspect, CSSC_BRIDGE_MIDDLE, GetBridgeSignalStyle(bridge_start_tile)).sprite;
PalSpriteID sprite = GetCustomSignalSprite(rti, bridge_start_tile, SIGTYPE_NORMAL, variant, aspect, CSSC_BRIDGE_MIDDLE, style).sprite;
if (sprite.sprite != 0) {
sprite.sprite += position;
@ -1920,8 +1925,13 @@ void MarkSingleBridgeSignalDirty(TileIndex tile, TileIndex bridge_start_tile)
return;
}
bool opposite_side = false;
if (_signal_opposite_side_style_mask != 0) {
opposite_side = HasBit(_signal_opposite_side_style_mask, GetTunnelBridgeSignalStyle(bridge_start_tile));
}
uint position, x, y;
GetBridgeSignalXY(tile, GetTunnelBridgeDirection(bridge_start_tile), position, x, y);
GetBridgeSignalXY(tile, GetTunnelBridgeDirection(bridge_start_tile), opposite_side, position, x, y);
Point pt = RemapCoords(x, y, GetBridgePixelHeight(bridge_start_tile) + 5 - BRIDGE_Z_START);
MarkAllViewportsDirty(
pt.x - SIGNAL_DIRTY_LEFT,
@ -1939,15 +1949,22 @@ void MarkTunnelBridgeSignalDirty(TileIndex tile, bool exit)
return;
}
bool opposite_side = false;
if (_signal_opposite_side_style_mask != 0) {
opposite_side = HasBit(_signal_opposite_side_style_mask, GetTunnelBridgeSignalStyle(tile));
}
if (IsRailCustomBridgeHeadTile(tile)) {
Trackdir td = exit ? GetTunnelBridgeExitTrackdir(tile) : GetTunnelBridgeEntranceTrackdir(tile);
MarkSingleSignalDirtyAtZ(tile, td, GetTileMaxPixelZ(tile));
MarkSingleSignalDirtyAtZ(tile, td, opposite_side, GetTileMaxPixelZ(tile));
return;
}
bool side = (_settings_game.vehicle.road_side != 0) && _settings_game.construction.train_signal_side;
DiagDirection dir = GetTunnelBridgeDirection(tile);
side ^= opposite_side;
uint position;
switch (dir) {
default: NOT_REACHED();

Loading…
Cancel
Save