From e02585f68e41d352d29bb85e95c731b609b720ac Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 4 Apr 2023 20:29:22 +0100 Subject: [PATCH] Add railtype and signals variables for signal vertical clearance --- docs/newgrf-additions-nml.html | 12 ++++++++ docs/newgrf-additions.html | 22 +++++++++++++++ src/newgrf_extension.cpp | 4 +++ src/newgrf_extension.h | 2 ++ src/newgrf_newsignals.cpp | 18 ++++++++++-- src/newgrf_newsignals.h | 9 ++++-- src/newgrf_optimiser.cpp | 28 +++++++++++++++++++ src/newgrf_railtype.cpp | 21 +++++++++----- src/newgrf_railtype.h | 11 +++++--- src/rail.h | 1 + src/rail_cmd.cpp | 29 ++++++++++++++------ src/table/newgrf_debug_data.h | 11 +++++++- src/tunnelbridge.h | 1 + src/tunnelbridge_cmd.cpp | 50 +++++++++++++++++++++++++--------- 14 files changed, 181 insertions(+), 38 deletions(-) diff --git a/docs/newgrf-additions-nml.html b/docs/newgrf-additions-nml.html index 1cc147572b..c2abbdfb19 100644 --- a/docs/newgrf-additions-nml.html +++ b/docs/newgrf-additions-nml.html @@ -209,6 +209,12 @@ + signal_vertical_clearance0 - 255 + + Pixels of vertical clearance between the signal and any bridge above.
+ If there is no bridge above, the value is 0xFF. + +

Roadtype properties

@@ -710,6 +716,12 @@ item (FEAT_GLOBALVARS) { The style ID defined using define_style for signals using a custom style, or 0 for signals using the default style + + +
signal_vertical_clearance0 - 255 + Pixels of vertical clearance between the signal and any bridge above.
+ If there is no bridge above, the value is 0xFF. +

Custom signal sprites example: diff --git a/docs/newgrf-additions.html b/docs/newgrf-additions.html index 60e31b3618..3dbbc2e598 100644 --- a/docs/newgrf-additions.html +++ b/docs/newgrf-additions.html @@ -828,6 +828,17 @@

This is indicated by the feature name: varaction2_railtype_signal_side, version 1

+

Vertical clearance (mappable variable: railtype_signal_vertical_clearance)

+

This applies to Action 2/3 - Railtype custom signal sprites.
+ + + +
BitMeaning
0 - 7 + Pixels of vertical clearance between the signal and any bridge above.
+ If there is no bridge above, the value is 0xFF. +
+

+

This is indicated by the feature name: varaction2_railtype_signal_vertical_clearance, version 1


Variational Action 2 - Objects

Tile slope after foundation applied (mappable variable: object_foundation_tile_slope)

@@ -890,6 +901,17 @@ Otherwise for signals using the default style, the value is 0.

This is indicated by the feature name: action0_signals_style, version 1.

+

Vertical clearance (mappable variable: signals_signal_vertical_clearance)

+

This applies to Action 2/3 Signals (Feature 0E) custom signal sprites.
+ + + +
BitMeaning
0 - 7 + Pixels of vertical clearance between the signal and any bridge above.
+ If there is no bridge above, the value is 0xFF. +
+

+

This is indicated by the feature name: varaction2_signals_signal_vertical_clearance, version 1



Callbacks - Ships

diff --git a/src/newgrf_extension.cpp b/src/newgrf_extension.cpp index b9746d07b9..7c5a4d6898 100644 --- a/src/newgrf_extension.cpp +++ b/src/newgrf_extension.cpp @@ -42,6 +42,7 @@ extern const GRFFeatureInfo _grf_feature_list[] = { GRFFeatureInfo("action0_roadtype_collision_mode", 1), GRFFeatureInfo("varaction2_railtype_signal_context", 1), GRFFeatureInfo("varaction2_railtype_signal_side", 1), + GRFFeatureInfo("varaction2_railtype_signal_vertical_clearance", 1), GRFFeatureInfo("action0_global_extra_station_names", 2), GRFFeatureInfo("action0_global_default_object_generate_amount", 1), GRFFeatureInfo("action0_global_allow_rocks_in_desert", 1), @@ -53,6 +54,7 @@ extern const GRFFeatureInfo _grf_feature_list[] = { GRFFeatureInfo("action0_signals_style", 1), GRFFeatureInfo("varaction2_signals_signal_context", 1), GRFFeatureInfo("varaction2_signals_signal_side", 1), + GRFFeatureInfo("varaction2_signals_signal_vertical_clearance", 1), GRFFeatureInfo("action3_signals_custom_signal_sprites", 1), GRFFeatureInfo("action0_object_use_land_ground", 1), GRFFeatureInfo("action0_object_edge_foundation_mode", 2), @@ -167,10 +169,12 @@ extern const GRFVariableMapDefinition _grf_action2_remappable_variables[] = { GRFVariableMapDefinition(GSF_RAILTYPES, A2VRI_RAILTYPE_SIGNAL_RESTRICTION_INFO, "railtype_signal_restriction_info"), GRFVariableMapDefinition(GSF_RAILTYPES, A2VRI_RAILTYPE_SIGNAL_CONTEXT, "railtype_signal_context"), GRFVariableMapDefinition(GSF_RAILTYPES, A2VRI_RAILTYPE_SIGNAL_SIDE, "railtype_signal_side"), + GRFVariableMapDefinition(GSF_RAILTYPES, A2VRI_RAILTYPE_SIGNAL_VERTICAL_CLEARANCE, "railtype_signal_vertical_clearance"), GRFVariableMapDefinition(GSF_SIGNALS, A2VRI_SIGNALS_SIGNAL_RESTRICTION_INFO, "signals_signal_restriction_info"), GRFVariableMapDefinition(GSF_SIGNALS, A2VRI_SIGNALS_SIGNAL_CONTEXT, "signals_signal_context"), GRFVariableMapDefinition(GSF_SIGNALS, A2VRI_SIGNALS_SIGNAL_STYLE, "signals_signal_style"), GRFVariableMapDefinition(GSF_SIGNALS, A2VRI_SIGNALS_SIGNAL_SIDE, "signals_signal_side"), + GRFVariableMapDefinition(GSF_SIGNALS, A2VRI_SIGNALS_SIGNAL_VERTICAL_CLEARANCE, "signals_signal_vertical_clearance"), GRFVariableMapDefinition(GSF_FAKE_TOWNS, A2VRI_TOWNS_HOUSE_COUNT, "town_house_count"), GRFVariableMapDefinition(GSF_FAKE_TOWNS, A2VRI_TOWNS_POPULATION, "town_population"), GRFVariableMapDefinition(GSF_FAKE_TOWNS, A2VRI_ZONE_0, "town_zone_0_radius_square"), diff --git a/src/newgrf_extension.h b/src/newgrf_extension.h index 38b4196f88..037804510c 100644 --- a/src/newgrf_extension.h +++ b/src/newgrf_extension.h @@ -83,10 +83,12 @@ enum Action2VariableRemapIds { A2VRI_RAILTYPE_SIGNAL_RESTRICTION_INFO, A2VRI_RAILTYPE_SIGNAL_CONTEXT, A2VRI_RAILTYPE_SIGNAL_SIDE, + A2VRI_RAILTYPE_SIGNAL_VERTICAL_CLEARANCE, A2VRI_SIGNALS_SIGNAL_RESTRICTION_INFO, A2VRI_SIGNALS_SIGNAL_CONTEXT, A2VRI_SIGNALS_SIGNAL_STYLE, A2VRI_SIGNALS_SIGNAL_SIDE, + A2VRI_SIGNALS_SIGNAL_VERTICAL_CLEARANCE, A2VRI_TOWNS_HOUSE_COUNT, A2VRI_TOWNS_POPULATION, A2VRI_ZONE_0, diff --git a/src/newgrf_newsignals.cpp b/src/newgrf_newsignals.cpp index 1f0fb0a942..b089b8dfe6 100644 --- a/src/newgrf_newsignals.cpp +++ b/src/newgrf_newsignals.cpp @@ -54,6 +54,7 @@ uint32 GetNewSignalsSideVariable() case A2VRI_SIGNALS_SIGNAL_CONTEXT: return this->signal_context; case A2VRI_SIGNALS_SIGNAL_STYLE: return MapSignalStyle(this->signal_style); case A2VRI_SIGNALS_SIGNAL_SIDE: return GetNewSignalsSideVariable(); + case A2VRI_SIGNALS_SIGNAL_VERTICAL_CLEARANCE: return 0xFF; } } @@ -65,6 +66,7 @@ uint32 GetNewSignalsSideVariable() return GetNewSignalsSignalContext(this->signal_context, this->tile); case A2VRI_SIGNALS_SIGNAL_STYLE: return MapSignalStyle(this->signal_style); case A2VRI_SIGNALS_SIGNAL_SIDE: return GetNewSignalsSideVariable(); + case A2VRI_SIGNALS_SIGNAL_VERTICAL_CLEARANCE: return GetNewSignalsVerticalClearanceInfo(this->tile, this->z); } DEBUG(grf, 1, "Unhandled new signals tile variable 0x%X", variable); @@ -94,9 +96,11 @@ GrfSpecFeature NewSignalsResolverObject::GetFeature() const * @param param2 Extra parameter (second parameter of the callback, except railtypes do not have callbacks). * @param signal_context Signal context. * @param prog Routing restriction program. + * @param z Signal pixel z. */ -NewSignalsResolverObject::NewSignalsResolverObject(const GRFFile *grffile, TileIndex tile, TileContext context, uint32 param1, uint32 param2, CustomSignalSpriteContext signal_context, uint8 signal_style, const TraceRestrictProgram *prog) - : ResolverObject(grffile, CBID_NO_CALLBACK, param1, param2), newsignals_scope(*this, tile, context, signal_context, signal_style, prog) +NewSignalsResolverObject::NewSignalsResolverObject(const GRFFile *grffile, TileIndex tile, TileContext context, uint32 param1, uint32 param2, + CustomSignalSpriteContext signal_context, uint8 signal_style, const TraceRestrictProgram *prog, uint z) + : ResolverObject(grffile, CBID_NO_CALLBACK, param1, param2), newsignals_scope(*this, tile, context, signal_context, signal_style, prog, z) { this->root_spritegroup = grffile != nullptr ? grffile->new_signals_group : nullptr; } @@ -113,6 +117,16 @@ uint GetNewSignalsRestrictedSignalsInfo(const TraceRestrictProgram *prog, TileIn return result; } +uint GetNewSignalsVerticalClearanceInfo(TileIndex tile, uint z) +{ + if (IsBridgeAbove(tile)) { + uint height = GetBridgePixelHeight(GetNorthernBridgeEnd(tile)); + return std::min(0xFF, height - z); + } else { + return 0xFF; + } +} + void DumpNewSignalsSpriteGroups(DumpSpriteGroupPrinter print) { SpriteGroupDumper dumper(print); diff --git a/src/newgrf_newsignals.h b/src/newgrf_newsignals.h index 1c72edd875..e229383d60 100644 --- a/src/newgrf_newsignals.h +++ b/src/newgrf_newsignals.h @@ -66,6 +66,7 @@ struct NewSignalsScopeResolver : public ScopeResolver { CustomSignalSpriteContext signal_context; uint8 signal_style; const TraceRestrictProgram *prog; + uint z; /** * Constructor of the railtype scope resolvers. @@ -74,8 +75,8 @@ struct NewSignalsScopeResolver : public ScopeResolver { * @param context Are we resolving sprites for the upper halftile, or on a bridge? * @param signal_context Signal context. */ - NewSignalsScopeResolver(ResolverObject &ro, TileIndex tile, TileContext context, CustomSignalSpriteContext signal_context, uint8 signal_style, const TraceRestrictProgram *prog) - : ScopeResolver(ro), tile(tile), context(context), signal_context(signal_context), signal_style(signal_style), prog(prog) + NewSignalsScopeResolver(ResolverObject &ro, TileIndex tile, TileContext context, CustomSignalSpriteContext signal_context, uint8 signal_style, const TraceRestrictProgram *prog, uint z) + : ScopeResolver(ro), tile(tile), context(context), signal_context(signal_context), signal_style(signal_style), prog(prog), z(z) { } @@ -87,7 +88,8 @@ struct NewSignalsScopeResolver : public ScopeResolver { struct NewSignalsResolverObject : public ResolverObject { NewSignalsScopeResolver newsignals_scope; ///< Resolver for the new signals scope. - NewSignalsResolverObject(const GRFFile *grffile, TileIndex tile, TileContext context, uint32 param1, uint32 param2, CustomSignalSpriteContext signal_context, uint8 signal_style, const TraceRestrictProgram *prog = nullptr); + NewSignalsResolverObject(const GRFFile *grffile, TileIndex tile, TileContext context, uint32 param1, uint32 param2, + CustomSignalSpriteContext signal_context, uint8 signal_style, const TraceRestrictProgram *prog = nullptr, uint z = 0); ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, VarSpriteGroupScopeOffset relative = 0) override { @@ -103,6 +105,7 @@ struct NewSignalsResolverObject : public ResolverObject { }; uint GetNewSignalsRestrictedSignalsInfo(const TraceRestrictProgram *prog, TileIndex tile, uint8 signal_style); +uint GetNewSignalsVerticalClearanceInfo(TileIndex tile, uint z); inline uint GetNewSignalsSignalContext(CustomSignalSpriteContext signal_context, TileIndex tile) { diff --git a/src/newgrf_optimiser.cpp b/src/newgrf_optimiser.cpp index 54b1f1676f..c4ec3ca8a8 100644 --- a/src/newgrf_optimiser.cpp +++ b/src/newgrf_optimiser.cpp @@ -101,6 +101,28 @@ static bool IsExpensiveRoadStopsVariable(uint16 variable) } } +static bool IsExpensiveRailtypeVariable(uint16 variable) +{ + switch (variable) { + case A2VRI_RAILTYPE_SIGNAL_VERTICAL_CLEARANCE: + return true; + + default: + return false; + } +} + +static bool IsExpensiveSignalVariable(uint16 variable) +{ + switch (variable) { + case A2VRI_SIGNALS_SIGNAL_VERTICAL_CLEARANCE: + return true; + + default: + return false; + } +} + static bool IsExpensiveVariable(uint16 variable, GrfSpecFeature scope_feature) { switch (scope_feature) { @@ -122,6 +144,12 @@ static bool IsExpensiveVariable(uint16 variable, GrfSpecFeature scope_feature) case GSF_ROADSTOPS: return IsExpensiveRoadStopsVariable(variable); + case GSF_RAILTYPES: + return IsExpensiveRailtypeVariable(variable); + + case GSF_SIGNALS: + return IsExpensiveSignalVariable(variable); + default: return false; } diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index 3446366395..426d49c657 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -37,6 +37,7 @@ case A2VRI_RAILTYPE_SIGNAL_RESTRICTION_INFO: return 0; case A2VRI_RAILTYPE_SIGNAL_CONTEXT: return this->signal_context; case A2VRI_RAILTYPE_SIGNAL_SIDE: return GetNewSignalsSideVariable(); + case A2VRI_RAILTYPE_SIGNAL_VERTICAL_CLEARANCE: return 0xFF; } } @@ -62,6 +63,8 @@ return GetNewSignalsSignalContext(this->signal_context, this->tile); case A2VRI_RAILTYPE_SIGNAL_SIDE: return GetNewSignalsSideVariable(); + case A2VRI_RAILTYPE_SIGNAL_VERTICAL_CLEARANCE: + return GetNewSignalsVerticalClearanceInfo(this->tile, this->z); } DEBUG(grf, 1, "Unhandled rail type tile variable 0x%X", variable); @@ -89,10 +92,12 @@ uint32 RailTypeResolverObject::GetDebugID() const * @param param1 Extra parameter (first parameter of the callback, except railtypes do not have callbacks). * @param param2 Extra parameter (second parameter of the callback, except railtypes do not have callbacks). * @param signal_context Signal context. + * @param z Signal pixel z. * @param prog Routing restriction program. */ -RailTypeResolverObject::RailTypeResolverObject(const RailtypeInfo *rti, TileIndex tile, TileContext context, RailTypeSpriteGroup rtsg, uint32 param1, uint32 param2, CustomSignalSpriteContext signal_context, const TraceRestrictProgram *prog) - : ResolverObject(rti != nullptr ? rti->grffile[rtsg] : nullptr, CBID_NO_CALLBACK, param1, param2), railtype_scope(*this, rti, tile, context, signal_context, prog) +RailTypeResolverObject::RailTypeResolverObject(const RailtypeInfo *rti, TileIndex tile, TileContext context, RailTypeSpriteGroup rtsg, uint32 param1, uint32 param2, + CustomSignalSpriteContext signal_context, const TraceRestrictProgram *prog, uint z) + : ResolverObject(rti != nullptr ? rti->grffile[rtsg] : nullptr, CBID_NO_CALLBACK, param1, param2), railtype_scope(*this, rti, tile, context, signal_context, prog, z) { this->root_spritegroup = rti != nullptr ? rti->group[rtsg] : nullptr; } @@ -135,7 +140,8 @@ inline uint8 RemapAspect(uint8 aspect, uint8 extra_aspects, uint8 style) return aspect + 1; } -static PalSpriteID GetRailTypeCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, uint8 aspect, CustomSignalSpriteContext context, const TraceRestrictProgram *prog) +static PalSpriteID GetRailTypeCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, uint8 aspect, + CustomSignalSpriteContext context, const TraceRestrictProgram *prog, uint z) { if (rti->group[RTSG_SIGNALS] == nullptr) return { 0, PAL_NONE }; if (type == SIGTYPE_PROG && !HasBit(rti->ctrl_flags, RTCF_PROGSIG)) return { 0, PAL_NONE }; @@ -144,7 +150,7 @@ static PalSpriteID GetRailTypeCustomSignalSprite(const RailtypeInfo *rti, TileIn uint32 param1 = (context == CSSC_GUI) ? 0x10 : 0x00; uint32 param2 = (type << 16) | (var << 8) | RemapAspect(aspect, rti->signal_extra_aspects, 0); if ((prog != nullptr) && HasBit(rti->ctrl_flags, RTCF_RESTRICTEDSIG)) SetBit(param2, 24); - RailTypeResolverObject object(rti, tile, TCX_NORMAL, RTSG_SIGNALS, param1, param2, context, prog); + RailTypeResolverObject object(rti, tile, TCX_NORMAL, RTSG_SIGNALS, param1, param2, context, prog, z); const SpriteGroup *group = object.Resolve(); if (group == nullptr || group->GetNumResults() == 0) return { 0, PAL_NONE }; @@ -163,12 +169,13 @@ static PalSpriteID GetRailTypeCustomSignalSprite(const RailtypeInfo *rti, TileIn * @param gui Is the sprite being used on the map or in the GUI? * @return The sprite to draw. */ -CustomSignalSpriteResult GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, uint8 aspect, CustomSignalSpriteContext context, uint8 style, const TraceRestrictProgram *prog) +CustomSignalSpriteResult GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, uint8 aspect, + CustomSignalSpriteContext context, uint8 style, const TraceRestrictProgram *prog, uint z) { if (_settings_client.gui.show_all_signal_default && style == 0) return { { 0, PAL_NONE }, false }; if (style == 0) { - PalSpriteID spr = GetRailTypeCustomSignalSprite(rti, tile, type, var, aspect, context, prog); + PalSpriteID spr = GetRailTypeCustomSignalSprite(rti, tile, type, var, aspect, context, prog, z); if (spr.sprite != 0) return { spr, HasBit(rti->ctrl_flags, RTCF_RESTRICTEDSIG) }; } @@ -182,7 +189,7 @@ CustomSignalSpriteResult GetCustomSignalSprite(const RailtypeInfo *rti, TileInde uint32 param1 = (context == CSSC_GUI) ? 0x10 : 0x00; uint32 param2 = (type << 16) | (var << 8) | RemapAspect(aspect, grf->new_signal_extra_aspects, style); if ((prog != nullptr) && HasBit(grf->new_signal_ctrl_flags, NSCF_RESTRICTEDSIG)) SetBit(param2, 24); - NewSignalsResolverObject object(grf, tile, TCX_NORMAL, param1, param2, context, style, prog); + NewSignalsResolverObject object(grf, tile, TCX_NORMAL, param1, param2, context, style, prog, z); const SpriteGroup *group = object.Resolve(); if (group != nullptr && group->GetNumResults() != 0) { diff --git a/src/newgrf_railtype.h b/src/newgrf_railtype.h index a4dc0f43e0..7545b5b190 100644 --- a/src/newgrf_railtype.h +++ b/src/newgrf_railtype.h @@ -23,6 +23,7 @@ struct RailTypeScopeResolver : public ScopeResolver { CustomSignalSpriteContext signal_context; const RailtypeInfo *rti; const TraceRestrictProgram *prog; + uint z; /** * Constructor of the railtype scope resolvers. @@ -31,8 +32,8 @@ struct RailTypeScopeResolver : public ScopeResolver { * @param context Are we resolving sprites for the upper halftile, or on a bridge? * @param signal_context Signal context. */ - RailTypeScopeResolver(ResolverObject &ro, const RailtypeInfo *rti, TileIndex tile, TileContext context, CustomSignalSpriteContext signal_context, const TraceRestrictProgram *prog) - : ScopeResolver(ro), tile(tile), context(context), signal_context(signal_context), rti(rti), prog(prog) + RailTypeScopeResolver(ResolverObject &ro, const RailtypeInfo *rti, TileIndex tile, TileContext context, CustomSignalSpriteContext signal_context, const TraceRestrictProgram *prog, uint z) + : ScopeResolver(ro), tile(tile), context(context), signal_context(signal_context), rti(rti), prog(prog), z(z) { } @@ -44,7 +45,8 @@ struct RailTypeScopeResolver : public ScopeResolver { struct RailTypeResolverObject : public ResolverObject { RailTypeScopeResolver railtype_scope; ///< Resolver for the railtype scope. - RailTypeResolverObject(const RailtypeInfo *rti, TileIndex tile, TileContext context, RailTypeSpriteGroup rtsg, uint32 param1 = 0, uint32 param2 = 0, CustomSignalSpriteContext signal_context = CSSC_GUI, const TraceRestrictProgram *prog = nullptr); + RailTypeResolverObject(const RailtypeInfo *rti, TileIndex tile, TileContext context, RailTypeSpriteGroup rtsg, uint32 param1 = 0, uint32 param2 = 0, + CustomSignalSpriteContext signal_context = CSSC_GUI, const TraceRestrictProgram *prog = nullptr, uint z = 0); ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, VarSpriteGroupScopeOffset relative = 0) override { @@ -64,7 +66,8 @@ struct CustomSignalSpriteResult { }; SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context = TCX_NORMAL, uint *num_results = nullptr); -CustomSignalSpriteResult GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, uint8 aspect, CustomSignalSpriteContext context, uint8 style, const TraceRestrictProgram *prog = nullptr); +CustomSignalSpriteResult GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, uint8 aspect, + CustomSignalSpriteContext context, uint8 style, const TraceRestrictProgram *prog = nullptr, uint z = 0); RailType GetRailTypeTranslation(uint8 railtype, const GRFFile *grffile); uint8 GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile); diff --git a/src/rail.h b/src/rail.h index 262c0b5145..4efd4c3489 100644 --- a/src/rail.h +++ b/src/rail.h @@ -480,6 +480,7 @@ static inline Money SignalMaintenanceCost(uint32 num) void MarkSingleSignalDirty(TileIndex tile, Trackdir td); void MarkSingleSignalDirtyAtZ(TileIndex tile, Trackdir td, bool opposite_side, uint z); +void GetSignalXYZByTrackdir(TileIndex tile, Trackdir td, bool opposite_side, uint &x, uint &y, uint &z); void DrawTrainDepotSprite(int x, int y, int image, RailType railtype); int TicksToLeaveDepot(const Train *v); diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 4db2bc9a8b..fe7b6a2914 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -2858,7 +2858,9 @@ void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, Sign aspect = 0; } - const CustomSignalSpriteResult result = GetCustomSignalSprite(rti, tile, type, variant, aspect, context, style, prog); + const uint z = GetSaveSlopeZ(x, y, track); + + const CustomSignalSpriteResult result = GetCustomSignalSprite(rti, tile, type, variant, aspect, context, style, prog, z); SpriteID sprite = result.sprite.sprite; PaletteID pal = PAL_NONE; bool is_custom_sprite = (sprite != 0); @@ -2919,13 +2921,13 @@ void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, Sign static const SubSprite lower_part = { -50, -10, 50, 50 }; static const SubSprite upper_part = { -50, -50, 50, -11 }; - AddSortableSpriteToDraw(sprite, SPR_TRACERESTRICT_BASE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track), false, 0, 0, 0, &lower_part); - AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track), false, 0, 0, 0, &upper_part); + AddSortableSpriteToDraw(sprite, SPR_TRACERESTRICT_BASE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, z, false, 0, 0, 0, &lower_part); + AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, z, false, 0, 0, 0, &upper_part); } else { - AddSortableSpriteToDraw(sprite, SPR_TRACERESTRICT_BASE + (type == SIGTYPE_NO_ENTRY ? 0 : 1), x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track)); + AddSortableSpriteToDraw(sprite, SPR_TRACERESTRICT_BASE + (type == SIGTYPE_NO_ENTRY ? 0 : 1), x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, z); } } else { - AddSortableSpriteToDraw(sprite, pal, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track)); + AddSortableSpriteToDraw(sprite, pal, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, z); } const Sprite *sp = GetSprite(sprite, ST_NORMAL); if (sp->x_offs < -SIGNAL_DIRTY_LEFT || sp->x_offs + sp->width > SIGNAL_DIRTY_RIGHT || sp->y_offs < -SIGNAL_DIRTY_TOP || sp->y_offs + sp->height > SIGNAL_DIRTY_BOTTOM) { @@ -2942,8 +2944,7 @@ static void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track trac DrawSingleSignal(tile, rti, track, condition, image, pos, type, variant, prog, CSSC_TRACK); } -template -void MarkSingleSignalDirtyIntl(TileIndex tile, Trackdir td, bool opposite, F get_z) +static void GetSignalXYByTrackdir(TileIndex tile, Trackdir td, bool opposite, uint &x, uint &y) { static const uint8 trackdir_to_pos[TRACKDIR_END] = { 8, // TRACKDIR_X_NE @@ -2964,8 +2965,20 @@ void MarkSingleSignalDirtyIntl(TileIndex tile, Trackdir td, bool opposite, F get 0, // TRACKDIR_RVREV_NW }; - uint x, y; GetSignalXY(tile, trackdir_to_pos[td], opposite, x, y); +} + +void GetSignalXYZByTrackdir(TileIndex tile, Trackdir td, bool opposite_side, uint &x, uint &y, uint &z) +{ + GetSignalXYByTrackdir(tile, td, opposite_side, x, y); + z = GetSaveSlopeZ(x, y, TrackdirToTrack(td)); +} + +template +void MarkSingleSignalDirtyIntl(TileIndex tile, Trackdir td, bool opposite, F get_z) +{ + uint x, y; + GetSignalXYByTrackdir(tile, td, opposite, x, y); Point pt = RemapCoords(x, y, get_z(x, y)); MarkAllViewportsDirty( pt.x - SIGNAL_DIRTY_LEFT, diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index 8e2821d512..4d2315d771 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -24,6 +24,7 @@ #include "../newgrf_extension.h" #include "../animated_tile.h" #include "../clear_map.h" +#include "../tunnelbridge.h" /* Helper for filling property tables */ #define NIP(prop, base, variable, type, name) { name, (ptrdiff_t)cpp_offsetof(base, variable), cpp_sizeof(base, variable), prop, type } @@ -1215,6 +1216,7 @@ static const NIVariable _niv_signals[] = { NIV(A2VRI_SIGNALS_SIGNAL_CONTEXT, "context"), NIV(A2VRI_SIGNALS_SIGNAL_STYLE, "style"), NIV(A2VRI_SIGNALS_SIGNAL_SIDE, "side"), + NIV(A2VRI_SIGNALS_SIGNAL_VERTICAL_CLEARANCE, "vertical_clearance"), NIV_END() }; @@ -1233,20 +1235,27 @@ class NIHSignals : public NIHelper { extern TraceRestrictProgram *GetFirstTraceRestrictProgramOnTile(TileIndex t); CustomSignalSpriteContext ctx = CSSC_TRACK; uint8 style = 0; + uint z = 0; if (IsTunnelBridgeWithSignalSimulation(index)) { ctx = IsTunnelBridgeSignalSimulationEntrance(index) ? CSSC_TUNNEL_BRIDGE_ENTRANCE : CSSC_TUNNEL_BRIDGE_EXIT; style = GetTunnelBridgeSignalStyle(index); + z = GetTunnelBridgeSignalZ(index, !IsTunnelBridgeSignalSimulationEntrance(index)); } else if (IsTileType(index, MP_RAILWAY) && HasSignals(index)) { TrackBits bits = GetTrackBits(index); do { Track track = RemoveFirstTrack(&bits); if (HasSignalOnTrack(index, track)) { style = GetSignalStyle(index, track); + Trackdir td = TrackToTrackdir(track); + if (!HasSignalOnTrackdir(index, td)) td = ReverseTrackdir(td); + + uint x, y; + GetSignalXYZByTrackdir(index, td, HasBit(_signal_style_masks.signal_opposite_side, style), x, y, z); break; } } while (bits != TRACK_BIT_NONE); } - NewSignalsResolverObject ro(nullptr, index, TCX_NORMAL, 0, 0, ctx, style, GetFirstTraceRestrictProgramOnTile(index)); + NewSignalsResolverObject ro(nullptr, index, TCX_NORMAL, 0, 0, ctx, style, GetFirstTraceRestrictProgramOnTile(index), z); return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, extra); } diff --git a/src/tunnelbridge.h b/src/tunnelbridge.h index 4f42231eb7..8bdf434edd 100644 --- a/src/tunnelbridge.h +++ b/src/tunnelbridge.h @@ -17,6 +17,7 @@ uint GetBestTunnelBridgeSignalSimulationSpacing(TileIndex begin, TileIndex end, uint GetTunnelBridgeSignalSimulationSignalCount(TileIndex begin, TileIndex end); void MarkTunnelBridgeSignalDirty(TileIndex tile, bool exit); +int GetTunnelBridgeSignalZ(TileIndex tile, bool exit); /** * Calculates the length of a tunnel or a bridge (without end tiles) diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 4b78e2a521..e76155b0d9 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1765,7 +1765,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, style, prog); + const CustomSignalSpriteResult result = GetCustomSignalSprite(rti, ti->tile, type, variant, aspect, show_exit ? CSSC_TUNNEL_BRIDGE_EXIT : CSSC_TUNNEL_BRIDGE_ENTRANCE, style, prog, z); PalSpriteID sprite = result.sprite; bool is_custom_sprite = (sprite.sprite != 0); @@ -1943,6 +1943,41 @@ void MarkSingleBridgeSignalDirty(TileIndex tile, TileIndex bridge_start_tile) ); } +static int GetTunnelBridgeSignalZNonRailCustom(TileIndex tile, bool side, bool exit, DiagDirection dir) +{ + int z; + if (IsTunnel(tile)) { + z = GetTileZ(tile) * TILE_HEIGHT; + } else { + Slope slope = GetTilePixelSlope(tile, &z); + if (slope == SLOPE_FLAT) { + if (side == exit && dir == DIAGDIR_SE) z += 2; + if (side != exit && dir == DIAGDIR_SW) z += 2; + } else { + z += 8; + } + } + + return z; +} + +int GetTunnelBridgeSignalZ(TileIndex tile, bool exit) +{ + if (IsRailCustomBridgeHeadTile(tile)) { + return GetTileMaxPixelZ(tile); + } + + bool opposite_side = false; + if (_signal_style_masks.signal_opposite_side != 0) { + opposite_side = HasBit(_signal_style_masks.signal_opposite_side, GetTunnelBridgeSignalStyle(tile)); + } + + bool side = (_settings_game.vehicle.road_side != 0) && _settings_game.construction.train_signal_side; + side ^= opposite_side; + + return GetTunnelBridgeSignalZNonRailCustom(tile, side, exit, GetTunnelBridgeDirection(tile)); +} + void MarkTunnelBridgeSignalDirty(TileIndex tile, bool exit) { if (_signal_sprite_oversized) { @@ -1986,18 +2021,7 @@ void MarkTunnelBridgeSignalDirty(TileIndex tile, bool exit) uint x = TileX(tile) * TILE_SIZE + SignalPositions[side != exit][position].x; uint y = TileY(tile) * TILE_SIZE + SignalPositions[side != exit][position].y; - int z; - if (IsTunnel(tile)) { - z = GetTileZ(tile) * TILE_HEIGHT; - } else { - Slope slope = GetTilePixelSlope(tile, &z); - if (slope == SLOPE_FLAT) { - if (side == exit && dir == DIAGDIR_SE) z += 2; - if (side != exit && dir == DIAGDIR_SW) z += 2; - } else { - z += 8; - } - } + int z = GetTunnelBridgeSignalZNonRailCustom(tile, side, exit, dir); Point pt = RemapCoords(x, y, z); MarkAllViewportsDirty(