diff --git a/src/object/ObjectManager.cpp b/src/object/ObjectManager.cpp index 1daa07634d..f430c668cb 100644 --- a/src/object/ObjectManager.cpp +++ b/src/object/ObjectManager.cpp @@ -67,16 +67,10 @@ public: uint8 GetLoadedObjectEntryIndex(const Object * object) override { uint8 result = UINT8_MAX; - if (_loadedObjects != nullptr) + size_t index = GetLoadedObjectIndex(object); + if (index != SIZE_MAX) { - for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++) - { - if (_loadedObjects[i] == object) - { - get_type_entry_index(i, nullptr, &result); - break; - } - } + get_type_entry_index(index, nullptr, &result); } return result; } @@ -141,6 +135,36 @@ public: } } + void UnloadObjects(const rct_object_entry * entries, size_t count) override + { + // TODO there are two performance issues here: + // - FindObject for every entry which is a dictionary lookup + // - GetLoadedObjectIndex for every entry which enumerates _loadedList + + size_t numObjectsUnloaded = 0; + for (size_t i = 0; i < count; i++) + { + const rct_object_entry * entry = &entries[i]; + const ObjectRepositoryItem * ori = _objectRepository->FindObject(entry); + if (ori != nullptr) + { + Object * loadedObject = ori->LoadedObject; + size_t index = GetLoadedObjectIndex(loadedObject); + + UnloadObject(loadedObject); + _loadedObjects[index] = nullptr; + + numObjectsUnloaded++; + } + } + + if (numObjectsUnloaded > 0) + { + UpdateLegacyLoadedObjectList(); + reset_type_to_ride_entry_index_map(); + } + } + void UnloadAll() override { if (_loadedObjects != nullptr) @@ -173,6 +197,23 @@ private: return -1; } + size_t GetLoadedObjectIndex(const Object * object) + { + size_t result = SIZE_MAX; + if (_loadedObjects != nullptr) + { + for (size_t i = 0; i < OBJECT_ENTRY_COUNT; i++) + { + if (_loadedObjects[i] == object) + { + result = i; + break; + } + } + } + return result; + } + void SetNewLoadedObjectList(Object * * newLoadedObjects) { if (newLoadedObjects == nullptr) @@ -415,4 +456,10 @@ extern "C" Object * loadedObject = objectManager->LoadObject(entry); return (void *)loadedObject; } + + void object_manager_unload_objects(const rct_object_entry * entries, size_t count) + { + IObjectManager * objectManager = GetObjectManager(); + objectManager->UnloadObjects(entries, count); + } } diff --git a/src/object/ObjectManager.h b/src/object/ObjectManager.h index a2a2ad1ea4..21c37b260b 100644 --- a/src/object/ObjectManager.h +++ b/src/object/ObjectManager.h @@ -39,6 +39,7 @@ interface IObjectManager virtual Object * LoadObject(const rct_object_entry * entry) abstract; virtual bool LoadObjects(const rct_object_entry * entries, size_t count) abstract; + virtual void UnloadObjects(const rct_object_entry * entries, size_t count) abstract; virtual void UnloadAll() abstract; }; @@ -49,5 +50,6 @@ IObjectManager * GetObjectManager(); void * object_manager_get_loaded_object(const rct_object_entry * entry); uint8 object_manager_get_loaded_object_entry_index(const void * loadedObject); void * object_manager_load_object(const rct_object_entry * entry); +void object_manager_unload_objects(const rct_object_entry * entries, size_t count); #endif diff --git a/src/object/ObjectRepository.cpp b/src/object/ObjectRepository.cpp index e89f21dd7c..cc2e742d46 100644 --- a/src/object/ObjectRepository.cpp +++ b/src/object/ObjectRepository.cpp @@ -711,11 +711,6 @@ extern "C" return (void *)object; } - void object_repository_unload(size_t itemIndex) - { - // TODO - } - void object_unload_all() { IObjectManager * objectManager = GetObjectManager(); diff --git a/src/object/ObjectRepository.h b/src/object/ObjectRepository.h index 9652f13708..6779471b2b 100644 --- a/src/object/ObjectRepository.h +++ b/src/object/ObjectRepository.h @@ -86,7 +86,6 @@ const ObjectRepositoryItem * object_repository_get_items(); const ObjectRepositoryItem * object_repository_find_object_by_entry(const rct_object_entry * entry); const ObjectRepositoryItem * object_repository_find_object_by_name(const char * name); void * object_repository_load_object(const rct_object_entry * objectEntry); -void object_repository_unload(size_t itemIndex); void object_delete(void * object); const utf8 * object_get_description(const void * object); diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index 946cce1152..a9f67bf558 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -27,6 +27,7 @@ #include "../management/research.h" #include "../object.h" #include "../object_list.h" +#include "../object/ObjectManager.h" #include "../object/ObjectRepository.h" #include "../rct1.h" #include "../ride/ride.h" @@ -714,12 +715,21 @@ void unload_unselected_objects() { int numItems = object_repository_get_items_count(); const ObjectRepositoryItem * items = object_repository_get_items(); + + size_t numObjectsToUnload = 0; + rct_object_entry * objectsToUnload = (rct_object_entry *)malloc(numItems * sizeof(rct_object_entry)); + for (int i = 0; i < numItems; i++) { if (!(_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_SELECTED)) { - remove_selected_objects_from_research(&items[i].ObjectEntry); - object_repository_unload(i); + const rct_object_entry * entry = &items[i].ObjectEntry; + + remove_selected_objects_from_research(entry); + objectsToUnload[numObjectsToUnload++] = *entry; } } + + object_manager_unload_objects(objectsToUnload, numObjectsToUnload); + free(objectsToUnload); } /** @@ -1703,27 +1713,28 @@ static void window_editor_object_selection_manage_tracks() */ static void editor_load_selected_objects() { - int numObjects = (int)object_repository_get_items_count(); + int numItems = (int)object_repository_get_items_count(); const ObjectRepositoryItem * items = object_repository_get_items(); - for (int i = 0; i < numObjects; i++) { + for (int i = 0; i < numItems; i++) { if (_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_SELECTED) { - uint8 entry_index, entry_type; - if (!find_object_in_entry_group(&items[i].ObjectEntry, &entry_type, &entry_index)) { - if (!object_load_chunk(-1, &items[i].ObjectEntry, NULL)) { - log_error("Failed to load entry %.8s", items->Name); + const ObjectRepositoryItem * item = &items[i]; + const rct_object_entry * entry = &item->ObjectEntry; + void * loadedObject = object_manager_get_loaded_object(entry); + if (loadedObject == NULL) { + loadedObject = object_manager_load_object(entry); + if (loadedObject == NULL) { + log_error("Failed to load entry %.8s", entry->name); } - - // For in game use (cheat) - if (!(gScreenFlags & SCREEN_FLAGS_EDITOR)) { - // Defaults selected items to researched. - if (find_object_in_entry_group(&items[i].ObjectEntry, &entry_type, &entry_index)) { - if (entry_type == OBJECT_TYPE_RIDE) { - rct_ride_entry* rideType = get_ride_entry(entry_index); - research_insert(1, 0x10000 | (rideType->ride_type[0] << 8) | entry_index, rideType->category[0]); - } - else if (entry_type == OBJECT_TYPE_SCENERY_SETS) { - research_insert(1, entry_index, RESEARCH_CATEGORY_SCENERYSET); - } + else if (!(gScreenFlags & SCREEN_FLAGS_EDITOR)) { + // Defaults selected items to researched (if in-game) + uint8 objectType = entry->flags & 0x0F; + uint8 entryIndex = object_manager_get_loaded_object_entry_index(loadedObject); + if (objectType == OBJECT_TYPE_RIDE) { + rct_ride_entry *rideType = get_ride_entry(entryIndex); + research_insert(1, 0x10000 | (rideType->ride_type[0] << 8) | entryIndex, rideType->category[0]); + } + else if (objectType == OBJECT_TYPE_SCENERY_SETS) { + research_insert(1, entryIndex, RESEARCH_CATEGORY_SCENERYSET); } } }