diff --git a/src/interface/window.h b/src/interface/window.h index f43bc69b12..a5e07822c5 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -210,8 +210,8 @@ typedef struct { typedef struct { uint16 var_480; - uint16 var_482; uint16 var_484; + bool reload_track_designs; } track_list_variables; typedef struct { diff --git a/src/ride/track_design.c b/src/ride/track_design.c index a614883349..7858971ea1 100644 --- a/src/ride/track_design.c +++ b/src/ride/track_design.c @@ -1954,121 +1954,3 @@ static void track_design_preview_clear_map() } #pragma endregion - -/** - * - * rct2: 0x006D3664 - */ -bool track_design_rename(const char *text) -{ - const char* txt_chr = text; - - while (*txt_chr != '\0'){ - switch (*txt_chr){ - case '.': - case '/': - case '\\': - case '*': - case '?': - // Invalid characters - gGameCommandErrorText = STR_NEW_NAME_CONTAINS_INVALID_CHARACTERS; - return false; - } - txt_chr++; - } - - char new_path[MAX_PATH]; - substitute_path(new_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), text); - strcat(new_path, ".TD6"); - - rct_window* w = window_find_by_class(WC_TRACK_DESIGN_LIST); - - char old_path[MAX_PATH]; - substitute_path(old_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char)[128 * w->track_list.var_482]); - - if (!platform_file_move(old_path, new_path)) { - gGameCommandErrorText = STR_ANOTHER_FILE_EXISTS_WITH_NAME_OR_FILE_IS_WRITE_PROTECTED; - return false; - } - - ride_list_item item = { 0xFC, 0 }; - // track_load_list(item); - - item.type = RCT2_GLOBAL(0xF44158, uint8); - item.entry_index = RCT2_GLOBAL(0xF44159, uint8); - // track_load_list(item); - - // reset_track_list_cache(); - - window_invalidate(w); - return true; -} - -/** - * - * rct2: 0x006D3761 - */ -int track_delete() -{ - rct_window* w = window_find_by_class(WC_TRACK_DESIGN_LIST); - - char path[MAX_PATH]; - substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char)[128 * w->track_list.var_482]); - - if (!platform_file_delete(path)) { - gGameCommandErrorText = STR_FILE_IS_WRITE_PROTECTED_OR_LOCKED; - return 0; - } - - ride_list_item item = { 0xFC, 0 }; - // track_load_list(item); - - item.type = RCT2_GLOBAL(0xF44158, uint8); - item.entry_index = RCT2_GLOBAL(0xF44159, uint8); - // track_load_list(item); - - // reset_track_list_cache(); - - window_invalidate(w); - return 1; -} - -/** -* -* rct2: 0x006D40B2 -* returns 0 for copy fail, 1 for success, 2 for file exists. -*/ -int install_track(char* source_path, char* dest_name){ - - // Make a copy of the track name (no extension) - char track_name[MAX_PATH] = { 0 }; - char* dest = track_name; - char* dest_name_pointer = dest_name; - while (*dest_name_pointer != '.') *dest++ = *dest_name_pointer++; - - // Check if .TD4 file exists under that name - char* temp_extension_pointer = dest; - strcat(track_name, ".TD4"); - - char dest_path[MAX_PATH]; - substitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name); - - if (platform_file_exists(dest_path)) - return 2; - - // Allow a concat onto the track_name but before extension - *temp_extension_pointer = '\0'; - - // Check if .TD6 file exists under that name - strcat(track_name, ".TD6"); - - substitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name); - - if (platform_file_exists(dest_path)) - return 2; - - // Set path for actual copy - substitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), dest_name); - - return platform_file_copy(source_path, dest_path, false); -} diff --git a/src/ride/track_design.h b/src/ride/track_design.h index 5d74f7f66e..b056e96121 100644 --- a/src/ride/track_design.h +++ b/src/ride/track_design.h @@ -163,7 +163,6 @@ extern uint8 gTrackDesignPlaceFlags; extern bool gTrackDesignSceneryToggle; rct_track_design *temp_track_get_info(char* path, uint8** preview); -int track_delete(); void track_design_mirror(rct_track_td6 *td6); rct_track_td6 *track_design_open(const utf8 *path); void track_design_dispose(rct_track_td6 *td6); @@ -175,6 +174,8 @@ void track_design_index_create(); size_t track_design_index_get_count_for_ride(uint8 rideType, const char *entry); size_t track_design_index_get_for_ride(track_design_file_ref **tdRefs, uint8 rideType, const char *entry); utf8 *track_design_get_name_from_path(const utf8 *path); +bool track_design_index_rename(const utf8 *path, const utf8 *newName); +bool track_design_index_delete(const utf8 *path); void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void game_command_place_maze_design(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); diff --git a/src/ride/track_design_index.c b/src/ride/track_design_index.c index 01316bb4c5..9df576d494 100644 --- a/src/ride/track_design_index.c +++ b/src/ride/track_design_index.c @@ -1,5 +1,8 @@ #include "../common.h" #include "../config.h" +#include "../game.h" +#include "../interface/window.h" +#include "../localisation/string_ids.h" #include "../util/util.h" #include "track.h" #include "track_design.h" @@ -118,6 +121,7 @@ size_t track_design_index_get_for_ride(track_design_file_ref **tdRefs, uint8 rid refs[nextIndex].path = _strdup(tdItem.path); refsCount++; } + SDL_RWclose(file); } *tdRefs = realloc(refs, refsCount * sizeof(track_design_file_ref)); @@ -137,6 +141,107 @@ utf8 *track_design_get_name_from_path(const utf8 *path) return strndup(filename, nameLength); } +/** + * + * rct2: 0x006D3664 + */ +bool track_design_index_rename(const utf8 *path, const utf8 *newName) +{ + if (str_is_null_or_empty(newName)) { + gGameCommandErrorText = STR_CANT_RENAME_TRACK_DESIGN; + return false; + } + + if (!filename_valid_characters(newName)) { + gGameCommandErrorText = STR_NEW_NAME_CONTAINS_INVALID_CHARACTERS; + return false; + } + + utf8 newPath[MAX_PATH]; + const char *lastPathSep = strrchr(path, platform_get_path_separator()); + if (lastPathSep == NULL) { + gGameCommandErrorText = STR_CANT_RENAME_TRACK_DESIGN; + return false; + } + size_t directoryLength = (size_t)(lastPathSep - path + 1); + memcpy(newPath, path, directoryLength); + strcpy(newPath + directoryLength, newName); + strcat(newPath, ".td6"); + + if (!platform_file_move(path, newPath)) { + gGameCommandErrorText = STR_ANOTHER_FILE_EXISTS_WITH_NAME_OR_FILE_IS_WRITE_PROTECTED; + return false; + } + + track_design_index_create(); + + rct_window *trackListWindow = window_find_by_class(WC_TRACK_DESIGN_LIST); + if (trackListWindow != NULL) { + trackListWindow->track_list.reload_track_designs = true; + } + return true; +} + +/** + * + * rct2: 0x006D3761 + */ +bool track_design_index_delete(const utf8 *path) +{ + if (!platform_file_delete(path)) { + gGameCommandErrorText = STR_FILE_IS_WRITE_PROTECTED_OR_LOCKED; + return false; + } + + track_design_index_create(); + + rct_window *trackListWindow = window_find_by_class(WC_TRACK_DESIGN_LIST); + if (trackListWindow != NULL) { + trackListWindow->track_list.reload_track_designs = true; + } + return true; +} + +/** +* +* rct2: 0x006D40B2 +* returns 0 for copy fail, 1 for success, 2 for file exists. +*/ +int install_track(char* source_path, char* dest_name){ + + // Make a copy of the track name (no extension) + char track_name[MAX_PATH] = { 0 }; + char* dest = track_name; + char* dest_name_pointer = dest_name; + while (*dest_name_pointer != '.') *dest++ = *dest_name_pointer++; + + // Check if .TD4 file exists under that name + char* temp_extension_pointer = dest; + strcat(track_name, ".TD4"); + + char dest_path[MAX_PATH]; + substitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name); + + if (platform_file_exists(dest_path)) + return 2; + + // Allow a concat onto the track_name but before extension + *temp_extension_pointer = '\0'; + + // Check if .TD6 file exists under that name + strcat(track_name, ".TD6"); + + substitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name); + + if (platform_file_exists(dest_path)) + return 2; + + // Set path for actual copy + substitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), dest_name); + + return platform_file_copy(source_path, dest_path, false); +} + static bool track_design_index_read_header(SDL_RWops *file, uint32 *tdidxCount) { uint32 tdidxMagicNumber, tdidxVersion; @@ -182,7 +287,7 @@ static int track_design_index_item_compare(const void *a, const void *b) const utf8 *tdAName = path_get_filename(tdA->path); const utf8 *tdBName = path_get_filename(tdB->path); - return strcmp(tdAName, tdBName); + return _stricmp(tdAName, tdBName); } static void track_design_index_include(const utf8 *directory) @@ -246,7 +351,7 @@ static void track_design_add(const td_index_item *item) static void track_design_index_dispose() { - free(_tdIndex); + SafeFree(_tdIndex); _tdIndexSize = 0; _tdIndexCapacity = 0; } diff --git a/src/windows/install_track.c b/src/windows/install_track.c index a3f29c7ca8..6259b3acf9 100644 --- a/src/windows/install_track.c +++ b/src/windows/install_track.c @@ -127,7 +127,6 @@ void window_install_track_open(const char* path) w->widgets = window_install_track_widgets; w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_ROTATE) | (1 << WIDX_TOGGLE_SCENERY) | (1 << WIDX_INSTALL) | (1 << WIDX_CANCEL); window_init_scroll_widgets(w); - w->track_list.var_482 = 0; w->track_list.var_484 = 0; window_push_others_right(w); @@ -268,11 +267,11 @@ static void window_install_track_invalidate(rct_window *w) w->pressed_widgets &= ~(1 << WIDX_TOGGLE_SCENERY); } - if (w->track_list.var_482 != 0xFFFF) { - w->disabled_widgets &= ~(1 << WIDX_TRACK_PREVIEW); - } else { - w->disabled_widgets |= (1 << WIDX_TRACK_PREVIEW); - } + // if (w->track_list.var_482 != 0xFFFF) { + // w->disabled_widgets &= ~(1 << WIDX_TRACK_PREVIEW); + // } else { + // w->disabled_widgets |= (1 << WIDX_TRACK_PREVIEW); + // } } /** @@ -291,8 +290,8 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi) window_draw_widgets(w, dpi); - if (w->track_list.var_482 == 0xFFFF) - return; + // if (w->track_list.var_482 == 0xFFFF) + // return; // Track preview widget = &window_install_track_widgets[WIDX_TRACK_PREVIEW]; diff --git a/src/windows/track_list.c b/src/windows/track_list.c index 9f6a92eee4..c2818e6bc2 100644 --- a/src/windows/track_list.c +++ b/src/windows/track_list.c @@ -53,6 +53,7 @@ static rct_widget window_track_list_widgets[] = { static void window_track_list_close(rct_window *w); static void window_track_list_mouseup(rct_window *w, int widgetIndex); +static void window_track_list_update(rct_window *w); static void window_track_list_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height); static void window_track_list_scrollmousedown(rct_window *w, int scrollIndex, int x, int y); static void window_track_list_scrollmouseover(rct_window *w, int scrollIndex, int x, int y); @@ -72,7 +73,7 @@ static rct_window_event_list window_track_list_events = { NULL, NULL, NULL, - NULL, + window_track_list_update, NULL, NULL, NULL, @@ -138,8 +139,9 @@ void window_track_list_open(ride_list_item item) w->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_ROTATE) | (1 << WIDX_TOGGLE_SCENERY) | (1 << WIDX_BACK); window_init_scroll_widgets(w); w->track_list.var_480 = 0xFFFF; - w->track_list.var_482 = gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER ? 0 : 1; w->track_list.var_484 = 0; + w->track_list.reload_track_designs = false; + w->selected_list_item = gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER ? 0 : 1; gTrackDesignSceneryToggle = false; window_push_others_right(w); _currentTrackPieceDirection = 2; @@ -287,8 +289,8 @@ static void window_track_list_scrollmouseover(rct_window *w, int scrollIndex, in { if (!(w->track_list.var_484 & 1)) { int i = window_track_list_get_list_item_index_from_position(x, y); - if (i != -1 && w->track_list.var_482 != i) { - w->track_list.var_482 = i; + if (i != -1 && w->selected_list_item != i) { + w->selected_list_item = i; window_invalidate(w); } } @@ -303,6 +305,15 @@ static void window_track_list_tooltip(rct_window* w, int widgetIndex, rct_string RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_LIST; } +static void window_track_list_update(rct_window *w) +{ + if (w->track_list.reload_track_designs) { + track_list_load_designs(_window_track_list_item); + w->selected_list_item = 0; + window_invalidate(w); + } +} + /** * * rct2: 0x006CF2D6 @@ -329,7 +340,7 @@ static void window_track_list_invalidate(rct_window *w) window_track_list_widgets[WIDX_TRACK_LIST].tooltip = STR_CLICK_ON_DESIGN_TO_BUILD_IT_TIP; } - if ((gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) || w->track_list.var_482 != 0) { + if ((gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) || w->selected_list_item != 0) { w->pressed_widgets |= 1 << WIDX_TRACK_PREVIEW; w->disabled_widgets &= ~(1 << WIDX_TRACK_PREVIEW); window_track_list_widgets[WIDX_ROTATE].type = WWT_FLATBTN; @@ -355,7 +366,7 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); - int trackIndex = w->track_list.var_482; + int trackIndex = w->selected_list_item; if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) { if (_trackDesignsCount == 0 || trackIndex == -1) { return; @@ -551,7 +562,7 @@ static void window_track_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, } else { // Build custom track item rct_string_id stringId; - if (listIndex == w->track_list.var_482) { + if (listIndex == w->selected_list_item) { // Highlight gfx_fill_rect(dpi, x, y, w->width, y + 9, 0x2000000 | 49); stringId = 1193; @@ -568,7 +579,7 @@ static void window_track_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, for (size_t i = 0; i < _trackDesignsCount; i++, listIndex++) { if (y + 10 >= dpi->y && y < dpi->y + dpi->height) { rct_string_id stringId; - if (listIndex == w->track_list.var_482) { + if (listIndex == w->selected_list_item) { // Highlight gfx_fill_rect(dpi, x, y, w->width, y + 9, 0x2000000 | 49); stringId = 1193; diff --git a/src/windows/track_manage.c b/src/windows/track_manage.c index 6a40958025..39ca3660ac 100644 --- a/src/windows/track_manage.c +++ b/src/windows/track_manage.c @@ -217,16 +217,16 @@ static void window_track_manage_mouseup(rct_window *w, int widgetIndex) */ static void window_track_manage_textinput(rct_window *w, int widgetIndex, char *text) { - if (widgetIndex != WIDX_RENAME || text == NULL) { + if (widgetIndex != WIDX_RENAME || str_is_null_or_empty(text)) { return; } - // if (track_rename(text)) { - // window_close_by_class(WC_TRACK_DELETE_PROMPT); - // window_close(w); - // } else { - // window_error_open(STR_CANT_RENAME_TRACK_DESIGN, gGameCommandErrorText); - // } + if (track_design_index_rename(_trackDesignFileReference->path, text)) { + window_close_by_class(WC_TRACK_DELETE_PROMPT); + window_close(w); + } else { + window_error_open(STR_CANT_RENAME_TRACK_DESIGN, gGameCommandErrorText); + } } static void window_track_manage_invalidate(rct_window *w) @@ -284,7 +284,7 @@ static void window_track_delete_prompt_mouseup(rct_window *w, int widgetIndex) break; case WIDX_PROMPT_DELETE: window_close(w); - if (track_delete()) { + if (track_design_index_delete(_trackDesignFileReference->path)) { window_close_by_class(WC_MANAGE_TRACK_DESIGN); } else { window_error_open(STR_CANT_DELETE_TRACK_DESIGN, gGameCommandErrorText);