diff --git a/media/baseset/openttd.grf b/media/baseset/openttd.grf
index 4464c415f3..ed897ecd4e 100644
Binary files a/media/baseset/openttd.grf and b/media/baseset/openttd.grf differ
diff --git a/media/baseset/openttd.grf.hash b/media/baseset/openttd.grf.hash
index f940ca5d62..9c734c87a4 100644
--- a/media/baseset/openttd.grf.hash
+++ b/media/baseset/openttd.grf.hash
@@ -1 +1 @@
-b779126d7cd1567eb09a0a7871f70a71
+c56aad31380c077d619e124bd87c8270
diff --git a/media/baseset/openttd/CMakeLists.txt b/media/baseset/openttd/CMakeLists.txt
index a7d768326e..5a37b35148 100644
--- a/media/baseset/openttd/CMakeLists.txt
+++ b/media/baseset/openttd/CMakeLists.txt
@@ -33,6 +33,7 @@ if(GRFCODEC_FOUND)
${CMAKE_CURRENT_SOURCE_DIR}/aqueduct.png
${CMAKE_CURRENT_SOURCE_DIR}/autorail.png
${CMAKE_CURRENT_SOURCE_DIR}/bridge_decks.png
+ ${CMAKE_CURRENT_SOURCE_DIR}/bridge_decks_toyland.png
${CMAKE_CURRENT_SOURCE_DIR}/canals.png
${CMAKE_CURRENT_SOURCE_DIR}/canal_locks.png
${CMAKE_CURRENT_SOURCE_DIR}/chars.png
diff --git a/media/baseset/openttd/bridge_decks.nfo b/media/baseset/openttd/bridge_decks.nfo
index beced3f59f..b7edf0f143 100644
--- a/media/baseset/openttd/bridge_decks.nfo
+++ b/media/baseset/openttd/bridge_decks.nfo
@@ -4,6 +4,7 @@
// See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see .
//
-1 * 0 0C "Bridge decks"
+ -1 * 0 07 83 01 \7= 03 19
-1 * 3 05 1B 18
-1 sprites/bridge_decks.png 8bpp 96 16 64 31 -31 0 normal
@@ -34,3 +35,36 @@
-1 sprites/bridge_decks.png 8bpp 256 181 64 23 -31 0 normal
-1 sprites/bridge_decks.png 8bpp 336 181 64 23 -31 0 normal
-1 sprites/bridge_decks.png 8bpp 416 181 64 39 -31 -8 normal
+
+// Toyland bridge decks, skip if not toyland.
+ -1 * 0 07 83 01 \7! 03 19
+ -1 * 3 05 1B 18
+
+ -1 sprites/bridge_decks_toyland.png 8bpp 96 16 64 31 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 16 16 64 31 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 176 16 64 39 -31 -8 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 256 16 64 23 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 336 16 64 23 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 416 16 64 39 -31 -8 normal
+
+ -1 sprites/bridge_decks_toyland.png 8bpp 96 71 64 31 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 16 71 64 31 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 176 71 64 39 -31 -8 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 256 71 64 23 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 336 71 64 23 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 416 71 64 39 -31 -8 normal
+
+ -1 sprites/bridge_decks_toyland.png 8bpp 96 126 64 31 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 16 126 64 31 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 176 126 64 39 -31 -8 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 256 126 64 23 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 336 126 64 23 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 416 126 64 39 -31 -8 normal
+
+// X and Y axis are swapped for road surface.
+ -1 sprites/bridge_decks_toyland.png 8bpp 16 181 64 31 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 96 181 64 31 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 176 181 64 39 -31 -8 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 256 181 64 23 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 336 181 64 23 -31 0 normal
+ -1 sprites/bridge_decks_toyland.png 8bpp 416 181 64 39 -31 -8 normal
diff --git a/media/baseset/openttd/bridge_decks_toyland.png b/media/baseset/openttd/bridge_decks_toyland.png
new file mode 100644
index 0000000000..0c1495d766
Binary files /dev/null and b/media/baseset/openttd/bridge_decks_toyland.png differ
diff --git a/src/command_type.h b/src/command_type.h
index 0f13917d0a..d62ce06f5c 100644
--- a/src/command_type.h
+++ b/src/command_type.h
@@ -218,6 +218,7 @@ enum Commands : uint8_t {
CMD_BUILD_RAIL_WAYPOINT, ///< build a waypoint
CMD_RENAME_WAYPOINT, ///< rename a waypoint
+ CMD_MOVE_WAYPOINT_NAME, ///< move a waypoint name
CMD_REMOVE_FROM_RAIL_WAYPOINT, ///< remove a (rectangle of) tiles from a rail waypoint
CMD_BUILD_ROAD_WAYPOINT, ///< build a road waypoint
@@ -279,10 +280,12 @@ enum Commands : uint8_t {
CMD_RENAME_COMPANY, ///< change the company name
CMD_RENAME_PRESIDENT, ///< change the president name
CMD_RENAME_STATION, ///< rename a station
+ CMD_MOVE_STATION_NAME, ///< move a station name
CMD_RENAME_DEPOT, ///< rename a depot
CMD_PLACE_SIGN, ///< place a sign
CMD_RENAME_SIGN, ///< rename a sign
+ CMD_MOVE_SIGN, ///< move a sign
CMD_TURN_ROADVEH, ///< turn a road vehicle around
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 2b72e86f95..73353498f5 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -313,6 +313,7 @@ STR_SHOW_HIDDEN_ENGINES_VEHICLE_AIRCRAFT_TOOLTIP :{BLACK}By enabl
STR_BUTTON_DEFAULT :{BLACK}Default
STR_BUTTON_CANCEL :{BLACK}Cancel
STR_BUTTON_OK :{BLACK}OK
+STR_BUTTON_MOVE :{BLACK}Move
# On screen keyboard window
STR_OSK_KEYBOARD_LAYOUT :`1234567890-= qwertyuiop[]asdfghjkl;'#\zxcvbnm,./ .
@@ -3690,7 +3691,7 @@ STR_SIGN_LIST_MATCH_CASE :{BLACK}Match ca
STR_SIGN_LIST_MATCH_CASE_TOOLTIP :{BLACK}Toggle matching case when comparing sign names against the filter string
# Sign window
-STR_EDIT_SIGN_CAPTION :{WHITE}Edit sign text
+STR_EDIT_SIGN_CAPTION :{WHITE}Edit sign
STR_EDIT_SIGN_LOCATION_TOOLTIP :{BLACK}Centre the main view on sign location. Ctrl+Click to open a new viewport on sign location
STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP :{BLACK}Go to next sign
STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP :{BLACK}Go to previous sign
@@ -3907,14 +3908,14 @@ STR_CARGO_RATING_EXCELLENT :Excellent
STR_CARGO_RATING_OUTSTANDING :Outstanding
STR_STATION_VIEW_CENTER_TOOLTIP :{BLACK}Centre main view on station location. Ctrl+Click to open a new viewport on station location
-STR_STATION_VIEW_RENAME_TOOLTIP :{BLACK}Change name of station
+STR_STATION_VIEW_EDIT_TOOLTIP :{BLACK}Rename station or move sign
STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP :{BLACK}Show all trains which have this station on their schedule
STR_STATION_VIEW_SCHEDULED_ROAD_VEHICLES_TOOLTIP :{BLACK}Show all road vehicles which have this station on their schedule
STR_STATION_VIEW_SCHEDULED_AIRCRAFT_TOOLTIP :{BLACK}Show all aircraft which have this station on their schedule
STR_STATION_VIEW_SCHEDULED_SHIPS_TOOLTIP :{BLACK}Show all ships which have this station on their schedule
-STR_STATION_VIEW_RENAME_STATION_CAPTION :Rename station/loading area
+STR_STATION_VIEW_EDIT_STATION_SIGN :{WHITE}Edit station sign
STR_STATION_VIEW_CLOSE_AIRPORT :{BLACK}Close airport
STR_STATION_VIEW_CLOSE_AIRPORT_TOOLTIP :{BLACK}Prevent aircraft from landing on this airport
@@ -3922,11 +3923,11 @@ STR_STATION_VIEW_CLOSE_AIRPORT_TOOLTIP :{BLACK}Prevent
# Waypoint/buoy view window
STR_WAYPOINT_VIEW_CAPTION :{WHITE}{WAYPOINT}
STR_WAYPOINT_VIEW_CENTER_TOOLTIP :{BLACK}Centre main view on waypoint location. Ctrl+Click to open a new viewport on waypoint location
-STR_WAYPOINT_VIEW_CHANGE_WAYPOINT_NAME :{BLACK}Change waypoint name
+STR_WAYPOINT_VIEW_EDIT_TOOLTIP :{BLACK}Rename waypoint or move sign
STR_BUOY_VIEW_CENTER_TOOLTIP :{BLACK}Centre main view on buoy location. Ctrl+Click to open a new viewport on buoy location
STR_BUOY_VIEW_RENAME_TOOLTIP :{BLACK}Change buoy name
-STR_EDIT_WAYPOINT_NAME :{WHITE}Edit waypoint name
+STR_WAYPOINT_VIEW_EDIT_WAYPOINT_SIGN :{WHITE}Edit waypoint sign
# Finances window
STR_FINANCES_CAPTION :{WHITE}{COMPANY} Finances {BLACK}{COMPANY_NUM}
@@ -5140,6 +5141,7 @@ STR_ERROR_TOO_MANY_TRUCK_STOPS :{WHITE}Too many
STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Too close to another dock
STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Too close to another airport
STR_ERROR_CAN_T_RENAME_STATION :{WHITE}Can't rename station...
+STR_ERROR_CAN_T_MOVE_STATION_NAME :{WHITE}Can't move station sign...
STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... road owned by a town
STR_ERROR_DRIVE_THROUGH_DIRECTION :{WHITE}... road facing in the wrong direction
STR_ERROR_DRIVE_THROUGH_CORNER :{WHITE}... drive through stops can't have corners
@@ -5171,6 +5173,7 @@ STR_ERROR_CAN_T_BUILD_RAIL_WAYPOINT :{WHITE}Can't bu
STR_ERROR_CAN_T_BUILD_ROAD_WAYPOINT :{WHITE}Can't build road waypoint here...
STR_ERROR_CAN_T_POSITION_BUOY_HERE :{WHITE}Can't place buoy here...
STR_ERROR_CAN_T_CHANGE_WAYPOINT_NAME :{WHITE}Can't change waypoint name...
+STR_ERROR_CAN_T_MOVE_WAYPOINT_NAME :{WHITE}Can't move waypoint sign...
STR_ERROR_CAN_T_REMOVE_RAIL_WAYPOINT :{WHITE}Can't remove rail waypoint here...
STR_ERROR_CAN_T_REMOVE_ROAD_WAYPOINT :{WHITE}Can't remove road waypoint here...
diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp
index 8734d1fe08..04b24a87c6 100644
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -13,11 +13,14 @@
#include "error.h"
#include "gui.h"
#include "gfx_layout.h"
+#include "tilehighlight_func.h"
#include "command_func.h"
#include "company_func.h"
#include "town.h"
#include "string_func.h"
#include "company_base.h"
+#include "station_base.h"
+#include "waypoint_base.h"
#include "texteff.hpp"
#include "strings_func.h"
#include "window_func.h"
@@ -27,6 +30,8 @@
#include "zoom_func.h"
#include "viewport_func.h"
#include "landscape_cmd.h"
+#include "station_cmd.h"
+#include "waypoint_cmd.h"
#include "rev.h"
#include "timer/timer.h"
#include "timer/timer_window.h"
@@ -938,6 +943,8 @@ struct QueryStringWindow : public Window
QueryString editbox; ///< Editbox.
QueryStringFlags flags{}; ///< Flags controlling behaviour of the window.
+ WidgetID last_user_action = INVALID_WIDGET; ///< Last started user action.
+
QueryStringWindow(std::string_view str, StringID caption, uint max_bytes, uint max_chars, WindowDesc &desc, Window *parent, CharSetFilter afilter, QueryStringFlags flags) :
Window(desc), editbox(max_bytes, max_chars)
{
@@ -952,7 +959,9 @@ struct QueryStringWindow : public Window
this->editbox.text.afilter = afilter;
this->flags = flags;
- this->InitNested(WN_QUERY_STRING);
+ this->CreateNestedTree();
+ this->GetWidget(WID_QS_MOVE_SEL)->SetDisplayedPlane((this->flags.Test(QueryStringFlag::EnableMove)) ? 0 : SZSP_NONE);
+ this->FinishInitNested(WN_QUERY_STRING);
this->parent = parent;
@@ -1000,16 +1009,64 @@ struct QueryStringWindow : public Window
case WID_QS_CANCEL:
this->Close();
break;
+
+ case WID_QS_MOVE:
+ this->last_user_action = widget;
+
+ if (Station::IsExpected(Station::Get(this->parent->window_number))) {
+ /* this is a station */
+ SetViewportStationRect(Station::Get(this->parent->window_number), !this->IsWidgetLowered(WID_QS_MOVE));
+ } else {
+ /* this is a waypoint */
+ SetViewportWaypointRect(Waypoint::Get(this->parent->window_number), !this->IsWidgetLowered(WID_QS_MOVE));
+ }
+
+ HandlePlacePushButton(this, WID_QS_MOVE, SPR_CURSOR_SIGN, HT_RECT, CM_DDSP_MOVE_SIGN);
+ break;
}
}
+ void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
+ {
+ switch (this->last_user_action) {
+ case WID_QS_MOVE: // Move name button
+ if (Station::IsExpected(Station::Get(this->parent->window_number))) {
+ /* this is a station */
+ Command::Post(STR_ERROR_CAN_T_MOVE_STATION_NAME, CcMoveStationName, this->parent->window_number, tile);
+ } else {
+ /* this is a waypoint */
+ Command::Post(STR_ERROR_CAN_T_MOVE_WAYPOINT_NAME, CcMoveWaypointName, this->parent->window_number, tile);
+ }
+ break;
+
+ default: NOT_REACHED();
+ }
+ }
+
+ void OnPlaceObjectAbort() override
+ {
+ if (Station::IsExpected(Station::Get(this->parent->window_number))) {
+ /* this is a station */
+ SetViewportStationRect(Station::Get(this->parent->window_number), false);
+ } else {
+ /* this is a waypoint */
+ SetViewportWaypointRect(Waypoint::Get(this->parent->window_number), false);
+ }
+
+ this->RaiseButtons();
+ }
+
void Close([[maybe_unused]] int data = 0) override
{
+ if (this->parent->window_class == WC_STATION_VIEW) SetViewportStationRect(Station::Get(this->parent->window_number), false);
+ if (this->parent->window_class == WC_WAYPOINT_VIEW) SetViewportWaypointRect(Waypoint::Get(this->parent->window_number), false);
+
if (!this->editbox.handled && this->parent != nullptr) {
Window *parent = this->parent;
this->parent = nullptr; // so parent doesn't try to close us again
parent->OnQueryTextFinished(std::nullopt);
}
+
this->Window::Close();
}
};
@@ -1023,9 +1080,12 @@ static constexpr std::initializer_list _nested_query_string_widgets
NWidget(WWT_EDITBOX, COLOUR_GREY, WID_QS_TEXT), SetMinimalSize(256, 0), SetFill(1, 0), SetPadding(2, 2, 2, 2),
EndContainer(),
NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_DEFAULT), SetMinimalSize(87, 12), SetFill(1, 1), SetStringTip(STR_BUTTON_DEFAULT),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_CANCEL), SetMinimalSize(86, 12), SetFill(1, 1), SetStringTip(STR_BUTTON_CANCEL),
- NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_OK), SetMinimalSize(87, 12), SetFill(1, 1), SetStringTip(STR_BUTTON_OK),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_DEFAULT), SetMinimalSize(65, 12), SetFill(1, 1), SetStringTip(STR_BUTTON_DEFAULT),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_CANCEL), SetMinimalSize(65, 12), SetFill(1, 1), SetStringTip(STR_BUTTON_CANCEL),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_OK), SetMinimalSize(65, 12), SetFill(1, 1), SetStringTip(STR_BUTTON_OK),
+ NWidget(NWID_SELECTION, INVALID_COLOUR, WID_QS_MOVE_SEL),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QS_MOVE), SetMinimalSize(65, 12), SetFill(1, 1), SetStringTip(STR_BUTTON_MOVE),
+ EndContainer(),
EndContainer(),
};
diff --git a/src/signs.cpp b/src/signs.cpp
index a2bf7ab979..90fcf00cf2 100644
--- a/src/signs.cpp
+++ b/src/signs.cpp
@@ -55,11 +55,11 @@ void UpdateAllSignVirtCoords()
}
/**
- * Check if the current company can rename a given sign.
+ * Check if the current company can rename or move a given sign.
* @param *si The sign in question.
- * @return true if the sign can be renamed, else false.
+ * @return true if the sign can be renamed or moved, else false.
*/
-bool CompanyCanRenameSign(const Sign *si)
+bool CompanyCanEditSign(const Sign *si)
{
if (si->owner == OWNER_DEITY && _current_company != OWNER_DEITY && _game_mode != GM_EDITOR) return false;
return true;
diff --git a/src/signs_cmd.cpp b/src/signs_cmd.cpp
index 0e02401129..9ac496ce1b 100644
--- a/src/signs_cmd.cpp
+++ b/src/signs_cmd.cpp
@@ -68,7 +68,7 @@ CommandCost CmdRenameSign(DoCommandFlags flags, SignID sign_id, const std::strin
{
Sign *si = Sign::GetIfValid(sign_id);
if (si == nullptr) return CMD_ERROR;
- if (!CompanyCanRenameSign(si)) return CMD_ERROR;
+ if (!CompanyCanEditSign(si)) return CMD_ERROR;
/* Rename the signs when empty, otherwise remove it */
if (!text.empty()) {
@@ -95,6 +95,36 @@ CommandCost CmdRenameSign(DoCommandFlags flags, SignID sign_id, const std::strin
return CommandCost();
}
+/**
+ * Move a sign to the given coordinates. Ownership of signs
+ * has no meaning/effect whatsoever except for eyecandy.
+ * @param flags type of operation
+ * @param sign_id index of the sign to be moved
+ * @param tile tile to place the sign at
+ * @return the cost of this operation or an error
+ */
+CommandCost CmdMoveSign(DoCommandFlags flags, SignID sign_id, TileIndex tile)
+{
+ Sign *si = Sign::GetIfValid(sign_id);
+ if (si == nullptr) return CMD_ERROR;
+ if (!CompanyCanEditSign(si)) return CMD_ERROR;
+
+ /* Move the sign */
+ if (flags.Test(DoCommandFlag::Execute)) {
+ int x = TileX(tile) * TILE_SIZE;
+ int y = TileY(tile) * TILE_SIZE;
+
+ si->x = x;
+ si->y = y;
+ si->z = GetSlopePixelZ(x, y);
+ if (_game_mode != GM_EDITOR) si->owner = _current_company;
+
+ si->UpdateVirtCoord();
+ }
+
+ return CommandCost();
+}
+
/**
* Callback function that is called after a sign is placed
* @param result of the operation
diff --git a/src/signs_cmd.h b/src/signs_cmd.h
index 3d8722b070..b51abd88d1 100644
--- a/src/signs_cmd.h
+++ b/src/signs_cmd.h
@@ -15,9 +15,11 @@
std::tuple CmdPlaceSign(DoCommandFlags flags, TileIndex tile, const std::string &text);
CommandCost CmdRenameSign(DoCommandFlags flags, SignID sign_id, const std::string &text);
+CommandCost CmdMoveSign(DoCommandFlags flags, SignID sign_id, TileIndex tile);
DEF_CMD_TRAIT(CMD_PLACE_SIGN, CmdPlaceSign, CommandFlag::Deity, CommandType::OtherManagement)
DEF_CMD_TRAIT(CMD_RENAME_SIGN, CmdRenameSign, CommandFlag::Deity, CommandType::OtherManagement)
+DEF_CMD_TRAIT(CMD_MOVE_SIGN, CmdMoveSign, CommandFlag::Deity, CommandType::OtherManagement)
void CcPlaceSign(Commands cmd, const CommandCost &result, SignID new_sign);
diff --git a/src/signs_func.h b/src/signs_func.h
index 18f27fc81e..21abdc98fe 100644
--- a/src/signs_func.h
+++ b/src/signs_func.h
@@ -17,7 +17,7 @@ struct Window;
void UpdateAllSignVirtCoords();
void PlaceProc_Sign(TileIndex tile);
-bool CompanyCanRenameSign(const Sign *si);
+bool CompanyCanEditSign(const Sign *si);
/* signs_gui.cpp */
void ShowRenameSignWindow(const Sign *si);
diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp
index be1072e9c8..ce1c3f7440 100644
--- a/src/signs_gui.cpp
+++ b/src/signs_gui.cpp
@@ -20,6 +20,7 @@
#include "viewport_func.h"
#include "querystring_gui.h"
#include "sortlist_type.h"
+#include "tilehighlight_func.h"
#include "stringfilter_type.h"
#include "string_func.h"
#include "core/geometry_func.hpp"
@@ -389,9 +390,20 @@ static bool RenameSign(SignID index, std::string_view text)
return remove;
}
+/**
+ * Actually move the sign.
+ * @param index the sign to move.
+ * @param tile on which to move the sign to.
+ */
+void MoveSign(SignID index, TileIndex tile)
+{
+ Command::Post(STR_ERROR_CAN_T_PLACE_SIGN_HERE, index, tile);
+}
+
struct SignWindow : Window, SignList {
QueryString name_editbox;
SignID cur_sign{};
+ WidgetID last_user_action = INVALID_WIDGET; ///< Last started user action.
SignWindow(WindowDesc &desc, const Sign *si) : Window(desc), name_editbox(MAX_LENGTH_SIGN_NAME_CHARS * MAX_CHAR_LENGTH, MAX_LENGTH_SIGN_NAME_CHARS)
{
@@ -489,12 +501,6 @@ struct SignWindow : Window, SignList {
break;
}
- case WID_QES_DELETE:
- /* Only need to set the buffer to null, the rest is handled as the OK button */
- RenameSign(this->cur_sign, "");
- /* don't delete this, we are deleted in Sign::~Sign() -> DeleteRenameSignWindow() */
- break;
-
case WID_QES_OK:
if (RenameSign(this->cur_sign, this->name_editbox.text.GetText())) break;
[[fallthrough]];
@@ -502,8 +508,37 @@ struct SignWindow : Window, SignList {
case WID_QES_CANCEL:
this->Close();
break;
+
+ case WID_QES_DELETE:
+ /* Only need to set the buffer to null, the rest is handled as the OK button */
+ RenameSign(this->cur_sign, "");
+ /* don't delete this, we are deleted in Sign::~Sign() -> DeleteRenameSignWindow() */
+ break;
+
+ case WID_QES_MOVE:
+ HandlePlacePushButton(this, WID_QES_MOVE, SPR_CURSOR_SIGN, HT_RECT, CM_DDSP_MOVE_SIGN);
+ this->last_user_action = widget;
+ break;
}
}
+
+ void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
+ {
+ switch (this->last_user_action) {
+ case WID_QES_MOVE: // Place sign button
+ RenameSign(this->cur_sign, this->name_editbox.text.GetText());
+ MoveSign(this->cur_sign, tile);
+ this->Close();
+ break;
+
+ default: NOT_REACHED();
+ }
+ }
+
+ void OnPlaceObjectAbort() override
+ {
+ this->RaiseButtons();
+ }
};
static constexpr std::initializer_list _nested_query_sign_edit_widgets = {
@@ -519,7 +554,7 @@ static constexpr std::initializer_list _nested_query_sign_edit_widg
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_QES_OK), SetMinimalSize(61, 12), SetStringTip(STR_BUTTON_OK),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_QES_CANCEL), SetMinimalSize(60, 12), SetStringTip(STR_BUTTON_CANCEL),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_QES_DELETE), SetMinimalSize(60, 12), SetStringTip(STR_TOWN_VIEW_DELETE_BUTTON),
- NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), EndContainer(),
+ NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_QES_MOVE), SetMinimalSize(60, 12), SetStringTip(STR_BUTTON_MOVE),
NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_QES_PREVIOUS), SetMinimalSize(11, 12), SetArrowWidgetTypeTip(AWV_DECREASE, STR_EDIT_SIGN_PREVIOUS_SIGN_TOOLTIP),
NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_QES_NEXT), SetMinimalSize(11, 12), SetArrowWidgetTypeTip(AWV_INCREASE, STR_EDIT_SIGN_NEXT_SIGN_TOOLTIP),
EndContainer(),
@@ -538,8 +573,8 @@ static WindowDesc _query_sign_edit_desc(
*/
void HandleClickOnSign(const Sign *si)
{
- /* If we can't rename the sign, don't even open the rename GUI. */
- if (!CompanyCanRenameSign(si)) return;
+ /* If we can't edit the sign, don't even open the rename GUI. */
+ if (!CompanyCanEditSign(si)) return;
if (citymania::_fn_mod && (si->owner == _local_company || (si->owner == OWNER_DEITY && _game_mode == GM_EDITOR))) {
RenameSign(si->index, "");
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 0a9718d1ee..6f1a63ea36 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -29,6 +29,7 @@
#include "road_internal.h" /* For drawing catenary/checking road removal */
#include "autoslope.h"
#include "water.h"
+#include "tilehighlight_func.h"
#include "strings_func.h"
#include "clear_func.h"
#include "timer/timer_game_calendar.h"
@@ -71,6 +72,7 @@
#include "station_layout_type.h"
#include "widgets/station_widget.h"
+#include "widgets/misc_widget.h"
#include "table/strings.h"
#include "table/station_land.h"
@@ -4482,6 +4484,59 @@ CommandCost CmdRenameStation(DoCommandFlags flags, StationID station_id, const s
return CommandCost();
}
+/**
+ * Move a station name.
+ * @param flags type of operation
+ * @param station_id id of the station
+ * @param tile to move the station name to
+ * @return the cost of this operation or an error and the station ID
+ */
+std::tuple CmdMoveStationName(DoCommandFlags flags, StationID station_id, TileIndex tile)
+{
+ Station *st = Station::GetIfValid(station_id);
+ if (st == nullptr) return { CMD_ERROR, StationID::Invalid() };
+
+ if (st->owner != OWNER_NONE) {
+ CommandCost ret = CheckOwnership(st->owner);
+ if (ret.Failed()) return { ret, StationID::Invalid() };
+ }
+
+ const StationRect *r = &st->rect;
+ if (!r->PtInExtendedRect(TileX(tile), TileY(tile))) {
+ return { CommandCost(STR_ERROR_SITE_UNSUITABLE), StationID::Invalid() };
+ }
+
+ bool other_station = false;
+ /* Check if the tile is the base tile of another station */
+ ForAllStationsRadius(tile, 0, [&](BaseStation *s) {
+ if (s != nullptr) {
+ if (s != st && s->xy == tile) other_station = true;
+ }
+ });
+ if (other_station) return { CommandCost(STR_ERROR_SITE_UNSUITABLE), StationID::Invalid() };
+
+ if (flags.Test(DoCommandFlag::Execute)) {
+ st->MoveSign(tile);
+
+ st->UpdateVirtCoord();
+ }
+ return { CommandCost(), station_id };
+}
+
+/**
+* Callback function that is called after a name is moved
+* @param result of the operation
+* @param station_id ID of the changed station
+*/
+void CcMoveStationName(Commands, const CommandCost &result, StationID station_id)
+ {
+ if (result.Failed()) return;
+
+ ResetObjectToPlace();
+ Station *st = Station::Get(station_id);
+ SetViewportStationRect(st, false);
+ }
+
static void AddNearbyStationsByCatchment(TileIndex tile, StationList &stations, StationList &nearby)
{
for (Station *st : nearby) {
diff --git a/src/station_cmd.h b/src/station_cmd.h
index a73380730e..a56666bd3e 100644
--- a/src/station_cmd.h
+++ b/src/station_cmd.h
@@ -30,6 +30,7 @@ CommandCost CmdRemoveFromRailStation(DoCommandFlags flags, TileIndex start, Tile
CommandCost CmdBuildRoadStop(DoCommandFlags flags, TileIndex tile, uint8_t width, uint8_t length, RoadStopType stop_type, bool is_drive_through, DiagDirection ddir, RoadType rt, RoadStopClassID spec_class, uint16_t spec_index, StationID station_to_join, bool adjacent);
CommandCost CmdRemoveRoadStop(DoCommandFlags flags, TileIndex tile, uint8_t width, uint8_t height, RoadStopType stop_type, bool remove_road);
CommandCost CmdRenameStation(DoCommandFlags flags, StationID station_id, const std::string &text);
+std::tuple CmdMoveStationName(DoCommandFlags flags, StationID station_id, TileIndex tile);
CommandCost CmdOpenCloseAirport(DoCommandFlags flags, StationID station_id);
DEF_CMD_TRAIT(CMD_BUILD_AIRPORT, CmdBuildAirport, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CommandType::LandscapeConstruction)
@@ -39,6 +40,9 @@ DEF_CMD_TRAIT(CMD_REMOVE_FROM_RAIL_STATION, CmdRemoveFromRailStation, {},
DEF_CMD_TRAIT(CMD_BUILD_ROAD_STOP, CmdBuildRoadStop, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CommandType::LandscapeConstruction)
DEF_CMD_TRAIT(CMD_REMOVE_ROAD_STOP, CmdRemoveRoadStop, {}, CommandType::LandscapeConstruction)
DEF_CMD_TRAIT(CMD_RENAME_STATION, CmdRenameStation, {}, CommandType::OtherManagement)
+DEF_CMD_TRAIT(CMD_MOVE_STATION_NAME, CmdMoveStationName, {}, CommandType::OtherManagement)
DEF_CMD_TRAIT(CMD_OPEN_CLOSE_AIRPORT, CmdOpenCloseAirport, {}, CommandType::RouteManagement)
+void CcMoveStationName(Commands cmd, const CommandCost &result, StationID station_id);
+
#endif /* STATION_CMD_H */
diff --git a/src/station_gui.cpp b/src/station_gui.cpp
index f6e6be8608..161c0b5640 100644
--- a/src/station_gui.cpp
+++ b/src/station_gui.cpp
@@ -36,6 +36,7 @@
#include "station_cmd.h"
#include "widgets/station_widget.h"
+#include "widgets/misc_widget.h"
#include "table/strings.h"
@@ -842,7 +843,7 @@ void ShowCompanyStations(CompanyID company)
static constexpr std::initializer_list _nested_station_view_widgets = {
NWidget(NWID_HORIZONTAL),
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
- NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_SV_RENAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME, STR_STATION_VIEW_RENAME_TOOLTIP),
+ NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_SV_RENAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME, STR_STATION_VIEW_EDIT_TOOLTIP),
NWidget(WWT_CAPTION, COLOUR_GREY, WID_SV_CAPTION),
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_SV_LOCATION), SetAspect(WidgetDimensions::ASPECT_LOCATION), SetSpriteTip(SPR_GOTO_LOCATION, STR_STATION_VIEW_CENTER_TOOLTIP),
NWidget(WWT_SHADEBOX, COLOUR_GREY),
@@ -1987,6 +1988,8 @@ struct StationViewWindow : public Window {
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
+ Window *w = FindWindowByClass(WC_QUERY_STRING);
+
switch (widget) {
case WID_SV_WAITING:
this->HandleCargoWaitingClick(this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SV_WAITING, WidgetDimensions::scaled.framerect.top) - this->vscroll->GetPosition());
@@ -1994,7 +1997,11 @@ struct StationViewWindow : public Window {
case WID_SV_CATCHMENT:
citymania::SetHighlightCoverageStation(Station::Get(this->window_number), !this->IsWidgetLowered(WID_SV_CATCHMENT));
- // SetViewportCatchmentStation(Station::Get(this->window_number), !this->IsWidgetLowered(WID_SV_CATCHMENT));
+
+ if (w != nullptr && this->IsWidgetLowered(WID_SV_CATCHMENT)) {
+ if (w->parent->window_class == WC_STATION_VIEW && w->IsWidgetLowered(WID_QS_MOVE)) SetViewportStationRect(Station::Get(w->parent->window_number), true);
+ if (w->parent->window_class == WC_WAYPOINT_VIEW && w->IsWidgetLowered(WID_QS_MOVE)) SetViewportWaypointRect(Waypoint::Get(w->parent->window_number), true);
+ }
break;
case WID_SV_LOCATION:
@@ -2021,8 +2028,8 @@ struct StationViewWindow : public Window {
}
case WID_SV_RENAME:
- ShowQueryString(GetString(STR_STATION_NAME, this->window_number), STR_STATION_VIEW_RENAME_STATION_CAPTION, MAX_LENGTH_STATION_NAME_CHARS,
- this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
+ ShowQueryString(GetString(STR_STATION_NAME, this->window_number), STR_STATION_VIEW_EDIT_STATION_SIGN, MAX_LENGTH_STATION_NAME_CHARS,
+ this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars, QueryStringFlag::EnableMove});
break;
case WID_SV_CLOSE_AIRPORT:
diff --git a/src/textbuf_gui.h b/src/textbuf_gui.h
index 5b758183c7..d3f4f9915d 100644
--- a/src/textbuf_gui.h
+++ b/src/textbuf_gui.h
@@ -19,6 +19,7 @@ enum class QueryStringFlag : uint8_t {
AcceptUnchanged, ///< return success even when the text didn't change
EnableDefault, ///< enable the 'Default' button ("\0" is returned)
LengthIsInChars, ///< the length of the string is counted in characters
+ EnableMove, ///< enable the 'Move' button
};
using QueryStringFlags = EnumBitSet;
diff --git a/src/viewport.cpp b/src/viewport.cpp
index 10b8ac73d4..0f4d81df4f 100644
--- a/src/viewport.cpp
+++ b/src/viewport.cpp
@@ -1076,7 +1076,9 @@ static void DrawAutorailSelection(const TileInfo *ti, HighLightStyle autorail_ty
// };
const Station *_viewport_highlight_station; ///< Currently selected station for coverage area highlight
+const Station *_viewport_highlight_station_rect; ///< Currently selected station for rectangle highlight
const Waypoint *_viewport_highlight_waypoint; ///< Currently selected waypoint for coverage area highlight
+const Waypoint *_viewport_highlight_waypoint_rect; ///< Currently selected waypoint for rectangle highlight
const Town *_viewport_highlight_town; ///< Currently selected town for coverage area highlight
/**
@@ -1093,10 +1095,23 @@ static TileHighlightType GetTileHighlightType(TileIndex t)
}
#endif
// TODO CM should handle this too
+
+ if (_viewport_highlight_station_rect != nullptr) {
+ if (IsTileType(t, MP_STATION) && GetStationIndex(t) == _viewport_highlight_station_rect->index) return THT_WHITE;
+ const StationRect *r = &_viewport_highlight_station_rect->rect;
+ if (r->PtInExtendedRect(TileX(t), TileY(t))) return THT_BLUE;
+ }
+
if (_viewport_highlight_waypoint != nullptr) {
if (IsTileType(t, MP_STATION) && GetStationIndex(t) == _viewport_highlight_waypoint->index) return THT_BLUE;
}
+ if (_viewport_highlight_waypoint_rect != nullptr) {
+ if (IsTileType(t, MP_STATION) && GetStationIndex(t) == _viewport_highlight_waypoint_rect->index) return THT_WHITE;
+ const StationRect *r = &_viewport_highlight_waypoint_rect->rect;
+ if (r->PtInExtendedRect(TileX(t), TileY(t))) return THT_BLUE;
+ }
+
if (_viewport_highlight_town != nullptr) {
if (IsTileType(t, MP_HOUSE)) {
if (GetTownIndex(t) == _viewport_highlight_town->index) {
@@ -4213,6 +4228,7 @@ void MarkCatchmentTilesDirty()
MarkWholeScreenDirty();
return;
}
+
if (_viewport_highlight_station != nullptr) {
if (_viewport_highlight_station->catchment_tiles.tile == INVALID_TILE) {
MarkWholeScreenDirty();
@@ -4224,18 +4240,35 @@ void MarkCatchmentTilesDirty()
}
}
}
+
+ if (_viewport_highlight_station_rect != nullptr) {
+ if (!_viewport_highlight_station_rect->IsInUse()) {
+ _viewport_highlight_station_rect = nullptr;
+ }
+ MarkWholeScreenDirty();
+ }
+
if (_viewport_highlight_waypoint != nullptr) {
if (!_viewport_highlight_waypoint->IsInUse()) {
_viewport_highlight_waypoint = nullptr;
}
MarkWholeScreenDirty();
}
+
+ if (_viewport_highlight_waypoint_rect != nullptr) {
+ if (!_viewport_highlight_waypoint_rect->IsInUse()) {
+ _viewport_highlight_waypoint_rect = nullptr;
+ }
+ MarkWholeScreenDirty();
+ }
}
static void SetWindowDirtyForViewportCatchment()
{
if (_viewport_highlight_station != nullptr) SetWindowDirty(WC_STATION_VIEW, _viewport_highlight_station->index);
+ if (_viewport_highlight_station_rect != nullptr) SetWindowDirty(WC_STATION_VIEW, _viewport_highlight_station_rect->index);
if (_viewport_highlight_waypoint != nullptr) SetWindowDirty(WC_WAYPOINT_VIEW, _viewport_highlight_waypoint->index);
+ if (_viewport_highlight_waypoint_rect != nullptr) SetWindowDirty(WC_WAYPOINT_VIEW, _viewport_highlight_waypoint_rect->index);
if (_viewport_highlight_town != nullptr) SetWindowDirty(WC_TOWN_VIEW, _viewport_highlight_town->index);
}
@@ -4243,7 +4276,9 @@ static void ClearViewportCatchment()
{
MarkCatchmentTilesDirty();
_viewport_highlight_station = nullptr;
+ _viewport_highlight_station_rect = nullptr;
_viewport_highlight_waypoint = nullptr;
+ _viewport_highlight_waypoint_rect = nullptr;
_viewport_highlight_town = nullptr;
}
@@ -4267,6 +4302,26 @@ void SetViewportCatchmentStation(const Station *st, bool sel)
if (_viewport_highlight_station != nullptr) SetWindowDirty(WC_STATION_VIEW, _viewport_highlight_station->index);
}
+/**
+ * Select or deselect station for rectangle area highlight.
+ * Selecting a station will deselect a town.
+ * @param *st Station in question
+ * @param sel Select or deselect given station
+ */
+void SetViewportStationRect(const Station *st, bool sel)
+{
+ SetWindowDirtyForViewportCatchment();
+ if (sel && _viewport_highlight_station_rect != st) { // mark tiles dirty for redrawing and update selected station if a different station is already highlighted
+ ClearViewportCatchment();
+ _viewport_highlight_station_rect = st;
+ MarkCatchmentTilesDirty();
+ } else if (!sel && _viewport_highlight_station_rect == st) { // mark tiles dirty for redrawing and clear station selection if deselecting highlight
+ MarkCatchmentTilesDirty();
+ _viewport_highlight_station_rect = nullptr;
+ }
+ if (_viewport_highlight_station_rect != nullptr) SetWindowDirty(WC_STATION_VIEW, _viewport_highlight_station_rect->index); // redraw the currently selected station window
+}
+
/**
* Select or deselect waypoint for coverage area highlight.
* Selecting a waypoint will deselect a town.
@@ -4287,6 +4342,26 @@ void SetViewportCatchmentWaypoint(const Waypoint *wp, bool sel)
if (_viewport_highlight_waypoint != nullptr) SetWindowDirty(WC_WAYPOINT_VIEW, _viewport_highlight_waypoint->index);
}
+/**
+ * Select or deselect waypoint for rectangle area highlight.
+ * Selecting a waypoint will deselect a town.
+ * @param *wp Waypoint in question
+ * @param sel Select or deselect given waypoint
+ */
+void SetViewportWaypointRect(const Waypoint *wp, bool sel)
+{
+ SetWindowDirtyForViewportCatchment();
+ if (sel && _viewport_highlight_waypoint_rect != wp) { // mark tiles dirty for redrawing and update selected waypoint if a different waypoint is already highlighted
+ ClearViewportCatchment();
+ _viewport_highlight_waypoint_rect = wp;
+ MarkCatchmentTilesDirty();
+ } else if (!sel && _viewport_highlight_waypoint_rect == wp) { // mark tiles dirty for redrawing and clear waypoint selection if deselecting highlight
+ MarkCatchmentTilesDirty();
+ _viewport_highlight_waypoint_rect = nullptr;
+ }
+ if (_viewport_highlight_waypoint_rect != nullptr) SetWindowDirty(WC_WAYPOINT_VIEW, _viewport_highlight_waypoint_rect->index); // redraw the currently selected waypoint window
+}
+
/**
* Select or deselect town for coverage area highlight.
* Selecting a town will deselect a station.
diff --git a/src/viewport_func.h b/src/viewport_func.h
index f21edd24fe..5e4a5ea72d 100644
--- a/src/viewport_func.h
+++ b/src/viewport_func.h
@@ -105,7 +105,9 @@ struct Waypoint;
struct Town;
void SetViewportCatchmentStation(const Station *st, bool sel);
+void SetViewportStationRect(const Station *st, bool sel);
void SetViewportCatchmentWaypoint(const Waypoint *wp, bool sel);
+void SetViewportWaypointRect(const Waypoint *wp, bool sel);
void SetViewportCatchmentTown(const Town *t, bool sel);
void MarkCatchmentTilesDirty();
diff --git a/src/viewport_type.h b/src/viewport_type.h
index 031d7d92fc..20214c63ec 100644
--- a/src/viewport_type.h
+++ b/src/viewport_type.h
@@ -219,6 +219,7 @@ enum ViewportDragDropSelectionProcess : uint8_t {
CM_DDSP_RAIL_BLUEPRINT,
CM_DDSP_BLUEPRINT_AREA, ///< Blueprint area to copy selection
CM_DDSP_BUILD_HOUSE,
+ CM_DDSP_MOVE_SIGN,
};
diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp
index f76d9bd1f7..aee8f9dbd0 100644
--- a/src/waypoint_cmd.cpp
+++ b/src/waypoint_cmd.cpp
@@ -16,9 +16,11 @@
#include "waypoint_base.h"
#include "pathfinder/yapf/yapf_cache.h"
#include "pathfinder/water_regions.h"
+#include "tilehighlight_func.h"
#include "strings_func.h"
#include "viewport_func.h"
#include "viewport_kdtree.h"
+#include "station_kdtree.h"
#include "window_func.h"
#include "timer/timer_game_calendar.h"
#include "vehicle_func.h"
@@ -33,6 +35,8 @@
#include "landscape_cmd.h"
#include "station_layout_type.h"
+#include "widgets/misc_widget.h"
+
#include "table/strings.h"
#include "safeguards.h"
@@ -603,3 +607,56 @@ CommandCost CmdRenameWaypoint(DoCommandFlags flags, StationID waypoint_id, const
}
return CommandCost();
}
+
+/**
+ * Move a waypoint name.
+ * @param flags type of operation
+ * @param waypoint_id id of waypoint
+ * @param tile to move the waypoint name to
+ * @return the cost of this operation or an error and the waypoint ID
+ */
+std::tuple CmdMoveWaypointName(DoCommandFlags flags, StationID waypoint_id, TileIndex tile)
+{
+ Waypoint *wp = Waypoint::GetIfValid(waypoint_id);
+ if (wp == nullptr) return { CMD_ERROR, StationID::Invalid() };
+
+ if (wp->owner != OWNER_NONE) {
+ CommandCost ret = CheckOwnership(wp->owner);
+ if (ret.Failed()) return { ret, StationID::Invalid() };
+ }
+
+ const StationRect *r = &wp->rect;
+ if (!r->PtInExtendedRect(TileX(tile), TileY(tile))) {
+ return { CommandCost(STR_ERROR_SITE_UNSUITABLE), StationID::Invalid() };
+ }
+
+ bool other_station = false;
+ /* Check if the tile is the base tile of another station */
+ ForAllStationsRadius(tile, 0, [&](BaseStation *st) {
+ if (st != nullptr) {
+ if (st != wp && st->xy == tile) other_station = true;
+ }
+ });
+ if (other_station) return { CommandCost(STR_ERROR_SITE_UNSUITABLE), StationID::Invalid() };
+
+ if (flags.Test(DoCommandFlag::Execute)) {
+ wp->MoveSign(tile);
+
+ wp->UpdateVirtCoord();
+ }
+ return { CommandCost(), waypoint_id };
+}
+
+/**
+ * Callback function that is called after a name is moved
+ * @param result of the operation
+ * @param waypoint_id ID of the changed waypoint
+ */
+void CcMoveWaypointName(Commands, const CommandCost &result, StationID waypoint_id)
+{
+ if (result.Failed()) return;
+
+ ResetObjectToPlace();
+ Waypoint *wp = Waypoint::Get(waypoint_id);
+ SetViewportCatchmentWaypoint(wp, false);
+}
diff --git a/src/waypoint_cmd.h b/src/waypoint_cmd.h
index 2831c5c981..61cd6f4581 100644
--- a/src/waypoint_cmd.h
+++ b/src/waypoint_cmd.h
@@ -22,6 +22,7 @@ CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi
CommandCost CmdRemoveFromRoadWaypoint(DoCommandFlags flags, TileIndex start, TileIndex end);
CommandCost CmdBuildBuoy(DoCommandFlags flags, TileIndex tile);
CommandCost CmdRenameWaypoint(DoCommandFlags flags, StationID waypoint_id, const std::string &text);
+std::tuple CmdMoveWaypointName(DoCommandFlags flags, StationID waypoint_id, TileIndex tile);
DEF_CMD_TRAIT(CMD_BUILD_RAIL_WAYPOINT, CmdBuildRailWaypoint, {}, CommandType::LandscapeConstruction)
DEF_CMD_TRAIT(CMD_REMOVE_FROM_RAIL_WAYPOINT, CmdRemoveFromRailWaypoint, {}, CommandType::LandscapeConstruction)
@@ -29,5 +30,8 @@ DEF_CMD_TRAIT(CMD_BUILD_ROAD_WAYPOINT, CmdBuildRoadWaypoint, {},
DEF_CMD_TRAIT(CMD_REMOVE_FROM_ROAD_WAYPOINT, CmdRemoveFromRoadWaypoint, {}, CommandType::LandscapeConstruction)
DEF_CMD_TRAIT(CMD_BUILD_BUOY, CmdBuildBuoy, CommandFlag::Auto, CommandType::LandscapeConstruction)
DEF_CMD_TRAIT(CMD_RENAME_WAYPOINT, CmdRenameWaypoint, {}, CommandType::OtherManagement)
+DEF_CMD_TRAIT(CMD_MOVE_WAYPOINT_NAME, CmdMoveWaypointName, {}, CommandType::OtherManagement)
+
+void CcMoveWaypointName(Commands cmd, const CommandCost &result, StationID waypoint_id);
#endif /* WAYPOINT_CMD_H */
diff --git a/src/waypoint_gui.cpp b/src/waypoint_gui.cpp
index a27d77a319..698009adec 100644
--- a/src/waypoint_gui.cpp
+++ b/src/waypoint_gui.cpp
@@ -20,10 +20,12 @@
#include "company_base.h"
#include "window_func.h"
#include "waypoint_base.h"
+#include "station_base.h"
#include "waypoint_cmd.h"
#include "zoom_func.h"
#include "widgets/waypoint_widget.h"
+#include "widgets/misc_widget.h"
#include "table/strings.h"
@@ -89,7 +91,7 @@ public:
}
if (this->vt != VEH_SHIP) {
this->GetWidget(WID_W_CENTER_VIEW)->SetToolTip(STR_WAYPOINT_VIEW_CENTER_TOOLTIP);
- this->GetWidget(WID_W_RENAME)->SetToolTip(STR_WAYPOINT_VIEW_CHANGE_WAYPOINT_NAME);
+ this->GetWidget(WID_W_RENAME)->SetToolTip(STR_WAYPOINT_VIEW_EDIT_TOOLTIP);
}
this->FinishInitNested(window_number);
@@ -127,6 +129,8 @@ public:
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
{
+ Window *w = FindWindowByClass(WC_QUERY_STRING);
+
switch (widget) {
case WID_W_CENTER_VIEW: // scroll to location
if (citymania::_fn_mod) {
@@ -137,7 +141,8 @@ public:
break;
case WID_W_RENAME: // rename
- ShowQueryString(GetString(STR_WAYPOINT_NAME, this->wp->index), STR_EDIT_WAYPOINT_NAME, MAX_LENGTH_STATION_NAME_CHARS, this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
+ ShowQueryString(GetString(STR_WAYPOINT_NAME, this->wp->index), STR_WAYPOINT_VIEW_EDIT_WAYPOINT_SIGN, MAX_LENGTH_STATION_NAME_CHARS, this, CS_ALPHANUMERAL,
+ {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars, QueryStringFlag::EnableMove});
break;
case WID_W_SHOW_VEHICLES: // show list of vehicles having this waypoint in their orders
@@ -146,6 +151,11 @@ public:
case WID_W_CATCHMENT:
SetViewportCatchmentWaypoint(Waypoint::Get(this->window_number), !this->IsWidgetLowered(WID_W_CATCHMENT));
+
+ if (w != nullptr && this->IsWidgetLowered(WID_W_CATCHMENT)) {
+ if (w->parent->window_class == WC_STATION_VIEW && w->IsWidgetLowered(WID_QS_MOVE)) SetViewportStationRect(Station::Get(w->parent->window_number), true);
+ if (w->parent->window_class == WC_WAYPOINT_VIEW && w->IsWidgetLowered(WID_QS_MOVE)) SetViewportWaypointRect(Waypoint::Get(w->parent->window_number), true);
+ }
break;
}
}
diff --git a/src/widgets/misc_widget.h b/src/widgets/misc_widget.h
index 0d59ee4f8e..758d418014 100644
--- a/src/widgets/misc_widget.h
+++ b/src/widgets/misc_widget.h
@@ -35,6 +35,8 @@ enum QueryStringWidgets : WidgetID {
WID_QS_DEFAULT, ///< Default button.
WID_QS_CANCEL, ///< Cancel button.
WID_QS_OK, ///< OK button.
+ WID_QS_MOVE, ///< Move button.
+ WID_QS_MOVE_SEL, ///< Container for move button, which can be hidden.
};
/** Widgets of the #QueryWindow class. */
diff --git a/src/widgets/sign_widget.h b/src/widgets/sign_widget.h
index e8b9a95866..d6c023465c 100644
--- a/src/widgets/sign_widget.h
+++ b/src/widgets/sign_widget.h
@@ -28,6 +28,7 @@ enum QueryEditSignWidgets : WidgetID {
WID_QES_OK, ///< OK button.
WID_QES_CANCEL, ///< Cancel button.
WID_QES_DELETE, ///< Delete button.
+ WID_QES_MOVE, ///< Move Sign button.
WID_QES_PREVIOUS, ///< Previous button.
WID_QES_NEXT, ///< Next button.
};