mirror of https://github.com/OpenRCT2/OpenRCT2.git
Allow filtering in Scenery window (#19272)
* WIP: scenery searching * refactor snake case * actually start filtering scenery * prepare for merge from develop * use ObjectManager to get scenery info * clear selected scenery when it is filtered out * Clear tool when no scenery is selected * updating changelog * fix clang formatting issues
This commit is contained in:
parent
85b72c766e
commit
258b569deb
|
@ -17,6 +17,7 @@
|
||||||
- Improved: [#19131] Track missing objects when selecting scenery groups in console.
|
- Improved: [#19131] Track missing objects when selecting scenery groups in console.
|
||||||
- Improved: [#19253] Queue junctions drawn properly when using regular paths as queue.
|
- Improved: [#19253] Queue junctions drawn properly when using regular paths as queue.
|
||||||
- Improved: [#19067] New Ride window now allows filtering similarly to Object Selection.
|
- Improved: [#19067] New Ride window now allows filtering similarly to Object Selection.
|
||||||
|
- Improved: [#19272] Scenery window now allows filtering similarly to Object Selection.
|
||||||
- Change: [#19018] Renamed actions to fit the naming scheme.
|
- Change: [#19018] Renamed actions to fit the naming scheme.
|
||||||
- Change: [#19091] [Plugin] Add game action information to callback arguments of custom actions.
|
- Change: [#19091] [Plugin] Add game action information to callback arguments of custom actions.
|
||||||
- Change: [#19233] Reduce lift speed minimum and maximum values for “Classic Wooden Coaster”.
|
- Change: [#19233] Reduce lift speed minimum and maximum values for “Classic Wooden Coaster”.
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include <openrct2/object/FootpathItemEntry.h>
|
#include <openrct2/object/FootpathItemEntry.h>
|
||||||
#include <openrct2/object/LargeSceneryEntry.h>
|
#include <openrct2/object/LargeSceneryEntry.h>
|
||||||
#include <openrct2/object/ObjectList.h>
|
#include <openrct2/object/ObjectList.h>
|
||||||
|
#include <openrct2/object/ObjectManager.h>
|
||||||
|
#include <openrct2/object/ObjectRepository.h>
|
||||||
#include <openrct2/object/SmallSceneryEntry.h>
|
#include <openrct2/object/SmallSceneryEntry.h>
|
||||||
#include <openrct2/object/WallSceneryEntry.h>
|
#include <openrct2/object/WallSceneryEntry.h>
|
||||||
#include <openrct2/sprites.h>
|
#include <openrct2/sprites.h>
|
||||||
|
@ -32,6 +34,8 @@
|
||||||
#include <openrct2/world/Scenery.h>
|
#include <openrct2/world/Scenery.h>
|
||||||
#include <openrct2/world/SmallScenery.h>
|
#include <openrct2/world/SmallScenery.h>
|
||||||
|
|
||||||
|
using namespace OpenRCT2;
|
||||||
|
|
||||||
static constexpr const StringId WINDOW_TITLE = STR_NONE;
|
static constexpr const StringId WINDOW_TITLE = STR_NONE;
|
||||||
constexpr int32_t WINDOW_SCENERY_MIN_WIDTH = 634;
|
constexpr int32_t WINDOW_SCENERY_MIN_WIDTH = 634;
|
||||||
constexpr int32_t WINDOW_SCENERY_MIN_HEIGHT = 180;
|
constexpr int32_t WINDOW_SCENERY_MIN_HEIGHT = 180;
|
||||||
|
@ -56,6 +60,8 @@ enum WindowSceneryListWidgetIdx
|
||||||
WIDX_SCENERY_TERTIARY_COLOUR_BUTTON,
|
WIDX_SCENERY_TERTIARY_COLOUR_BUTTON,
|
||||||
WIDX_SCENERY_EYEDROPPER_BUTTON,
|
WIDX_SCENERY_EYEDROPPER_BUTTON,
|
||||||
WIDX_SCENERY_BUILD_CLUSTER_BUTTON,
|
WIDX_SCENERY_BUILD_CLUSTER_BUTTON,
|
||||||
|
WIDX_FILTER_TEXT_BOX,
|
||||||
|
WIDX_FILTER_CLEAR_BUTTON,
|
||||||
WIDX_SCENERY_TAB_1,
|
WIDX_SCENERY_TAB_1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,7 +73,7 @@ validate_global_widx(WC_SCENERY, WIDX_SCENERY_EYEDROPPER_BUTTON);
|
||||||
static Widget WindowSceneryBaseWidgets[] = {
|
static Widget WindowSceneryBaseWidgets[] = {
|
||||||
WINDOW_SHIM(WINDOW_TITLE, WINDOW_SCENERY_MIN_WIDTH, WINDOW_SCENERY_MIN_HEIGHT),
|
WINDOW_SHIM(WINDOW_TITLE, WINDOW_SCENERY_MIN_WIDTH, WINDOW_SCENERY_MIN_HEIGHT),
|
||||||
MakeWidget ({ 0, 43}, {634, 99}, WindowWidgetType::Resize, WindowColour::Secondary ), // 8 0x009DE2C8
|
MakeWidget ({ 0, 43}, {634, 99}, WindowWidgetType::Resize, WindowColour::Secondary ), // 8 0x009DE2C8
|
||||||
MakeWidget ({ 2, 47}, {607, 80}, WindowWidgetType::Scroll, WindowColour::Secondary, SCROLL_VERTICAL ), // 1000000 0x009DE418
|
MakeWidget ({ 2, 62}, {607, 80}, WindowWidgetType::Scroll, WindowColour::Secondary, SCROLL_VERTICAL ), // 1000000 0x009DE418
|
||||||
MakeWidget ({609, 44}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_ROTATE_ARROW), STR_ROTATE_OBJECTS_90 ), // 2000000 0x009DE428
|
MakeWidget ({609, 44}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_ROTATE_ARROW), STR_ROTATE_OBJECTS_90 ), // 2000000 0x009DE428
|
||||||
MakeWidget ({609, 68}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_PAINTBRUSH), STR_SCENERY_PAINTBRUSH_TIP ), // 4000000 0x009DE438
|
MakeWidget ({609, 68}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_PAINTBRUSH), STR_SCENERY_PAINTBRUSH_TIP ), // 4000000 0x009DE438
|
||||||
MakeWidget ({615, 93}, { 12, 12}, WindowWidgetType::ColourBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_SELECT_COLOUR ), // 8000000 0x009DE448
|
MakeWidget ({615, 93}, { 12, 12}, WindowWidgetType::ColourBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_SELECT_COLOUR ), // 8000000 0x009DE448
|
||||||
|
@ -75,6 +81,8 @@ static Widget WindowSceneryBaseWidgets[] = {
|
||||||
MakeWidget ({615, 117}, { 12, 12}, WindowWidgetType::ColourBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_SELECT_TERNARY_COLOUR ), // 20000000 0x009DE468
|
MakeWidget ({615, 117}, { 12, 12}, WindowWidgetType::ColourBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_SELECT_TERNARY_COLOUR ), // 20000000 0x009DE468
|
||||||
MakeWidget ({609, 130}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_G2_EYEDROPPER), STR_SCENERY_EYEDROPPER_TIP ), // 40000000 0x009DE478
|
MakeWidget ({609, 130}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_G2_EYEDROPPER), STR_SCENERY_EYEDROPPER_TIP ), // 40000000 0x009DE478
|
||||||
MakeWidget ({609, 154}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_SCENERY_CLUSTER), STR_SCENERY_CLUSTER_TIP ), // 40000000 0x009DE478
|
MakeWidget ({609, 154}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_SCENERY_CLUSTER), STR_SCENERY_CLUSTER_TIP ), // 40000000 0x009DE478
|
||||||
|
MakeWidget ({ 4, 46}, {211, 14}, WindowWidgetType::TextBox, WindowColour::Secondary ),
|
||||||
|
MakeWidget ({218, 46}, { 70, 14}, WindowWidgetType::Button, WindowColour::Secondary, STR_OBJECT_SEARCH_CLEAR ),
|
||||||
WIDGETS_END,
|
WIDGETS_END,
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
@ -134,12 +142,15 @@ private:
|
||||||
int32_t _requiredWidth;
|
int32_t _requiredWidth;
|
||||||
ScenerySelection _selectedScenery;
|
ScenerySelection _selectedScenery;
|
||||||
int16_t _hoverCounter;
|
int16_t _hoverCounter;
|
||||||
|
u8string _filter;
|
||||||
|
std::vector<ScenerySelection> _filteredScenery;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void OnOpen() override
|
void OnOpen() override
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
|
|
||||||
|
_filter.clear();
|
||||||
InitScrollWidgets();
|
InitScrollWidgets();
|
||||||
ContentUpdateScroll();
|
ContentUpdateScroll();
|
||||||
ShowGridlines();
|
ShowGridlines();
|
||||||
|
@ -227,6 +238,15 @@ public:
|
||||||
}
|
}
|
||||||
Invalidate();
|
Invalidate();
|
||||||
break;
|
break;
|
||||||
|
case WIDX_FILTER_TEXT_BOX:
|
||||||
|
WindowStartTextbox(*this, widgetIndex, STR_STRING, _filter.data(), MAX_PATH);
|
||||||
|
break;
|
||||||
|
case WIDX_FILTER_CLEAR_BUTTON:
|
||||||
|
_filter.clear();
|
||||||
|
ContentUpdateScroll();
|
||||||
|
scrolls->v_top = 0;
|
||||||
|
Invalidate();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,6 +411,12 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gCurrentTextBox.window.classification == classification && gCurrentTextBox.window.number == number)
|
||||||
|
{
|
||||||
|
WindowUpdateTextboxCaret();
|
||||||
|
WidgetInvalidate(*this, WIDX_FILTER_TEXT_BOX);
|
||||||
|
}
|
||||||
|
|
||||||
Invalidate();
|
Invalidate();
|
||||||
|
|
||||||
if (!SceneryToolIsActive())
|
if (!SceneryToolIsActive())
|
||||||
|
@ -434,8 +460,27 @@ public:
|
||||||
gCurrentToolId = static_cast<Tool>(GetSmallSceneryEntry(tabSelectedScenery.EntryIndex)->tool_id);
|
gCurrentToolId = static_cast<Tool>(GetSmallSceneryEntry(tabSelectedScenery.EntryIndex)->tool_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gCurrentToolId = Tool::Arrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnTextInput(WidgetIndex widgetIndex, std::string_view text) override
|
||||||
|
{
|
||||||
|
if (widgetIndex != WIDX_FILTER_TEXT_BOX)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (text == _filter)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_filter.assign(text);
|
||||||
|
ContentUpdateScroll();
|
||||||
|
|
||||||
|
scrolls->v_top = 0;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
ScreenSize OnScrollGetSize(int32_t scrollIndex) override
|
ScreenSize OnScrollGetSize(int32_t scrollIndex) override
|
||||||
{
|
{
|
||||||
|
@ -504,6 +549,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
widgets[WIDX_SCENERY_TITLE].text = titleStringId;
|
widgets[WIDX_SCENERY_TITLE].text = titleStringId;
|
||||||
|
widgets[WIDX_FILTER_TEXT_BOX].string = _filter.data();
|
||||||
|
|
||||||
pressed_widgets = 0;
|
pressed_widgets = 0;
|
||||||
pressed_widgets |= 1uLL << (tabIndex + WIDX_SCENERY_TAB_1);
|
pressed_widgets |= 1uLL << (tabIndex + WIDX_SCENERY_TAB_1);
|
||||||
|
@ -865,7 +911,7 @@ private:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto totalItems = _tabEntries[tabIndex].Entries.size();
|
const auto totalItems = _filteredScenery.size();
|
||||||
const auto numColumns = GetNumColumns();
|
const auto numColumns = GetNumColumns();
|
||||||
const auto rows = CountRows(totalItems + numColumns - 1);
|
const auto rows = CountRows(totalItems + numColumns - 1);
|
||||||
return rows;
|
return rows;
|
||||||
|
@ -884,6 +930,8 @@ private:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetFilteredScenery(tabIndex);
|
||||||
|
|
||||||
const int32_t listHeight = height - 14 - widgets[WIDX_SCENERY_LIST].top - 1;
|
const int32_t listHeight = height - 14 - widgets[WIDX_SCENERY_LIST].top - 1;
|
||||||
|
|
||||||
const auto sceneryItem = ContentCountRowsWithSelectedItem(tabIndex);
|
const auto sceneryItem = ContentCountRowsWithSelectedItem(tabIndex);
|
||||||
|
@ -893,13 +941,17 @@ private:
|
||||||
auto rowSelected = CountRows(sceneryItem.selected_item);
|
auto rowSelected = CountRows(sceneryItem.selected_item);
|
||||||
if (sceneryItem.scenerySelection.IsUndefined())
|
if (sceneryItem.scenerySelection.IsUndefined())
|
||||||
{
|
{
|
||||||
|
SetSelectedScenery(tabIndex, ScenerySelection());
|
||||||
rowSelected = 0;
|
rowSelected = 0;
|
||||||
const auto& scenery = _tabEntries[tabIndex].Entries[0];
|
if (!_filteredScenery.empty())
|
||||||
|
{
|
||||||
|
const auto& scenery = _filteredScenery[0];
|
||||||
if (!scenery.IsUndefined())
|
if (!scenery.IsUndefined())
|
||||||
{
|
{
|
||||||
SetSelectedScenery(tabIndex, scenery);
|
SetSelectedScenery(tabIndex, scenery);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scrolls[SceneryContentScrollIndex].v_top = ContentRowsHeight(rowSelected);
|
scrolls[SceneryContentScrollIndex].v_top = ContentRowsHeight(rowSelected);
|
||||||
scrolls[SceneryContentScrollIndex].v_top = std::min<int32_t>(maxTop, scrolls[SceneryContentScrollIndex].v_top);
|
scrolls[SceneryContentScrollIndex].v_top = std::min<int32_t>(maxTop, scrolls[SceneryContentScrollIndex].v_top);
|
||||||
|
@ -911,17 +963,16 @@ private:
|
||||||
{
|
{
|
||||||
SceneryItem sceneryItem = { 0, 0, ScenerySelection() };
|
SceneryItem sceneryItem = { 0, 0, ScenerySelection() };
|
||||||
const auto scenerySelection = GetSelectedScenery(tabIndex);
|
const auto scenerySelection = GetSelectedScenery(tabIndex);
|
||||||
const auto& tabInfo = _tabEntries[tabIndex];
|
for (size_t i = 0; i < _filteredScenery.size(); i++)
|
||||||
for (size_t i = 0; i < tabInfo.Entries.size(); i++)
|
|
||||||
{
|
{
|
||||||
const auto& currentEntry = tabInfo.Entries[i];
|
const auto& currentEntry = _filteredScenery[i];
|
||||||
if (currentEntry == scenerySelection)
|
if (currentEntry == scenerySelection)
|
||||||
{
|
{
|
||||||
sceneryItem.selected_item = static_cast<int32_t>(i);
|
sceneryItem.selected_item = static_cast<int32_t>(i);
|
||||||
sceneryItem.scenerySelection = scenerySelection;
|
sceneryItem.scenerySelection = scenerySelection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sceneryItem.allRows = static_cast<int32_t>(CountRows(tabInfo.Entries.size() + 8));
|
sceneryItem.allRows = static_cast<int32_t>(CountRows(_filteredScenery.size() + 8));
|
||||||
return sceneryItem;
|
return sceneryItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1004,6 +1055,56 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetFilteredScenery(const size_t tabIndex)
|
||||||
|
{
|
||||||
|
auto currentTab = _tabEntries[tabIndex];
|
||||||
|
|
||||||
|
_filteredScenery.clear();
|
||||||
|
for (auto selection : currentTab.Entries)
|
||||||
|
{
|
||||||
|
if (IsFiltered(selection))
|
||||||
|
_filteredScenery.push_back(selection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFiltered(const ScenerySelection& selection)
|
||||||
|
{
|
||||||
|
if (_filter.empty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
auto& objManager = GetContext()->GetObjectManager();
|
||||||
|
auto sceneryObjectType = GetObjectTypeFromSceneryType(selection.SceneryType);
|
||||||
|
auto sceneryObject = objManager.GetLoadedObject(sceneryObjectType, selection.EntryIndex);
|
||||||
|
|
||||||
|
return IsFilterInName(*sceneryObject) || IsFilterInAuthors(*sceneryObject) || IsFilterInIdentifier(*sceneryObject)
|
||||||
|
|| IsFilterInFilename(*sceneryObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFilterInName(const Object& object)
|
||||||
|
{
|
||||||
|
return String::Contains(object.GetName(), _filter, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFilterInAuthors(const Object& object)
|
||||||
|
{
|
||||||
|
for (auto author : object.GetAuthors())
|
||||||
|
if (String::Contains(author, _filter, true))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFilterInIdentifier(const Object& object)
|
||||||
|
{
|
||||||
|
return String::Contains(object.GetIdentifier(), _filter, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFilterInFilename(const Object& object)
|
||||||
|
{
|
||||||
|
auto repoItem = ObjectRepositoryFindObjectByEntry(&(object.GetObjectEntry()));
|
||||||
|
return String::Contains(repoItem->Path, _filter, true);
|
||||||
|
}
|
||||||
|
|
||||||
void SortTabs()
|
void SortTabs()
|
||||||
{
|
{
|
||||||
std::sort(_tabEntries.begin(), _tabEntries.end(), [](const SceneryTabInfo& a, const SceneryTabInfo& b) {
|
std::sort(_tabEntries.begin(), _tabEntries.end(), [](const SceneryTabInfo& a, const SceneryTabInfo& b) {
|
||||||
|
@ -1064,14 +1165,9 @@ private:
|
||||||
if (colIndex >= 0 && colIndex < numColumns && rowIndex >= 0)
|
if (colIndex >= 0 && colIndex < numColumns && rowIndex >= 0)
|
||||||
{
|
{
|
||||||
const auto tabSceneryIndex = static_cast<size_t>((rowIndex * numColumns) + colIndex);
|
const auto tabSceneryIndex = static_cast<size_t>((rowIndex * numColumns) + colIndex);
|
||||||
const auto tabIndex = _activeTabIndex;
|
if (tabSceneryIndex < _filteredScenery.size())
|
||||||
if (tabIndex < _tabEntries.size())
|
|
||||||
{
|
{
|
||||||
auto& tabInfo = _tabEntries[tabIndex];
|
return _filteredScenery[tabSceneryIndex];
|
||||||
if (tabSceneryIndex < tabInfo.Entries.size())
|
|
||||||
{
|
|
||||||
return tabInfo.Entries[tabSceneryIndex];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return scenery;
|
return scenery;
|
||||||
|
@ -1307,10 +1403,9 @@ private:
|
||||||
|
|
||||||
ScreenCoordsXY topLeft{ 0, 0 };
|
ScreenCoordsXY topLeft{ 0, 0 };
|
||||||
|
|
||||||
const auto& tabInfo = _tabEntries[tabIndex];
|
for (size_t sceneryTabItemIndex = 0; sceneryTabItemIndex < _filteredScenery.size(); sceneryTabItemIndex++)
|
||||||
for (size_t sceneryTabItemIndex = 0; sceneryTabItemIndex < tabInfo.Entries.size(); sceneryTabItemIndex++)
|
|
||||||
{
|
{
|
||||||
const auto& currentSceneryGlobal = tabInfo.Entries[sceneryTabItemIndex];
|
const auto& currentSceneryGlobal = _filteredScenery[sceneryTabItemIndex];
|
||||||
const auto tabSelectedScenery = GetSelectedScenery(tabIndex);
|
const auto tabSelectedScenery = GetSelectedScenery(tabIndex);
|
||||||
if (gWindowSceneryPaintEnabled == 1 || gWindowSceneryEyedropperEnabled)
|
if (gWindowSceneryPaintEnabled == 1 || gWindowSceneryEyedropperEnabled)
|
||||||
{
|
{
|
||||||
|
|
|
@ -419,7 +419,7 @@ enum WindowDetail
|
||||||
#define WC_MAZE_CONSTRUCTION__WIDX_MAZE_DIRECTION_GROUPBOX WC_RIDE_CONSTRUCTION__WIDX_CONSTRUCT
|
#define WC_MAZE_CONSTRUCTION__WIDX_MAZE_DIRECTION_GROUPBOX WC_RIDE_CONSTRUCTION__WIDX_CONSTRUCT
|
||||||
#define WC_MAZE_CONSTRUCTION__WIDX_MAZE_ENTRANCE WC_RIDE_CONSTRUCTION__WIDX_ENTRANCE
|
#define WC_MAZE_CONSTRUCTION__WIDX_MAZE_ENTRANCE WC_RIDE_CONSTRUCTION__WIDX_ENTRANCE
|
||||||
#define WC_MAZE_CONSTRUCTION__WIDX_MAZE_EXIT WC_RIDE_CONSTRUCTION__WIDX_EXIT
|
#define WC_MAZE_CONSTRUCTION__WIDX_MAZE_EXIT WC_RIDE_CONSTRUCTION__WIDX_EXIT
|
||||||
#define WC_SCENERY__WIDX_SCENERY_TAB_1 12
|
#define WC_SCENERY__WIDX_SCENERY_TAB_1 14
|
||||||
#define WC_SCENERY__WIDX_SCENERY_ROTATE_OBJECTS_BUTTON 5
|
#define WC_SCENERY__WIDX_SCENERY_ROTATE_OBJECTS_BUTTON 5
|
||||||
#define WC_SCENERY__WIDX_SCENERY_EYEDROPPER_BUTTON 10
|
#define WC_SCENERY__WIDX_SCENERY_EYEDROPPER_BUTTON 10
|
||||||
#define WC_PEEP__WIDX_PATROL 10
|
#define WC_PEEP__WIDX_PATROL 10
|
||||||
|
|
Loading…
Reference in New Issue