mirror of https://github.com/OpenRCT2/OpenRCT2.git
Extract functions from EditorObjectSelection
This commit is contained in:
parent
862ab26cc1
commit
2d776de772
|
@ -22,7 +22,6 @@
|
|||
#include <openrct2/config/Config.h>
|
||||
#include <openrct2/Context.h>
|
||||
#include <openrct2/core/Memory.hpp>
|
||||
#include <openrct2/core/Util.hpp>
|
||||
#include <openrct2/Editor.h>
|
||||
#include <openrct2/Game.h>
|
||||
#include <openrct2/interface/widget.h>
|
||||
|
@ -33,13 +32,11 @@
|
|||
#include <openrct2/OpenRCT2.h>
|
||||
#include <openrct2/platform/platform.h>
|
||||
#include <openrct2/ride/RideGroupManager.h>
|
||||
#include <openrct2/ride/ride_data.h>
|
||||
#include <openrct2/sprites.h>
|
||||
#include <openrct2/util/util.h>
|
||||
#include <openrct2/windows/dropdown.h>
|
||||
#include <openrct2/windows/Intent.h>
|
||||
#include <openrct2/windows/_legacy.h>
|
||||
#include <openrct2/world/LargeScenery.h>
|
||||
#include <openrct2/EditorObjectSelectionSession.h>
|
||||
|
||||
enum {
|
||||
FILTER_RCT2 = (1 << 0),
|
||||
|
@ -235,9 +232,6 @@ const sint32 window_editor_object_selection_animation_divisor[] = { 4, 8, 2, 4,
|
|||
|
||||
static void window_editor_object_set_page(rct_window *w, sint32 page);
|
||||
static void window_editor_object_selection_set_pressed_tab(rct_window *w);
|
||||
static void window_editor_object_selection_select_default_objects();
|
||||
static void window_editor_object_selection_select_required_objects();
|
||||
static sint32 window_editor_object_selection_select_object(uint8 bh, sint32 flags, const rct_object_entry *entry);
|
||||
static sint32 get_object_from_object_selection(uint8 object_type, sint32 y);
|
||||
static void window_editor_object_selection_manage_tracks();
|
||||
static void editor_load_selected_objects();
|
||||
|
@ -247,10 +241,6 @@ static bool filter_source(const ObjectRepositoryItem * item);
|
|||
static bool filter_chunks(const ObjectRepositoryItem * item);
|
||||
static void filter_update_counts();
|
||||
|
||||
static void reset_selected_object_count_and_size();
|
||||
static sint32 sub_6AB211();
|
||||
|
||||
|
||||
enum {
|
||||
RIDE_SORT_TYPE,
|
||||
RIDE_SORT_RIDE
|
||||
|
@ -282,10 +272,6 @@ static list_item *_listItems = nullptr;
|
|||
static sint32 _listSortType = RIDE_SORT_TYPE;
|
||||
static bool _listSortDescending = false;
|
||||
static void * _loadedObject = nullptr;
|
||||
static uint8 * _objectSelectionFlags = nullptr;
|
||||
static sint32 _numSelectedObjectsForType[OBJECT_TYPE_COUNT];
|
||||
static sint32 _numAvailableObjectsForType[OBJECT_TYPE_COUNT];
|
||||
static bool _maxObjectsWasHit;
|
||||
|
||||
static void visible_list_dispose()
|
||||
{
|
||||
|
@ -447,268 +433,6 @@ rct_window * window_editor_object_selection_open()
|
|||
return window;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006ABCD1
|
||||
*/
|
||||
static void setup_track_manager_objects()
|
||||
{
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 * selectionFlags = &_objectSelectionFlags[i];
|
||||
const ObjectRepositoryItem * item = &items[i];
|
||||
uint8 object_type = item->ObjectEntry.flags & 0xF;
|
||||
if (object_type == OBJECT_TYPE_RIDE) {
|
||||
*selectionFlags |= OBJECT_SELECTION_FLAG_6;
|
||||
|
||||
for (uint8 j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++) {
|
||||
uint8 rideType = item->RideType[j];
|
||||
if (rideType != RIDE_TYPE_NULL && ride_type_has_flag(rideType, RIDE_TYPE_FLAG_HAS_TRACK)) {
|
||||
*selectionFlags &= ~OBJECT_SELECTION_FLAG_6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006ABC1E
|
||||
*/
|
||||
static void setup_track_designer_objects()
|
||||
{
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 * selectionFlags = &_objectSelectionFlags[i];
|
||||
const ObjectRepositoryItem * item = &items[i];
|
||||
uint8 objectType = item->ObjectEntry.flags & 0xF;
|
||||
if (objectType == OBJECT_TYPE_RIDE){
|
||||
*selectionFlags |= OBJECT_SELECTION_FLAG_6;
|
||||
|
||||
for (uint8 j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++) {
|
||||
uint8 rideType = item->RideType[j];
|
||||
if (rideType != RIDE_TYPE_NULL) {
|
||||
if (RideData4[rideType].flags & RIDE_TYPE_FLAG4_SHOW_IN_TRACK_DESIGNER) {
|
||||
*selectionFlags &= ~OBJECT_SELECTION_FLAG_6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AA82B
|
||||
*/
|
||||
static 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tile_element_iterator iter;
|
||||
tile_element_iterator_begin(&iter);
|
||||
do {
|
||||
uint16 type;
|
||||
rct_banner* banner;
|
||||
|
||||
switch (tile_element_get_type(iter.element)) {
|
||||
default:
|
||||
case TILE_ELEMENT_TYPE_SURFACE:
|
||||
case TILE_ELEMENT_TYPE_TRACK:
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_PATH:
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_ENTRANCE:
|
||||
if (iter.element->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE)
|
||||
break;
|
||||
|
||||
Editor::SelectedObjects[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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
} while (tile_element_iterator_next(&iter));
|
||||
|
||||
for (uint8 ride_index = 0; ride_index < 0xFF; ride_index++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 *selectionFlags = &_objectSelectionFlags[i];
|
||||
const ObjectRepositoryItem * item = &items[i];
|
||||
*selectionFlags &= ~OBJECT_SELECTION_FLAG_IN_USE;
|
||||
|
||||
uint8 entryType, entryIndex;
|
||||
if (find_object_in_entry_group(&item->ObjectEntry, &entryType, &entryIndex)) {
|
||||
if (Editor::SelectedObjects[entryType][entryIndex] & OBJECT_SELECTION_FLAG_SELECTED) {
|
||||
*selectionFlags |=
|
||||
OBJECT_SELECTION_FLAG_IN_USE |
|
||||
OBJECT_SELECTION_FLAG_SELECTED;
|
||||
}
|
||||
if (Editor::SelectedObjects[entryType][entryIndex] & OBJECT_SELECTION_FLAG_2) {
|
||||
*selectionFlags |= OBJECT_SELECTION_FLAG_SELECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AB211
|
||||
*/
|
||||
static sint32 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 0;
|
||||
}
|
||||
|
||||
for (uint8 objectType = 0; objectType < 11; objectType++) {
|
||||
_numSelectedObjectsForType[objectType] = 0;
|
||||
_numAvailableObjectsForType[objectType] = 0;
|
||||
}
|
||||
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 objectType = items[i].ObjectEntry.flags & 0xF;
|
||||
_numAvailableObjectsForType[objectType]++;
|
||||
}
|
||||
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) {
|
||||
setup_track_designer_objects();
|
||||
}
|
||||
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
|
||||
setup_track_manager_objects();
|
||||
}
|
||||
|
||||
setup_in_use_selection_flags();
|
||||
reset_selected_object_count_and_size();
|
||||
|
||||
if (!(gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER))) {
|
||||
window_editor_object_selection_select_required_objects();
|
||||
|
||||
// To prevent it breaking in scenario mode.
|
||||
if (gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) {
|
||||
window_editor_object_selection_select_default_objects();
|
||||
}
|
||||
}
|
||||
|
||||
reset_selected_object_count_and_size();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AB316
|
||||
*/
|
||||
static void editor_object_flags_free()
|
||||
{
|
||||
SafeFree(_objectSelectionFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00685791
|
||||
*/
|
||||
static void remove_selected_objects_from_research(const rct_object_entry* installedObject){
|
||||
uint8 entry_type, entry_index;
|
||||
if (!find_object_in_entry_group(installedObject, &entry_type, &entry_index))
|
||||
return;
|
||||
|
||||
if (entry_type == OBJECT_TYPE_RIDE){
|
||||
rct_ride_entry* rideEntry = (rct_ride_entry*)object_entry_groups[entry_type].chunks[entry_index];
|
||||
|
||||
for (uint8 j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++) {
|
||||
research_remove(entry_index | rideEntry->ride_type[j] << 8 | 0x10000);
|
||||
}
|
||||
}
|
||||
else if (entry_type == OBJECT_TYPE_SCENERY_GROUP){
|
||||
research_remove(entry_index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006ABB66
|
||||
*/
|
||||
static void unload_unselected_objects()
|
||||
{
|
||||
sint32 numItems = (sint32)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 (sint32 i = 0; i < numItems; i++) {
|
||||
if (!(_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_SELECTED)) {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AB199
|
||||
|
@ -1482,158 +1206,6 @@ static void window_editor_object_selection_set_pressed_tab(rct_window *w)
|
|||
w->pressed_widgets |= 1LL << (WIDX_TAB_1 + w->selected_tab);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AA805
|
||||
*/
|
||||
static void window_editor_object_selection_select_default_objects()
|
||||
{
|
||||
if (_numSelectedObjectsForType[0] == 0) {
|
||||
for (sint32 i = 0; i < (sint32)Util::CountOf(DefaultSelectedObjects); i++) {
|
||||
window_editor_object_selection_select_object(0, 7, &DefaultSelectedObjects[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AA7E9
|
||||
*/
|
||||
static void window_editor_object_selection_select_required_objects()
|
||||
{
|
||||
sint32 i;
|
||||
|
||||
for (i = 0; i < (sint32)Util::CountOf(RequiredSelectedObjects); i++)
|
||||
window_editor_object_selection_select_object(0, 0xF, &RequiredSelectedObjects[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AA770
|
||||
*/
|
||||
static void reset_selected_object_count_and_size()
|
||||
{
|
||||
for (uint8 objectType = 0; objectType < 11; objectType++) {
|
||||
_numSelectedObjectsForType[objectType] = 0;
|
||||
}
|
||||
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 objectType = items[i].ObjectEntry.flags & 0xF;
|
||||
if (_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_SELECTED) {
|
||||
_numSelectedObjectsForType[objectType]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Master objects are objects that are not
|
||||
* optional / required dependants of an
|
||||
* object.
|
||||
*/
|
||||
static void set_object_selection_error(uint8 is_master_object, rct_string_id error_msg){
|
||||
gGameCommandErrorText = error_msg;
|
||||
if (!is_master_object){
|
||||
reset_selected_object_count_and_size();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AB54F
|
||||
*/
|
||||
static sint32 window_editor_object_selection_select_object(uint8 bh, sint32 flags, const rct_object_entry *entry)
|
||||
{
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * item = object_repository_find_object_by_entry(entry);
|
||||
if (item == nullptr) {
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_OBJECT_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get repository item index
|
||||
sint32 index = -1;
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
if (&items[i] == item) {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 * selectionFlags = &_objectSelectionFlags[index];
|
||||
if (!(flags & 1)) {
|
||||
if (!(*selectionFlags & OBJECT_SELECTION_FLAG_SELECTED)) {
|
||||
return 1;
|
||||
}
|
||||
else if (*selectionFlags & OBJECT_SELECTION_FLAG_IN_USE) {
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_CURRENTLY_IN_USE);
|
||||
return 0;
|
||||
}
|
||||
else if (*selectionFlags & OBJECT_SELECTION_FLAG_ALWAYS_REQUIRED) {
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_ALWAYS_REQUIRED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 objectType = item->ObjectEntry.flags & 0xF;
|
||||
if (objectType == OBJECT_TYPE_SCENERY_GROUP && (flags & (1 << 2))) {
|
||||
for (sint32 j = 0; j < item->NumThemeObjects; j++) {
|
||||
window_editor_object_selection_select_object(++bh, flags, &item->ThemeObjects[j]);
|
||||
}
|
||||
}
|
||||
|
||||
_numSelectedObjectsForType[objectType]--;
|
||||
*selectionFlags &= ~OBJECT_SELECTION_FLAG_SELECTED;
|
||||
return 1;
|
||||
} else {
|
||||
if (bh == 0) {
|
||||
if (flags & (1 << 3)) {
|
||||
*selectionFlags |= OBJECT_SELECTION_FLAG_ALWAYS_REQUIRED;
|
||||
}
|
||||
}
|
||||
if (*selectionFlags & OBJECT_SELECTION_FLAG_SELECTED) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8 objectType = item->ObjectEntry.flags & 0xF;
|
||||
uint16 maxObjects = object_entry_group_counts[objectType];
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) {
|
||||
maxObjects = 4;
|
||||
}
|
||||
|
||||
if (maxObjects <= _numSelectedObjectsForType[objectType]) {
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_TOO_MANY_OF_TYPE_SELECTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (objectType == OBJECT_TYPE_SCENERY_GROUP && (flags & (1 << 2))) {
|
||||
for (uint16 j = 0; j < item->NumThemeObjects; j++) {
|
||||
if (!window_editor_object_selection_select_object(++bh, flags, &item->ThemeObjects[j])) {
|
||||
_maxObjectsWasHit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bh != 0 && !(flags & (1 << 1))) {
|
||||
char objectName[64];
|
||||
object_create_identifier_name(objectName, 64, &item->ObjectEntry);
|
||||
set_format_arg(0, const char *, objectName);
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_SHOULD_SELECT_X_FIRST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (maxObjects <= _numSelectedObjectsForType[objectType]) {
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_TOO_MANY_OF_TYPE_SELECTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_numSelectedObjectsForType[objectType]++;
|
||||
|
||||
*selectionFlags |= OBJECT_SELECTION_FLAG_SELECTED;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the y coordinate of the clicked on scroll list
|
||||
* and converts this into an object selection.
|
||||
|
@ -1881,61 +1453,3 @@ static rct_string_id get_ride_type_string_id(const ObjectRepositoryItem * item)
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool editor_check_object_group_at_least_one_selected(sint32 checkObjectType)
|
||||
{
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 objectType = items[i].ObjectEntry.flags & 0x0F;
|
||||
if (checkObjectType == objectType && (_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_SELECTED)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
sint32 editor_remove_unused_objects()
|
||||
{
|
||||
bool createSelectionFlags = (_objectSelectionFlags == nullptr);
|
||||
if (createSelectionFlags && !sub_6AB211())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
setup_in_use_selection_flags();
|
||||
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
|
||||
sint32 numUnselectedObjects = 0;
|
||||
for (sint32 i = 0; i < numObjects; i++)
|
||||
{
|
||||
if (!(_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_IN_USE) && !(_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_ALWAYS_REQUIRED))
|
||||
{
|
||||
const ObjectRepositoryItem * item = &items[i];
|
||||
uint8 objectType = item->ObjectEntry.flags & 0xF;
|
||||
|
||||
if (objectType == OBJECT_TYPE_PARK_ENTRANCE || objectType == OBJECT_TYPE_SCENARIO_TEXT || objectType == OBJECT_TYPE_WATER || objectType == OBJECT_TYPE_SCENERY_GROUP)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_numSelectedObjectsForType[objectType]--;
|
||||
_objectSelectionFlags[i] &= ~OBJECT_SELECTION_FLAG_SELECTED;
|
||||
numUnselectedObjects++;
|
||||
}
|
||||
}
|
||||
unload_unselected_objects();
|
||||
|
||||
if (createSelectionFlags)
|
||||
{
|
||||
editor_object_flags_free();
|
||||
}
|
||||
|
||||
auto intent = Intent(INTENT_ACTION_REFRESH_SCENERY);
|
||||
context_broadcast_intent(&intent);
|
||||
|
||||
return numUnselectedObjects;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "windows/Intent.h"
|
||||
#include "world/Climate.h"
|
||||
#include "object/ObjectRepository.h"
|
||||
#include "EditorObjectSelectionSession.h"
|
||||
|
||||
namespace Editor
|
||||
{
|
||||
|
|
|
@ -40,8 +40,6 @@ namespace Editor
|
|||
void GameCommandEditScenarioOptions(sint32*, sint32*, sint32*, sint32*, sint32*, sint32*, sint32*);
|
||||
}
|
||||
|
||||
bool editor_check_object_group_at_least_one_selected(sint32 objectType);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
@ -84,12 +82,6 @@ extern "C"
|
|||
};
|
||||
|
||||
void editor_open_windows_for_current_step();
|
||||
|
||||
/**
|
||||
* Removes all unused objects from the object selection.
|
||||
* @return The number of removed objects.
|
||||
*/
|
||||
sint32 editor_remove_unused_objects();
|
||||
|
||||
void game_command_edit_scenario_options(sint32* eax, sint32* ebx, sint32* ecx, sint32* edx, sint32* esi, sint32* edi, sint32* ebp);
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -0,0 +1,513 @@
|
|||
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
||||
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* A full copy of the GNU General Public License can be found in licence.txt
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#include "Context.h"
|
||||
#include "core/Util.hpp"
|
||||
#include "Editor.h"
|
||||
#include "EditorObjectSelectionSession.h"
|
||||
#include "Game.h"
|
||||
#include "localisation/localisation.h"
|
||||
#include "object/ObjectManager.h"
|
||||
#include "object/ObjectRepository.h"
|
||||
#include "OpenRCT2.h"
|
||||
#include "ride/ride_data.h"
|
||||
#include "windows/Intent.h"
|
||||
#include "windows/_legacy.h"
|
||||
#include "world/footpath.h"
|
||||
#include "world/LargeScenery.h"
|
||||
|
||||
bool _maxObjectsWasHit;
|
||||
uint8 * _objectSelectionFlags = nullptr;
|
||||
sint32 _numSelectedObjectsForType[OBJECT_TYPE_COUNT];
|
||||
static sint32 _numAvailableObjectsForType[OBJECT_TYPE_COUNT];
|
||||
|
||||
static void setup_in_use_selection_flags();
|
||||
static void setup_track_designer_objects();
|
||||
static void setup_track_manager_objects();
|
||||
static void window_editor_object_selection_select_required_objects();
|
||||
static void window_editor_object_selection_select_default_objects();
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006ABCD1
|
||||
*/
|
||||
static void setup_track_manager_objects()
|
||||
{
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 * selectionFlags = &_objectSelectionFlags[i];
|
||||
const ObjectRepositoryItem * item = &items[i];
|
||||
uint8 object_type = item->ObjectEntry.flags & 0xF;
|
||||
if (object_type == OBJECT_TYPE_RIDE) {
|
||||
*selectionFlags |= OBJECT_SELECTION_FLAG_6;
|
||||
|
||||
for (uint8 j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++) {
|
||||
uint8 rideType = item->RideType[j];
|
||||
if (rideType != RIDE_TYPE_NULL && ride_type_has_flag(rideType, RIDE_TYPE_FLAG_HAS_TRACK)) {
|
||||
*selectionFlags &= ~OBJECT_SELECTION_FLAG_6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006ABC1E
|
||||
*/
|
||||
static void setup_track_designer_objects()
|
||||
{
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 * selectionFlags = &_objectSelectionFlags[i];
|
||||
const ObjectRepositoryItem * item = &items[i];
|
||||
uint8 objectType = item->ObjectEntry.flags & 0xF;
|
||||
if (objectType == OBJECT_TYPE_RIDE){
|
||||
*selectionFlags |= OBJECT_SELECTION_FLAG_6;
|
||||
|
||||
for (uint8 j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++) {
|
||||
uint8 rideType = item->RideType[j];
|
||||
if (rideType != RIDE_TYPE_NULL) {
|
||||
if (RideData4[rideType].flags & RIDE_TYPE_FLAG4_SHOW_IN_TRACK_DESIGNER) {
|
||||
*selectionFlags &= ~OBJECT_SELECTION_FLAG_6;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AA82B
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tile_element_iterator iter;
|
||||
tile_element_iterator_begin(&iter);
|
||||
do {
|
||||
uint16 type;
|
||||
rct_banner* banner;
|
||||
|
||||
switch (tile_element_get_type(iter.element)) {
|
||||
default:
|
||||
case TILE_ELEMENT_TYPE_SURFACE:
|
||||
case TILE_ELEMENT_TYPE_TRACK:
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_PATH:
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
break;
|
||||
case TILE_ELEMENT_TYPE_ENTRANCE:
|
||||
if (iter.element->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE)
|
||||
break;
|
||||
|
||||
Editor::SelectedObjects[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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
break;
|
||||
}
|
||||
} while (tile_element_iterator_next(&iter));
|
||||
|
||||
for (uint8 ride_index = 0; ride_index < 0xFF; ride_index++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 *selectionFlags = &_objectSelectionFlags[i];
|
||||
const ObjectRepositoryItem * item = &items[i];
|
||||
*selectionFlags &= ~OBJECT_SELECTION_FLAG_IN_USE;
|
||||
|
||||
uint8 entryType, entryIndex;
|
||||
if (find_object_in_entry_group(&item->ObjectEntry, &entryType, &entryIndex)) {
|
||||
if (Editor::SelectedObjects[entryType][entryIndex] & OBJECT_SELECTION_FLAG_SELECTED) {
|
||||
*selectionFlags |=
|
||||
OBJECT_SELECTION_FLAG_IN_USE |
|
||||
OBJECT_SELECTION_FLAG_SELECTED;
|
||||
}
|
||||
if (Editor::SelectedObjects[entryType][entryIndex] & OBJECT_SELECTION_FLAG_2) {
|
||||
*selectionFlags |= OBJECT_SELECTION_FLAG_SELECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AB211
|
||||
*/
|
||||
bool 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;
|
||||
}
|
||||
|
||||
for (uint8 objectType = 0; objectType < 11; objectType++) {
|
||||
_numSelectedObjectsForType[objectType] = 0;
|
||||
_numAvailableObjectsForType[objectType] = 0;
|
||||
}
|
||||
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 objectType = items[i].ObjectEntry.flags & 0xF;
|
||||
_numAvailableObjectsForType[objectType]++;
|
||||
}
|
||||
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) {
|
||||
setup_track_designer_objects();
|
||||
}
|
||||
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
|
||||
setup_track_manager_objects();
|
||||
}
|
||||
|
||||
setup_in_use_selection_flags();
|
||||
reset_selected_object_count_and_size();
|
||||
|
||||
if (!(gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER))) {
|
||||
window_editor_object_selection_select_required_objects();
|
||||
|
||||
// To prevent it breaking in scenario mode.
|
||||
if (gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) {
|
||||
window_editor_object_selection_select_default_objects();
|
||||
}
|
||||
}
|
||||
|
||||
reset_selected_object_count_and_size();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AB316
|
||||
*/
|
||||
void editor_object_flags_free()
|
||||
{
|
||||
SafeFree(_objectSelectionFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00685791
|
||||
*/
|
||||
static void remove_selected_objects_from_research(const rct_object_entry* installedObject){
|
||||
uint8 entry_type, entry_index;
|
||||
if (!find_object_in_entry_group(installedObject, &entry_type, &entry_index))
|
||||
return;
|
||||
|
||||
if (entry_type == OBJECT_TYPE_RIDE){
|
||||
rct_ride_entry* rideEntry = (rct_ride_entry*)object_entry_groups[entry_type].chunks[entry_index];
|
||||
|
||||
for (uint8 j = 0; j < MAX_RIDE_TYPES_PER_RIDE_ENTRY; j++) {
|
||||
research_remove(entry_index | rideEntry->ride_type[j] << 8 | 0x10000);
|
||||
}
|
||||
}
|
||||
else if (entry_type == OBJECT_TYPE_SCENERY_GROUP){
|
||||
research_remove(entry_index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006ABB66
|
||||
*/
|
||||
void unload_unselected_objects()
|
||||
{
|
||||
sint32 numItems = (sint32)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 (sint32 i = 0; i < numItems; i++) {
|
||||
if (!(_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_SELECTED)) {
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AA805
|
||||
*/
|
||||
static void window_editor_object_selection_select_default_objects()
|
||||
{
|
||||
if (_numSelectedObjectsForType[0] == 0) {
|
||||
for (sint32 i = 0; i < (sint32)Util::CountOf(DefaultSelectedObjects); i++) {
|
||||
window_editor_object_selection_select_object(0, 7, &DefaultSelectedObjects[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AA7E9
|
||||
*/
|
||||
static void window_editor_object_selection_select_required_objects()
|
||||
{
|
||||
sint32 i;
|
||||
|
||||
for (i = 0; i < (sint32)Util::CountOf(RequiredSelectedObjects); i++)
|
||||
window_editor_object_selection_select_object(0, 0xF, &RequiredSelectedObjects[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AA770
|
||||
*/
|
||||
void reset_selected_object_count_and_size()
|
||||
{
|
||||
for (uint8 objectType = 0; objectType < 11; objectType++) {
|
||||
_numSelectedObjectsForType[objectType] = 0;
|
||||
}
|
||||
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 objectType = items[i].ObjectEntry.flags & 0xF;
|
||||
if (_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_SELECTED) {
|
||||
_numSelectedObjectsForType[objectType]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Master objects are objects that are not
|
||||
* optional / required dependants of an
|
||||
* object.
|
||||
*/
|
||||
static void set_object_selection_error(uint8 is_master_object, rct_string_id error_msg){
|
||||
gGameCommandErrorText = error_msg;
|
||||
if (!is_master_object){
|
||||
reset_selected_object_count_and_size();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AB54F
|
||||
*/
|
||||
sint32 window_editor_object_selection_select_object(uint8 bh, sint32 flags, const rct_object_entry *entry)
|
||||
{
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * item = object_repository_find_object_by_entry(entry);
|
||||
if (item == nullptr) {
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_OBJECT_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get repository item index
|
||||
sint32 index = -1;
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
if (&items[i] == item) {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 * selectionFlags = &_objectSelectionFlags[index];
|
||||
if (!(flags & 1)) {
|
||||
if (!(*selectionFlags & OBJECT_SELECTION_FLAG_SELECTED)) {
|
||||
return 1;
|
||||
}
|
||||
else if (*selectionFlags & OBJECT_SELECTION_FLAG_IN_USE) {
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_CURRENTLY_IN_USE);
|
||||
return 0;
|
||||
}
|
||||
else if (*selectionFlags & OBJECT_SELECTION_FLAG_ALWAYS_REQUIRED) {
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_ALWAYS_REQUIRED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8 objectType = item->ObjectEntry.flags & 0xF;
|
||||
if (objectType == OBJECT_TYPE_SCENERY_GROUP && (flags & (1 << 2))) {
|
||||
for (sint32 j = 0; j < item->NumThemeObjects; j++) {
|
||||
window_editor_object_selection_select_object(++bh, flags, &item->ThemeObjects[j]);
|
||||
}
|
||||
}
|
||||
|
||||
_numSelectedObjectsForType[objectType]--;
|
||||
*selectionFlags &= ~OBJECT_SELECTION_FLAG_SELECTED;
|
||||
return 1;
|
||||
} else {
|
||||
if (bh == 0) {
|
||||
if (flags & (1 << 3)) {
|
||||
*selectionFlags |= OBJECT_SELECTION_FLAG_ALWAYS_REQUIRED;
|
||||
}
|
||||
}
|
||||
if (*selectionFlags & OBJECT_SELECTION_FLAG_SELECTED) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8 objectType = item->ObjectEntry.flags & 0xF;
|
||||
uint16 maxObjects = object_entry_group_counts[objectType];
|
||||
if (gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) {
|
||||
maxObjects = 4;
|
||||
}
|
||||
|
||||
if (maxObjects <= _numSelectedObjectsForType[objectType]) {
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_TOO_MANY_OF_TYPE_SELECTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (objectType == OBJECT_TYPE_SCENERY_GROUP && (flags & (1 << 2))) {
|
||||
for (uint16 j = 0; j < item->NumThemeObjects; j++) {
|
||||
if (!window_editor_object_selection_select_object(++bh, flags, &item->ThemeObjects[j])) {
|
||||
_maxObjectsWasHit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bh != 0 && !(flags & (1 << 1))) {
|
||||
char objectName[64];
|
||||
object_create_identifier_name(objectName, 64, &item->ObjectEntry);
|
||||
set_format_arg(0, const char *, objectName);
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_SHOULD_SELECT_X_FIRST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (maxObjects <= _numSelectedObjectsForType[objectType]) {
|
||||
set_object_selection_error(bh, STR_OBJECT_SELECTION_ERR_TOO_MANY_OF_TYPE_SELECTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_numSelectedObjectsForType[objectType]++;
|
||||
|
||||
*selectionFlags |= OBJECT_SELECTION_FLAG_SELECTED;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool editor_check_object_group_at_least_one_selected(sint32 checkObjectType)
|
||||
{
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
|
||||
for (sint32 i = 0; i < numObjects; i++) {
|
||||
uint8 objectType = items[i].ObjectEntry.flags & 0x0F;
|
||||
if (checkObjectType == objectType && (_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_SELECTED)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
sint32 editor_remove_unused_objects()
|
||||
{
|
||||
bool createSelectionFlags = (_objectSelectionFlags == nullptr);
|
||||
if (createSelectionFlags && !sub_6AB211())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
setup_in_use_selection_flags();
|
||||
|
||||
sint32 numObjects = (sint32)object_repository_get_items_count();
|
||||
const ObjectRepositoryItem * items = object_repository_get_items();
|
||||
|
||||
sint32 numUnselectedObjects = 0;
|
||||
for (sint32 i = 0; i < numObjects; i++)
|
||||
{
|
||||
if (!(_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_IN_USE) && !(_objectSelectionFlags[i] & OBJECT_SELECTION_FLAG_ALWAYS_REQUIRED))
|
||||
{
|
||||
const ObjectRepositoryItem * item = &items[i];
|
||||
uint8 objectType = item->ObjectEntry.flags & 0xF;
|
||||
|
||||
if (objectType == OBJECT_TYPE_PARK_ENTRANCE || objectType == OBJECT_TYPE_SCENARIO_TEXT || objectType == OBJECT_TYPE_WATER || objectType == OBJECT_TYPE_SCENERY_GROUP)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_numSelectedObjectsForType[objectType]--;
|
||||
_objectSelectionFlags[i] &= ~OBJECT_SELECTION_FLAG_SELECTED;
|
||||
numUnselectedObjects++;
|
||||
}
|
||||
}
|
||||
unload_unselected_objects();
|
||||
|
||||
if (createSelectionFlags)
|
||||
{
|
||||
editor_object_flags_free();
|
||||
}
|
||||
|
||||
auto intent = Intent(INTENT_ACTION_REFRESH_SCENERY);
|
||||
context_broadcast_intent(&intent);
|
||||
|
||||
return numUnselectedObjects;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
||||
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* A full copy of the GNU General Public License can be found in licence.txt
|
||||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "object.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern bool _maxObjectsWasHit;
|
||||
extern 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 reset_selected_object_count_and_size();
|
||||
sint32 window_editor_object_selection_select_object(uint8 bh, sint32 flags, const rct_object_entry *entry);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Removes all unused objects from the object selection.
|
||||
* @return The number of removed objects.
|
||||
*/
|
||||
sint32 editor_remove_unused_objects();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
|
@ -20,6 +20,7 @@
|
|||
#include "../Context.h"
|
||||
#include "../drawing/drawing.h"
|
||||
#include "../Editor.h"
|
||||
#include "../EditorObjectSelectionSession.h"
|
||||
#include "../Game.h"
|
||||
#include "../input.h"
|
||||
#include "../interface/themes.h"
|
||||
|
|
Loading…
Reference in New Issue