mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2025-12-23 15:52:55 +01:00
* Fix #24888: Add search for ride list * Cache ride name * Hide unwanted ride list entries rather than rebuilding the list * Minor touchups * Display count of filtered rides/stalls in ride list --------- Co-authored-by: Aaron van Geffen <aaron@aaronweb.net>
This commit is contained in:
committed by
GitHub
parent
1436d8ef2a
commit
b32d29330b
@@ -2,6 +2,7 @@
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
- Feature: [#24949] Add an option to the command line screenshot function to draw debug bounding boxes.
|
- Feature: [#24949] Add an option to the command line screenshot function to draw debug bounding boxes.
|
||||||
- Improved: [#24734] Save files now use Zstd compression for faster saving and smaller files.
|
- Improved: [#24734] Save files now use Zstd compression for faster saving and smaller files.
|
||||||
|
- Improved: [#24890] The ride list is now searchable.
|
||||||
- Improved: [#24893] The ride list now has headers, and can be sorted in both directions.
|
- Improved: [#24893] The ride list now has headers, and can be sorted in both directions.
|
||||||
- Improved: [#24921] The command line sprite build command now prints out the images table entry for the compiled sprite file.
|
- Improved: [#24921] The command line sprite build command now prints out the images table entry for the compiled sprite file.
|
||||||
- Improved: [#24953] Opening the Scenario Editor, Track Designer or Track Designs Manager now display the progress bar.
|
- Improved: [#24953] Opening the Scenario Editor, Track Designer or Track Designs Manager now display the progress bar.
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
WIDX_TAB_1,
|
WIDX_TAB_1,
|
||||||
WIDX_TAB_2,
|
WIDX_TAB_2,
|
||||||
WIDX_TAB_3,
|
WIDX_TAB_3,
|
||||||
|
WIDX_SEARCH_TEXT_BOX,
|
||||||
|
WIDX_SEARCH_CLEAR_BUTTON,
|
||||||
WIDX_HEADER_NAME,
|
WIDX_HEADER_NAME,
|
||||||
WIDX_HEADER_OTHER,
|
WIDX_HEADER_OTHER,
|
||||||
WIDX_HEADER_CUSTOMISE,
|
WIDX_HEADER_CUSTOMISE,
|
||||||
@@ -69,13 +71,15 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
makeTab ({ 3, 17}, STR_LIST_RIDES_TIP ), // tab 1
|
makeTab ({ 3, 17}, STR_LIST_RIDES_TIP ), // tab 1
|
||||||
makeTab ({ 34, 17}, STR_LIST_SHOPS_AND_STALLS_TIP ), // tab 2
|
makeTab ({ 34, 17}, STR_LIST_SHOPS_AND_STALLS_TIP ), // tab 2
|
||||||
makeTab ({ 65, 17}, STR_LIST_KIOSKS_AND_FACILITIES_TIP ), // tab 3
|
makeTab ({ 65, 17}, STR_LIST_KIOSKS_AND_FACILITIES_TIP ), // tab 3
|
||||||
makeWidget({ 3, 47}, {150, 14}, WidgetType::tableHeader, WindowColour::secondary ), // name header
|
makeWidget({ 3, 47}, {284, 14}, WidgetType::textBox, WindowColour::secondary ), // search text box
|
||||||
makeWidget({153, 47}, {147, 14}, WidgetType::tableHeader, WindowColour::secondary ), // other header
|
makeWidget({284, 47}, { 50, 14}, WidgetType::button, WindowColour::secondary, STR_OBJECT_SEARCH_CLEAR, STR_CLEAR_SCENERY_TIP ), // search clear button
|
||||||
makeWidget({300, 47}, { 14, 14}, WidgetType::button, WindowColour::secondary, STR_DROPDOWN_GLYPH ), // customise button
|
makeWidget({ 3, 62}, {150, 14}, WidgetType::tableHeader, WindowColour::secondary ), // name header
|
||||||
makeWidget({ 3, 60}, {334, 177}, WidgetType::scroll, WindowColour::secondary, SCROLL_VERTICAL ), // list
|
makeWidget({153, 62}, {147, 14}, WidgetType::tableHeader, WindowColour::secondary ), // other header
|
||||||
makeWidget({320, 62}, { 14, 14}, WidgetType::imgBtn, WindowColour::secondary, ImageId(SPR_G2_RCT1_CLOSE_BUTTON_0) ),
|
makeWidget({300, 62}, { 14, 14}, WidgetType::button, WindowColour::secondary, STR_DROPDOWN_GLYPH ), // customise button
|
||||||
makeWidget({320, 76}, { 14, 14}, WidgetType::imgBtn, WindowColour::secondary, ImageId(SPR_G2_RCT1_OPEN_BUTTON_0) ),
|
makeWidget({ 3, 75}, {334, 177}, WidgetType::scroll, WindowColour::secondary, SCROLL_VERTICAL ), // list
|
||||||
makeWidget({315, 90}, { 24, 24}, WidgetType::flatBtn, WindowColour::secondary, ImageId(SPR_DEMOLISH), STR_QUICK_DEMOLISH_RIDE )
|
makeWidget({320, 77}, { 14, 14}, WidgetType::imgBtn, WindowColour::secondary, ImageId(SPR_G2_RCT1_CLOSE_BUTTON_0) ),
|
||||||
|
makeWidget({320, 91}, { 14, 14}, WidgetType::imgBtn, WindowColour::secondary, ImageId(SPR_G2_RCT1_OPEN_BUTTON_0) ),
|
||||||
|
makeWidget({315,105}, { 24, 24}, WidgetType::flatBtn, WindowColour::secondary, ImageId(SPR_DEMOLISH), STR_QUICK_DEMOLISH_RIDE )
|
||||||
);
|
);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@@ -165,11 +169,13 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
bool _quickDemolishMode = false;
|
bool _quickDemolishMode = false;
|
||||||
InformationType _windowRideListInformationType = INFORMATION_TYPE_STATUS;
|
InformationType _windowRideListInformationType = INFORMATION_TYPE_STATUS;
|
||||||
bool _windowListSortDescending = false;
|
bool _windowListSortDescending = false;
|
||||||
|
u8string _searchFilter;
|
||||||
|
|
||||||
struct RideListEntry
|
struct RideListEntry
|
||||||
{
|
{
|
||||||
RideId Id;
|
RideId Id;
|
||||||
u8string Name;
|
u8string Name;
|
||||||
|
bool Visible;
|
||||||
};
|
};
|
||||||
std::vector<RideListEntry> _rideList;
|
std::vector<RideListEntry> _rideList;
|
||||||
|
|
||||||
@@ -188,6 +194,7 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
|
|
||||||
_windowRideListInformationType = INFORMATION_TYPE_STATUS;
|
_windowRideListInformationType = INFORMATION_TYPE_STATUS;
|
||||||
_quickDemolishMode = false;
|
_quickDemolishMode = false;
|
||||||
|
_searchFilter.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -257,6 +264,14 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
RefreshList();
|
RefreshList();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case WIDX_SEARCH_TEXT_BOX:
|
||||||
|
WindowStartTextbox(*this, widgetIndex, _searchFilter, kTextInputSize);
|
||||||
|
break;
|
||||||
|
case WIDX_SEARCH_CLEAR_BUTTON:
|
||||||
|
_searchFilter.clear();
|
||||||
|
ApplySearchQuery();
|
||||||
|
InvalidateWidget(WIDX_SEARCH_TEXT_BOX);
|
||||||
|
break;
|
||||||
case WIDX_CLOSE_LIGHT:
|
case WIDX_CLOSE_LIGHT:
|
||||||
CloseAllRides();
|
CloseAllRides();
|
||||||
break;
|
break;
|
||||||
@@ -399,13 +414,25 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
SortList();
|
SortList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnTextInput(WidgetIndex widgetIndex, std::string_view text) override
|
||||||
|
{
|
||||||
|
if (widgetIndex != WIDX_SEARCH_TEXT_BOX)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (text == _searchFilter)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_searchFilter.assign(text);
|
||||||
|
ApplySearchQuery();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* rct2: 0x006B35A1
|
* rct2: 0x006B35A1
|
||||||
*/
|
*/
|
||||||
ScreenSize OnScrollGetSize(int32_t scrollIndex) override
|
ScreenSize OnScrollGetSize(int32_t scrollIndex) override
|
||||||
{
|
{
|
||||||
const auto newHeight = static_cast<int32_t>(_rideList.size() * kScrollableRowHeight);
|
const auto newHeight = static_cast<int32_t>(CountVisibleItems() * kScrollableRowHeight);
|
||||||
auto top = std::max(0, newHeight - widgets[WIDX_LIST].bottom + widgets[WIDX_LIST].top + 21);
|
auto top = std::max(0, newHeight - widgets[WIDX_LIST].bottom + widgets[WIDX_LIST].top + 21);
|
||||||
if (top < scrolls[0].contentOffsetY)
|
if (top < scrolls[0].contentOffsetY)
|
||||||
{
|
{
|
||||||
@@ -416,14 +443,30 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
return { 0, newHeight };
|
return { 0, newHeight };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t GetNthVisibleItemIndex(int32_t target) const
|
||||||
|
{
|
||||||
|
auto j = 0;
|
||||||
|
for (auto i = 0u; i < _rideList.size(); i++)
|
||||||
|
{
|
||||||
|
if (!_rideList[i].Visible)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (j == target)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* rct2: 0x006B361F
|
* rct2: 0x006B361F
|
||||||
*/
|
*/
|
||||||
void OnScrollMouseDown(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override
|
void OnScrollMouseDown(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override
|
||||||
{
|
{
|
||||||
const auto index = screenCoords.y / kScrollableRowHeight;
|
const auto index = GetNthVisibleItemIndex(screenCoords.y / kScrollableRowHeight);
|
||||||
if (index < 0 || static_cast<size_t>(index) >= _rideList.size())
|
if (index < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Open ride window
|
// Open ride window
|
||||||
@@ -448,8 +491,8 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
*/
|
*/
|
||||||
void OnScrollMouseOver(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override
|
void OnScrollMouseOver(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override
|
||||||
{
|
{
|
||||||
const auto index = screenCoords.y / kScrollableRowHeight;
|
const auto index = GetNthVisibleItemIndex(screenCoords.y / kScrollableRowHeight);
|
||||||
if (index < 0 || static_cast<size_t>(index) >= _rideList.size())
|
if (index < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
selected_list_item = index;
|
selected_list_item = index;
|
||||||
@@ -480,6 +523,11 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
widgets[WIDX_LIST].right = width - 26;
|
widgets[WIDX_LIST].right = width - 26;
|
||||||
widgets[WIDX_LIST].bottom = height - 15;
|
widgets[WIDX_LIST].bottom = height - 15;
|
||||||
|
|
||||||
|
widgets[WIDX_SEARCH_CLEAR_BUTTON].right = widgets[WIDX_LIST].right - 1;
|
||||||
|
widgets[WIDX_SEARCH_CLEAR_BUTTON].left = widgets[WIDX_SEARCH_CLEAR_BUTTON].right - 40;
|
||||||
|
widgets[WIDX_SEARCH_TEXT_BOX].right = widgets[WIDX_SEARCH_CLEAR_BUTTON].left - 2;
|
||||||
|
widgets[WIDX_SEARCH_TEXT_BOX].string = _searchFilter.data();
|
||||||
|
|
||||||
widgets[WIDX_HEADER_CUSTOMISE].right = widgets[WIDX_LIST].right - 1;
|
widgets[WIDX_HEADER_CUSTOMISE].right = widgets[WIDX_LIST].right - 1;
|
||||||
widgets[WIDX_HEADER_CUSTOMISE].left = widgets[WIDX_HEADER_CUSTOMISE].right - 14;
|
widgets[WIDX_HEADER_CUSTOMISE].left = widgets[WIDX_HEADER_CUSTOMISE].right - 14;
|
||||||
|
|
||||||
@@ -570,7 +618,7 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
|
|
||||||
// Draw number of attractions on bottom
|
// Draw number of attractions on bottom
|
||||||
auto ft = Formatter();
|
auto ft = Formatter();
|
||||||
ft.Add<uint16_t>(static_cast<uint16_t>(_rideList.size()));
|
ft.Add<uint16_t>(static_cast<uint16_t>(CountVisibleItems()));
|
||||||
DrawTextBasic(
|
DrawTextBasic(
|
||||||
rt, windowPos + ScreenCoordsXY{ 4, widgets[WIDX_LIST].bottom + 2 }, ride_list_statusbar_count_strings[page],
|
rt, windowPos + ScreenCoordsXY{ 4, widgets[WIDX_LIST].bottom + 2 }, ride_list_statusbar_count_strings[page],
|
||||||
ft);
|
ft);
|
||||||
@@ -589,6 +637,9 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
auto y = 0;
|
auto y = 0;
|
||||||
for (size_t i = 0; i < _rideList.size(); i++)
|
for (size_t i = 0; i < _rideList.size(); i++)
|
||||||
{
|
{
|
||||||
|
if (!_rideList[i].Visible)
|
||||||
|
continue;
|
||||||
|
|
||||||
StringId format = STR_BLACK_STRING;
|
StringId format = STR_BLACK_STRING;
|
||||||
if (_quickDemolishMode)
|
if (_quickDemolishMode)
|
||||||
format = STR_RED_STRINGID;
|
format = STR_RED_STRINGID;
|
||||||
@@ -882,6 +933,28 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsFiltered(const u8string& rideName)
|
||||||
|
{
|
||||||
|
if (_searchFilter.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Check if the filter matches the ride name
|
||||||
|
return String::contains(u8string_view(rideName), _searchFilter, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplySearchQuery()
|
||||||
|
{
|
||||||
|
for (auto& entry : _rideList)
|
||||||
|
{
|
||||||
|
entry.Visible = IsFiltered(entry.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t CountVisibleItems() const
|
||||||
|
{
|
||||||
|
return std::count_if(_rideList.begin(), _rideList.end(), [](const RideListEntry& entry) { return entry.Visible; });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* rct2: 0x006B39A8
|
* rct2: 0x006B39A8
|
||||||
@@ -897,14 +970,19 @@ namespace OpenRCT2::Ui::Windows
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the ride name once and use it for both filtering and storage
|
||||||
|
auto rideName = rideRef.getName();
|
||||||
|
|
||||||
if (rideRef.windowInvalidateFlags & RIDE_INVALIDATE_RIDE_LIST)
|
if (rideRef.windowInvalidateFlags & RIDE_INVALIDATE_RIDE_LIST)
|
||||||
{
|
{
|
||||||
rideRef.windowInvalidateFlags &= ~RIDE_INVALIDATE_RIDE_LIST;
|
rideRef.windowInvalidateFlags &= ~RIDE_INVALIDATE_RIDE_LIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
RideListEntry entry{};
|
RideListEntry entry{
|
||||||
entry.Id = rideRef.id;
|
.Id = rideRef.id,
|
||||||
entry.Name = rideRef.getName();
|
.Name = std::move(rideName),
|
||||||
|
.Visible = IsFiltered(rideName),
|
||||||
|
};
|
||||||
|
|
||||||
_rideList.push_back(std::move(entry));
|
_rideList.push_back(std::move(entry));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user