Add instruction move up/down buttons to GUI.
Has block and individual instruction move modes, depending on ctrl.
This commit is contained in:
@@ -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
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include "group.h"
|
||||
#include "pathfinder/yapf/yapf_cache.h"
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/** @file
|
||||
*
|
||||
@@ -929,13 +930,67 @@ CommandCost TraceRestrictProgramRemoveItemAt(std::vector<TraceRestrictItem> &ite
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
CommandCost TraceRestrictProgramMoveItemAt(std::vector<TraceRestrictItem> &items, uint32 &offset, bool up, bool shallow_mode)
|
||||
{
|
||||
std::vector<TraceRestrictItem>::iterator move_start = TraceRestrictProgram::InstructionAt(items, offset);
|
||||
std::vector<TraceRestrictItem>::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;
|
||||
|
@@ -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<TraceRestrictItem> &items, uint32 offset, bool shallow_mode);
|
||||
CommandCost TraceRestrictProgramMoveItemAt(std::vector<TraceRestrictItem> &items, uint32 &offset, bool up, bool shallow_mode);
|
||||
|
||||
void ShowTraceRestrictProgramWindow(TileIndex tile, Track track);
|
||||
|
||||
|
@@ -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<TraceRestrictItem> 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),
|
||||
|
Reference in New Issue
Block a user