Use std::vector for ObjectManager

This commit is contained in:
Ted John 2018-02-11 22:49:11 +00:00
parent 7e01dcdaaf
commit 0433803ae1
1 changed files with 90 additions and 133 deletions

View File

@ -35,8 +35,8 @@
class ObjectManager final : public IObjectManager
{
private:
IObjectRepository * _objectRepository;
Object * * _loadedObjects = nullptr;
IObjectRepository * _objectRepository;
std::vector<Object *> _loadedObjects;
public:
explicit ObjectManager(IObjectRepository * objectRepository)
@ -44,11 +44,7 @@ public:
Guard::ArgumentNotNull(objectRepository);
_objectRepository = objectRepository;
_loadedObjects = Memory::AllocateArray<Object *>(OBJECT_ENTRY_COUNT);
for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++)
{
_loadedObjects[i] = nullptr;
}
_loadedObjects.resize(OBJECT_ENTRY_COUNT);
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
@ -56,7 +52,7 @@ public:
~ObjectManager() override
{
SetNewLoadedObjectList(nullptr);
UnloadAll();
}
Object * GetLoadedObject(size_t index) override
@ -68,7 +64,7 @@ public:
#endif
return nullptr;
}
if (_loadedObjects == nullptr)
if (index >= _loadedObjects.size())
{
return nullptr;
}
@ -131,6 +127,10 @@ public:
loadedObject = GetOrLoadObject(ori);
if (loadedObject != nullptr)
{
if (_loadedObjects.size() <= (size_t)slot)
{
_loadedObjects.resize(slot + 1);
}
_loadedObjects[slot] = loadedObject;
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
@ -144,31 +144,28 @@ public:
bool LoadObjects(const rct_object_entry * entries, size_t count) override
{
// Find all the required objects
size_t numRequiredObjects;
auto requiredObjects = new const ObjectRepositoryItem *[OBJECT_ENTRY_COUNT];
if (!GetRequiredObjects(entries, requiredObjects, &numRequiredObjects))
bool missingObjects;
auto requiredObjects = GetRequiredObjects(entries, &missingObjects);
if (missingObjects)
{
delete[] requiredObjects;
return false;
}
// Create a new list of loaded objects
size_t numNewLoadedObjects;
Object * * loadedObjects = LoadObjects(requiredObjects, &numNewLoadedObjects);
size_t numNewLoadedObjects = 0;
auto loadedObjects = LoadObjects(requiredObjects, &numNewLoadedObjects);
delete[] requiredObjects;
if (loadedObjects == nullptr)
if (!std::get<0>(loadedObjects))
{
UnloadAll();
return false;
}
else
{
SetNewLoadedObjectList(loadedObjects);
SetNewLoadedObjectList(std::get<1>(loadedObjects));
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
log_verbose("%u / %u new objects loaded", numNewLoadedObjects, numRequiredObjects);
log_verbose("%u / %u new objects loaded", numNewLoadedObjects, requiredObjects.size());
return true;
}
}
@ -204,12 +201,9 @@ public:
void UnloadAll() override
{
if (_loadedObjects != nullptr)
for (auto object : _loadedObjects)
{
for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++)
{
UnloadObject(_loadedObjects[i]);
}
UnloadObject(object);
}
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
@ -217,20 +211,16 @@ public:
void ResetObjects() override
{
if (_loadedObjects != nullptr)
for (auto loadedObject : _loadedObjects)
{
for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++)
if (loadedObject != nullptr)
{
Object * loadedObject = _loadedObjects[i];
if (loadedObject != nullptr)
{
loadedObject->Unload();
loadedObject->Load();
}
loadedObject->Unload();
loadedObject->Load();
}
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
}
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
}
std::vector<const ObjectRepositoryItem *> GetPackableObjects() override
@ -276,16 +266,13 @@ public:
private:
sint32 FindSpareSlot(uint8 objectType)
{
if (_loadedObjects != nullptr)
sint32 firstIndex = GetIndexFromTypeEntry(objectType, 0);
sint32 endIndex = firstIndex + object_entry_group_counts[objectType];
for (sint32 i = firstIndex; i < endIndex; i++)
{
sint32 firstIndex = GetIndexFromTypeEntry(objectType, 0);
sint32 endIndex = firstIndex + object_entry_group_counts[objectType];
for (sint32 i = firstIndex; i < endIndex; i++)
if (_loadedObjects.size() > (size_t)i && _loadedObjects[i] == nullptr)
{
if (_loadedObjects[i] == nullptr)
{
return i;
}
return i;
}
}
return -1;
@ -295,24 +282,18 @@ private:
{
Guard::ArgumentNotNull(object, GUARD_LINE);
size_t result = SIZE_MAX;
if (_loadedObjects != nullptr)
auto result = std::numeric_limits<size_t>().max();
auto it = std::find(_loadedObjects.begin(), _loadedObjects.end(), object);
if (it != _loadedObjects.end())
{
for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++)
{
if (_loadedObjects[i] == object)
{
result = i;
break;
}
}
result = std::distance(_loadedObjects.begin(), it);
}
return result;
}
void SetNewLoadedObjectList(Object * * newLoadedObjects)
void SetNewLoadedObjectList(const std::vector<Object *> &newLoadedObjects)
{
if (newLoadedObjects == nullptr)
if (newLoadedObjects.size() == 0)
{
UnloadAll();
}
@ -320,7 +301,6 @@ private:
{
UnloadObjectsExcept(newLoadedObjects);
}
Memory::Free(_loadedObjects);
_loadedObjects = newLoadedObjects;
}
@ -335,36 +315,27 @@ private:
_objectRepository->UnregisterLoadedObject(ori, object);
}
object->Unload();
delete object;
// Because it's possible to have the same loaded object for multiple
// slots, we have to make sure find and set all of them to nullptr
if (_loadedObjects != nullptr)
for (auto &obj : _loadedObjects)
{
for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++)
if (obj == object)
{
if (_loadedObjects[i] == object)
{
_loadedObjects[i] = nullptr;
}
obj = nullptr;
}
}
object->Unload();
delete object;
}
}
void UnloadObjectsExcept(Object * * newLoadedObjects)
void UnloadObjectsExcept(const std::vector<Object *> &newLoadedObjects)
{
if (_loadedObjects == nullptr)
{
return;
}
// Build a hash set for quick checking
auto exceptSet = std::unordered_set<Object *>();
for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++)
for (auto object : newLoadedObjects)
{
Object * object = newLoadedObjects[i];
if (object != nullptr)
{
exceptSet.insert(object);
@ -374,9 +345,8 @@ private:
// Unload objects that are not in the hash set
size_t totalObjectsLoaded = 0;
size_t numObjectsUnloaded = 0;
for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++)
for (auto object : _loadedObjects)
{
Object * object = _loadedObjects[i];
if (object != nullptr)
{
totalObjectsLoaded++;
@ -393,47 +363,43 @@ private:
void UpdateSceneryGroupIndexes()
{
if (_loadedObjects != nullptr)
for (auto loadedObject : _loadedObjects)
{
for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++)
if (loadedObject != nullptr)
{
Object * loadedObject = _loadedObjects[i];
if (loadedObject != nullptr)
{
rct_scenery_entry * sceneryEntry;
switch (loadedObject->GetObjectType()) {
case OBJECT_TYPE_SMALL_SCENERY:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->small_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_LARGE_SCENERY:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->large_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_WALLS:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->wall.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_BANNERS:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->banner.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_PATH_BITS:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->path_bit.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_SCENERY_GROUP:
auto sgObject = dynamic_cast<SceneryGroupObject *>(loadedObject);
sgObject->UpdateEntryIndexes();
break;
}
rct_scenery_entry * sceneryEntry;
switch (loadedObject->GetObjectType()) {
case OBJECT_TYPE_SMALL_SCENERY:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->small_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_LARGE_SCENERY:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->large_scenery.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_WALLS:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->wall.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_BANNERS:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->banner.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_PATH_BITS:
sceneryEntry = (rct_scenery_entry *)loadedObject->GetLegacyData();
sceneryEntry->path_bit.scenery_tab_id = GetPrimarySceneryGroupEntryIndex(loadedObject);
break;
case OBJECT_TYPE_SCENERY_GROUP:
auto sgObject = dynamic_cast<SceneryGroupObject *>(loadedObject);
sgObject->UpdateEntryIndexes();
break;
}
}
// HACK Scenery window will lose its tabs after changing the scenery group indexing
// for now just close it, but it will be better to later tell it to invalidate the tabs
window_close_by_class(WC_SCENERY);
}
// HACK Scenery window will lose its tabs after changing the scenery group indexing
// for now just close it, but it will be better to later tell it to invalidate the tabs
window_close_by_class(WC_SCENERY);
}
uint8 GetPrimarySceneryGroupEntryIndex(Object * loadedObject)
@ -507,12 +473,10 @@ private:
return invalidEntries;
}
bool GetRequiredObjects(const rct_object_entry * entries,
const ObjectRepositoryItem * * requiredObjects,
size_t * outNumRequiredObjects)
std::vector<const ObjectRepositoryItem *> GetRequiredObjects(const rct_object_entry * entries, bool * missingObjects)
{
bool missingObjects = false;
size_t numRequiredObjects = 0;
std::vector<const ObjectRepositoryItem *> requiredObjects;
*missingObjects = false;
for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++)
{
const rct_object_entry * entry = &entries[i];
@ -522,29 +486,23 @@ private:
ori = _objectRepository->FindObject(entry);
if (ori == nullptr && object_entry_get_type(entry) != OBJECT_TYPE_SCENARIO_TEXT)
{
missingObjects = true;
*missingObjects = true;
ReportMissingObject(entry);
}
numRequiredObjects++;
}
requiredObjects[i] = ori;
requiredObjects.push_back(ori);
}
if (outNumRequiredObjects != nullptr)
{
*outNumRequiredObjects = numRequiredObjects;
}
return !missingObjects;
return requiredObjects;
}
Object * * LoadObjects(const ObjectRepositoryItem * * requiredObjects, size_t * outNewObjectsLoaded)
std::pair<bool, std::vector<Object *>> LoadObjects(std::vector<const ObjectRepositoryItem *> &requiredObjects, size_t * outNewObjectsLoaded)
{
size_t newObjectsLoaded = 0;
Object * * loadedObjects = Memory::AllocateArray<Object *>(OBJECT_ENTRY_COUNT);
for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++)
std::vector<Object *> loadedObjects;
loadedObjects.reserve(OBJECT_ENTRY_COUNT);
for (auto ori : requiredObjects)
{
Object * loadedObject = nullptr;
const ObjectRepositoryItem * ori = requiredObjects[i];
if (ori != nullptr)
{
loadedObject = ori->LoadedObject;
@ -554,20 +512,19 @@ private:
if (loadedObject == nullptr)
{
ReportObjectLoadProblem(&ori->ObjectEntry);
Memory::Free(loadedObjects);
return nullptr;
return std::make_pair(false, std::vector<Object *>());
} else {
newObjectsLoaded++;
}
}
}
loadedObjects[i] = loadedObject;
loadedObjects.push_back(loadedObject);
}
if (outNewObjectsLoaded != nullptr)
{
*outNewObjectsLoaded = newObjectsLoaded;
}
return loadedObjects;
return std::make_pair(true, loadedObjects);
}
Object * GetOrLoadObject(const ObjectRepositoryItem * ori)