From f192865c274b0d561e5d96e2184fee61dfb2bece Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Sun, 26 Feb 2017 21:39:04 +0000 Subject: [PATCH] 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; }