1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-20 06:12:57 +01:00

Refactor WindowOtherWheelInput to be safer and script window compatible

This commit is contained in:
Aaron van Geffen
2024-05-18 15:59:12 +02:00
parent 0eee7377f5
commit 57bdae9d49
3 changed files with 73 additions and 84 deletions

View File

@@ -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.

View File

@@ -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<WidgetIndex> 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;
}

View File

@@ -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);
}