Add "All Scenery" tab to scenery window

This commit is contained in:
Josh Trzebiatowski 2023-02-22 17:31:21 -06:00 committed by GitHub
parent d5b7569537
commit 04aeed8692
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 125 additions and 28 deletions

View File

@ -103,6 +103,7 @@ The following people are not part of the development team, but have been contrib
* (8street) - Misc.
* Umar Ahmed (umar-ahmed) - MacOS file watcher
* Andrew Arnold (fidwell) - Added window support for more scenery groups.
* Josh Trzebiatowski (trzejos) - Ride and scenery filtering
## Bug fixes
* (KirilAngelov)

View File

@ -3649,6 +3649,7 @@ STR_6543 :Contributors…
STR_6544 :Loan cannot be negative!
STR_6545 :Use RCT1 interest calculation
STR_6546 :Use the interest calculation algorithm of RollerCoaster Tycoon 1, which used a fixed percentage of approximately 1.33%.
STR_6547 :All Scenery
#############
# Scenarios #

View File

@ -5,6 +5,7 @@
- Feature: [#18732] [Plugin] API to get the guests thoughts.
- Feature: [#18744] Cheat to allow using a regular path as a queue path.
- Feature: [#19023] Add Canadian French translation.
- Feature: [#19341] Add "All Scenery" tab to scenery window.
- Feature: [#19378] Add command to combine CSG1i.DAT and CSG1.DAT.
- Feature: [objects#226] Port RCT1 Corkscrew Coaster train.
- Feature: [objects#229] Port RCT1 go karts with helmets.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -197,6 +197,10 @@
{
"path": "icons/rct1_simulate_on_pressed.png"
},
{
"path": "icons/infinity.png",
"palette": "keep"
},
{
"path": "tool/normal_selection_6x6.png",
"x_offset": 1,

View File

@ -42,10 +42,13 @@ constexpr int32_t WINDOW_SCENERY_MIN_WIDTH = 634;
constexpr int32_t WINDOW_SCENERY_MIN_HEIGHT = 195;
constexpr int32_t SCENERY_BUTTON_WIDTH = 66;
constexpr int32_t SCENERY_BUTTON_HEIGHT = 80;
constexpr int32_t InitTabPosX = 3;
constexpr int32_t InitTabPosY = 17;
constexpr int32_t TabWidth = 31;
constexpr int32_t TabHeight = 28;
constexpr int32_t MaxTabs = 257; // 255 selected tabs + misc + search
constexpr int32_t MaxTabsPerRow = 20;
constexpr int32_t ReservedTabCount = 2;
constexpr int32_t MaxTabs = 257; // 255 selected tabs + misc + all
constexpr int32_t MaxTabsPerRow = 19;
constexpr uint8_t SceneryContentScrollIndex = 0;
@ -104,6 +107,13 @@ bool gWindowSceneryEyedropperEnabled;
class SceneryWindow final : public Window
{
private:
enum SceneryTabType
{
SCENERY_TAB_TYPE_GROUP,
SCENERY_TAB_TYPE_MISC,
SCENERY_TAB_TYPE_ALL,
};
struct SceneryItem
{
int32_t allRows;
@ -113,13 +123,24 @@ private:
struct SceneryTabInfo
{
SceneryTabType Type = SCENERY_TAB_TYPE_GROUP;
ObjectEntryIndex SceneryGroupIndex = OBJECT_ENTRY_INDEX_NULL;
std::deque<ScenerySelection> Entries;
std::deque<ScenerySelection> Entries{};
u8string Filter = "";
bool IsMisc() const
{
return SceneryGroupIndex == OBJECT_ENTRY_INDEX_NULL;
return Type == SCENERY_TAB_TYPE_MISC;
}
bool IsAll() const
{
return Type == SCENERY_TAB_TYPE_ALL;
}
bool IsSceneryGroup() const
{
return Type == SCENERY_TAB_TYPE_GROUP;
}
bool Contains(const ScenerySelection& entry) const
@ -537,6 +558,13 @@ public:
return { fallback, ft };
}
if (tabInfo.IsAll())
{
auto ft = Formatter();
ft.Add<StringId>(STR_ALL_SCENERY);
return { fallback, ft };
}
const auto* sceneryEntry = tabInfo.GetSceneryGroupEntry();
if (sceneryEntry != nullptr)
{
@ -557,10 +585,17 @@ public:
if (tabIndex < _tabEntries.size())
{
const auto& tabInfo = _tabEntries[tabIndex];
const auto* sgEntry = tabInfo.GetSceneryGroupEntry();
if (sgEntry != nullptr)
if (tabInfo.IsAll())
{
titleStringId = sgEntry->name;
titleStringId = STR_ALL_SCENERY;
}
else
{
const auto* sgEntry = tabInfo.GetSceneryGroupEntry();
if (sgEntry != nullptr)
{
titleStringId = sgEntry->name;
}
}
}
widgets[WIDX_SCENERY_TITLE].text = titleStringId;
@ -684,6 +719,15 @@ public:
const auto lastTabIndex = GetMaxTabCountInARow() == MaxTabsPerRow ? MaxTabsPerRow - 1 : _tabEntries.size() - 1;
const auto lastTabWidget = &widgets[WIDX_SCENERY_TAB_1 + lastTabIndex];
windowWidth = std::max<int32_t>(windowWidth, lastTabWidget->right + 3);
if (_tabEntries.back().IsAll())
{
auto allTabWidget = &widgets[WIDX_SCENERY_TAB_1 + _tabEntries.size() - 1];
allTabWidget->left = windowWidth - TabWidth - 6;
allTabWidget->right = windowWidth - 7;
allTabWidget->top = InitTabPosY;
allTabWidget->bottom = InitTabPosY + TabHeight;
}
}
widgets[WIDX_SCENERY_BACKGROUND].right = windowWidth - 1;
@ -811,7 +855,7 @@ public:
{
_tabEntries.clear();
for (ObjectEntryIndex scenerySetIndex = 0; scenerySetIndex < MaxTabs - 1; scenerySetIndex++)
for (ObjectEntryIndex scenerySetIndex = 0; scenerySetIndex < MaxTabs - ReservedTabCount; scenerySetIndex++)
{
const auto* sceneryGroupEntry = OpenRCT2::ObjectManager::GetObjectEntry<SceneryGroupEntry>(scenerySetIndex);
if (sceneryGroupEntry != nullptr && SceneryGroupIsInvented(scenerySetIndex))
@ -832,8 +876,12 @@ public:
}
}
// Add misc tab
_tabEntries.emplace_back();
// Sort scenery group tabs before adding other tabs
SortTabs();
// Add misc and all tab
_tabEntries.emplace_back(SceneryWindow::SceneryTabInfo{ SCENERY_TAB_TYPE_MISC });
_tabEntries.emplace_back(SceneryWindow::SceneryTabInfo{ SCENERY_TAB_TYPE_ALL });
// small scenery
for (ObjectEntryIndex sceneryId = 0; sceneryId < MAX_SMALL_SCENERY_OBJECTS; sceneryId++)
@ -885,16 +933,15 @@ public:
}
}
// Remove misc tab if empty
if (_tabEntries.back().Entries.size() == 0)
{
_tabEntries.pop_back();
}
// Remove empty tabs
_tabEntries.erase(
std::remove_if(
_tabEntries.begin(), _tabEntries.end(), [](const SceneryTabInfo& tabInfo) { return tabInfo.Entries.empty(); }),
_tabEntries.end());
// Set required width
_requiredWidth = std::min(static_cast<int32_t>(_tabEntries.size()), MaxTabsPerRow) * TabWidth + 5;
SortTabs();
PrepareWidgets();
WindowInvalidateByClass(WindowClass::Scenery);
}
@ -1020,13 +1067,30 @@ private:
_tabSelections[tabIndex] = value;
}
SceneryTabInfo* GetSceneryTabInfoForGroup(const ObjectEntryIndex sceneryGroupIndex)
SceneryTabInfo* GetSceneryTabInfoForMisc()
{
if (sceneryGroupIndex == OBJECT_ENTRY_INDEX_NULL)
if (_tabEntries.size() >= 2)
{
return &_tabEntries[_tabEntries.size() - 1];
if (_tabEntries[_tabEntries.size() - 2].IsMisc())
return &_tabEntries[_tabEntries.size() - 2];
}
return nullptr;
}
SceneryTabInfo* GetSceneryTabInfoForAll()
{
if (!_tabEntries.empty())
{
if (_tabEntries.back().IsAll())
return &_tabEntries.back();
}
return nullptr;
}
SceneryTabInfo* GetSceneryTabInfoForGroup(const ObjectEntryIndex sceneryGroupIndex)
{
for (auto& tabEntry : _tabEntries)
{
if (tabEntry.SceneryGroupIndex == sceneryGroupIndex)
@ -1072,12 +1136,19 @@ private:
// If scenery is no tab, add it to misc
if (!tabIndex.has_value())
{
auto* tabInfo = GetSceneryTabInfoForGroup(OBJECT_ENTRY_INDEX_NULL);
auto* tabInfo = GetSceneryTabInfoForMisc();
if (tabInfo != nullptr)
{
tabInfo->AddEntryToBack(selection);
}
}
// Add all scenery to all tab
auto tabInfo = GetSceneryTabInfoForAll();
if (tabInfo != nullptr)
{
tabInfo->AddEntryToBack(selection);
}
}
}
@ -1177,19 +1248,35 @@ private:
// Add tabs
_actualMinHeight = WINDOW_SCENERY_MIN_HEIGHT;
int32_t xInit = 3;
int32_t xInit = InitTabPosX;
int32_t tabsInThisRow = 0;
ScreenCoordsXY pos = { xInit, 17 };
ScreenCoordsXY pos = { xInit, InitTabPosY };
for (const auto& tabInfo : _tabEntries)
{
auto widget = MakeTab(pos, STR_STRING_DEFINED_TOOLTIP);
pos.x += TabWidth;
if (tabInfo.SceneryGroupIndex == OBJECT_ENTRY_INDEX_NULL)
if (tabInfo.IsMisc())
{
widget.image = ImageId(SPR_TAB_QUESTION, FilterPaletteID::PaletteNull);
}
else if (tabInfo.IsAll())
{
widget.image = ImageId(SPR_TAB, FilterPaletteID::PaletteNull);
}
else if (tabInfo.IsSceneryGroup())
{
// Default tab image
widget.image = ImageId(SPR_TAB_QUESTION, FilterPaletteID::PaletteNull);
// Scenery Group image
auto scgEntry = tabInfo.GetSceneryGroupEntry();
if (scgEntry != nullptr)
{
widget.image = ImageId(scgEntry->image, colours[1]);
}
}
_widgets.push_back(widget);
@ -1362,12 +1449,12 @@ private:
for (size_t tabIndex = 0; tabIndex < _tabEntries.size(); tabIndex++)
{
auto widgetIndex = static_cast<WidgetIndex>(WIDX_SCENERY_TAB_1 + tabIndex);
auto scgEntry = _tabEntries[tabIndex].GetSceneryGroupEntry();
if (scgEntry != nullptr)
auto widgetCoordsXY = ScreenCoordsXY(widgets[widgetIndex].left, widgets[widgetIndex].top);
if (_tabEntries[tabIndex].IsAll())
{
auto imageOffset = tabIndex == _activeTabIndex ? 1 : 0;
auto imageId = ImageId(scgEntry->image + imageOffset, colours[1]);
GfxDrawSprite(&dpi, imageId, offset + ScreenCoordsXY{ widgets[widgetIndex].left, widgets[widgetIndex].top });
auto imageId = ImageId(SPR_G2_INFINITY, FilterPaletteID::PaletteNull);
GfxDrawSprite(&dpi, imageId, offset + widgetCoordsXY + ScreenCoordsXY(2, 6));
}
}
}

View File

@ -3943,6 +3943,7 @@ enum : uint16_t
STR_RCT1_INTEREST = 6545,
STR_RCT1_INTEREST_TIP = 6546,
STR_ALL_SCENERY = 6547,
// 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

View File

@ -84,6 +84,7 @@ namespace OpenRCT2::Scripting
{ "rct1_simulate_off_pressed", SPR_G2_RCT1_SIMULATE_BUTTON_1 },
{ "rct1_simulate_on", SPR_G2_RCT1_SIMULATE_BUTTON_2 },
{ "rct1_simulate_on_pressed", SPR_G2_RCT1_SIMULATE_BUTTON_3 },
{ "infinity", SPR_G2_INFINITY },
{ "normal_selection_6x6", SPR_G2_LAND_TOOL_SIZE_6 },
{ "mountain_tool_even", SPR_G2_MOUNTAIN_TOOL_EVEN },
{ "mountain_tool_odd", SPR_G2_MOUNTAIN_TOOL_ODD },

View File

@ -945,6 +945,7 @@ enum
SPR_G2_RCT1_SIMULATE_BUTTON_1,
SPR_G2_RCT1_SIMULATE_BUTTON_2,
SPR_G2_RCT1_SIMULATE_BUTTON_3,
SPR_G2_INFINITY,
SPR_G2_LAND_TOOL_SIZE_6,
SPR_G2_MOUNTAIN_TOOL_EVEN,
SPR_G2_MOUNTAIN_TOOL_ODD,