diff --git a/src/lang/english.txt b/src/lang/english.txt index 785dc754db..b390e09f5c 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2390,6 +2390,7 @@ STR_TRACE_RESTRICT_VARIABLE_CURRENT_ORDER :current order STR_TRACE_RESTRICT_VARIABLE_NEXT_ORDER :next order STR_TRACE_RESTRICT_VARIABLE_LAST_VISITED_STATION :last visited station STR_TRACE_RESTRICT_VARIABLE_CARGO :cargo +STR_TRACE_RESTRICT_VARIABLE_ENTRY_DIRECTION :entry direction STR_TRACE_RESTRICT_VARIABLE_UNDEFINED :undefined STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_INTEGER :{STRING} {STRING} {STRING} {COMMA} then STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_SPEED :{STRING} {STRING} {STRING} {VELOCITY} then @@ -2397,6 +2398,8 @@ STR_TRACE_RESTRICT_CONDITIONAL_ORDER_STATION :{STRING} {STRIN STR_TRACE_RESTRICT_CONDITIONAL_ORDER_WAYPOINT :{STRING} {STRING} {STRING} {WAYPOINT} then STR_TRACE_RESTRICT_CONDITIONAL_ORDER_DEPOT :{STRING} {STRING} {STRING} {DEPOT} then STR_TRACE_RESTRICT_CONDITIONAL_CARGO :{STRING} train {STRING} cargo: {STRING} then +STR_TRACE_RESTRICT_CONDITIONAL_ENTRY_DIRECTION :{STRING} train {STRING} entering from {STRING} tile edge then +STR_TRACE_RESTRICT_CONDITIONAL_ENTRY_SIGNAL_FACE :{STRING} train {STRING} entering from {STRING} of signal then STR_TRACE_RESTRICT_CONDITIONAL_UNDEFINED :{STRING} {STRING} {STRING} {RED}undefined {BLACK}{STRING}then STR_TRACE_RESTRICT_CONDITIONAL_COMPARE_UNDEFINED :{STRING} {RED}undefined {BLACK}{STRING}then STR_TRACE_RESTRICT_PF_PENALTY_ITEM :Add pathfinder penalty: {COMMA} @@ -2407,6 +2410,12 @@ STR_TRACE_RESTRICT_PF_DENY :Deny STR_TRACE_RESTRICT_PF_ALLOW :Allow STR_TRACE_RESTRICT_PF_ALLOW_LONG :Allow (cancel previous Deny) STR_TRACE_RESTRICT_PF_PENALTY :Penalty +STR_TRACE_RESTRICT_DIRECTION_FRONT :front +STR_TRACE_RESTRICT_DIRECTION_BACK :back +STR_TRACE_RESTRICT_DIRECTION_NE :north-east +STR_TRACE_RESTRICT_DIRECTION_SE :south-east +STR_TRACE_RESTRICT_DIRECTION_SW :south-west +STR_TRACE_RESTRICT_DIRECTION_NW :north-west STR_TRACE_RESTRICT_VALUE_CAPTION :{WHITE}Value STR_TRACE_RESTRICT_CAPTION :{WHITE}Routefinding restriction STR_TRACE_RESTRICT_CAPTION_SHARED :{WHITE}Routefinding restriction - shared by {COMMA} signals diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index 81c362ae31..5a4b6531c3 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -194,7 +194,7 @@ private: { const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(tile, TrackdirToTrack(trackdir)); if (prog) { - prog->Execute(Yapf().GetVehicle(), out); + prog->Execute(Yapf().GetVehicle(), TraceRestrictProgramInput(tile, trackdir), out); if (out.flags & TRPRF_DENY) { n.m_segment->m_end_segment_reason |= ESRB_DEAD_END; return true; diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index ccfee30c39..968ab49eb0 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -211,7 +211,7 @@ static bool TestStationCondition(StationID station, TraceRestrictItem item) * @p v may not be NULL * @p out should be zero-initialised */ -void TraceRestrictProgram::Execute(const Train* v, TraceRestrictProgramResult& out) const +void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInput &input, TraceRestrictProgramResult& out) const { // static to avoid needing to re-alloc/resize on each execution static std::vector condstack; @@ -287,6 +287,32 @@ void TraceRestrictProgram::Execute(const Train* v, TraceRestrictProgramResult& o break; } + case TRIT_COND_ENTRY_DIRECTION: { + bool direction_match; + switch (GetTraceRestrictValue(item)) { + case TRNTSV_NE: + case TRNTSV_SE: + case TRNTSV_SW: + case TRNTSV_NW: + direction_match = (static_cast(GetTraceRestrictValue(item)) == TrackdirToExitdir(ReverseTrackdir(input.trackdir))); + break; + + case TRDTSV_FRONT: + direction_match = IsTileType(input.tile, MP_RAILWAY) && HasSignalOnTrackdir(input.tile, input.trackdir); + break; + + case TRDTSV_BACK: + direction_match = IsTileType(input.tile, MP_RAILWAY) && !HasSignalOnTrackdir(input.tile, input.trackdir); + break; + + default: + NOT_REACHED(); + break; + } + result = TestBinaryConditionCommon(item, direction_match); + break; + } + default: NOT_REACHED(); } @@ -402,6 +428,11 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp SetTraceRestrictAuxField(item, 0); break; + case TRVT_DIRECTION: + SetTraceRestrictValue(item, TRDTSV_FRONT); + SetTraceRestrictAuxField(item, 0); + break; + default: NOT_REACHED(); break; diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 91148facc7..4e0f0f52bb 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -105,6 +105,7 @@ enum TraceRestrictItemType { TRIT_COND_NEXT_ORDER = 13, ///< Test train next order (station, waypoint or depot) TRIT_COND_LAST_STATION = 14, ///< Test train last visited station TRIT_COND_CARGO = 15, ///< Test if train can carry cargo type + TRIT_COND_ENTRY_DIRECTION = 16, ///< Test which side of signal/signal tile is being entered from /* space up to 31 */ }; @@ -128,6 +129,18 @@ enum TraceRestrictNullTypeSpecialValue { TRNTSV_END = 2, ///< end tag, generated within GUI }; +/** + * Enumeration of TraceRestrictItemvalue type field when value type is TRVT_DIRECTION + */ +enum TraceRestrictDirectionTypeSpecialValue { + TRNTSV_NE = 0, ///< DIAGDIR_NE: entering at NE tile edge + TRNTSV_SE = 1, ///< DIAGDIR_SE: entering at SE tile edge + TRNTSV_SW = 2, ///< DIAGDIR_SW: entering at SW tile edge + TRNTSV_NW = 3, ///< DIAGDIR_NW: entering at NW tile edge + TRDTSV_FRONT = 4, ///< entering at front face of signal + TRDTSV_BACK = 5, ///< entering at rear face of signal +}; + /** * TraceRestrictItem condition operator field, only valid with conditional types (IsTraceRestrictTypeConditional() is true) */ @@ -159,6 +172,17 @@ enum TraceRestrictProgramResultFlags { }; DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags) +/** + * Execution input of a TraceRestrictProgram + */ +struct TraceRestrictProgramInput { + TileIndex tile; ///< Tile of restrict signal, for direction testing + Trackdir trackdir; ///< Track direction on tile of restrict signal, for direction testing + + TraceRestrictProgramInput(TileIndex tile_, Trackdir trackdir_) + : tile(tile_), trackdir(trackdir_) { } +}; + /** * Execution result of a TraceRestrictProgram */ @@ -181,7 +205,7 @@ struct TraceRestrictProgram : TraceRestrictProgramPool::PoolItem<&_tracerestrict TraceRestrictProgram() : refcount(0) { } - void Execute(const Train *v, TraceRestrictProgramResult &out) const; + void Execute(const Train *v, const TraceRestrictProgramInput &input, TraceRestrictProgramResult &out) const; /** * Increment ref count, only use when creating a mapping @@ -292,6 +316,7 @@ enum TraceRestrictValueType { TRVT_SPEED = 4, ///< takes an integer speed value TRVT_ORDER = 5, ///< takes an order target ID, as per the auxiliary field as type: TraceRestrictOrderCondAuxField TRVT_CARGO_ID = 6, ///< takes a CargoID + TRVT_DIRECTION = 7, ///< takes a TraceRestrictDirectionTypeSpecialValue }; /** @@ -343,6 +368,11 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR out.cond_type = TRCOT_BINARY; break; + case TRIT_COND_ENTRY_DIRECTION: + out.value_type = TRVT_DIRECTION; + out.cond_type = TRCOT_BINARY; + break; + default: NOT_REACHED(); break; diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 1255b28a1d..630c3abbd6 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -149,6 +149,29 @@ static const TraceRestrictDropDownListSet _deny_value = { _deny_value_str, _deny_value_val, }; +static const StringID _direction_value_str[] = { + STR_TRACE_RESTRICT_DIRECTION_FRONT, + STR_TRACE_RESTRICT_DIRECTION_BACK, + STR_TRACE_RESTRICT_DIRECTION_NE, + STR_TRACE_RESTRICT_DIRECTION_SE, + STR_TRACE_RESTRICT_DIRECTION_SW, + STR_TRACE_RESTRICT_DIRECTION_NW, + INVALID_STRING_ID +}; +static const uint _direction_value_val[] = { + TRDTSV_FRONT, + TRDTSV_BACK, + TRNTSV_NE, + TRNTSV_SE, + TRNTSV_SW, + TRNTSV_NW, +}; + +/** value drop down list for direction type strings and values */ +static const TraceRestrictDropDownListSet _direction_value = { + _direction_value_str, _direction_value_val, +}; + /** * Get index of @p value in @p list_set * if @p value is not present, assert if @p missing_ok is false, otherwise return -1 @@ -201,6 +224,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictI STR_TRACE_RESTRICT_VARIABLE_NEXT_ORDER, STR_TRACE_RESTRICT_VARIABLE_LAST_VISITED_STATION, STR_TRACE_RESTRICT_VARIABLE_CARGO, + STR_TRACE_RESTRICT_VARIABLE_ENTRY_DIRECTION, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED, INVALID_STRING_ID, }; @@ -211,6 +235,7 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictI TRIT_COND_NEXT_ORDER, TRIT_COND_LAST_STATION, TRIT_COND_CARGO, + TRIT_COND_ENTRY_DIRECTION, TRIT_COND_UNDEFINED, }; static const TraceRestrictDropDownListSet set_cond = { @@ -490,6 +515,17 @@ static void DrawInstructionString(TraceRestrictItem item, int y, bool selected, SetDParam(2, GetCargoStringByID(GetTraceRestrictValue(item))); break; + case TRVT_DIRECTION: + if (GetTraceRestrictValue(item) >= TRDTSV_FRONT) { + instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_ENTRY_SIGNAL_FACE; + } else { + instruction_string = STR_TRACE_RESTRICT_CONDITIONAL_ENTRY_DIRECTION; + } + SetDParam(0, _program_cond_type[GetTraceRestrictCondFlags(item)]); + SetDParam(1, GetDropDownStringByValue(GetCondOpDropDownListSet(properties), GetTraceRestrictCondOp(item))); + SetDParam(2, GetDropDownStringByValue(&_direction_value, GetTraceRestrictValue(item))); + break; + default: NOT_REACHED(); break; @@ -706,6 +742,10 @@ public: this->ShowDropDownListWithValue(GetSortedCargoTypeDropDownListSet(), GetTraceRestrictValue(item), true, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); // current cargo is permitted to not be in list break; + case TRVT_DIRECTION: + this->ShowDropDownListWithValue(&_direction_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0); + break; + default: break; } @@ -1357,6 +1397,13 @@ private: GetCargoStringByID(GetTraceRestrictValue(item)); break; + case TRVT_DIRECTION: + right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN); + this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN); + this->GetWidget(TR_WIDGET_VALUE_DROPDOWN)->widget_data = + GetDropDownStringByValue(&_direction_value, GetTraceRestrictValue(item)); + break; + default: break; }