diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 6048d6f368..d86efeb505 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -11,6 +11,7 @@ - Improved: [#21981] The map window now defaults to showing as much of the map as fits the screen. - Improved: [#21983] Taking a screenshot now shows a message again, closing when taking another. - Improved: [#22026] The options window now stays centred when window scaling is changed. +- Improved: [#22060] [Plugin] The scroll wheel can now be used to modify spinner widget values in custom/script windows. - Improved: [#22084] The game now temporarily pauses while the load/save window is open. - Change: [#7248] Small mini-maps are now centred in the map window. - Change: [#20240] Heavy snow and blizzards now make guests buy and use umbrellas. diff --git a/src/openrct2-ui/interface/Window.cpp b/src/openrct2-ui/interface/Window.cpp index 0d583e86bb..0e14e9c306 100644 --- a/src/openrct2-ui/interface/Window.cpp +++ b/src/openrct2-ui/interface/Window.cpp @@ -410,101 +410,89 @@ static void WindowViewportWheelInput(WindowBase& w, int32_t wheel) WindowZoomOut(w, true); } +static bool isSpinnerGroup(WindowBase& w, WidgetIndex index, WindowWidgetType buttonType) +{ + const auto& widgets = w.widgets; + + if (widgets[index].type != WindowWidgetType::Spinner && widgets[index].type != WindowWidgetType::ImgBtn) + return false; + + if (widgets[index + 1].type != buttonType) + return false; + + if (widgets[index + 2].type != buttonType) + return false; + + return true; +} + +static std::optional getSpinnerGroupWidgetIndex(WindowBase& w, WidgetIndex startIndex) +{ + // We only iterate 3 times as we might be at the spinner or one of its buttons. + for (WidgetIndex index = 0; index < 3; index++) + { + const auto reverseIndex = startIndex - index; + if (reverseIndex < 0) + { + break; + } + + if (isSpinnerGroup(w, reverseIndex, WindowWidgetType::TrnBtn)) + { + return reverseIndex; + } + + if (isSpinnerGroup(w, reverseIndex, WindowWidgetType::Button)) + { + return reverseIndex; + } + } + + return std::nullopt; +} + +// Allow mouse wheel scrolling to manipulate spinner widgets and tool sizes static bool WindowOtherWheelInput(WindowBase& w, WidgetIndex widgetIndex, int32_t wheel) { // HACK: Until we have a new window system that allows us to add new events like mouse wheel easily, // this selective approach will have to do. - // Allow mouse wheel scrolling to increment or decrement the land tool size for various windows - auto widgetType = w.widgets[widgetIndex].type; - - // Lower widgetIndex once or twice we got a type that matches, to allow scrolling on the increase/decrease buttons too - int32_t attempts = 0; - while (widgetType != WindowWidgetType::ImgBtn && widgetType != WindowWidgetType::Spinner && widgetIndex > 0) - { - switch (widgetType) - { - case WindowWidgetType::TrnBtn: // + and - for preview widget - case WindowWidgetType::Button: // + and - for spinner widget - { - if (attempts > 0) - { - // Verify that the previous button was of the same type - auto previousType = w.widgets[widgetIndex + 1].type; - if (previousType != widgetType) - { - return false; - } - } - break; - } - default: - // The widget type is not an increment or decrement button - return false; - } - - attempts++; - if (attempts > 2) - { - // We're 2 buttons up, and no preview or spinner widget was found - return false; - } - - widgetIndex--; - widgetType = w.widgets[widgetIndex].type; - } - - WidgetIndex buttonWidgetIndex; - WindowWidgetType expectedType; - - switch (widgetType) - { - case WindowWidgetType::ImgBtn: - { - auto expectedContent1 = ImageId(SPR_LAND_TOOL_DECREASE, FilterPaletteID::PaletteNull); - auto expectedContent2 = ImageId(SPR_LAND_TOOL_INCREASE, FilterPaletteID::PaletteNull); - - auto button1Image = w.widgets[widgetIndex + 1].image; - auto button2Image = w.widgets[widgetIndex + 2].image; - if (button1Image != expectedContent1 || button2Image != expectedContent2) - { - return false; - } - - buttonWidgetIndex = wheel < 0 ? widgetIndex + 2 : widgetIndex + 1; - expectedType = WindowWidgetType::TrnBtn; - break; - } - case WindowWidgetType::Spinner: - { - auto button1StringID = w.widgets[widgetIndex + 1].text; - auto button2StringID = w.widgets[widgetIndex + 2].text; - if (button1StringID != STR_NUMERIC_UP || button2StringID != STR_NUMERIC_DOWN) - { - return false; - } - - buttonWidgetIndex = wheel < 0 ? widgetIndex + 1 : widgetIndex + 2; - expectedType = WindowWidgetType::Button; - break; - } - default: - return false; - } - - if (WidgetIsDisabled(w, buttonWidgetIndex)) + const auto spinnerGroupIndex = getSpinnerGroupWidgetIndex(w, widgetIndex); + if (!spinnerGroupIndex.has_value()) { return false; } - auto button1Type = w.widgets[widgetIndex + 1].type; - auto button2Type = w.widgets[widgetIndex + 2].type; - if (button1Type != expectedType || button2Type != expectedType) + const auto entryWidgetType = w.widgets[*spinnerGroupIndex].type; + if (entryWidgetType == WindowWidgetType::ImgBtn) + { + auto expectedContent1 = ImageId(SPR_LAND_TOOL_DECREASE, FilterPaletteID::PaletteNull); + auto expectedContent2 = ImageId(SPR_LAND_TOOL_INCREASE, FilterPaletteID::PaletteNull); + + auto button1Image = w.widgets[*spinnerGroupIndex + 1].image; + auto button2Image = w.widgets[*spinnerGroupIndex + 2].image; + if (button1Image != expectedContent1 || button2Image != expectedContent2) + { + return false; + } + } + else if (entryWidgetType == WindowWidgetType::Spinner) + { + auto button1StringId = w.widgets[*spinnerGroupIndex + 1].text; + auto button2StringId = w.widgets[*spinnerGroupIndex + 2].text; + if (button1StringId != STR_NUMERIC_UP || button2StringId != STR_NUMERIC_DOWN) + { + return false; + } + } + + const auto targetWidgetIndex = wheel < 0 ? *spinnerGroupIndex + 1 : *spinnerGroupIndex + 2; + if (WidgetIsDisabled(w, targetWidgetIndex)) { return false; } - w.OnMouseDown(buttonWidgetIndex); + w.OnMouseDown(targetWidgetIndex); return true; } diff --git a/src/openrct2-ui/scripting/CustomWindow.cpp b/src/openrct2-ui/scripting/CustomWindow.cpp index b18c33da2e..42359855df 100644 --- a/src/openrct2-ui/scripting/CustomWindow.cpp +++ b/src/openrct2-ui/scripting/CustomWindow.cpp @@ -909,8 +909,8 @@ namespace OpenRCT2::Ui::Windows : _info.Desc.Tabs[page].Widgets[widgetDescIndex - tabWidgetsOffset]; auto preWidgetSize = widgetList.size(); CreateWidget(widgetList, widgetDesc); - auto numWidetsAdded = widgetList.size() - preWidgetSize; - for (size_t i = 0; i < numWidetsAdded; i++) + auto numWidgetsAdded = widgetList.size() - preWidgetSize; + for (size_t i = 0; i < numWidgetsAdded; i++) { _info.WidgetIndexMap.push_back(widgetDescIndex); }