mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-20 14:23:08 +01:00
Refactor WindowOtherWheelInput to be safer and script window compatible
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
const auto spinnerGroupIndex = getSpinnerGroupWidgetIndex(w, widgetIndex);
|
||||
if (!spinnerGroupIndex.has_value())
|
||||
{
|
||||
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:
|
||||
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[widgetIndex + 1].image;
|
||||
auto button2Image = w.widgets[widgetIndex + 2].image;
|
||||
auto button1Image = w.widgets[*spinnerGroupIndex + 1].image;
|
||||
auto button2Image = w.widgets[*spinnerGroupIndex + 2].image;
|
||||
if (button1Image != expectedContent1 || button2Image != expectedContent2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
buttonWidgetIndex = wheel < 0 ? widgetIndex + 2 : widgetIndex + 1;
|
||||
expectedType = WindowWidgetType::TrnBtn;
|
||||
break;
|
||||
}
|
||||
case WindowWidgetType::Spinner:
|
||||
else if (entryWidgetType == 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)
|
||||
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;
|
||||
}
|
||||
|
||||
buttonWidgetIndex = wheel < 0 ? widgetIndex + 1 : widgetIndex + 2;
|
||||
expectedType = WindowWidgetType::Button;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (WidgetIsDisabled(w, buttonWidgetIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto button1Type = w.widgets[widgetIndex + 1].type;
|
||||
auto button2Type = w.widgets[widgetIndex + 2].type;
|
||||
if (button1Type != expectedType || button2Type != expectedType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
w.OnMouseDown(buttonWidgetIndex);
|
||||
w.OnMouseDown(targetWidgetIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user