Merge pull request #7167 from IntelOrca/refactor/easy-new-object-types

Refactor things related to object types
This commit is contained in:
Ted John 2018-02-12 19:43:49 +00:00 committed by GitHub
commit 683ffcdadc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 375 additions and 415 deletions

View File

@ -175,18 +175,23 @@ static void move_research_item(rct_research_item *beforeItem);
*/
static void research_rides_setup(){
// Reset all objects to not required
for (uint8 object_type = OBJECT_TYPE_RIDE; object_type < OBJECT_TYPE_COUNT; object_type++){
uint8* in_use = Editor::SelectedObjects[object_type];
for (uint8 num_objects = object_entry_group_counts[object_type]; num_objects != 0; num_objects--){
*in_use++ = OBJECT_SELECTION_NOT_SELECTED_OR_REQUIRED;
for (uint8 objectType = OBJECT_TYPE_RIDE; objectType < OBJECT_TYPE_COUNT; objectType++)
{
auto maxObjects = object_entry_group_counts[objectType];
for (sint32 i = 0; i < maxObjects; i++)
{
Editor::ClearSelectedObject(objectType, i, OBJECT_SELECTION_FLAG_ALL);
}
}
// Set research required for rides in use
for (uint16 rideIndex = 0; rideIndex < 255; rideIndex++){
Ride * ride = get_ride(rideIndex);
if (ride->type == RIDE_TYPE_NULL)continue;
Editor::SelectedObjects[OBJECT_TYPE_RIDE][ride->subtype] |= OBJECT_SELECTION_FLAG_SELECTED;
for (uint16 rideIndex = 0; rideIndex < MAX_RIDES; rideIndex++)
{
auto ride = get_ride(rideIndex);
if (ride->type != RIDE_TYPE_NULL)
{
Editor::SetSelectedObject(OBJECT_TYPE_RIDE, ride->subtype, OBJECT_SELECTION_FLAG_SELECTED);
}
}
for (rct_research_item* research = gResearchItems; research->rawValue != RESEARCHED_ITEMS_END; research++)
@ -216,7 +221,8 @@ static void research_rides_setup(){
continue;
// If master ride not in use
if (!(Editor::SelectedObjects[OBJECT_TYPE_RIDE][rideType] & OBJECT_SELECTION_FLAG_SELECTED))
auto flags = Editor::GetSelectedObjectFlags(OBJECT_TYPE_RIDE, rideType);
if (!(flags & OBJECT_SELECTION_FLAG_SELECTED))
continue;
for (uint8 j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++)
@ -237,7 +243,8 @@ static void research_rides_setup(){
if (!master_found){
// If not in use
if (!(Editor::SelectedObjects[OBJECT_TYPE_RIDE][object_index] & OBJECT_SELECTION_FLAG_SELECTED)) {
auto flags = Editor::GetSelectedObjectFlags(OBJECT_TYPE_RIDE, object_index);
if (!(flags & OBJECT_SELECTION_FLAG_SELECTED)) {
continue;
}
@ -679,12 +686,11 @@ static void window_editor_inventions_list_paint(rct_window *w, rct_drawpixelinfo
if (researchItem->type == RESEARCH_ENTRY_TYPE_RIDE)
objectEntryType = OBJECT_TYPE_RIDE;
void * chunk = object_entry_groups[objectEntryType].chunks[researchItem->entryIndex];
auto chunk = object_entry_get_chunk(objectEntryType, researchItem->entryIndex);
if (chunk == nullptr)
return;
rct_object_entry * entry = &object_entry_groups[objectEntryType].entries[researchItem->entryIndex].entry;
auto entry = object_entry_get_entry(objectEntryType, researchItem->entryIndex);
// Draw preview
widget = &w->widgets[WIDX_PREVIEW];

View File

@ -385,8 +385,7 @@ rct_window * window_editor_object_selection_open()
if (window != nullptr)
return window;
if (!sub_6AB211())
return nullptr;
sub_6AB211();
reset_selected_object_count_and_size();
window = window_create_centred(
@ -1227,7 +1226,7 @@ static void window_editor_object_selection_manage_tracks()
gS6Info.editor_step = EDITOR_STEP_TRACK_DESIGNS_MANAGER;
sint32 entry_index = 0;
for (; (object_entry_groups[0].chunks[entry_index]) == nullptr; ++entry_index);
for (; object_entry_get_chunk(OBJECT_TYPE_RIDE, entry_index) == nullptr; entry_index++);
rct_ride_entry* ride_entry = get_ride_entry(entry_index);
uint8 ride_type = ride_entry_get_first_non_null_ride_type(ride_entry);
@ -1419,7 +1418,7 @@ static bool filter_chunks(const ObjectRepositoryItem * item)
static void filter_update_counts()
{
if (!_FILTER_ALL || strlen(_filter_string) > 0) {
uint8 *selectionFlags = _objectSelectionFlags;
const auto &selectionFlags = _objectSelectionFlags;
for (sint32 i = 0; i < 11; i++) {
_filter_object_counts[i] = 0;
}
@ -1431,12 +1430,11 @@ static void filter_update_counts()
if (filter_source(item) &&
filter_string(item) &&
filter_chunks(item) &&
filter_selected(*selectionFlags)
filter_selected(selectionFlags[i])
) {
uint8 objectType = item->ObjectEntry.flags & 0xF;
_filter_object_counts[objectType]++;
}
selectionFlags++;
}
}
}

View File

@ -814,12 +814,7 @@ static void window_editor_objective_options_main_textinput(rct_window *w, rct_wi
*/
static void window_editor_objective_options_main_invalidate(rct_window *w)
{
rct_widget *widgets;
rct_stex_entry *stex;
stex = g_stexEntries[0];
widgets = window_editor_objective_options_widgets[w->page];
auto widgets = window_editor_objective_options_widgets[w->page];
if (w->widgets != widgets) {
w->widgets = widgets;
window_init_scroll_widgets(w);
@ -827,6 +822,7 @@ static void window_editor_objective_options_main_invalidate(rct_window *w)
window_editor_objective_options_set_pressed_tab(w);
auto stex = (rct_stex_entry *)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0);
if (stex == nullptr)
w->disabled_widgets &= ~((1 << WIDX_PARK_NAME) | (1 << WIDX_SCENARIO_NAME));
else
@ -877,7 +873,6 @@ static void window_editor_objective_options_main_invalidate(rct_window *w)
*/
static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
rct_stex_entry *stex;
sint32 x, y, width;
rct_string_id stringId;
uint32 arg;
@ -885,8 +880,6 @@ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpi
window_draw_widgets(w, dpi);
window_editor_objective_options_draw_tab_images(w, dpi);
stex = g_stexEntries[0];
// Objective label
x = w->x + 8;
y = w->y + w->widgets[WIDX_OBJECTIVE].top;
@ -983,6 +976,7 @@ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpi
y = w->y + w->widgets[WIDX_PARK_NAME].top;
width = w->widgets[WIDX_PARK_NAME].left - 16;
auto stex = (rct_stex_entry *)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0);
if (stex != nullptr) {
set_format_arg(0, rct_string_id, stex->park_name);
} else {

View File

@ -349,7 +349,7 @@ static ride_list_item * window_new_ride_iterate_over_ride_group(uint8 rideType,
{
uint8 rideEntryIndex = *rideEntryIndexPtr++;
char rideEntryName[DAT_NAME_LENGTH + 1];
memcpy(rideEntryName,object_entry_groups[OBJECT_TYPE_RIDE].entries[rideEntryIndex].name,8);
memcpy(rideEntryName, object_entry_get_entry(OBJECT_TYPE_RIDE, rideEntryIndex)->name, 8);
rideEntryName[DAT_NAME_LENGTH] = 0;
// Skip if vehicle type is not invented yet

View File

@ -14,6 +14,8 @@
*****************************************************************************/
#pragma endregion
#include <array>
#include <vector>
#include "Context.h"
#include "Editor.h"
#include "EditorObjectSelectionSession.h"
@ -38,32 +40,7 @@
namespace Editor
{
static uint8 _editorSelectedRides[MAX_RIDE_OBJECTS];
static uint8 _editorSelectedSmallScenery[MAX_SMALL_SCENERY_OBJECTS];
static uint8 _editorSelectedLargeScenery[MAX_LARGE_SCENERY_OBJECTS];
static uint8 _editorSelectedWalls[MAX_WALL_SCENERY_OBJECTS];
static uint8 _editorSelectedBanners[MAX_BANNER_OBJECTS];
static uint8 _editorSelectedFootpaths[MAX_PATH_OBJECTS];
static uint8 _editorSelectedFootpathAdditions[MAX_PATH_ADDITION_OBJECTS];
static uint8 _editorSelectedSceneryGroups[MAX_SCENERY_GROUP_OBJECTS];
static uint8 _editorSelectedParkEntrances[MAX_PARK_ENTRANCE_OBJECTS];
static uint8 _editorSelectedWaters[MAX_WATER_OBJECTS];
static uint8 _editorSelectedStexs[MAX_SCENARIO_TEXT_OBJECTS];
uint8 * SelectedObjects[OBJECT_TYPE_COUNT] =
{
_editorSelectedRides,
_editorSelectedSmallScenery,
_editorSelectedLargeScenery,
_editorSelectedWalls,
_editorSelectedBanners,
_editorSelectedFootpaths,
_editorSelectedFootpathAdditions,
_editorSelectedSceneryGroups,
_editorSelectedParkEntrances,
_editorSelectedWaters,
_editorSelectedStexs,
};
static std::array<std::vector<uint8>, OBJECT_TYPE_COUNT> _editorSelectedObjectFlags;
static void ConvertSaveToScenarioCallback(sint32 result, const utf8 * path);
static void SetAllLandOwned();
@ -806,6 +783,37 @@ namespace Editor
window_invalidate_by_class(WC_EDITOR_SCENARIO_OPTIONS);
*ebx = 0;
}
uint8 GetSelectedObjectFlags(sint32 objectType, size_t index)
{
uint8 result = 0;
auto &list = _editorSelectedObjectFlags[objectType];
if (list.size() > index)
{
result = list[index];
}
return result;
}
void ClearSelectedObject(sint32 objectType, size_t index, uint32 flags)
{
auto &list = _editorSelectedObjectFlags[objectType];
if (list.size() <= index)
{
list.resize(index + 1);
}
list[index] &= ~flags;
}
void SetSelectedObject(sint32 objectType, size_t index, uint32 flags)
{
auto &list = _editorSelectedObjectFlags[objectType];
if (list.size() <= index)
{
list.resize(index + 1);
}
list[index] |= flags;
}
}
void editor_open_windows_for_current_step()

View File

@ -25,8 +25,6 @@
namespace Editor
{
extern uint8 * SelectedObjects[OBJECT_TYPE_COUNT];
void Load();
void ConvertSaveToScenario();
void LoadTrackDesigner();
@ -38,6 +36,10 @@ namespace Editor
void OpenWindowsForCurrentStep();
void GameCommandEditScenarioOptions(sint32*, sint32*, sint32*, sint32*, sint32*, sint32*, sint32*);
uint8 GetSelectedObjectFlags(sint32 objectType, size_t index);
void ClearSelectedObject(sint32 objectType, size_t index, uint32 flags);
void SetSelectedObject(sint32 objectType, size_t index, uint32 flags);
}
typedef enum

View File

@ -14,6 +14,7 @@
*****************************************************************************/
#pragma endregion
#include <vector>
#include "Context.h"
#include "core/Util.hpp"
#include "Editor.h"
@ -30,7 +31,7 @@
#include "world/LargeScenery.h"
bool _maxObjectsWasHit;
uint8 * _objectSelectionFlags = nullptr;
std::vector<uint8> _objectSelectionFlags;
sint32 _numSelectedObjectsForType[OBJECT_TYPE_COUNT];
static sint32 _numAvailableObjectsForType[OBJECT_TYPE_COUNT];
@ -107,16 +108,14 @@ static void setup_track_designer_objects()
*/
void setup_in_use_selection_flags()
{
for (uint8 object_type = 0; object_type < OBJECT_TYPE_COUNT; object_type++){
for (uint16 i = 0; i < object_entry_group_counts[object_type]; i++){
Editor::SelectedObjects[object_type][i] = OBJECT_SELECTION_NOT_SELECTED_OR_REQUIRED;
}
}
for (uint8 object_type = 0; object_type < OBJECT_TYPE_COUNT; object_type++){
for (uint16 i = 0; i < object_entry_group_counts[object_type]; i++){
if (object_entry_groups[object_type].chunks[i] != nullptr) {
Editor::SelectedObjects[object_type][i] |= OBJECT_SELECTION_FLAG_2;
for (uint8 objectType = 0; objectType < OBJECT_TYPE_COUNT; objectType++)
{
for (sint32 i = 0; i < object_entry_group_counts[objectType]; i++)
{
Editor::ClearSelectedObject(objectType, i, OBJECT_SELECTION_FLAG_ALL);
if (object_entry_get_chunk(objectType, i) != nullptr)
{
Editor::SetSelectedObject(objectType, i, OBJECT_SELECTION_FLAG_2);
}
}
}
@ -136,17 +135,17 @@ void setup_in_use_selection_flags()
type = iter.element->properties.path.type;
type >>= 4;
assert(type < object_entry_group_counts[OBJECT_TYPE_PATHS]);
Editor::SelectedObjects[OBJECT_TYPE_PATHS][type] |= OBJECT_SELECTION_FLAG_SELECTED;
Editor::SetSelectedObject(OBJECT_TYPE_PATHS, type, OBJECT_SELECTION_FLAG_SELECTED);
if (footpath_element_has_path_scenery(iter.element)) {
uint8 path_additions = footpath_element_get_path_scenery_index(iter.element);
Editor::SelectedObjects[OBJECT_TYPE_PATH_BITS][path_additions] |= OBJECT_SELECTION_FLAG_SELECTED;
Editor::SetSelectedObject(OBJECT_TYPE_PATH_BITS, path_additions, OBJECT_SELECTION_FLAG_SELECTED);
}
break;
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
type = iter.element->properties.scenery.type;
assert(type < object_entry_group_counts[OBJECT_TYPE_SMALL_SCENERY]);
Editor::SelectedObjects[OBJECT_TYPE_SMALL_SCENERY][type] |= OBJECT_SELECTION_FLAG_SELECTED;
Editor::SetSelectedObject(OBJECT_TYPE_SMALL_SCENERY, type, OBJECT_SELECTION_FLAG_SELECTED);
break;
case TILE_ELEMENT_TYPE_ENTRANCE:
if (iter.element->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE)
@ -155,27 +154,27 @@ void setup_in_use_selection_flags()
if (iter.element->properties.entrance.index != 0)
break;
Editor::SelectedObjects[OBJECT_TYPE_PARK_ENTRANCE][0] |= OBJECT_SELECTION_FLAG_SELECTED;
Editor::SetSelectedObject(OBJECT_TYPE_PARK_ENTRANCE, 0, OBJECT_SELECTION_FLAG_SELECTED);
type = iter.element->properties.entrance.path_type;
assert(type < object_entry_group_counts[OBJECT_TYPE_PATHS]);
Editor::SelectedObjects[OBJECT_TYPE_PATHS][type] |= OBJECT_SELECTION_FLAG_SELECTED;
Editor::SetSelectedObject(OBJECT_TYPE_PATHS, type, OBJECT_SELECTION_FLAG_SELECTED);
break;
case TILE_ELEMENT_TYPE_WALL:
type = iter.element->properties.wall.type;
assert(type < object_entry_group_counts[OBJECT_TYPE_WALLS]);
Editor::SelectedObjects[OBJECT_TYPE_WALLS][type] |= OBJECT_SELECTION_FLAG_SELECTED;
Editor::SetSelectedObject(OBJECT_TYPE_WALLS, type, OBJECT_SELECTION_FLAG_SELECTED);
break;
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
type = scenery_large_get_type(iter.element);
assert(type < object_entry_group_counts[OBJECT_TYPE_LARGE_SCENERY]);
Editor::SelectedObjects[OBJECT_TYPE_LARGE_SCENERY][type] |= OBJECT_SELECTION_FLAG_SELECTED;
Editor::SetSelectedObject(OBJECT_TYPE_LARGE_SCENERY, type, OBJECT_SELECTION_FLAG_SELECTED);
break;
case TILE_ELEMENT_TYPE_BANNER:
banner = &gBanners[iter.element->properties.banner.index];
type = banner->type;
assert(type < object_entry_group_counts[OBJECT_TYPE_BANNERS]);
Editor::SelectedObjects[OBJECT_TYPE_BANNERS][type] |= OBJECT_SELECTION_FLAG_SELECTED;
Editor::SetSelectedObject(OBJECT_TYPE_BANNERS, type, OBJECT_SELECTION_FLAG_SELECTED);
break;
}
} while (tile_element_iterator_next(&iter));
@ -184,7 +183,7 @@ void setup_in_use_selection_flags()
Ride* ride = get_ride(ride_index);
if (ride->type != RIDE_TYPE_NULL) {
uint8 type = ride->subtype;
Editor::SelectedObjects[OBJECT_TYPE_RIDE][type] |= OBJECT_SELECTION_FLAG_SELECTED;
Editor::SetSelectedObject(OBJECT_TYPE_RIDE, type, OBJECT_SELECTION_FLAG_SELECTED);
}
}
@ -197,12 +196,15 @@ void setup_in_use_selection_flags()
uint8 entryType, entryIndex;
if (find_object_in_entry_group(&item->ObjectEntry, &entryType, &entryIndex)) {
if (Editor::SelectedObjects[entryType][entryIndex] & OBJECT_SELECTION_FLAG_SELECTED) {
auto flags = Editor::GetSelectedObjectFlags(entryType, entryIndex);
if (flags & OBJECT_SELECTION_FLAG_SELECTED)
{
*selectionFlags |=
OBJECT_SELECTION_FLAG_IN_USE |
OBJECT_SELECTION_FLAG_SELECTED;
OBJECT_SELECTION_FLAG_SELECTED;
}
if (Editor::SelectedObjects[entryType][entryIndex] & OBJECT_SELECTION_FLAG_2) {
if (flags & OBJECT_SELECTION_FLAG_2)
{
*selectionFlags |= OBJECT_SELECTION_FLAG_SELECTED;
}
}
@ -213,14 +215,10 @@ void setup_in_use_selection_flags()
*
* rct2: 0x006AB211
*/
bool sub_6AB211()
void sub_6AB211()
{
sint32 numObjects = (sint32)object_repository_get_items_count();
_objectSelectionFlags = (uint8*)calloc(numObjects, sizeof(uint8));
if (_objectSelectionFlags == nullptr){
log_error("Failed to allocate memory for object flag list.");
return false;
}
_objectSelectionFlags = std::vector<uint8>(numObjects);
for (uint8 objectType = 0; objectType < 11; objectType++) {
_numSelectedObjectsForType[objectType] = 0;
@ -254,7 +252,6 @@ bool sub_6AB211()
}
reset_selected_object_count_and_size();
return true;
}
/**
@ -263,7 +260,8 @@ bool sub_6AB211()
*/
void editor_object_flags_free()
{
SafeFree(_objectSelectionFlags);
_objectSelectionFlags.clear();
_objectSelectionFlags.shrink_to_fit();
}
/**
@ -276,7 +274,7 @@ static void remove_selected_objects_from_research(const rct_object_entry* instal
return;
if (entry_type == OBJECT_TYPE_RIDE){
rct_ride_entry* rideEntry = (rct_ride_entry*)object_entry_groups[entry_type].chunks[entry_index];
auto rideEntry = (rct_ride_entry *)object_entry_get_entry(entry_type, entry_index);
for (auto rideType : rideEntry->ride_type)
{
@ -492,12 +490,7 @@ bool editor_check_object_group_at_least_one_selected(sint32 checkObjectType)
sint32 editor_remove_unused_objects()
{
bool createSelectionFlags = (_objectSelectionFlags == nullptr);
if (createSelectionFlags && !sub_6AB211())
{
return 0;
}
sub_6AB211();
setup_in_use_selection_flags();
sint32 numObjects = (sint32)object_repository_get_items_count();
@ -522,11 +515,7 @@ sint32 editor_remove_unused_objects()
}
}
unload_unselected_objects();
if (createSelectionFlags)
{
editor_object_flags_free();
}
editor_object_flags_free();
auto intent = Intent(INTENT_ACTION_REFRESH_SCENERY);
context_broadcast_intent(&intent);

View File

@ -16,17 +16,18 @@
#pragma once
#include <vector>
#include "common.h"
#include "object/Object.h"
extern bool _maxObjectsWasHit;
extern uint8 * _objectSelectionFlags;
extern std::vector<uint8> _objectSelectionFlags;
extern sint32 _numSelectedObjectsForType[OBJECT_TYPE_COUNT];
bool editor_check_object_group_at_least_one_selected(sint32 objectType);
void editor_object_flags_free();
void unload_unselected_objects();
bool sub_6AB211();
void sub_6AB211();
void reset_selected_object_count_and_size();
sint32 window_editor_object_selection_select_object(uint8 bh, sint32 flags, const rct_object_entry *entry);

View File

@ -177,7 +177,7 @@ enum
*/
void update_palette_effects()
{
rct_water_type * water_type = (rct_water_type *) object_entry_groups[OBJECT_TYPE_WATER].chunks[0];
auto water_type = (rct_water_type *)object_entry_get_chunk(OBJECT_TYPE_WATER, 0);
if (gClimateLightningFlash == 1)
{

View File

@ -537,7 +537,7 @@ void load_palette()
return;
}
rct_water_type* water_type = (rct_water_type*)object_entry_groups[OBJECT_TYPE_WATER].chunks[0];
auto water_type = (rct_water_type *)object_entry_get_chunk(OBJECT_TYPE_WATER, 0);
uint32 palette = 0x5FC;

View File

@ -1196,7 +1196,8 @@ static sint32 cc_object_count(const utf8 **argv, sint32 argc) {
sint32 entryGroupIndex = 0;
for (; entryGroupIndex < object_entry_group_counts[i]; entryGroupIndex++){
if (object_entry_groups[i].chunks[entryGroupIndex] == nullptr){
if (object_entry_get_chunk(i, entryGroupIndex) == nullptr)
{
break;
}
}

View File

@ -48,6 +48,7 @@ typedef enum
OBJECT_SELECTION_FLAG_6 = (1 << 5),
OBJECT_SELECTION_FLAG_7 = (1 << 6),
OBJECT_SELECTION_FLAG_8 = (1 << 7),
OBJECT_SELECTION_FLAG_ALL = 0xFF,
} OBJECT_SELECTION_FLAGS;
#define OBJECT_SELECTION_NOT_SELECTED_OR_REQUIRED 0
@ -87,26 +88,9 @@ typedef struct rct_object_entry {
} rct_object_entry;
assert_struct_size(rct_object_entry, 0x10);
/**
* Object entry structure extended.
* size: 0x14
*/
typedef struct rct_object_entry_extended {
union {
rct_object_entry entry;
struct {
uint32 flags;
char name[8];
uint32 checksum;
uint32 chunk_size;
};
};
} rct_object_entry_extended;
assert_struct_size(rct_object_entry_extended, 0x14);
typedef struct rct_object_entry_group {
void **chunks;
rct_object_entry_extended *entries;
rct_object_entry *entries;
} rct_object_entry_group;
#ifdef PLATFORM_32BIT
assert_struct_size(rct_object_entry_group, 8);
@ -218,8 +202,6 @@ enum OBJECT_ERROR : uint32
extern sint32 object_entry_group_counts[];
extern sint32 object_entry_group_encoding[];
extern const rct_object_entry_group object_entry_groups[];
void object_list_load();
bool object_entry_is_empty(const rct_object_entry *entry);
@ -232,3 +214,6 @@ const rct_object_entry * object_list_find_by_name(const char *name);
const rct_object_entry * object_list_find(rct_object_entry *entry);
void object_entry_get_name_fixed(utf8 * buffer, size_t bufferSize, const rct_object_entry * entry);
void * object_entry_get_chunk(sint32 objectType, size_t index);
const rct_object_entry * object_entry_get_entry(sint32 objectType, size_t index);

View File

@ -20,6 +20,7 @@
#include "../object/Object.h"
#include "ObjectList.h"
#include "ObjectRepository.h"
#include "ObjectManager.h"
#include "../util/SawyerCoding.h"
#include "../util/Util.h"
@ -53,46 +54,6 @@ sint32 object_entry_group_encoding[] = {
CHUNK_ENCODING_RLE,
CHUNK_ENCODING_ROTATE
};
rct_ride_entry *gRideEntries[MAX_RIDE_OBJECTS];
rct_small_scenery_entry *gSmallSceneryEntries[MAX_SMALL_SCENERY_OBJECTS];
rct_large_scenery_entry *gLargeSceneryEntries[MAX_LARGE_SCENERY_OBJECTS];
rct_wall_scenery_entry *gWallSceneryEntries[MAX_WALL_SCENERY_OBJECTS];
rct_banner *gBannerSceneryEntries[MAX_BANNER_OBJECTS];
rct_footpath_entry *gFootpathEntries[MAX_PATH_OBJECTS];
rct_path_bit_scenery_entry *gFootpathAdditionEntries[MAX_PATH_ADDITION_OBJECTS];
rct_scenery_group_entry *gSceneryGroupEntries[MAX_SCENERY_GROUP_OBJECTS];
rct_entrance_type *gParkEntranceEntries[MAX_PARK_ENTRANCE_OBJECTS];
rct_water_type *gWaterEntries[MAX_WATER_OBJECTS];
rct_stex_entry *gStexEntries[MAX_SCENARIO_TEXT_OBJECTS];
static rct_object_entry_extended _objectEntriesRides[MAX_RIDE_OBJECTS];
static rct_object_entry_extended _objectEntriesSmallScenery[MAX_SMALL_SCENERY_OBJECTS];
static rct_object_entry_extended _objectEntriesLargeScenery[MAX_LARGE_SCENERY_OBJECTS];
static rct_object_entry_extended _objectEntriesWalls[MAX_WALL_SCENERY_OBJECTS];
static rct_object_entry_extended _objectEntriesBanners[MAX_BANNER_OBJECTS];
static rct_object_entry_extended _objectEntriesFootpaths[MAX_PATH_OBJECTS];
static rct_object_entry_extended _objectEntriesFootpathAdditions[MAX_PATH_ADDITION_OBJECTS];
static rct_object_entry_extended _objectEntriesSceneryGroups[MAX_SCENERY_GROUP_OBJECTS];
static rct_object_entry_extended _objectEntriesParkEntrances[MAX_PARK_ENTRANCE_OBJECTS];
static rct_object_entry_extended _objectEntriesWaters[MAX_WATER_OBJECTS];
static rct_object_entry_extended _objectEntriesStexs[MAX_SCENARIO_TEXT_OBJECTS];
// 0x98D97C chunk address', 0x98D980 object_entries
const rct_object_entry_group object_entry_groups[] = {
(void**)(gRideEntries ), _objectEntriesRides, // rides
(void**)(gSmallSceneryEntries ), _objectEntriesSmallScenery, // small scenery 0x009AD1A4, 0xF2FA3C
(void**)(gLargeSceneryEntries ), _objectEntriesLargeScenery, // large scenery 0x009AD594, 0xF40DEC
(void**)(gWallSceneryEntries ), _objectEntriesWalls, // walls 0x009AD794, 0xF417EC
(void**)(gBannerSceneryEntries ), _objectEntriesBanners, // banners 0x009AD994, 0xF421EC
(void**)(gFootpathEntries ), _objectEntriesFootpaths, // paths 0x009ADA14, 0xF4246C
(void**)(gFootpathAdditionEntries ), _objectEntriesFootpathAdditions, // path bits 0x009ADA54, 0xF425AC
(void**)(gSceneryGroupEntries ), _objectEntriesSceneryGroups, // scenery sets 0x009ADA90, 0xF426D8
(void**)(gParkEntranceEntries ), _objectEntriesParkEntrances, // park entrance 0x009ADADC, 0xF42854
(void**)(gWaterEntries ), _objectEntriesWaters, // water 0x009ADAE0, 0xF42868
(void**)(gStexEntries ), _objectEntriesStexs, // scenario text 0x009ADAE4, 0xF4287C
};
// clang-format on
bool object_entry_is_empty(const rct_object_entry *entry)
@ -133,26 +94,27 @@ void object_create_identifier_name(char* string_buffer, size_t size, const rct_o
*/
bool find_object_in_entry_group(const rct_object_entry * entry, uint8 * entry_type, uint8 * entry_index)
{
if ((entry->flags & 0xF) >= Util::CountOf(object_entry_groups)) {
return false;
}
*entry_type = entry->flags & 0xF;
rct_object_entry_group entry_group = object_entry_groups[*entry_type];
for (*entry_index = 0;
*entry_index < object_entry_group_counts[*entry_type];
++(*entry_index), entry_group.chunks++, entry_group.entries++)
sint32 objectType = object_entry_get_type(entry);
if (objectType >= OBJECT_TYPE_COUNT)
{
if (*entry_group.chunks == nullptr)
continue;
if (object_entry_compare((rct_object_entry*)entry_group.entries, entry))
break;
return false;
}
if (*entry_index == object_entry_group_counts[*entry_type])
return false;
return true;
auto maxObjects = object_entry_group_counts[objectType];
for (sint32 i = 0; i < maxObjects; i++)
{
if (object_entry_get_chunk(objectType, i) != nullptr)
{
auto thisEntry = object_entry_get_entry(*entry_type, i);
if (object_entry_compare(thisEntry, entry))
{
*entry_type = objectType;
*entry_index = i;
return true;
}
}
}
return false;
}
void get_type_entry_index(size_t index, uint8 * outObjectType, uint8 * outEntryIndex)
@ -177,17 +139,14 @@ const rct_object_entry * get_loaded_object_entry(size_t index)
uint8 objectType, entryIndex;
get_type_entry_index(index, &objectType, &entryIndex);
rct_object_entry * entry = (rct_object_entry *)&(object_entry_groups[objectType].entries[entryIndex]);
return entry;
return object_entry_get_entry(objectType, entryIndex);
}
void * get_loaded_object_chunk(size_t index)
{
uint8 objectType, entryIndex;
get_type_entry_index(index, &objectType, &entryIndex);
void *entry = object_entry_groups[objectType].chunks[entryIndex];
return entry;
return object_entry_get_chunk(objectType, entryIndex);
}
void object_entry_get_name_fixed(utf8 * buffer, size_t bufferSize, const rct_object_entry * entry)
@ -196,3 +155,28 @@ void object_entry_get_name_fixed(utf8 * buffer, size_t bufferSize, const rct_obj
memcpy(buffer, entry->name, bufferSize - 1);
buffer[bufferSize - 1] = 0;
}
void * object_entry_get_chunk(sint32 objectType, size_t index)
{
size_t objectIndex = index;
for (sint32 i = 0; i < objectType; i++)
{
objectIndex += object_entry_group_counts[i];
}
void * result = nullptr;
auto objectMgr = GetObjectManager();
auto obj = objectMgr->GetLoadedObject(objectIndex);
if (obj != nullptr)
{
result = obj->GetLegacyData();
}
return result;
}
const rct_object_entry * object_entry_get_entry(sint32 objectType, size_t index)
{
auto objectMgr = GetObjectManager();
auto obj = objectMgr->GetLoadedObject(objectType, index);
return obj->GetObjectEntry();
}

View File

@ -8,21 +8,8 @@
#include "../world/Water.h"
#include "ObjectLimits.h"
extern rct_ride_entry *gRideEntries[MAX_RIDE_OBJECTS];
extern rct_small_scenery_entry *gSmallSceneryEntries[MAX_SMALL_SCENERY_OBJECTS];
extern rct_large_scenery_entry *gLargeSceneryEntries[MAX_LARGE_SCENERY_OBJECTS];
extern rct_wall_scenery_entry *gWallSceneryEntries[MAX_WALL_SCENERY_OBJECTS];
extern rct_banner *gBannerSceneryEntries[MAX_BANNER_OBJECTS];
extern rct_footpath_entry *gFootpathEntries[MAX_PATH_OBJECTS];
extern rct_path_bit_scenery_entry *gFootpathAdditionEntries[MAX_PATH_ADDITION_OBJECTS];
extern rct_scenery_group_entry *gSceneryGroupEntries[MAX_SCENERY_GROUP_OBJECTS];
extern rct_entrance_type *gParkEntranceEntries[MAX_PARK_ENTRANCE_OBJECTS];
extern rct_water_type *gWaterEntries[MAX_WATER_OBJECTS];
extern rct_stex_entry *gStexEntries[MAX_SCENARIO_TEXT_OBJECTS];
void get_type_entry_index(size_t index, uint8 * outObjectType, uint8 * outEntryIndex);
const rct_object_entry * get_loaded_object_entry(size_t index);
void * get_loaded_object_chunk(size_t index);
uint8 object_entry_get_type(const rct_object_entry * objectEntry);
uint8 object_entry_get_source_game(const rct_object_entry * objectEntry);

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,31 +44,51 @@ 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);
UpdateLegacyLoadedObjectList();
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
}
~ObjectManager() override
{
SetNewLoadedObjectList(nullptr);
UnloadAll();
}
Object * GetLoadedObject(size_t index) override
{
if (_loadedObjects == nullptr)
if (index >= OBJECT_ENTRY_COUNT)
{
#ifdef DEBUG
log_warning("Object index %u exceeds maximum of %d.", index, OBJECT_ENTRY_COUNT);
#endif
return nullptr;
}
if (index >= _loadedObjects.size())
{
return nullptr;
}
return _loadedObjects[index];
}
Object * GetLoadedObject(sint32 objectType, size_t index) override
{
if (index >= (size_t)object_entry_group_counts[objectType])
{
#ifdef DEBUG
log_warning("Object index %u exceeds maximum for type type %d.", index, objectType);
#endif
return nullptr;
}
size_t objectIndex = index;
for (sint32 i = 0; i < objectType; i++)
{
objectIndex += object_entry_group_counts[i];
}
return GetLoadedObject(objectIndex);
}
Object * GetLoadedObject(const rct_object_entry * entry) override
{
Object * loadedObject = nullptr;
@ -107,8 +127,11 @@ public:
loadedObject = GetOrLoadObject(ori);
if (loadedObject != nullptr)
{
if (_loadedObjects.size() <= (size_t)slot)
{
_loadedObjects.resize(slot + 1);
}
_loadedObjects[slot] = loadedObject;
UpdateLegacyLoadedObjectList();
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
}
@ -121,32 +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);
UpdateLegacyLoadedObjectList();
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;
}
}
@ -175,7 +194,6 @@ public:
if (numObjectsUnloaded > 0)
{
UpdateLegacyLoadedObjectList();
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
}
@ -183,35 +201,26 @@ 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);
}
UpdateLegacyLoadedObjectList();
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
}
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();
}
UpdateLegacyLoadedObjectList();
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
}
UpdateSceneryGroupIndexes();
reset_type_to_ride_entry_index_map();
}
std::vector<const ObjectRepositoryItem *> GetPackableObjects() override
@ -257,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;
@ -276,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();
}
@ -301,7 +301,6 @@ private:
{
UnloadObjectsExcept(newLoadedObjects);
}
Memory::Free(_loadedObjects);
_loadedObjects = newLoadedObjects;
}
@ -316,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);
@ -355,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++;
@ -372,78 +361,45 @@ private:
log_verbose("%u / %u objects unloaded", numObjectsUnloaded, totalObjectsLoaded);
}
void UpdateLegacyLoadedObjectList()
{
for (sint32 i = 0; i < OBJECT_ENTRY_COUNT; i++)
{
Object * loadedObject = nullptr;
if (_loadedObjects != nullptr)
{
loadedObject = _loadedObjects[i];
}
uint8 objectType, entryIndex;
get_type_entry_index(i, &objectType, &entryIndex);
rct_object_entry_extended * legacyEntry = &object_entry_groups[objectType].entries[entryIndex];
void * * legacyChunk = &object_entry_groups[objectType].chunks[entryIndex];
if (loadedObject == nullptr)
{
*legacyEntry = { 0 };
*legacyChunk = nullptr;
}
else
{
legacyEntry->entry = *loadedObject->GetObjectEntry();
legacyEntry->chunk_size = 0;
*legacyChunk = loadedObject->GetLegacyData();
}
}
}
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)
@ -517,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];
@ -532,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;
@ -564,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)

View File

@ -29,6 +29,7 @@ interface IObjectManager
virtual ~IObjectManager() { }
virtual Object * GetLoadedObject(size_t index) abstract;
virtual Object * GetLoadedObject(sint32 objectType, size_t index) abstract;
virtual Object * GetLoadedObject(const rct_object_entry * entry) abstract;
virtual uint8 GetLoadedObjectEntryIndex(const Object * object) abstract;
virtual std::vector<rct_object_entry> GetInvalidObjects(const rct_object_entry * entries) abstract;

View File

@ -221,7 +221,7 @@ static void park_entrance_paint(paint_session * session, uint8 direction, sint32
sub_98197C(session, image_id, 0, 0, 32, 0x1C, 0, height, 0, 2, height, get_current_rotation());
}
entrance = (rct_entrance_type*)object_entry_groups[OBJECT_TYPE_PARK_ENTRANCE].chunks[0];
entrance = (rct_entrance_type *)object_entry_get_chunk(OBJECT_TYPE_PARK_ENTRANCE, 0);
if (entrance == nullptr)
{
return;
@ -268,7 +268,7 @@ static void park_entrance_paint(paint_session * session, uint8 direction, sint32
break;
case 1:
case 2:
entrance = (rct_entrance_type*)object_entry_groups[OBJECT_TYPE_PARK_ENTRANCE].chunks[0];
entrance = (rct_entrance_type *)object_entry_get_chunk(OBJECT_TYPE_PARK_ENTRANCE, 0);
if (entrance == nullptr)
{
return;

View File

@ -35,6 +35,7 @@
#include "../management/NewsItem.h"
#include "../network/network.h"
#include "../object/ObjectList.h"
#include "../object/ObjectManager.h"
#include "../OpenRCT2.h"
#include "../peep/Peep.h"
#include "../peep/Staff.h"
@ -233,13 +234,17 @@ Ride *get_ride(sint32 index)
rct_ride_entry * get_ride_entry(sint32 index)
{
if (index < 0 || index >= object_entry_group_counts[OBJECT_TYPE_RIDE])
rct_ride_entry * result = nullptr;
auto objMgr = GetObjectManager();
if (objMgr != nullptr)
{
log_error("invalid index %d for ride type", index);
return nullptr;
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_RIDE, index);
if (obj != nullptr)
{
result = (rct_ride_entry *)obj->GetLegacyData();
}
}
return gRideEntries[index];
return result;
}
void get_ride_entry_name(char *name, sint32 index)
@ -250,7 +255,7 @@ void get_ride_entry_name(char *name, sint32 index)
return;
}
const char *entryName = object_entry_groups[OBJECT_TYPE_RIDE].entries[index].name;
const auto entryName = object_entry_get_entry(OBJECT_TYPE_RIDE, index)->name;
memcpy(name, entryName, 8);
name[8] = '\0';
}

View File

@ -492,7 +492,7 @@ static void track_design_mirror_scenery(rct_track_td6 * td6)
}
}
rct_scenery_entry * scenery_entry = (rct_scenery_entry *) object_entry_groups[entry_type].chunks[entry_index];
rct_scenery_entry * scenery_entry = (rct_scenery_entry *)object_entry_get_chunk(entry_type, entry_index);
switch (entry_type)
{
case OBJECT_TYPE_LARGE_SCENERY:

View File

@ -261,7 +261,7 @@ static void track_design_save_push_tile_element(sint32 x, sint32 y, rct_tile_ele
*
* rct2: 0x006D2FA7
*/
static void track_design_save_push_tile_element_desc(rct_object_entry *entry, sint32 x, sint32 y, sint32 z, uint8 flags, uint8 primaryColour, uint8 secondaryColour)
static void track_design_save_push_tile_element_desc(const rct_object_entry * entry, sint32 x, sint32 y, sint32 z, uint8 flags, uint8 primaryColour, uint8 secondaryColour)
{
rct_td6_scenery_element *item = &_trackSavedTileElementsDesc[_trackSavedTileElementsDescCount++];
item->scenery_object = *entry;
@ -276,7 +276,7 @@ static void track_design_save_push_tile_element_desc(rct_object_entry *entry, si
static void track_design_save_add_scenery(sint32 x, sint32 y, rct_tile_element *tileElement)
{
sint32 entryType = tileElement->properties.scenery.type;
rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].entries[entryType];
auto entry = object_entry_get_entry(OBJECT_TYPE_SMALL_SCENERY, entryType);
uint8 flags = 0;
flags |= tileElement->type & 3;
@ -296,7 +296,7 @@ static void track_design_save_add_large_scenery(sint32 x, sint32 y, rct_tile_ele
sint32 direction, sequence;
sint32 entryType = scenery_large_get_type(tileElement);
rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_LARGE_SCENERY].entries[entryType];
auto entry = object_entry_get_entry(OBJECT_TYPE_LARGE_SCENERY, entryType);
sceneryTiles = get_large_scenery_entry(entryType)->large_scenery.tiles;
z = tileElement->base_height;
@ -336,7 +336,7 @@ static void track_design_save_add_large_scenery(sint32 x, sint32 y, rct_tile_ele
static void track_design_save_add_wall(sint32 x, sint32 y, rct_tile_element *tileElement)
{
sint32 entryType = tileElement->properties.wall.type;
rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_WALLS].entries[entryType];
auto entry = object_entry_get_entry(OBJECT_TYPE_WALLS, entryType);
uint8 flags = 0;
flags |= tileElement->type & 3;
@ -352,7 +352,7 @@ static void track_design_save_add_wall(sint32 x, sint32 y, rct_tile_element *til
static void track_design_save_add_footpath(sint32 x, sint32 y, rct_tile_element *tileElement)
{
sint32 entryType = tileElement->properties.path.type >> 4;
rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_PATHS].entries[entryType];
auto entry = object_entry_get_entry(OBJECT_TYPE_PATHS, entryType);
uint8 flags = 0;
flags |= tileElement->properties.path.edges & FOOTPATH_PROPERTIES_EDGES_EDGES_MASK;
@ -427,7 +427,7 @@ static void track_design_save_pop_tile_element(sint32 x, sint32 y, rct_tile_elem
*
* rct2: 0x006D2FDD
*/
static void track_design_save_pop_tile_element_desc(rct_object_entry *entry, sint32 x, sint32 y, sint32 z, uint8 flags, uint8 primaryColour, uint8 secondaryColour)
static void track_design_save_pop_tile_element_desc(const rct_object_entry *entry, sint32 x, sint32 y, sint32 z, uint8 flags, uint8 primaryColour, uint8 secondaryColour)
{
size_t removeIndex = SIZE_MAX;
for (size_t i = 0; i < _trackSavedTileElementsDescCount; i++) {
@ -457,7 +457,7 @@ static void track_design_save_pop_tile_element_desc(rct_object_entry *entry, sin
static void track_design_save_remove_scenery(sint32 x, sint32 y, rct_tile_element *tileElement)
{
sint32 entryType = tileElement->properties.scenery.type;
rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].entries[entryType];
auto entry = object_entry_get_entry(OBJECT_TYPE_SMALL_SCENERY, entryType);
uint8 flags = 0;
flags |= tileElement->type & 3;
@ -477,7 +477,7 @@ static void track_design_save_remove_large_scenery(sint32 x, sint32 y, rct_tile_
sint32 direction, sequence;
sint32 entryType = scenery_large_get_type(tileElement);
rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_LARGE_SCENERY].entries[entryType];
auto entry = object_entry_get_entry(OBJECT_TYPE_LARGE_SCENERY, entryType);
sceneryTiles = get_large_scenery_entry(entryType)->large_scenery.tiles;
z = tileElement->base_height;
@ -517,7 +517,7 @@ static void track_design_save_remove_large_scenery(sint32 x, sint32 y, rct_tile_
static void track_design_save_remove_wall(sint32 x, sint32 y, rct_tile_element *tileElement)
{
sint32 entryType = tileElement->properties.wall.type;
rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_WALLS].entries[entryType];
auto entry = object_entry_get_entry(OBJECT_TYPE_WALLS, entryType);
uint8 flags = 0;
flags |= tileElement->type & 3;
@ -533,7 +533,7 @@ static void track_design_save_remove_wall(sint32 x, sint32 y, rct_tile_element *
static void track_design_save_remove_footpath(sint32 x, sint32 y, rct_tile_element *tileElement)
{
sint32 entryType = tileElement->properties.path.type >> 4;
rct_object_entry *entry = (rct_object_entry*)&object_entry_groups[OBJECT_TYPE_PATHS].entries[entryType];
auto entry = object_entry_get_entry(OBJECT_TYPE_PATHS, entryType);
uint8 flags = 0;
flags |= tileElement->properties.path.edges & FOOTPATH_PROPERTIES_EDGES_EDGES_MASK;
@ -718,7 +718,7 @@ static rct_track_td6 *track_design_save_to_td6(uint8 rideIndex)
rct_track_td6 *td6 = (rct_track_td6 *)calloc(1, sizeof(rct_track_td6));
Ride *ride = get_ride(rideIndex);
td6->type = ride->type;
rct_object_entry_extended *object = &object_entry_groups[OBJECT_TYPE_RIDE].entries[ride->subtype];
auto object = object_entry_get_entry(OBJECT_TYPE_RIDE, ride->subtype);
// Note we are only copying rct_object_entry in size and
// not the extended as we don't need the chunk size.

View File

@ -134,7 +134,7 @@ void scenario_begin()
}
}
else {
rct_stex_entry* stex = g_stexEntries[0];
auto stex = (rct_stex_entry *)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0);
if (stex != nullptr) {
char *buffer = gCommonStringFormatBuffer;
@ -332,7 +332,7 @@ static void scenario_week_update()
ride_check_all_reachable();
ride_update_favourited_stat();
rct_water_type* water_type = (rct_water_type*)object_entry_groups[OBJECT_TYPE_WATER].chunks[0];
auto water_type = (rct_water_type *)object_entry_get_chunk(OBJECT_TYPE_WATER, 0);
if (month <= MONTH_APRIL && water_type != nullptr && water_type->flags & WATER_FLAGS_ALLOW_DUCKS) {
// 100 attempts at finding some water to create a few ducks at
@ -643,13 +643,13 @@ bool scenario_prepare_for_save()
{
gS6Info.entry.flags = 255;
rct_stex_entry* stex = g_stexEntries[0];
auto stex = (rct_stex_entry *)object_entry_get_chunk(OBJECT_TYPE_SCENARIO_TEXT, 0);
if (stex != nullptr) {
char buffer[256];
format_string(buffer, 256, stex->scenario_name, nullptr);
safe_strcpy(gS6Info.name, buffer, sizeof(gS6Info.name));
memcpy(&gS6Info.entry, &object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0], sizeof(rct_object_entry));
memcpy(&gS6Info.entry, object_entry_get_entry(OBJECT_TYPE_SCENARIO_TEXT, 0), sizeof(rct_object_entry));
}
if (gS6Info.name[0] == 0)

View File

@ -84,8 +84,6 @@ typedef struct rct_stex_entry {
} rct_stex_entry;
assert_struct_size(rct_stex_entry, 7);
#define g_stexEntries ((rct_stex_entry**)object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].chunks)
// This will be useful for backwards compatibility
typedef struct rct_s6_data {
// SC6[0]

View File

@ -21,6 +21,7 @@
#include "../localisation/Localisation.h"
#include "../network/network.h"
#include "../object/ObjectList.h"
#include "../object/ObjectManager.h"
#include "../OpenRCT2.h"
#include "../ride/Station.h"
#include "../ride/Track.h"
@ -2273,7 +2274,17 @@ void footpath_remove_edges_at(sint32 x, sint32 y, rct_tile_element *tileElement)
rct_footpath_entry *get_footpath_entry(sint32 entryIndex)
{
return gFootpathEntries[entryIndex];
rct_footpath_entry * result = nullptr;
auto objMgr = GetObjectManager();
if (objMgr != nullptr)
{
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_PATHS, entryIndex);
if (obj != nullptr)
{
result = (rct_footpath_entry *)obj->GetLegacyData();
}
}
return result;
}
uint8 footpath_get_edges(const rct_tile_element * element)

View File

@ -269,8 +269,8 @@ static void mapgen_place_trees()
for (sint32 i = 0; i < object_entry_group_counts[OBJECT_TYPE_SMALL_SCENERY]; i++)
{
rct_scenery_entry * sceneryEntry = get_small_scenery_entry(i);
rct_object_entry_extended * entry = &object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].entries[i];
auto sceneryEntry = get_small_scenery_entry(i);
auto entry = object_entry_get_entry(OBJECT_TYPE_SMALL_SCENERY, i);
if (sceneryEntry == nullptr)
continue;

View File

@ -20,6 +20,7 @@
#include "../localisation/Localisation.h"
#include "../network/network.h"
#include "../object/ObjectList.h"
#include "../object/ObjectManager.h"
#include "../scenario/Scenario.h"
#include "Climate.h"
#include "Footpath.h"
@ -279,50 +280,92 @@ void scenery_remove_ghost_tool_placement(){
rct_scenery_entry *get_small_scenery_entry(sint32 entryIndex)
{
if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_SMALL_SCENERY]) {
return nullptr;
rct_scenery_entry * result = nullptr;
auto objMgr = GetObjectManager();
if (objMgr != nullptr)
{
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_SMALL_SCENERY, entryIndex);
if (obj != nullptr)
{
result = (rct_scenery_entry *)obj->GetLegacyData();
}
}
return (rct_scenery_entry*)gSmallSceneryEntries[entryIndex];
return result;
}
rct_scenery_entry *get_large_scenery_entry(sint32 entryIndex)
{
if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_LARGE_SCENERY]) {
return nullptr;
rct_scenery_entry * result = nullptr;
auto objMgr = GetObjectManager();
if (objMgr != nullptr)
{
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_LARGE_SCENERY, entryIndex);
if (obj != nullptr)
{
result = (rct_scenery_entry *)obj->GetLegacyData();
}
}
return (rct_scenery_entry*)gLargeSceneryEntries[entryIndex];
return result;
}
rct_scenery_entry *get_wall_entry(sint32 entryIndex)
{
if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_WALLS]) {
return nullptr;
rct_scenery_entry * result = nullptr;
auto objMgr = GetObjectManager();
if (objMgr != nullptr)
{
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_WALLS, entryIndex);
if (obj != nullptr)
{
result = (rct_scenery_entry *)obj->GetLegacyData();
}
}
return (rct_scenery_entry*)gWallSceneryEntries[entryIndex];
return result;
}
rct_scenery_entry *get_banner_entry(sint32 entryIndex)
{
if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_BANNERS]) {
return nullptr;
rct_scenery_entry * result = nullptr;
auto objMgr = GetObjectManager();
if (objMgr != nullptr)
{
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_BANNERS, entryIndex);
if (obj != nullptr)
{
result = (rct_scenery_entry *)obj->GetLegacyData();
}
}
return (rct_scenery_entry*)gBannerSceneryEntries[entryIndex];
return result;
}
rct_scenery_entry *get_footpath_item_entry(sint32 entryIndex)
{
if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_PATH_BITS]) {
return nullptr;
rct_scenery_entry * result = nullptr;
auto objMgr = GetObjectManager();
if (objMgr != nullptr)
{
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_PATH_BITS, entryIndex);
if (obj != nullptr)
{
result = (rct_scenery_entry *)obj->GetLegacyData();
}
}
return (rct_scenery_entry*)gFootpathAdditionEntries[entryIndex];
return result;
}
rct_scenery_group_entry *get_scenery_group_entry(sint32 entryIndex)
{
if (entryIndex >= object_entry_group_counts[OBJECT_TYPE_SCENERY_GROUP]) {
return nullptr;
rct_scenery_group_entry * result = nullptr;
auto objMgr = GetObjectManager();
if (objMgr != nullptr)
{
auto obj = objMgr->GetLoadedObject(OBJECT_TYPE_SCENERY_GROUP, entryIndex);
if (obj != nullptr)
{
result = (rct_scenery_group_entry *)obj->GetLegacyData();
}
}
return (rct_scenery_group_entry*)gSceneryGroupEntries[entryIndex];
return result;
}
sint32 get_scenery_id_from_entry_index(uint8 objectType, sint32 entryIndex)