From 0ebfcc23a50a46b653607db7f2e48539a431a653 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 26 Feb 2017 20:37:57 +0000 Subject: [PATCH 1/6] Implement instruction scroll-to for PBS entry signal conditional in GUI. --- src/tracerestrict_gui.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 06c7b02fcf..5b8d98e497 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -944,6 +944,11 @@ public: break; } } + } else if (GetTraceRestrictTypeProperties(item).value_type == TRVT_TILE_INDEX) { + TileIndex tile = *(TraceRestrictProgram::InstructionAt(this->GetProgram()->items, sel - 1) + 1); + if (tile != INVALID_TILE) { + ScrollMainWindowToTile(tile); + } } return; } From f192865c274b0d561e5d96e2184fee61dfb2bece Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 26 Feb 2017 21:39:04 +0000 Subject: [PATCH 2/6] Allow shallow-removing conditional blocks by use of ctrl+click. --- src/lang/english.txt | 3 +- src/tracerestrict.cpp | 148 +++++++++++++++++++++----------------- src/tracerestrict.h | 3 + src/tracerestrict_gui.cpp | 3 +- 4 files changed, 90 insertions(+), 67 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 56a6760c07..428ae843ab 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2466,7 +2466,7 @@ STR_TRACE_RESTRICT_UNSHARE :{BLACK}Unshare STR_TRACE_RESTRICT_SELECT_TARGET :{BLACK}Select Target STR_TRACE_RESTRICT_SELECT_SIGNAL :{BLACK}Select Signal STR_TRACE_RESTRICT_INSERT_TOOLTIP :{BLACK}Insert an instruction -STR_TRACE_RESTRICT_REMOVE_TOOLTIP :{BLACK}Remove the selected instruction +STR_TRACE_RESTRICT_REMOVE_TOOLTIP :{BLACK}Remove the selected instruction{}Ctrl+Click to remove the selected conditional instruction but retain its contents STR_TRACE_RESTRICT_RESET_TOOLTIP :{BLACK}Reset the current signal (without affecting shared programs) STR_TRACE_RESTRICT_COPY_TOOLTIP :{BLACK}Copy program from another signal STR_TRACE_RESTRICT_SHARE_TOOLTIP :{BLACK}Share program with another signal @@ -2481,6 +2481,7 @@ STR_TRACE_RESTRICT_ERROR_NO_PROGRAM :No trace restri STR_TRACE_RESTRICT_ERROR_OFFSET_TOO_LARGE :Offset too large STR_TRACE_RESTRICT_ERROR_CAN_T_CHANGE_CONDITIONALITY :Can't change conditionality STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ENDIF :Can't remove an 'end if' +STR_TRACE_RESTRICT_ERROR_CAN_T_SHALLOW_REMOVE_IF_ELIF :Can't shallow remove an 'if' block with one or more 'else if', 'or if' or 'else' blocks STR_TRACE_RESTRICT_ERROR_VALIDATE_END_CONDSTACK :Validation failed: condstack non-empty at exit STR_TRACE_RESTRICT_ERROR_VALIDATE_NO_IF :Validation failed: else/endif without opening if STR_TRACE_RESTRICT_ERROR_VALIDATE_DUP_ELSE :Validation failed: duplicate else diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 8e70ed6d56..2e5cc5b0ac 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -844,6 +844,85 @@ static uint32 GetDualInstructionInitialValue(TraceRestrictItem item) } } +CommandCost TraceRestrictProgramRemoveItemAt(std::vector &items, uint32 offset, bool shallow_mode) +{ + TraceRestrictItem old_item = *TraceRestrictProgram::InstructionAt(items, offset); + if (IsTraceRestrictConditional(old_item) && GetTraceRestrictCondFlags(old_item) != TRCF_OR) { + bool remove_whole_block = false; + if (GetTraceRestrictCondFlags(old_item) == 0) { + if (GetTraceRestrictType(old_item) == TRIT_COND_ENDIF) { + // this is an end if, can't remove these + return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ENDIF); + } else { + // this is an opening if + remove_whole_block = true; + } + } + + uint32 recursion_depth = 1; + std::vector::iterator remove_start = TraceRestrictProgram::InstructionAt(items, offset); + std::vector::iterator remove_end = remove_start + 1; + + // iterate until matching end block found + for (; remove_end != items.end(); ++remove_end) { + TraceRestrictItem current_item = *remove_end; + if (IsTraceRestrictConditional(current_item)) { + if (GetTraceRestrictCondFlags(current_item) == 0) { + if (GetTraceRestrictType(current_item) == TRIT_COND_ENDIF) { + // this is an end if + recursion_depth--; + if (recursion_depth == 0) { + if (remove_whole_block) { + // inclusively remove up to here + ++remove_end; + break; + } else { + // exclusively remove up to here + break; + } + } + } else { + // this is an opening if + recursion_depth++; + } + } else { + // this is an else/or type block + if (recursion_depth == 1 && !remove_whole_block) { + // exclusively remove up to here + recursion_depth = 0; + break; + } + if (recursion_depth == 1 && remove_whole_block && shallow_mode) { + // shallow-removing whole if block, and it contains an else/or if, bail out + return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_SHALLOW_REMOVE_IF_ELIF); + } + } + } else if (IsTraceRestrictDoubleItem(current_item)) { + // this is a double-item, jump over the next item as well + ++remove_end; + } + } + if (recursion_depth != 0) return CMD_ERROR; // ran off the end + if (shallow_mode) { + // must erase endif first, as it is later in the vector + if (remove_whole_block) items.erase(remove_end - 1); + items.erase(remove_start); + } else { + items.erase(remove_start, remove_end); + } + } else { + std::vector::iterator remove_start = TraceRestrictProgram::InstructionAt(items, offset); + std::vector::iterator remove_end = remove_start + 1; + + if (IsTraceRestrictDoubleItem(old_item)) { + // this is a double-item, remove the next item as well + ++remove_end; + } + items.erase(remove_start, remove_end); + } + return CommandCost(); +} + /** * The main command for editing a signal tracerestrict program. * @param tile The tile which contains the signal. @@ -928,71 +1007,10 @@ CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, u break; } - case TRDCT_REMOVE_ITEM: { - TraceRestrictItem old_item = *TraceRestrictProgram::InstructionAt(items, offset); - if (IsTraceRestrictConditional(old_item) && GetTraceRestrictCondFlags(old_item) != TRCF_OR) { - bool remove_whole_block = false; - if (GetTraceRestrictCondFlags(old_item) == 0) { - if (GetTraceRestrictType(old_item) == TRIT_COND_ENDIF) { - // this is an end if, can't remove these - return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ENDIF); - } else { - // this is an opening if - remove_whole_block = true; - } - } - - uint32 recursion_depth = 1; - std::vector::iterator remove_start = TraceRestrictProgram::InstructionAt(items, offset); - std::vector::iterator remove_end = remove_start + 1; - - // iterate until matching end block found - for (; remove_end != items.end(); ++remove_end) { - TraceRestrictItem current_item = *remove_end; - if (IsTraceRestrictConditional(current_item)) { - if (GetTraceRestrictCondFlags(current_item) == 0) { - if (GetTraceRestrictType(current_item) == TRIT_COND_ENDIF) { - // this is an end if - recursion_depth--; - if (recursion_depth == 0) { - if (remove_whole_block) { - // inclusively remove up to here - ++remove_end; - break; - } else { - // exclusively remove up to here - break; - } - } - } else { - // this is an opening if - recursion_depth++; - } - } else { - // this is an else/or type block - if (recursion_depth == 1 && !remove_whole_block) { - // exclusively remove up to here - recursion_depth = 0; - break; - } - } - } else if (IsTraceRestrictDoubleItem(current_item)) { - // this is a double-item, jump over the next item as well - ++remove_end; - } - } - if (recursion_depth != 0) return CMD_ERROR; // ran off the end - items.erase(remove_start, remove_end); - } else { - std::vector::iterator remove_start = TraceRestrictProgram::InstructionAt(items, offset); - std::vector::iterator remove_end = remove_start + 1; - - if (IsTraceRestrictDoubleItem(old_item)) { - // this is a double-item, remove the next item as well - ++remove_end; - } - items.erase(remove_start, remove_end); - } + case TRDCT_REMOVE_ITEM: + case TRDCT_SHALLOW_REMOVE_ITEM: { + CommandCost res = TraceRestrictProgramRemoveItemAt(items, offset, type == TRDCT_SHALLOW_REMOVE_ITEM); + if (res.Failed()) return res; break; } diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 03a0b85a31..78b24e5c13 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -622,6 +622,7 @@ enum TraceRestrictDoCommandType { TRDCT_MODIFY_ITEM, ///< modify instruction at offset field to given value TRDCT_MODIFY_DUAL_ITEM, ///< modify second item of dual-part instruction at offset field to given value TRDCT_REMOVE_ITEM, ///< remove instruction at offset field + TRDCT_SHALLOW_REMOVE_ITEM, ///< shallow remove instruction at offset field, does not delete contents of block TRDCT_PROG_COPY, ///< copy program operation. Do not re-order this with respect to other values TRDCT_PROG_SHARE, ///< share program operation @@ -645,6 +646,8 @@ inline void TraceRestrictProgMgmtDoCommandP(TileIndex tile, Track track, TraceRe CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text); CommandCost CmdProgramSignalTraceRestrictProgMgmt(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text); +CommandCost TraceRestrictProgramRemoveItemAt(std::vector &items, uint32 offset, bool shallow_mode); + void ShowTraceRestrictProgramWindow(TileIndex tile, Track track); void TraceRestrictRemoveDestinationID(TraceRestrictOrderCondAuxField type, uint16 index); diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 5b8d98e497..79a450ceac 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -1006,7 +1006,8 @@ public: return; } - TraceRestrictDoCommandP(tile, track, TRDCT_REMOVE_ITEM, this->selected_instruction - 1, 0, STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ITEM); + TraceRestrictDoCommandP(tile, track, _ctrl_pressed ? TRDCT_SHALLOW_REMOVE_ITEM : TRDCT_REMOVE_ITEM, + this->selected_instruction - 1, 0, STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ITEM); break; } From a2a8f7f7b718a3244580a1daddb763f68b28521d Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 26 Feb 2017 22:37:38 +0000 Subject: [PATCH 3/6] Change goto signal button in GUI to have push-button behaviour. --- src/tracerestrict_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 79a450ceac..2da6221227 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -2077,7 +2077,7 @@ static const NWidgetPart _nested_program_widgets[] = { SetDataTip(STR_EMPTY, STR_NULL), SetResize(1, 0), EndContainer(), EndContainer(), - NWidget(WWT_IMGBTN, COLOUR_GREY, TR_WIDGET_GOTO_SIGNAL), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_RIGHT, STR_TRACE_RESTRICT_GOTO_SIGNAL_TOOLTIP), + NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TR_WIDGET_GOTO_SIGNAL), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_RIGHT, STR_TRACE_RESTRICT_GOTO_SIGNAL_TOOLTIP), EndContainer(), /* Second button row. */ From f10c32de5372058aa15ccaeedafc15d1aa4f94c6 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 26 Feb 2017 22:51:18 +0000 Subject: [PATCH 4/6] Fix removal of double-length conditional instructions (PBS entry signal). --- src/tracerestrict.cpp | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 2e5cc5b0ac..de56f64687 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -844,6 +844,16 @@ static uint32 GetDualInstructionInitialValue(TraceRestrictItem item) } } +template T InstructionIteratorNext(T iter) +{ + return IsTraceRestrictDoubleItem(*iter) ? iter + 2 : iter + 1; +} + +template void InstructionIteratorAdvance(T &iter) +{ + iter = InstructionIteratorNext(iter); +} + CommandCost TraceRestrictProgramRemoveItemAt(std::vector &items, uint32 offset, bool shallow_mode) { TraceRestrictItem old_item = *TraceRestrictProgram::InstructionAt(items, offset); @@ -861,10 +871,10 @@ CommandCost TraceRestrictProgramRemoveItemAt(std::vector &ite uint32 recursion_depth = 1; std::vector::iterator remove_start = TraceRestrictProgram::InstructionAt(items, offset); - std::vector::iterator remove_end = remove_start + 1; + std::vector::iterator remove_end = InstructionIteratorNext(remove_start); // iterate until matching end block found - for (; remove_end != items.end(); ++remove_end) { + for (; remove_end != items.end(); InstructionIteratorAdvance(remove_end)) { TraceRestrictItem current_item = *remove_end; if (IsTraceRestrictConditional(current_item)) { if (GetTraceRestrictCondFlags(current_item) == 0) { @@ -873,8 +883,13 @@ CommandCost TraceRestrictProgramRemoveItemAt(std::vector &ite recursion_depth--; if (recursion_depth == 0) { if (remove_whole_block) { - // inclusively remove up to here - ++remove_end; + if (shallow_mode) { + // must erase endif first, as it is later in the vector + items.erase(remove_end, InstructionIteratorNext(remove_end)); + } else { + // inclusively remove up to here + InstructionIteratorAdvance(remove_end); + } break; } else { // exclusively remove up to here @@ -897,27 +912,18 @@ CommandCost TraceRestrictProgramRemoveItemAt(std::vector &ite return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_SHALLOW_REMOVE_IF_ELIF); } } - } else if (IsTraceRestrictDoubleItem(current_item)) { - // this is a double-item, jump over the next item as well - ++remove_end; } } if (recursion_depth != 0) return CMD_ERROR; // ran off the end if (shallow_mode) { - // must erase endif first, as it is later in the vector - if (remove_whole_block) items.erase(remove_end - 1); - items.erase(remove_start); + items.erase(remove_start, InstructionIteratorNext(remove_start)); } else { items.erase(remove_start, remove_end); } } else { std::vector::iterator remove_start = TraceRestrictProgram::InstructionAt(items, offset); - std::vector::iterator remove_end = remove_start + 1; + std::vector::iterator remove_end = InstructionIteratorNext(remove_start); - if (IsTraceRestrictDoubleItem(old_item)) { - // this is a double-item, remove the next item as well - ++remove_end; - } items.erase(remove_start, remove_end); } return CommandCost(); From 13f8de58c3ea51e5d109b8623b5db648ca044b7d Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 26 Feb 2017 23:52:15 +0000 Subject: [PATCH 5/6] Add instruction move up/down buttons to GUI. Has block and individual instruction move modes, depending on ctrl. --- src/lang/english.txt | 3 ++ src/tracerestrict.cpp | 63 ++++++++++++++++++++++++++++++++++++++- src/tracerestrict.h | 2 ++ src/tracerestrict_gui.cpp | 55 ++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 1 deletion(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 428ae843ab..47d8fe8a87 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2452,6 +2452,8 @@ 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 +STR_TRACE_RESTRICT_UP_BTN_TOOLTIP :{BLACK}Move the selected instruction up{}Ctrl+Click to move conditional instruction instead of whole block +STR_TRACE_RESTRICT_DOWN_BTN_TOOLTIP :{BLACK}Move the selected instruction down{}Ctrl+Click to move conditional instruction instead of whole block STR_TRACE_RESTRICT_TYPE_TOOLTIP :{BLACK}Type STR_TRACE_RESTRICT_COND_COMPARATOR_TOOLTIP :{BLACK}Comparison operator STR_TRACE_RESTRICT_COND_VALUE_TOOLTIP :{BLACK}Value @@ -2476,6 +2478,7 @@ STR_TRACE_RESTRICT_INSTRUCTION_LIST_TOOLTIP :{BLACK}Click an STR_TRACE_RESTRICT_ERROR_CAN_T_INSERT_ITEM :{WHITE}Can't insert instruction STR_TRACE_RESTRICT_ERROR_CAN_T_MODIFY_ITEM :{WHITE}Can't modify instruction STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ITEM :{WHITE}Can't remove instruction +STR_TRACE_RESTRICT_ERROR_CAN_T_MOVE_ITEM :{WHITE}Can't move instruction STR_TRACE_RESTRICT_ERROR_VALUE_TOO_LARGE :{WHITE}Value too large, maximum is {DECIMAL} STR_TRACE_RESTRICT_ERROR_NO_PROGRAM :No trace restrict program exists STR_TRACE_RESTRICT_ERROR_OFFSET_TOO_LARGE :Offset too large diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index de56f64687..6b484e16d9 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -21,6 +21,7 @@ #include "group.h" #include "pathfinder/yapf/yapf_cache.h" #include +#include /** @file * @@ -929,13 +930,67 @@ CommandCost TraceRestrictProgramRemoveItemAt(std::vector &ite return CommandCost(); } +CommandCost TraceRestrictProgramMoveItemAt(std::vector &items, uint32 &offset, bool up, bool shallow_mode) +{ + std::vector::iterator move_start = TraceRestrictProgram::InstructionAt(items, offset); + std::vector::iterator move_end = InstructionIteratorNext(move_start); + + TraceRestrictItem old_item = *move_start; + if (!shallow_mode) { + if (IsTraceRestrictConditional(old_item)) { + if (GetTraceRestrictCondFlags(old_item) != 0) { + // can't move or/else blocks + return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_MOVE_ITEM); + } + if (GetTraceRestrictType(old_item) == TRIT_COND_ENDIF) { + // this is an end if, can't move these + return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_MOVE_ITEM); + } + + uint32 recursion_depth = 1; + // iterate until matching end block found + for (; move_end != items.end(); InstructionIteratorAdvance(move_end)) { + TraceRestrictItem current_item = *move_end; + if (IsTraceRestrictConditional(current_item)) { + if (GetTraceRestrictCondFlags(current_item) == 0) { + if (GetTraceRestrictType(current_item) == TRIT_COND_ENDIF) { + // this is an end if + recursion_depth--; + if (recursion_depth == 0) { + // inclusively remove up to here + InstructionIteratorAdvance(move_end); + break; + } + } else { + // this is an opening if + recursion_depth++; + } + } + } + } + if (recursion_depth != 0) return CMD_ERROR; // ran off the end + } + } + + if (up) { + if (move_start == items.begin()) return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_MOVE_ITEM); + std::rotate(TraceRestrictProgram::InstructionAt(items, offset - 1), move_start, move_end); + offset--; + } else { + if (move_end == items.end()) return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_MOVE_ITEM); + std::rotate(move_start, move_end, InstructionIteratorNext(move_end)); + offset++; + } + return CommandCost(); +} + /** * The main command for editing a signal tracerestrict program. * @param tile The tile which contains the signal. * @param flags Internal command handler stuff. * Below apply for instruction modification actions only * @param p1 Bitstuffed items - * @param p2 Item, for insert and modify operations + * @param p2 Item, for insert and modify operations. Flags for instruction move operations * @return the cost of this operation (which is free), or an error */ CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) @@ -1020,6 +1075,12 @@ CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, u break; } + case TRDCT_MOVE_ITEM: { + CommandCost res = TraceRestrictProgramMoveItemAt(items, offset, p2 & 1, p2 & 2); + if (res.Failed()) return res; + break; + } + default: NOT_REACHED(); break; diff --git a/src/tracerestrict.h b/src/tracerestrict.h index 78b24e5c13..3b6521e3e7 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -623,6 +623,7 @@ enum TraceRestrictDoCommandType { TRDCT_MODIFY_DUAL_ITEM, ///< modify second item of dual-part instruction at offset field to given value TRDCT_REMOVE_ITEM, ///< remove instruction at offset field TRDCT_SHALLOW_REMOVE_ITEM, ///< shallow remove instruction at offset field, does not delete contents of block + TRDCT_MOVE_ITEM, ///< move instruction or block at offset field TRDCT_PROG_COPY, ///< copy program operation. Do not re-order this with respect to other values TRDCT_PROG_SHARE, ///< share program operation @@ -647,6 +648,7 @@ CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, u CommandCost CmdProgramSignalTraceRestrictProgMgmt(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text); CommandCost TraceRestrictProgramRemoveItemAt(std::vector &items, uint32 offset, bool shallow_mode); +CommandCost TraceRestrictProgramMoveItemAt(std::vector &items, uint32 &offset, bool up, bool shallow_mode); void ShowTraceRestrictProgramWindow(TileIndex tile, Track track); diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index 2da6221227..1705c4a26f 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -51,6 +51,9 @@ enum TraceRestrictWindowWidgets { TR_WIDGET_SEL_TOP_RIGHT, TR_WIDGET_SEL_SHARE, + TR_WIDGET_UP_BTN, + TR_WIDGET_DOWN_BTN, + TR_WIDGET_TYPE_COND, TR_WIDGET_TYPE_NONCOND, TR_WIDGET_CONDFLAGS, @@ -1011,6 +1014,26 @@ public: break; } + case TR_WIDGET_UP_BTN: + case TR_WIDGET_DOWN_BTN: { + TraceRestrictItem item = this->GetSelected(); + if (this->GetOwner() != _local_company || item == 0) { + return; + } + + uint32 p2 = 0; + if (widget == TR_WIDGET_UP_BTN) p2 |= 1; + if (_ctrl_pressed) p2 |= 2; + + uint32 offset = this->selected_instruction - 1; + + this->IsUpDownBtnUsable(widget == TR_WIDGET_UP_BTN, true); + + TraceRestrictDoCommandP(tile, track, TRDCT_MOVE_ITEM, + offset, p2, STR_TRACE_RESTRICT_ERROR_CAN_T_MOVE_ITEM); + break; + } + case TR_WIDGET_CONDFLAGS: { TraceRestrictItem item = this->GetSelected(); if (this->GetOwner() != _local_company || item == 0) { @@ -1560,6 +1583,11 @@ public: } } + virtual EventState OnCTRLStateChange() { + this->UpdateButtonState(); + return ES_NOT_HANDLED; + } + private: /** * Helper function to make start and end instructions (these are not stored in the actual program) @@ -1685,6 +1713,26 @@ private: this->UpdateButtonState(); } + bool IsUpDownBtnUsable(bool up, bool update_selection = false) { + const TraceRestrictProgram *prog = this->GetProgram(); + if (!prog) return false; + + TraceRestrictItem item = this->GetSelected(); + if (GetTraceRestrictType(item) == TRIT_NULL) return false; + + std::vector items = prog->items; // copy + uint32 offset = this->selected_instruction - 1; + if (TraceRestrictProgramMoveItemAt(items, offset, up, _ctrl_pressed).Succeeded()) { + TraceRestrictProgramActionsUsedFlags actions_used_flags; + if (TraceRestrictProgram::Validate(items, actions_used_flags).Succeeded()) { + if (update_selection) this->selected_instruction = offset + 1; + return true; + } + } + + return false; + } + /** * Update button states, text values, etc. */ @@ -1730,6 +1778,9 @@ private: this->DisableWidget(TR_WIDGET_BLANK_M); this->DisableWidget(TR_WIDGET_BLANK_R); + this->DisableWidget(TR_WIDGET_UP_BTN); + this->DisableWidget(TR_WIDGET_DOWN_BTN); + left_2_sel->SetDisplayedPlane(DPL2_BLANK); left_sel->SetDisplayedPlane(DPL_BLANK); middle_sel->SetDisplayedPlane(DPM_BLANK); @@ -1936,6 +1987,8 @@ private: this->EnableWidget(TR_WIDGET_INSERT); this->EnableWidget(TR_WIDGET_REMOVE); } + if (this->IsUpDownBtnUsable(true)) this->EnableWidget(TR_WIDGET_UP_BTN); + if (this->IsUpDownBtnUsable(false)) this->EnableWidget(TR_WIDGET_DOWN_BTN); } this->SetDirty(); @@ -2041,6 +2094,8 @@ static const NWidgetPart _nested_program_widgets[] = { // Button Bar NWidget(NWID_HORIZONTAL), + NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TR_WIDGET_UP_BTN), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_UP, STR_TRACE_RESTRICT_UP_BTN_TOOLTIP), + NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, TR_WIDGET_DOWN_BTN), SetMinimalSize(12, 12), SetDataTip(SPR_ARROW_DOWN, STR_TRACE_RESTRICT_DOWN_BTN_TOOLTIP), NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(NWID_SELECTION, INVALID_COLOUR, TR_WIDGET_SEL_TOP_LEFT_2), NWidget(WWT_DROPDOWN, COLOUR_GREY, TR_WIDGET_TYPE_NONCOND), SetMinimalSize(124, 12), SetFill(1, 0), From b6e001f20e77e19a386d27d11db762f832048318 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Mon, 27 Feb 2017 15:02:52 +0000 Subject: [PATCH 6/6] Fix evaluation of PBS entry signal conditional after reserve through. --- src/pathfinder/yapf/yapf_costrail.hpp | 10 +++++++--- src/pathfinder/yapf/yapf_node_rail.hpp | 6 ++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index e9f1d582af..b77f2ba228 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -192,9 +192,9 @@ private: { const Node *node = static_cast(node_ptr); for (;;) { - TileIndex last_signal_tile = node->m_segment->m_last_signal_tile; + TileIndex last_signal_tile = node->m_last_non_reserve_through_signal_tile; if (last_signal_tile != INVALID_TILE) { - Trackdir last_signal_trackdir = node->m_segment->m_last_signal_td; + Trackdir last_signal_trackdir = node->m_last_non_reserve_through_signal_td; if (HasPbsSignalOnTrackdir(last_signal_tile, last_signal_trackdir)) { return last_signal_tile; } else { @@ -347,14 +347,18 @@ public: } } + bool is_reserve_through = false; if (ShouldCheckTraceRestrict(n, tile)) { TraceRestrictProgramResult out; - bool is_reserve_through = false; if (ExecuteTraceRestrict(n, tile, trackdir, cost, out, &is_reserve_through)) { return -1; } if (is_reserve_through) n.m_num_signals_res_through_passed++; } + if (!is_reserve_through) { + n.m_last_non_reserve_through_signal_tile = tile; + n.m_last_non_reserve_through_signal_td = trackdir; + } n.m_num_signals_passed++; n.m_segment->m_last_signal_tile = tile; diff --git a/src/pathfinder/yapf/yapf_node_rail.hpp b/src/pathfinder/yapf/yapf_node_rail.hpp index 3584366961..94c8d6c2f4 100644 --- a/src/pathfinder/yapf/yapf_node_rail.hpp +++ b/src/pathfinder/yapf/yapf_node_rail.hpp @@ -129,6 +129,8 @@ struct CYapfRailNodeT CYapfRailSegment *m_segment; uint16 m_num_signals_passed; uint16 m_num_signals_res_through_passed; + TileIndex m_last_non_reserve_through_signal_tile; + Trackdir m_last_non_reserve_through_signal_td; union { uint32 m_inherited_flags; struct { @@ -147,6 +149,8 @@ struct CYapfRailNodeT if (parent == NULL) { m_num_signals_passed = 0; m_num_signals_res_through_passed = 0; + m_last_non_reserve_through_signal_tile = INVALID_TILE; + m_last_non_reserve_through_signal_td = INVALID_TRACKDIR; flags_u.m_inherited_flags = 0; m_last_red_signal_type = SIGTYPE_NORMAL; /* We use PBS as initial signal type because if we are in @@ -163,6 +167,8 @@ struct CYapfRailNodeT } else { m_num_signals_passed = parent->m_num_signals_passed; m_num_signals_res_through_passed = parent->m_num_signals_res_through_passed; + m_last_non_reserve_through_signal_tile = parent->m_last_non_reserve_through_signal_tile; + m_last_non_reserve_through_signal_td = parent->m_last_non_reserve_through_signal_td; flags_u.m_inherited_flags = parent->flags_u.m_inherited_flags; m_last_red_signal_type = parent->m_last_red_signal_type; m_last_signal_type = parent->m_last_signal_type;