Merge pull request #21681 from AaronVanGeffen/obj-list-refactor

Move various object list properties out of ObjectTypes header
This commit is contained in:
Michael Steenbeek 2024-04-12 11:54:13 +02:00 committed by GitHub
commit 271a22d00e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 129 additions and 103 deletions

View File

@ -19,6 +19,7 @@
#include <openrct2/localisation/Localisation.h>
#include <openrct2/management/Research.h>
#include <openrct2/object/DefaultObjects.h>
#include <openrct2/object/ObjectList.h>
#include <openrct2/object/ObjectManager.h>
#include <openrct2/object/ObjectRepository.h>
#include <openrct2/ride/RideData.h>
@ -82,10 +83,10 @@ static Widget _inventionListDragWidgets[] = {
static void ResearchRidesSetup()
{
// Reset all objects to not required
for (auto objectType : TransientObjectTypes)
for (auto objectType : getTransientObjectTypes())
{
auto maxObjects = object_entry_group_counts[EnumValue(objectType)];
for (int32_t i = 0; i < maxObjects; i++)
auto maxObjects = getObjectEntryGroupCount(objectType);
for (auto i = 0u; i < maxObjects; i++)
{
Editor::ClearSelectedObject(objectType, i, ObjectSelectionFlags::AllFlags);
}

View File

@ -1048,8 +1048,8 @@ static std::vector<Widget> _window_editor_object_selection_widgets = {
{
auto screenPos = windowPos + ScreenCoordsXY{ 3, height - 13 };
int32_t numSelected = _numSelectedObjectsForType[EnumValue(GetSelectedObjectType())];
int32_t totalSelectable = object_entry_group_counts[EnumValue(GetSelectedObjectType())];
auto numSelected = _numSelectedObjectsForType[EnumValue(GetSelectedObjectType())];
auto totalSelectable = getObjectEntryGroupCount(GetSelectedObjectType());
auto ft = Formatter();
ft.Add<uint16_t>(numSelected);

View File

@ -799,9 +799,9 @@ namespace OpenRCT2
private:
bool HasObjectsThatUseFallbackImages()
{
for (auto objectType : ObjectTypes)
for (auto objectType : getAllObjectTypes())
{
auto maxObjectsOfType = static_cast<ObjectEntryIndex>(object_entry_group_counts[EnumValue(objectType)]);
auto maxObjectsOfType = static_cast<ObjectEntryIndex>(getObjectEntryGroupCount(objectType));
for (ObjectEntryIndex i = 0; i < maxObjectsOfType; i++)
{
auto obj = _objectManager->GetLoadedObject(objectType, i);

View File

@ -562,7 +562,7 @@ namespace Editor
{
if (index != OBJECT_ENTRY_INDEX_NULL)
{
assert(static_cast<int32_t>(objectType) < object_entry_group_counts[EnumValue(ObjectType::Paths)]);
assert(index < getObjectEntryGroupCount(ObjectType::Paths));
auto& list = _editorSelectedObjectFlags[EnumValue(objectType)];
if (list.size() <= index)
{

View File

@ -36,7 +36,7 @@
std::optional<StringId> _gSceneryGroupPartialSelectError;
std::vector<uint8_t> _objectSelectionFlags;
int32_t _numSelectedObjectsForType[EnumValue(ObjectType::Count)];
uint32_t _numSelectedObjectsForType[EnumValue(ObjectType::Count)];
static int32_t _numAvailableObjectsForType[EnumValue(ObjectType::Count)];
static void SetupInUseSelectionFlags();
@ -125,9 +125,9 @@ void SetupInUseSelectionFlags()
{
auto& objectMgr = OpenRCT2::GetContext()->GetObjectManager();
for (auto objectType : TransientObjectTypes)
for (auto objectType : getTransientObjectTypes())
{
for (int32_t i = 0; i < object_entry_group_counts[EnumValue(objectType)]; i++)
for (auto i = 0u; i < getObjectEntryGroupCount(objectType); i++)
{
Editor::ClearSelectedObject(static_cast<ObjectType>(objectType), i, ObjectSelectionFlags::AllFlags);
@ -580,7 +580,7 @@ ResultWithMessage WindowEditorObjectSelectionSelectObject(
}
ObjectType objectType = item->Type;
uint16_t maxObjects = object_entry_group_counts[EnumValue(objectType)];
auto maxObjects = getObjectEntryGroupCount(objectType);
if (maxObjects <= _numSelectedObjectsForType[EnumValue(objectType)])
{

View File

@ -27,7 +27,7 @@ enum EDITOR_INPUT_FLAGS
extern std::optional<StringId> _gSceneryGroupPartialSelectError;
extern std::vector<uint8_t> _objectSelectionFlags;
extern int32_t _numSelectedObjectsForType[EnumValue(ObjectType::Count)];
extern uint32_t _numSelectedObjectsForType[EnumValue(ObjectType::Count)];
bool EditorCheckObjectGroupAtLeastOneSelected(ObjectType checkObjectType);
bool EditorCheckObjectGroupAtLeastOneSurfaceSelected(bool queue);

View File

@ -1312,10 +1312,10 @@ static_assert(_objectTypeNames.size() == EnumValue(ObjectType::Count));
static int32_t ConsoleCommandCountObjects(InteractiveConsole& console, [[maybe_unused]] const arguments_t& argv)
{
for (auto objectType : ObjectTypes)
for (auto objectType : getAllObjectTypes())
{
int32_t entryGroupIndex = 0;
for (; entryGroupIndex < object_entry_group_counts[EnumValue(objectType)]; entryGroupIndex++)
uint32_t entryGroupIndex = 0;
for (; entryGroupIndex < getObjectEntryGroupCount(objectType); entryGroupIndex++)
{
if (ObjectEntryGetObject(objectType, entryGroupIndex) == nullptr)
{
@ -1323,8 +1323,7 @@ static int32_t ConsoleCommandCountObjects(InteractiveConsole& console, [[maybe_u
}
}
console.WriteFormatLine(
"%s: %d/%d", _objectTypeNames[EnumValue(objectType)], entryGroupIndex,
object_entry_group_counts[EnumValue(objectType)]);
"%s: %d/%d", _objectTypeNames[EnumValue(objectType)], entryGroupIndex, getObjectEntryGroupCount(objectType));
}
return 0;

View File

@ -342,9 +342,6 @@ public:
# pragma GCC diagnostic pop
#endif
extern int32_t object_entry_group_counts[];
extern int32_t object_entry_group_encoding[];
int32_t ObjectCalculateChecksum(const RCTObjectEntry* entry, const void* data, size_t dataLength);
void ObjectCreateIdentifierName(char* string_buffer, size_t size, const RCTObjectEntry* object);

View File

@ -14,6 +14,7 @@
#include "../object/Object.h"
#include "../util/SawyerCoding.h"
#include "../util/Util.h"
#include "ObjectLimits.h"
#include "ObjectManager.h"
#include "ObjectRepository.h"
@ -21,8 +22,8 @@
#include <array>
#include <cstring>
// 98DA00
int32_t object_entry_group_counts[] = {
// 0x0098DA00
static constexpr std::array<int32_t, EnumValue(ObjectType::Count)> kObjectEntryGroupCounts = {
MAX_RIDE_OBJECTS, // rides
MAX_SMALL_SCENERY_OBJECTS, // small scenery
MAX_LARGE_SCENERY_OBJECTS, // large scenery
@ -42,24 +43,20 @@ int32_t object_entry_group_counts[] = {
MAX_FOOTPATH_RAILINGS_OBJECTS,
MAX_AUDIO_OBJECTS,
};
static_assert(std::size(object_entry_group_counts) == EnumValue(ObjectType::Count));
static_assert(std::size(kObjectEntryGroupCounts) == EnumValue(ObjectType::Count));
// 98DA2C
// clang-format off
int32_t object_entry_group_encoding[] = {
CHUNK_ENCODING_RLE,
CHUNK_ENCODING_RLE,
CHUNK_ENCODING_RLE,
CHUNK_ENCODING_RLE,
CHUNK_ENCODING_RLE,
CHUNK_ENCODING_RLE,
CHUNK_ENCODING_RLE,
CHUNK_ENCODING_RLE,
CHUNK_ENCODING_RLE,
CHUNK_ENCODING_RLE,
CHUNK_ENCODING_ROTATE,
};
// clang-format on
size_t getObjectEntryGroupCount(ObjectType objectType)
{
return kObjectEntryGroupCounts[EnumValue(objectType)];
}
size_t getObjectTypeLimit(ObjectType type)
{
auto index = EnumValue(type);
if (index >= EnumValue(ObjectType::Count))
return 0;
return static_cast<size_t>(kObjectEntryGroupCounts[index]);
}
ObjectList::const_iterator::const_iterator(const ObjectList* parent, bool end)
{
@ -203,7 +200,7 @@ void ObjectCreateIdentifierName(char* string_buffer, size_t size, const RCTObjec
void ObjectGetTypeEntryIndex(size_t index, ObjectType* outObjectType, ObjectEntryIndex* outEntryIndex)
{
uint8_t objectType = EnumValue(ObjectType::Ride);
for (size_t groupCount : object_entry_group_counts)
for (size_t groupCount : kObjectEntryGroupCounts)
{
if (index >= groupCount)
{

View File

@ -10,7 +10,6 @@
#pragma once
#include "Object.h"
#include "ObjectLimits.h"
#include <vector>
@ -51,3 +50,6 @@ public:
};
void ObjectGetTypeEntryIndex(size_t index, ObjectType* outObjectType, ObjectEntryIndex* outEntryIndex);
size_t getObjectEntryGroupCount(ObjectType objectType);
size_t getObjectTypeLimit(ObjectType type);

View File

@ -21,6 +21,7 @@
#include "BannerSceneryEntry.h"
#include "LargeSceneryObject.h"
#include "Object.h"
#include "ObjectLimits.h"
#include "ObjectList.h"
#include "ObjectRepository.h"
#include "PathAdditionObject.h"
@ -79,7 +80,7 @@ public:
return nullptr;
}
if (index >= static_cast<size_t>(object_entry_group_counts[EnumValue(objectType)]))
if (index >= static_cast<size_t>(getObjectEntryGroupCount(objectType)))
{
#ifdef DEBUG
if (index != OBJECT_ENTRY_INDEX_NULL)
@ -142,9 +143,9 @@ public:
ObjectList GetLoadedObjects() override
{
ObjectList objectList;
for (auto objectType : ObjectTypes)
for (auto objectType : getAllObjectTypes())
{
auto maxObjectsOfType = static_cast<ObjectEntryIndex>(object_entry_group_counts[EnumValue(objectType)]);
auto maxObjectsOfType = static_cast<ObjectEntryIndex>(getObjectEntryGroupCount(objectType));
for (ObjectEntryIndex i = 0; i < maxObjectsOfType; i++)
{
auto obj = GetLoadedObject(objectType, i);
@ -311,7 +312,7 @@ private:
void UnloadAll(bool onlyTransient)
{
for (auto type : ObjectTypes)
for (auto type : getAllObjectTypes())
{
if (!onlyTransient || !IsIntransientObjectType(type))
{
@ -384,7 +385,7 @@ private:
return static_cast<ObjectEntryIndex>(std::distance(list.begin(), it));
}
auto maxSize = object_entry_group_counts[EnumValue(objectType)];
auto maxSize = getObjectEntryGroupCount(objectType);
if (list.size() < static_cast<size_t>(maxSize))
{
list.emplace_back();
@ -442,7 +443,7 @@ private:
// Unload objects that are not in the hash set
size_t totalObjectsLoaded = 0;
size_t numObjectsUnloaded = 0;
for (auto type : ObjectTypes)
for (auto type : getAllObjectTypes())
{
if (!IsIntransientObjectType(type))
{
@ -521,10 +522,10 @@ private:
std::vector<ObjectToLoad> requiredObjects;
std::vector<ObjectEntryDescriptor> missingObjects;
for (auto objectType : ObjectTypes)
for (auto objectType : getAllObjectTypes())
{
auto& descriptors = objectList.GetList(objectType);
auto maxSize = static_cast<size_t>(object_entry_group_counts[EnumValue(objectType)]);
auto maxSize = static_cast<size_t>(getObjectEntryGroupCount(objectType));
auto listSize = static_cast<ObjectEntryIndex>(std::min(descriptors.size(), maxSize));
for (ObjectEntryIndex i = 0; i < listSize; i++)
{
@ -672,7 +673,7 @@ private:
}
// Set the new object lists
for (auto type : ObjectTypes)
for (auto type : getAllObjectTypes())
{
if (!IsIntransientObjectType(type))
{
@ -724,7 +725,7 @@ private:
}
// Build object lists
const auto maxRideObjects = static_cast<size_t>(object_entry_group_counts[EnumValue(ObjectType::Ride)]);
const auto maxRideObjects = static_cast<size_t>(getObjectEntryGroupCount(ObjectType::Ride));
for (size_t i = 0; i < maxRideObjects; i++)
{
auto* rideObject = static_cast<RideObject*>(GetLoadedObject(ObjectType::Ride, i));

View File

@ -470,6 +470,13 @@ private:
}
}
// 0x0098DA2C
static constexpr std::array<int32_t, 11> kLegacyObjectEntryGroupEncoding = {
CHUNK_ENCODING_RLE, CHUNK_ENCODING_RLE, CHUNK_ENCODING_RLE, CHUNK_ENCODING_RLE,
CHUNK_ENCODING_RLE, CHUNK_ENCODING_RLE, CHUNK_ENCODING_RLE, CHUNK_ENCODING_RLE,
CHUNK_ENCODING_RLE, CHUNK_ENCODING_RLE, CHUNK_ENCODING_ROTATE,
};
static void SaveObject(
std::string_view path, const RCTObjectEntry* entry, const void* data, size_t dataSize, bool fixChecksum = true)
{
@ -525,7 +532,7 @@ private:
// Encode data
ObjectType objectType = entry->GetType();
SawyerCodingChunkHeader chunkHeader;
chunkHeader.encoding = object_entry_group_encoding[EnumValue(objectType)];
chunkHeader.encoding = kLegacyObjectEntryGroupEncoding[EnumValue(objectType)];
chunkHeader.length = static_cast<uint32_t>(dataSize);
uint8_t* encodedDataBuffer = Memory::Allocate<uint8_t>(0x600000);
size_t encodedDataSize = SawyerCodingWriteChunkBuffer(

View File

@ -7,24 +7,73 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "ObjectTypes.h"
#include "../util/Util.h"
#include "Object.h"
#include <algorithm>
constexpr std::array kAllObjectTypes = {
ObjectType::Ride,
ObjectType::SmallScenery,
ObjectType::LargeScenery,
ObjectType::Walls,
ObjectType::Banners,
ObjectType::Paths,
ObjectType::PathAdditions,
ObjectType::SceneryGroup,
ObjectType::ParkEntrance,
ObjectType::Water,
ObjectType::ScenarioText,
ObjectType::TerrainSurface,
ObjectType::TerrainEdge,
ObjectType::Station,
ObjectType::Music,
ObjectType::FootpathSurface,
ObjectType::FootpathRailings,
ObjectType::Audio,
};
static_assert(kAllObjectTypes.size() == EnumValue(ObjectType::Count));
// Object types that can be saved in a park file.
static constexpr std::array<const ObjectType, kNumTransientObjectTypes> kTransientObjectTypes = {
ObjectType::Ride, ObjectType::SmallScenery, ObjectType::LargeScenery, ObjectType::Walls,
ObjectType::Banners, ObjectType::Paths, ObjectType::PathAdditions, ObjectType::SceneryGroup,
ObjectType::ParkEntrance, ObjectType::Water, ObjectType::TerrainSurface, ObjectType::TerrainEdge,
ObjectType::Station, ObjectType::Music, ObjectType::FootpathSurface, ObjectType::FootpathRailings,
};
// Object types that cannot be saved in a park file.
static constexpr std::array<const ObjectType, kNumIntransientObjectTypes> kIntransientObjectTypes = {
ObjectType::ScenarioText,
ObjectType::Audio,
};
static_assert(kNumTransientObjectTypes + kNumIntransientObjectTypes == static_cast<size_t>(ObjectType::Count));
bool ObjectTypeIsTransient(ObjectType type)
{
return std::find(TransientObjectTypes.begin(), TransientObjectTypes.end(), type) != std::end(TransientObjectTypes);
return std::find(kTransientObjectTypes.begin(), kTransientObjectTypes.end(), type) != std::end(kTransientObjectTypes);
}
bool ObjectTypeIsIntransient(ObjectType type)
{
return std::find(IntransientObjectTypes.begin(), IntransientObjectTypes.end(), type) != std::end(IntransientObjectTypes);
return std::find(kIntransientObjectTypes.begin(), kIntransientObjectTypes.end(), type) != std::end(kIntransientObjectTypes);
}
size_t GetObjectTypeLimit(ObjectType type)
std::span<const ObjectType> getAllObjectTypes()
{
auto index = EnumValue(type);
if (index >= EnumValue(ObjectType::Count))
return 0;
return static_cast<size_t>(object_entry_group_counts[index]);
return kAllObjectTypes;
}
std::span<const ObjectType> getTransientObjectTypes()
{
return kTransientObjectTypes;
}
std::span<const ObjectType> getIntransientObjectTypes()
{
return kIntransientObjectTypes;
}

View File

@ -13,6 +13,7 @@
#include <cstddef>
#include <cstdint>
#include <limits>
#include <span>
using ObjectEntryIndex = uint16_t;
constexpr ObjectEntryIndex OBJECT_ENTRY_INDEX_NULL = std::numeric_limits<ObjectEntryIndex>::max();
@ -43,40 +44,12 @@ enum class ObjectType : uint8_t
None = 255
};
constexpr std::array ObjectTypes = {
ObjectType::Ride,
ObjectType::SmallScenery,
ObjectType::LargeScenery,
ObjectType::Walls,
ObjectType::Banners,
ObjectType::Paths,
ObjectType::PathAdditions,
ObjectType::SceneryGroup,
ObjectType::ParkEntrance,
ObjectType::Water,
ObjectType::ScenarioText,
ObjectType::TerrainSurface,
ObjectType::TerrainEdge,
ObjectType::Station,
ObjectType::Music,
ObjectType::FootpathSurface,
ObjectType::FootpathRailings,
ObjectType::Audio,
};
// Not using EnumValue to reduce header includes
static_assert(ObjectTypes.size() == static_cast<uint8_t>(ObjectType::Count));
// Object types that can be saved in a park file.
constexpr std::array<ObjectType, 16> TransientObjectTypes = {
ObjectType::Ride, ObjectType::SmallScenery, ObjectType::LargeScenery, ObjectType::Walls,
ObjectType::Banners, ObjectType::Paths, ObjectType::PathAdditions, ObjectType::SceneryGroup,
ObjectType::ParkEntrance, ObjectType::Water, ObjectType::TerrainSurface, ObjectType::TerrainEdge,
ObjectType::Station, ObjectType::Music, ObjectType::FootpathSurface, ObjectType::FootpathRailings,
};
// Object types that cannot be saved in a park file.
constexpr std::array<ObjectType, 2> IntransientObjectTypes = { ObjectType::ScenarioText, ObjectType::Audio };
static constexpr size_t kNumTransientObjectTypes = 16;
static constexpr size_t kNumIntransientObjectTypes = 2;
bool ObjectTypeIsTransient(ObjectType type);
bool ObjectTypeIsIntransient(ObjectType type);
size_t GetObjectTypeLimit(ObjectType type);
std::span<const ObjectType> getAllObjectTypes();
std::span<const ObjectType> getTransientObjectTypes();
std::span<const ObjectType> getIntransientObjectTypes();

View File

@ -382,8 +382,8 @@ namespace OpenRCT2
auto objectList = objManager.GetLoadedObjects();
// Write number of object sub lists
cs.Write(static_cast<uint16_t>(TransientObjectTypes.size()));
for (auto objectType : TransientObjectTypes)
cs.Write(static_cast<uint16_t>(getTransientObjectTypes().size()));
for (auto objectType : getTransientObjectTypes())
{
// Write sub list
const auto& list = objectList.GetList(objectType);

View File

@ -568,7 +568,7 @@ namespace RCT1
RCT12::EntryList* entries = GetEntryList(objectType);
// Check if there are spare entries available
size_t maxEntries = static_cast<size_t>(object_entry_group_counts[EnumValue(objectType)]);
size_t maxEntries = static_cast<size_t>(getObjectEntryGroupCount(objectType));
if (entries != nullptr && entries->GetCount() < maxEntries)
{
entries->GetOrAddEntry(objectName);

View File

@ -257,7 +257,7 @@ const RideObjectEntry* GetRideEntryByIndex(ObjectEntryIndex index)
std::string_view GetRideEntryName(ObjectEntryIndex index)
{
if (index >= object_entry_group_counts[EnumValue(ObjectType::Ride)])
if (index >= getObjectEntryGroupCount(ObjectType::Ride))
{
LOG_ERROR("invalid index %d for ride type", index);
return {};

View File

@ -106,7 +106,7 @@ DukValue ScObjectManager::load(const DukValue& p1, const DukValue& p2)
throw DukException() << "Expected number for 'index'.";
auto index = static_cast<size_t>(p2.as_int());
auto limit = GetObjectTypeLimit(installedObject->Type);
auto limit = getObjectTypeLimit(installedObject->Type);
if (index < limit)
{
auto loadedObject = objectManager.GetLoadedObject(installedObject->Type, index);
@ -214,8 +214,8 @@ std::vector<DukValue> ScObjectManager::getAllObjects(const std::string& typez) c
auto type = ScObject::StringToObjectType(typez);
if (type)
{
auto count = object_entry_group_counts[EnumValue(*type)];
for (int32_t i = 0; i < count; i++)
auto count = getObjectEntryGroupCount(*type);
for (auto i = 0u; i < count; i++)
{
auto obj = objManager.GetLoadedObject(*type, i);
if (obj != nullptr)

View File

@ -18,8 +18,8 @@
#include "../core/String.hpp"
#include "../localisation/Localisation.h"
#include "../localisation/StringIds.h"
#include "../object/Object.h"
#include "../object/ObjectEntryManager.h"
#include "../object/ObjectList.h"
#include "../object/ObjectManager.h"
#include "../object/SmallSceneryEntry.h"
#include "../object/TerrainEdgeObject.h"
@ -311,7 +311,7 @@ static void MapGenPlaceTrees()
std::vector<int32_t> desertTreeIds;
std::vector<int32_t> snowTreeIds;
for (int32_t i = 0; i < object_entry_group_counts[EnumValue(ObjectType::SmallScenery)]; i++)
for (auto i = 0u; i < getObjectEntryGroupCount(ObjectType::SmallScenery); i++)
{
auto* sceneryEntry = OpenRCT2::ObjectManager::GetObjectEntry<SmallSceneryEntry>(i);
auto entry = ObjectEntryGetObject(ObjectType::SmallScenery, i);