From 8d14016c3f2b3dab8f51c5ae47cc17006ae8a3fc Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Sun, 15 May 2022 22:25:45 +0200 Subject: [PATCH] Allow maps to be resized to non-rectangular shapes --- data/language/en-GB.txt | 3 +- resources/g2/icons/link_chain.png | Bin 0 -> 154 bytes resources/g2/sprites.json | 5 + src/openrct2-ui/windows/Map.cpp | 167 ++++++++++++++++++-------- src/openrct2/interface/Window.h | 2 +- src/openrct2/localisation/StringIds.h | 4 +- src/openrct2/sprites.h | 4 +- 7 files changed, 129 insertions(+), 56 deletions(-) create mode 100644 resources/g2/icons/link_chain.png diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 8351bebb4b..49a03d001c 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -2258,7 +2258,7 @@ STR_3208 :Track Designs Manager STR_3209 :Back to Previous Step: STR_3210 :Forward to Next Step: STR_3211 :Map size: -STR_3212 :{COMMA16} × {COMMA16} +STR_3212 :{POP16}{COMMA16} STR_3213 :Can’t decrease map size any further STR_3214 :Can’t increase map size any further STR_3215 :Too close to edge of map @@ -3603,6 +3603,7 @@ STR_6494 :Group by ride type STR_6495 :Group rides by ride types instead of showing each vehicle separately. STR_6496 :{WINDOW_COLOUR_2}{STRINGID} STR_6497 :Click on a tile to show its tile elements.{NEWLINE}Ctrl + click a tile element to select it directly. +STR_6498 :Enable to maintain square map shape. ############# # Scenarios # diff --git a/resources/g2/icons/link_chain.png b/resources/g2/icons/link_chain.png new file mode 100644 index 0000000000000000000000000000000000000000..7edf3872be58a218941ebc6df5bb9886616856fd GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^f_!@pW9jMQ7*Y|JoFE_~!jR17mY(b^kd`1|D8j;+%*d9= zxS_*f#?mEAPAI4xP*}q;EmSChp|in&`H%<$i!GbjYE^!aD;PXo{an^LB{Ts5_P{Ic literal 0 HcmV?d00001 diff --git a/resources/g2/sprites.json b/resources/g2/sprites.json index 31fa07ddd7..0b2ba1f0ce 100644 --- a/resources/g2/sprites.json +++ b/resources/g2/sprites.json @@ -529,6 +529,11 @@ "x_offset": 4, "y_offset": 2 }, + { + "path": "icons/link_chain.png", + "x_offset": 2, + "y_offset": 2 + }, { "path": "font/latin/ae-uc-small.png", "y_offset": 0, diff --git a/src/openrct2-ui/windows/Map.cpp b/src/openrct2-ui/windows/Map.cpp index 2e062148d7..8d517d5ce9 100644 --- a/src/openrct2-ui/windows/Map.cpp +++ b/src/openrct2-ui/windows/Map.cpp @@ -72,25 +72,29 @@ enum WindowMapWidgetIdx WIDX_BACKGROUND, WIDX_TITLE, WIDX_CLOSE, - WIDX_RESIZE = 3, - WIDX_PEOPLE_TAB = 4, - WIDX_RIDES_TAB = 5, - WIDX_MAP = 6, - WIDX_MAP_SIZE_SPINNER = 7, - WIDX_MAP_SIZE_SPINNER_UP = 8, - WIDX_MAP_SIZE_SPINNER_DOWN = 9, - WIDX_SET_LAND_RIGHTS = 10, - WIDX_BUILD_PARK_ENTRANCE = 11, - WIDX_PEOPLE_STARTING_POSITION = 12, - WIDX_LAND_TOOL = 13, - WIDX_LAND_TOOL_SMALLER = 14, - WIDX_LAND_TOOL_LARGER = 15, - WIDX_LAND_OWNED_CHECKBOX = 16, - WIDX_CONSTRUCTION_RIGHTS_OWNED_CHECKBOX = 17, - WIDX_LAND_SALE_CHECKBOX = 18, - WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX = 19, - WIDX_ROTATE_90 = 20, - WIDX_MAP_GENERATOR = 21 + WIDX_RESIZE, + WIDX_PEOPLE_TAB, + WIDX_RIDES_TAB, + WIDX_MAP, + WIDX_MAP_SIZE_SPINNER_Y, + WIDX_MAP_SIZE_SPINNER_Y_UP, + WIDX_MAP_SIZE_SPINNER_Y_DOWN, + WIDX_MAP_SIZE_LINK, + WIDX_MAP_SIZE_SPINNER_X, + WIDX_MAP_SIZE_SPINNER_X_UP, + WIDX_MAP_SIZE_SPINNER_X_DOWN, + WIDX_SET_LAND_RIGHTS, + WIDX_BUILD_PARK_ENTRANCE, + WIDX_PEOPLE_STARTING_POSITION, + WIDX_LAND_TOOL, + WIDX_LAND_TOOL_SMALLER, + WIDX_LAND_TOOL_LARGER, + WIDX_LAND_OWNED_CHECKBOX, + WIDX_CONSTRUCTION_RIGHTS_OWNED_CHECKBOX, + WIDX_LAND_SALE_CHECKBOX, + WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX, + WIDX_ROTATE_90, + WIDX_MAP_GENERATOR }; validate_global_widx(WC_MAP, WIDX_ROTATE_90); @@ -102,7 +106,9 @@ static rct_widget window_map_widgets[] = { MakeRemapWidget ({ 3, 17}, { 31, 27}, WindowWidgetType::ColourBtn, WindowColour::Secondary, SPR_TAB, STR_SHOW_PEOPLE_ON_MAP_TIP ), MakeRemapWidget ({ 34, 17}, { 31, 27}, WindowWidgetType::ColourBtn, WindowColour::Secondary, SPR_TAB, STR_SHOW_RIDES_STALLS_ON_MAP_TIP ), MakeWidget ({ 3, 46}, {239, 180}, WindowWidgetType::Scroll, WindowColour::Secondary, SCROLL_BOTH ), - MakeSpinnerWidgets({104, 229}, { 95, 12}, WindowWidgetType::Spinner, WindowColour::Secondary, STR_MAP_SIZE_VALUE ), // NB: 3 widgets + MakeSpinnerWidgets({102, 229}, { 50, 12}, WindowWidgetType::Spinner, WindowColour::Secondary, STR_COMMA16 ), // NB: 3 widgets + MakeWidget ({153, 230}, { 20, 12}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_G2_LINK_CHAIN, STR_MAINTAIN_SQUARE_MAP_TOOLTIP ), + MakeSpinnerWidgets({174, 229}, { 50, 12}, WindowWidgetType::Spinner, WindowColour::Secondary, STR_POP16_COMMA16 ), // NB: 3 widgets MakeWidget ({ 4, 1}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_BUY_LAND_RIGHTS, STR_SELECT_PARK_OWNED_LAND_TIP ), MakeWidget ({ 4, 1}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_PARK_ENTRANCE, STR_BUILD_PARK_ENTRANCE_TIP ), MakeWidget ({ 28, 1}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_SET_STARTING_POSITIONS_TIP ), @@ -140,8 +146,9 @@ public: { widgets = window_map_widgets; - hold_down_widgets = (1ULL << WIDX_MAP_SIZE_SPINNER_UP) | (1ULL << WIDX_MAP_SIZE_SPINNER_DOWN) - | (1ULL << WIDX_LAND_TOOL_LARGER) | (1ULL << WIDX_LAND_TOOL_SMALLER); + hold_down_widgets = (1ULL << WIDX_MAP_SIZE_SPINNER_Y_UP) | (1ULL << WIDX_MAP_SIZE_SPINNER_Y_DOWN) + | (1ULL << WIDX_MAP_SIZE_SPINNER_X_UP) | (1ULL << WIDX_MAP_SIZE_SPINNER_X_DOWN) | (1ULL << WIDX_LAND_TOOL_LARGER) + | (1ULL << WIDX_LAND_TOOL_SMALLER); InitScrollWidgets(); @@ -251,8 +258,12 @@ public: case WIDX_LAND_TOOL: InputLandSize(); break; - case WIDX_MAP_SIZE_SPINNER: - InputMapSize(); + case WIDX_MAP_SIZE_SPINNER_Y: + case WIDX_MAP_SIZE_SPINNER_X: + InputMapSize(widgetIndex); + break; + case WIDX_MAP_SIZE_LINK: + _mapWidthAndHeightLinked = !_mapWidthAndHeightLinked; break; case WIDX_MAP_GENERATOR: context_open_window(WC_MAPGEN); @@ -274,10 +285,20 @@ public: { switch (widgetIndex) { - case WIDX_MAP_SIZE_SPINNER_UP: + case WIDX_MAP_SIZE_SPINNER_Y_UP: + _resizeDirection = ResizeDirection::Y; IncreaseMapSize(); break; - case WIDX_MAP_SIZE_SPINNER_DOWN: + case WIDX_MAP_SIZE_SPINNER_Y_DOWN: + _resizeDirection = ResizeDirection::Y; + DecreaseMapSize(); + break; + case WIDX_MAP_SIZE_SPINNER_X_UP: + _resizeDirection = ResizeDirection::X; + IncreaseMapSize(); + break; + case WIDX_MAP_SIZE_SPINNER_X_DOWN: + _resizeDirection = ResizeDirection::X; DecreaseMapSize(); break; case WIDX_LAND_TOOL_SMALLER: @@ -577,7 +598,8 @@ public: } break; } - case WIDX_MAP_SIZE_SPINNER: + case WIDX_MAP_SIZE_SPINNER_Y: + case WIDX_MAP_SIZE_SPINNER_X: { char* end; std::string textStr = std::string(text); @@ -588,7 +610,13 @@ public: size += 2; size = std::clamp(size, MINIMUM_MAP_SIZE_TECHNICAL, MAXIMUM_MAP_SIZE_TECHNICAL); - auto changeMapSizeAction = ChangeMapSizeAction({ size, size }); + TileCoordsXY newMapSize = gMapSize; + if (_resizeDirection != ResizeDirection::X) + newMapSize.y = size; + if (_resizeDirection != ResizeDirection::Y) + newMapSize.x = size; + + auto changeMapSizeAction = ChangeMapSizeAction(newMapSize); GameActions::Execute(&changeMapSizeAction); Invalidate(); } @@ -689,14 +717,8 @@ public: void OnPrepareDraw() override { // Set the pressed widgets - pressed_widgets &= (1ULL << WIDX_PEOPLE_TAB); - pressed_widgets &= (1ULL << WIDX_RIDES_TAB); - pressed_widgets &= (1ULL << WIDX_MAP); - pressed_widgets &= (1ULL << WIDX_LAND_OWNED_CHECKBOX); - pressed_widgets &= (1ULL << WIDX_CONSTRUCTION_RIGHTS_OWNED_CHECKBOX); - pressed_widgets &= (1ULL << WIDX_LAND_SALE_CHECKBOX); - pressed_widgets &= (1ULL << WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX); - + pressed_widgets = 0; + SetWidgetPressed(WIDX_MAP_SIZE_LINK, _mapWidthAndHeightLinked); pressed_widgets |= (1ULL << (WIDX_PEOPLE_TAB + selected_tab)); pressed_widgets |= (1ULL << WIDX_LAND_TOOL); @@ -712,6 +734,9 @@ public: if (_activeTool & (1 << 0)) pressed_widgets |= (1ULL << WIDX_CONSTRUCTION_RIGHTS_OWNED_CHECKBOX); + // Set disabled widgets + SetWidgetDisabled(WIDX_MAP_SIZE_LINK, gMapSize.x != gMapSize.y); + // Resize widgets to window size widgets[WIDX_BACKGROUND].right = width - 1; widgets[WIDX_BACKGROUND].bottom = height - 1; @@ -729,12 +754,20 @@ public: else widgets[WIDX_MAP].bottom = height - 1 - 14; - widgets[WIDX_MAP_SIZE_SPINNER].top = height - 15; - widgets[WIDX_MAP_SIZE_SPINNER].bottom = height - 4; - widgets[WIDX_MAP_SIZE_SPINNER_UP].top = height - 14; - widgets[WIDX_MAP_SIZE_SPINNER_UP].bottom = height - 5; - widgets[WIDX_MAP_SIZE_SPINNER_DOWN].top = height - 14; - widgets[WIDX_MAP_SIZE_SPINNER_DOWN].bottom = height - 5; + widgets[WIDX_MAP_SIZE_SPINNER_Y].top = height - 15; + widgets[WIDX_MAP_SIZE_SPINNER_Y].bottom = height - 4; + widgets[WIDX_MAP_SIZE_SPINNER_Y_UP].top = height - 14; + widgets[WIDX_MAP_SIZE_SPINNER_Y_UP].bottom = height - 5; + widgets[WIDX_MAP_SIZE_SPINNER_Y_DOWN].top = height - 14; + widgets[WIDX_MAP_SIZE_SPINNER_Y_DOWN].bottom = height - 5; + widgets[WIDX_MAP_SIZE_LINK].top = height - 15; + widgets[WIDX_MAP_SIZE_LINK].bottom = height - 4; + widgets[WIDX_MAP_SIZE_SPINNER_X].top = height - 15; + widgets[WIDX_MAP_SIZE_SPINNER_X].bottom = height - 4; + widgets[WIDX_MAP_SIZE_SPINNER_X_UP].top = height - 14; + widgets[WIDX_MAP_SIZE_SPINNER_X_UP].bottom = height - 5; + widgets[WIDX_MAP_SIZE_SPINNER_X_DOWN].top = height - 14; + widgets[WIDX_MAP_SIZE_SPINNER_X_DOWN].bottom = height - 5; widgets[WIDX_SET_LAND_RIGHTS].top = height - 70; widgets[WIDX_SET_LAND_RIGHTS].bottom = height - 70 + 23; @@ -766,7 +799,7 @@ public: } // Disable all scenario editor related widgets - for (int32_t i = WIDX_MAP_SIZE_SPINNER; i <= WIDX_MAP_GENERATOR; i++) + for (int32_t i = WIDX_MAP_SIZE_SPINNER_Y; i <= WIDX_MAP_GENERATOR; i++) { widgets[i].type = WindowWidgetType::Empty; } @@ -848,6 +881,7 @@ public: STR_MAP_RIDE, STR_MAP_FOOD_STALL, STR_MAP_DRINK_STALL, STR_MAP_SOUVENIR_STALL, STR_MAP_INFO_KIOSK, STR_MAP_FIRST_AID, STR_MAP_CASH_MACHINE, STR_MAP_TOILET, }; + static_assert(std::size(RideKeyColours) == std::size(_mapLabels)); for (uint32_t i = 0; i < std::size(RideKeyColours); i++) { @@ -866,7 +900,7 @@ public: else if (!WidgetIsActiveTool(this, WIDX_SET_LAND_RIGHTS)) { DrawTextBasic( - &dpi, windowPos + ScreenCoordsXY{ 4, widgets[WIDX_MAP_SIZE_SPINNER].top + 1 }, STR_MAP_SIZE, {}, + &dpi, windowPos + ScreenCoordsXY{ 4, widgets[WIDX_MAP_SIZE_SPINNER_Y].top + 1 }, STR_MAP_SIZE, {}, { colours[1] }); } } @@ -930,13 +964,25 @@ private: void IncreaseMapSize() { - auto increaseMapSizeAction = ChangeMapSizeAction({ gMapSize.x + 1, gMapSize.y + 1 }); + auto newMapSize = gMapSize; + if (IsWidgetPressed(WIDX_MAP_SIZE_LINK) || _resizeDirection == ResizeDirection::Y) + newMapSize.y++; + if (IsWidgetPressed(WIDX_MAP_SIZE_LINK) || _resizeDirection == ResizeDirection::X) + newMapSize.x++; + + auto increaseMapSizeAction = ChangeMapSizeAction(newMapSize); GameActions::Execute(&increaseMapSizeAction); } void DecreaseMapSize() { - auto decreaseMapSizeAction = ChangeMapSizeAction({ gMapSize.x - 1, gMapSize.y - 1 }); + auto newMapSize = gMapSize; + if (IsWidgetPressed(WIDX_MAP_SIZE_LINK) || _resizeDirection == ResizeDirection::Y) + newMapSize.y--; + if (IsWidgetPressed(WIDX_MAP_SIZE_LINK) || _resizeDirection == ResizeDirection::X) + newMapSize.x--; + + auto decreaseMapSizeAction = ChangeMapSizeAction(newMapSize); GameActions::Execute(&decreaseMapSizeAction); } @@ -1246,17 +1292,22 @@ private: { widgets[WIDX_BUILD_PARK_ENTRANCE].type = WindowWidgetType::FlatBtn; widgets[WIDX_PEOPLE_STARTING_POSITION].type = WindowWidgetType::FlatBtn; - widgets[WIDX_MAP_SIZE_SPINNER].type = WindowWidgetType::Spinner; - widgets[WIDX_MAP_SIZE_SPINNER_UP].type = WindowWidgetType::Button; - widgets[WIDX_MAP_SIZE_SPINNER_DOWN].type = WindowWidgetType::Button; + widgets[WIDX_MAP_SIZE_SPINNER_Y].type = WindowWidgetType::Spinner; + widgets[WIDX_MAP_SIZE_SPINNER_Y_UP].type = WindowWidgetType::Button; + widgets[WIDX_MAP_SIZE_SPINNER_Y_DOWN].type = WindowWidgetType::Button; + widgets[WIDX_MAP_SIZE_LINK].type = WindowWidgetType::FlatBtn; + widgets[WIDX_MAP_SIZE_SPINNER_X].type = WindowWidgetType::Spinner; + widgets[WIDX_MAP_SIZE_SPINNER_X_UP].type = WindowWidgetType::Button; + widgets[WIDX_MAP_SIZE_SPINNER_X_DOWN].type = WindowWidgetType::Button; // Only show this in the scenario editor, even when in sandbox mode. if (gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) widgets[WIDX_MAP_GENERATOR].type = WindowWidgetType::Button; + // Push width (Y) and height (X) to the common formatter arguments for the map size spinners to use auto ft = Formatter::Common(); - ft.Add(gMapSize.x - 2); ft.Add(gMapSize.y - 2); + ft.Add(gMapSize.x - 2); } void InputLandSize() @@ -1267,12 +1318,17 @@ private: TextInputOpen(WIDX_LAND_TOOL, STR_SELECTION_SIZE, STR_ENTER_SELECTION_SIZE, ft, STR_NONE, STR_NONE, 3); } - void InputMapSize() + void InputMapSize(rct_widgetindex callingWidget) { + if (IsWidgetPressed(WIDX_MAP_SIZE_LINK)) + _resizeDirection = ResizeDirection::Both; + else + _resizeDirection = (callingWidget == WIDX_MAP_SIZE_SPINNER_Y) ? ResizeDirection::Y : ResizeDirection::X; + Formatter ft; ft.Add(MINIMUM_MAP_SIZE_PRACTICAL); ft.Add(MAXIMUM_MAP_SIZE_PRACTICAL); - TextInputOpen(WIDX_MAP_SIZE_SPINNER, STR_MAP_SIZE_2, STR_ENTER_MAP_SIZE, ft, STR_NONE, STR_NONE, 4); + TextInputOpen(callingWidget, STR_MAP_SIZE_2, STR_ENTER_MAP_SIZE, ft, STR_NONE, STR_NONE, 4); } CoordsXY ScreenToMap(ScreenCoordsXY screenCoords) @@ -1327,6 +1383,13 @@ private: uint32_t _currentLine; uint16_t _landRightsToolSize; std::vector _mapImageData; + bool _mapWidthAndHeightLinked{ true }; + enum class ResizeDirection + { + Both, + X, + Y, + } _resizeDirection{ ResizeDirection::Both }; static constexpr const uint16_t RideKeyColours[] = { MapColour(PALETTE_INDEX_61), // COLOUR_KEY_RIDE diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index 6ec65ce72f..12d29cab80 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -527,7 +527,7 @@ enum #define WC_PEEP__WIDX_PICKUP 14 #define WC_TRACK_DESIGN_LIST__WIDX_ROTATE 8 #define WC_TRACK_DESIGN_PLACE__WIDX_ROTATE 3 -#define WC_MAP__WIDX_ROTATE_90 20 +#define WC_MAP__WIDX_ROTATE_90 24 #define WC_EDITOR_OBJECT_SELECTION__WIDX_TAB_1 21 #define WC_STAFF__WIDX_PICKUP 9 #define WC_TILE_INSPECTOR__WIDX_BUTTON_ROTATE 13 diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h index 3f67339641..04466e12f4 100644 --- a/src/openrct2/localisation/StringIds.h +++ b/src/openrct2/localisation/StringIds.h @@ -2379,7 +2379,7 @@ enum : uint16_t STR_BACK_TO_PREVIOUS_STEP = 3209, STR_FORWARD_TO_NEXT_STEP = 3210, STR_MAP_SIZE = 3211, - STR_MAP_SIZE_VALUE = 3212, + STR_POP16_COMMA16 = 3212, STR_CANT_DECREASE_MAP_SIZE_ANY_FURTHER = 3213, STR_CANT_INCREASE_MAP_SIZE_ANY_FURTHER = 3214, STR_TOO_CLOSE_TO_EDGE_OF_MAP = 3215, @@ -3875,6 +3875,8 @@ enum : uint16_t STR_TILE_INSPECTOR_SELECT_TILE_HINT = 6497, + STR_MAINTAIN_SQUARE_MAP_TOOLTIP = 6498, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working /* MAX_STR_COUNT = 32768 */ // MAX_STR_COUNT - upper limit for number of strings, not the current count strings }; diff --git a/src/openrct2/sprites.h b/src/openrct2/sprites.h index fee025c4e0..3527d17eb2 100644 --- a/src/openrct2/sprites.h +++ b/src/openrct2/sprites.h @@ -895,7 +895,9 @@ enum SPR_G2_BUTTON_HIDE_PARTIAL = SPR_G2_BEGIN + 147, SPR_G2_BUTTON_HIDE_FULL = SPR_G2_BEGIN + 148, - SPR_G2_CHAR_BEGIN = SPR_G2_BEGIN + 149, + SPR_G2_LINK_CHAIN = SPR_G2_BEGIN + 149, + + SPR_G2_CHAR_BEGIN = SPR_G2_BEGIN + 150, SPR_G2_AE_UPPER = SPR_G2_CHAR_BEGIN, SPR_G2_AE_LOWER = SPR_G2_CHAR_BEGIN + 1,