diff --git a/src/lang/extra/english.txt b/src/lang/extra/english.txt index 24035ba5ae..776b19146f 100644 --- a/src/lang/extra/english.txt +++ b/src/lang/extra/english.txt @@ -1001,6 +1001,7 @@ STR_TRACE_RESTRICT_APPEND :{BLACK}Append STR_TRACE_RESTRICT_DUPLICATE :{BLACK}Duplicate STR_TRACE_RESTRICT_SHARE :{BLACK}Share STR_TRACE_RESTRICT_UNSHARE :{BLACK}Unshare +STR_TRACE_RESTRICT_SHARE_ONTO :{BLACK}Share Onto STR_TRACE_RESTRICT_SELECT_TARGET :{BLACK}Select Target STR_TRACE_RESTRICT_SELECT_SIGNAL :{BLACK}Select Signal STR_TRACE_RESTRICT_SELECT_TILE :{BLACK}Select Tile @@ -1011,6 +1012,7 @@ STR_TRACE_RESTRICT_COPY_TOOLTIP :{BLACK}Copy pro STR_TRACE_RESTRICT_DUPLICATE_TOOLTIP :{BLACK}Duplicate the selected instruction{}Ctrl+click to append program from another signal STR_TRACE_RESTRICT_SHARE_TOOLTIP :{BLACK}Share program with another signal STR_TRACE_RESTRICT_UNSHARE_TOOLTIP :{BLACK}Stop sharing program with other signals, create a copy of the program +STR_TRACE_RESTRICT_SHARE_TOOLTIP_EXTRA :{STRING}{}{BLACK}Ctrl+click to set other signals to share with this program STR_TRACE_RESTRICT_SIGNAL_GUI_TOOLTIP :{BLACK}Routefinding restriction STR_TRACE_RESTRICT_INSTRUCTION_LIST_TOOLTIP :{BLACK}Click an instruction to select it{}Ctrl+Click to scroll to the instruction's target (if any) STR_TRACE_RESTRICT_HIGHLIGHT_TOOLTIP :{BLACK}Toggle highlighting all signals sharing this program @@ -1023,7 +1025,7 @@ STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ITEM :{WHITE}Can't re STR_TRACE_RESTRICT_ERROR_CAN_T_MOVE_ITEM :{WHITE}Can't move instruction STR_TRACE_RESTRICT_ERROR_CAN_T_DUPLICATE_ITEM :{WHITE}Can't duplicate 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_NO_PROGRAM :No program exists 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' @@ -1034,6 +1036,7 @@ STR_TRACE_RESTRICT_ERROR_VALIDATE_DUP_ELSE :Validation fail STR_TRACE_RESTRICT_ERROR_VALIDATE_ELIF_NO_IF :Validation failed: else if without opening if STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION :Validation failed: unknown instruction STR_TRACE_RESTRICT_ERROR_SOURCE_SAME_AS_TARGET :Source and target signals are the same +STR_TRACE_RESTRICT_ERROR_TARGET_ALREADY_HAS_PROGRAM :Target signal already has a program STR_TRACE_RESTRICT_ERROR_CAN_T_RESET_SIGNAL :{WHITE}Can't reset signal STR_TRACE_RESTRICT_ERROR_CAN_T_COPY_PROGRAM :{WHITE}Can't copy program STR_TRACE_RESTRICT_ERROR_CAN_T_COPY_APPEND_PROGRAM :{WHITE}Can't append program diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 40c4b1da25..498c95ebc3 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -2238,18 +2238,22 @@ CommandCost CmdProgramSignalTraceRestrictProgMgmt(TileIndex tile, DoCommandFlag return ret; } - if (type == TRDCT_PROG_SHARE || type == TRDCT_PROG_COPY) { + if (type == TRDCT_PROG_SHARE || type == TRDCT_PROG_SHARE_IF_UNMAPPED || type == TRDCT_PROG_COPY) { if (self == source) { return_cmd_error(STR_TRACE_RESTRICT_ERROR_SOURCE_SAME_AS_TARGET); } } - if (type == TRDCT_PROG_SHARE || type == TRDCT_PROG_COPY || type == TRDCT_PROG_COPY_APPEND) { + if (type == TRDCT_PROG_SHARE || type == TRDCT_PROG_SHARE_IF_UNMAPPED || type == TRDCT_PROG_COPY || type == TRDCT_PROG_COPY_APPEND) { ret = TraceRestrictCheckTileIsUsable(source_tile, source_track); if (ret.Failed()) { return ret; } } + if (type == TRDCT_PROG_SHARE_IF_UNMAPPED && GetTraceRestrictProgram(self, false) != nullptr) { + return_cmd_error(STR_TRACE_RESTRICT_ERROR_TARGET_ALREADY_HAS_PROGRAM); + } + if (type != TRDCT_PROG_RESET && !TraceRestrictProgram::CanAllocateItem()) { return CMD_ERROR; } @@ -2298,7 +2302,8 @@ CommandCost CmdProgramSignalTraceRestrictProgMgmt(TileIndex tile, DoCommandFlag break; } - case TRDCT_PROG_SHARE: { + case TRDCT_PROG_SHARE: + case TRDCT_PROG_SHARE_IF_UNMAPPED: { TraceRestrictRemoveProgramMapping(self); TraceRestrictProgram *source_prog = GetTraceRestrictProgram(source, true); if (!source_prog) { diff --git a/src/tracerestrict.h b/src/tracerestrict.h index f57f0fcd31..bca7f2b8a8 100644 --- a/src/tracerestrict.h +++ b/src/tracerestrict.h @@ -1041,6 +1041,7 @@ enum TraceRestrictDoCommandType { TRDCT_PROG_COPY, ///< copy program operation. Do not re-order this with respect to other values TRDCT_PROG_COPY_APPEND, ///< copy and append program operation TRDCT_PROG_SHARE, ///< share program operation + TRDCT_PROG_SHARE_IF_UNMAPPED, ///< share program operation (if unmapped) TRDCT_PROG_UNSHARE, ///< unshare program (copy as a new program) TRDCT_PROG_RESET, ///< reset program state of signal }; diff --git a/src/tracerestrict_gui.cpp b/src/tracerestrict_gui.cpp index a363d8bb38..136ea744a8 100644 --- a/src/tracerestrict_gui.cpp +++ b/src/tracerestrict_gui.cpp @@ -96,6 +96,7 @@ enum TraceRestrictWindowWidgets { TR_WIDGET_DUPLICATE, TR_WIDGET_SHARE, TR_WIDGET_UNSHARE, + TR_WIDGET_SHARE_ONTO, }; /** Selection mappings for NWID_SELECTION selectors */ @@ -130,6 +131,7 @@ enum PanelWidgets { // Share DPS_SHARE = 0, DPS_UNSHARE, + DPS_SHARE_ONTO, // Copy DPC_COPY = 0, @@ -1759,6 +1761,7 @@ class TraceRestrictWindow: public Window { int current_placement_widget; ///< which widget has a SetObjectToPlaceWnd, if any int current_left_aux_plane; ///< current plane for TR_WIDGET_SEL_TOP_LEFT_AUX widget int base_copy_plane; ///< base plane for TR_WIDGET_SEL_COPY widget + int base_share_plane; ///< base plane for TR_WIDGET_SEL_SHARE widget public: TraceRestrictWindow(WindowDesc *desc, TileIndex tile, Track track) @@ -2173,7 +2176,28 @@ public: case TR_WIDGET_COPY: case TR_WIDGET_COPY_APPEND: case TR_WIDGET_SHARE: + case TR_WIDGET_SHARE_ONTO: SetObjectToPlaceAction(widget, ANIMCURSOR_BUILDSIGNALS); + switch (this->current_placement_widget) { + case TR_WIDGET_COPY: + _thd.square_palette = SPR_ZONING_INNER_HIGHLIGHT_GREEN; + break; + + case TR_WIDGET_COPY_APPEND: + _thd.square_palette = SPR_ZONING_INNER_HIGHLIGHT_LIGHT_BLUE; + break; + + case TR_WIDGET_SHARE: + _thd.square_palette = SPR_ZONING_INNER_HIGHLIGHT_YELLOW; + break; + + case TR_WIDGET_SHARE_ONTO: + _thd.square_palette = SPR_ZONING_INNER_HIGHLIGHT_ORANGE; + break; + + default: + break; + } break; case TR_WIDGET_UNSHARE: { @@ -2342,10 +2366,12 @@ public: virtual void OnPlaceObject(Point pt, TileIndex tile) override { int widget = this->current_placement_widget; - this->ResetObjectToPlaceAction(); + if (widget != TR_WIDGET_SHARE_ONTO) { + this->ResetObjectToPlaceAction(); - this->RaiseButtons(); - ResetObjectToPlace(); + this->RaiseButtons(); + ResetObjectToPlace(); + } if (widget < 0) { return; @@ -2361,6 +2387,7 @@ public: break; case TR_WIDGET_SHARE: + case TR_WIDGET_SHARE_ONTO: OnPlaceObjectSignal(pt, tile, widget, STR_TRACE_RESTRICT_ERROR_CAN_T_SHARE_PROGRAM); break; @@ -2444,6 +2471,11 @@ public: source_tile, source_track, STR_TRACE_RESTRICT_ERROR_CAN_T_SHARE_PROGRAM); break; + case TR_WIDGET_SHARE_ONTO: + TraceRestrictProgMgmtWithSourceDoCommandP(source_tile, source_track, TRDCT_PROG_SHARE_IF_UNMAPPED, + this->tile, this->track, STR_TRACE_RESTRICT_ERROR_CAN_T_SHARE_PROGRAM); + break; + default: NOT_REACHED(); break; @@ -2674,6 +2706,32 @@ public: } } + bool OnTooltip(Point pt, int widget, TooltipCloseCondition close_cond) override + { + switch (widget) { + case TR_WIDGET_SHARE: { + uint64 arg = STR_TRACE_RESTRICT_SHARE_TOOLTIP; + GuiShowTooltips(this, STR_TRACE_RESTRICT_SHARE_TOOLTIP_EXTRA, 1, &arg, close_cond); + return true; + } + + case TR_WIDGET_UNSHARE: { + uint64 arg = STR_TRACE_RESTRICT_UNSHARE_TOOLTIP; + GuiShowTooltips(this, STR_TRACE_RESTRICT_SHARE_TOOLTIP_EXTRA, 1, &arg, close_cond); + return true; + } + + case TR_WIDGET_SHARE_ONTO: { + uint64 arg = (this->base_share_plane == DPS_UNSHARE) ? STR_TRACE_RESTRICT_UNSHARE_TOOLTIP : STR_TRACE_RESTRICT_SHARE_TOOLTIP; + GuiShowTooltips(this, STR_TRACE_RESTRICT_SHARE_TOOLTIP_EXTRA, 1, &arg, close_cond); + return true; + } + + default: + return false; + } + } + virtual EventState OnCTRLStateChange() override { this->UpdateButtonState(); @@ -2840,14 +2898,21 @@ private: return false; } - void UpdateCopySelPlane() + void UpdatePlaceObjectPlanes() { int widget = this->current_placement_widget; - if (widget == TR_WIDGET_COPY || widget == TR_WIDGET_COPY_APPEND || widget == TR_WIDGET_COPY_APPEND) return; - NWidgetStacked *copy_sel = this->GetWidget(TR_WIDGET_SEL_COPY); - copy_sel->SetDisplayedPlane(_ctrl_pressed ? DPC_APPEND : this->base_copy_plane); - this->SetDirty(); + if (!(widget == TR_WIDGET_COPY || widget == TR_WIDGET_COPY_APPEND)) { + NWidgetStacked *copy_sel = this->GetWidget(TR_WIDGET_SEL_COPY); + copy_sel->SetDisplayedPlane(_ctrl_pressed ? DPC_APPEND : this->base_copy_plane); + this->SetDirty(); + } + + if (!(widget == TR_WIDGET_SHARE || widget == TR_WIDGET_SHARE_ONTO)) { + NWidgetStacked *share_sel = this->GetWidget(TR_WIDGET_SEL_SHARE); + share_sel->SetDisplayedPlane(_ctrl_pressed ? DPS_SHARE_ONTO : this->base_share_plane); + this->SetDirty(); + } } /** @@ -2876,7 +2941,6 @@ private: NWidgetStacked *left_aux_sel = this->GetWidget(TR_WIDGET_SEL_TOP_LEFT_AUX); NWidgetStacked *middle_sel = this->GetWidget(TR_WIDGET_SEL_TOP_MIDDLE); NWidgetStacked *right_sel = this->GetWidget(TR_WIDGET_SEL_TOP_RIGHT); - NWidgetStacked *share_sel = this->GetWidget(TR_WIDGET_SEL_SHARE); this->DisableWidget(TR_WIDGET_TYPE_COND); this->DisableWidget(TR_WIDGET_TYPE_NONCOND); @@ -2898,6 +2962,7 @@ private: this->DisableWidget(TR_WIDGET_COPY); this->DisableWidget(TR_WIDGET_SHARE); this->DisableWidget(TR_WIDGET_UNSHARE); + this->DisableWidget(TR_WIDGET_SHARE_ONTO); this->DisableWidget(TR_WIDGET_BLANK_L2); this->DisableWidget(TR_WIDGET_BLANK_L); @@ -2908,14 +2973,11 @@ private: this->DisableWidget(TR_WIDGET_DOWN_BTN); this->DisableWidget(TR_WIDGET_DUPLICATE); - this->EnableWidget(TR_WIDGET_COPY_APPEND); - left_2_sel->SetDisplayedPlane(DPL2_BLANK); left_sel->SetDisplayedPlane(DPL_BLANK); left_aux_sel->SetDisplayedPlane(SZSP_NONE); middle_sel->SetDisplayedPlane(DPM_BLANK); right_sel->SetDisplayedPlane(DPR_BLANK); - share_sel->SetDisplayedPlane(DPS_SHARE); const TraceRestrictProgram *prog = this->GetProgram(); @@ -2939,11 +3001,12 @@ private: return; } - this->base_copy_plane = DPC_DUPLICATE; + this->EnableWidget(TR_WIDGET_COPY_APPEND); + this->EnableWidget(TR_WIDGET_SHARE_ONTO); if (prog != nullptr && prog->refcount > 1) { // program is shared, show and enable unshare button, and reset button - share_sel->SetDisplayedPlane(DPS_UNSHARE); + this->base_share_plane = DPS_UNSHARE; this->EnableWidget(TR_WIDGET_UNSHARE); this->EnableWidget(TR_WIDGET_RESET); } else if (this->GetItemCount(prog) > 2) { @@ -2957,7 +3020,7 @@ private: } this->GetWidget(TR_WIDGET_COPY_APPEND)->tool_tip = (this->base_copy_plane == DPC_DUPLICATE) ? STR_TRACE_RESTRICT_DUPLICATE_TOOLTIP : STR_TRACE_RESTRICT_COPY_TOOLTIP; - UpdateCopySelPlane(); + this->UpdatePlaceObjectPlanes(); // haven't selected instruction if (this->selected_instruction < 1) { @@ -3370,13 +3433,13 @@ private: ResetObjectToPlace(); this->current_placement_widget = -1; } - this->UpdateCopySelPlane(); + this->UpdatePlaceObjectPlanes(); } void ResetObjectToPlaceAction() { this->current_placement_widget = -1; - this->UpdateCopySelPlane(); + this->UpdatePlaceObjectPlanes(); } /** @@ -3519,9 +3582,11 @@ static const NWidgetPart _nested_program_widgets[] = { EndContainer(), NWidget(NWID_SELECTION, INVALID_COLOUR, TR_WIDGET_SEL_SHARE), NWidget(WWT_TEXTBTN, COLOUR_GREY, TR_WIDGET_SHARE), SetMinimalSize(124, 12), SetFill(1, 0), - SetDataTip(STR_TRACE_RESTRICT_SHARE, STR_TRACE_RESTRICT_SHARE_TOOLTIP), SetResize(1, 0), + SetDataTip(STR_TRACE_RESTRICT_SHARE, STR_NULL), SetResize(1, 0), NWidget(WWT_TEXTBTN, COLOUR_GREY, TR_WIDGET_UNSHARE), SetMinimalSize(124, 12), SetFill(1, 0), - SetDataTip(STR_TRACE_RESTRICT_UNSHARE, STR_TRACE_RESTRICT_UNSHARE_TOOLTIP), SetResize(1, 0), + SetDataTip(STR_TRACE_RESTRICT_UNSHARE, STR_NULL), SetResize(1, 0), + NWidget(WWT_TEXTBTN, COLOUR_GREY, TR_WIDGET_SHARE_ONTO), SetMinimalSize(124, 12), SetFill(1, 0), + SetDataTip(STR_TRACE_RESTRICT_SHARE_ONTO, STR_NULL), SetResize(1, 0), EndContainer(), EndContainer(), NWidget(WWT_RESIZEBOX, COLOUR_GREY),