From c5aececcb1cd78290cbc24d179b82739dee90558 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Tue, 13 Mar 2018 00:30:27 +0100 Subject: [PATCH 1/5] Set scenario save path upon successfully loading a park Instead of setting the path when clicking on a file in the loadsave dialog, it's now set when the park gets actually loaded. This fixes the System Dialog not showing when saving a park loaded from command. --- src/openrct2-ui/windows/LoadSave.cpp | 3 --- src/openrct2/Context.cpp | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index 7f8cebf424..6901e4a68f 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -927,9 +927,6 @@ static void window_loadsave_select(rct_window *w, const char *path) switch (_type & 0x0F) { case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME): save_path(&gConfigGeneral.last_save_game_directory, pathBuffer); - safe_strcpy(gScenarioSavePath, pathBuffer, MAX_PATH); - safe_strcpy(gCurrentLoadedPath, pathBuffer, MAX_PATH); - gFirstTimeSaving = true; window_loadsave_invoke_callback(MODAL_RESULT_OK, pathBuffer); window_close_by_class(WC_LOADSAVE); gfx_invalidate_screen(); diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 960ca13024..09ec0ce153 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -34,6 +34,7 @@ #include "core/MemoryStream.h" #include "core/Path.hpp" #include "core/String.hpp" +#include "core/Util.hpp" #include "FileClassifier.h" #include "HandleParkLoad.h" #include "network/network.h" @@ -426,6 +427,9 @@ namespace OpenRCT2 if (result.Error == PARK_LOAD_ERROR_OK) { parkImporter->Import(); + String::Set(gScenarioSavePath, Util::CountOf(gScenarioSavePath), path.c_str()); + String::Set(gCurrentLoadedPath, Util::CountOf(gCurrentLoadedPath), path.c_str()); + gFirstTimeSaving = true; game_fix_save_vars(); sprite_position_tween_reset(); gScreenAge = 0; From 45a92a73564df4dc54a4eb725512f432f459d7e8 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Tue, 13 Mar 2018 19:52:18 +0100 Subject: [PATCH 2/5] Fix #5210 Unable to open system dialog for saving The reason the file dialog failed to open (on Windows at least) is that the dialog would be used to save a file, yet a folder was provided as the default path. This commit attempts to append a logical filename to the path, including an extension. --- distribution/changelog.txt | 2 + src/openrct2-ui/windows/LoadSave.cpp | 57 +++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index bdcb15c640..2e8eba0bfa 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -4,6 +4,8 @@ - Feature: [#7266] Make headless instances use an interactive terminal with access to the in-game console API. - Feature: [#7267] Leverage more historical data in Finances window. - Feature: [#7332] Keyboard shortcuts for view path issues and cutaway view. +- Fix: [#3596] Saving parks, landscapes and tracks with a period in the filenames don't get their extension. +- Fix: [#5210] Default system dialog not accessible from saving landscape window. - Improved: Raising land near the map edge makes the affected area smaller instead of showing an 'off edge map' error. 0.1.2 (2018-03-18) diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index 6901e4a68f..a1f7eb966a 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -313,37 +314,39 @@ static void window_loadsave_resize(rct_window *w) static bool browse(bool isSave, char *path, size_t pathSize) { - safe_strcpy(path, _directory, pathSize); - if (isSave) - safe_strcat_path(path, _defaultName, pathSize); - file_dialog_desc desc = { 0 }; - desc.initial_directory = _directory; - desc.type = isSave ? FD_SAVE : FD_OPEN; - desc.default_filename = isSave ? path : nullptr; - + const utf8 * extension = ""; + uint32 fileType = FILE_EXTENSION_UNKNOWN; rct_string_id title = STR_NONE; switch (_type & 0x0E) { case LOADSAVETYPE_GAME: + extension = ".sv6"; + fileType = FILE_EXTENSION_SV6; title = isSave ? STR_FILE_DIALOG_TITLE_SAVE_GAME : STR_FILE_DIALOG_TITLE_LOAD_GAME; desc.filters[0].name = language_get_string(STR_OPENRCT2_SAVED_GAME); desc.filters[0].pattern = isSave ? "*.sv6" : "*.sv6;*.sc6;*.sv4;*.sc4"; break; case LOADSAVETYPE_LANDSCAPE: + extension = ".sc6"; + fileType = FILE_EXTENSION_SC6; title = isSave ? STR_FILE_DIALOG_TITLE_SAVE_LANDSCAPE : STR_FILE_DIALOG_TITLE_LOAD_LANDSCAPE; desc.filters[0].name = language_get_string(STR_OPENRCT2_LANDSCAPE_FILE); desc.filters[0].pattern = isSave ? "*.sc6" : "*.sc6;*.sv6;*.sc4;*.sv4"; break; case LOADSAVETYPE_SCENARIO: + extension = ".sc6"; + fileType = FILE_EXTENSION_SC6; title = STR_FILE_DIALOG_TITLE_SAVE_SCENARIO; desc.filters[0].name = language_get_string(STR_OPENRCT2_SCENARIO_FILE); desc.filters[0].pattern = "*.sc6"; break; case LOADSAVETYPE_TRACK: + extension = ".td6"; + fileType = FILE_EXTENSION_TD6; title = isSave ? STR_FILE_DIALOG_TITLE_SAVE_TRACK : STR_FILE_DIALOG_TITLE_INSTALL_NEW_TRACK_DESIGN; desc.filters[0].name = language_get_string(STR_OPENRCT2_TRACK_DESIGN_FILE); desc.filters[0].pattern = isSave ? "*.td6" : "*.td6;*.td4"; @@ -356,12 +359,48 @@ static bool browse(bool isSave, char *path, size_t pathSize) break; } + safe_strcpy(path, _directory, pathSize); + if (isSave) + { + // The file browser requires a file path instead of just a directory + if (String::SizeOf(_defaultName) > 0) + { + safe_strcat_path(path, _defaultName, pathSize); + } + else + { + utf8 buffer[USER_STRING_MAX_LENGTH]{}; + if (gParkName != STR_NONE) + format_string(buffer, pathSize, gParkName, nullptr); + + // Use localized "Unnamed Park" if park name was empty + if (String::SizeOf(buffer) == 0) + format_string(buffer, pathSize, STR_UNNAMED_PARK, nullptr); + + safe_strcat_path(path, buffer, pathSize); + } + } + + desc.initial_directory = _directory; + desc.type = isSave ? FD_SAVE : FD_OPEN; + desc.default_filename = isSave ? path : nullptr; + // Add 'all files' filter. If the number of filters is increased, this code will need to be adjusted. desc.filters[1].name = language_get_string(STR_ALL_FILES); desc.filters[1].pattern = "*"; desc.title = language_get_string(title); - return platform_open_common_file_dialog(path, &desc, pathSize); + if (platform_open_common_file_dialog(path, &desc, pathSize)) + { + // When the given save type was given, Windows still interprets a filename with a dot in its name as a custom extension, + // meaning files like "My Coaster v1.2" will not get the .td6 extension by default. + if (get_file_extension_type(path) != fileType) + path_append_extension(path, extension, pathSize); + + return true; + } + + return false; } static void window_loadsave_mouseup(rct_window *w, rct_widgetindex widgetIndex) From 6528a2fe37241e33698f392257328990ec62dcca Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Tue, 13 Mar 2018 22:18:59 +0100 Subject: [PATCH 3/5] Invalidate window when populating list The new comment is there for clarity, because this confused me for a sec. --- src/openrct2-ui/windows/LoadSave.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index a1f7eb966a..1c60366e2c 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -792,7 +792,7 @@ static void window_loadsave_populate_list(rct_window *w, sint32 includeNewItem, utf8 absoluteDirectory[MAX_PATH]; Path::GetAbsolute(absoluteDirectory, Util::CountOf(absoluteDirectory), directory); safe_strcpy(_directory, absoluteDirectory, Util::CountOf(_directory)); - if (_extension != extension) + if (_extension != extension) // Note: This compares the pointers, not values { safe_strcpy(_extension, extension, Util::CountOf(_extension)); } @@ -922,6 +922,8 @@ static void window_loadsave_populate_list(rct_window *w, sint32 includeNewItem, window_loadsave_sort_list(); } + + window_invalidate(w); } static void window_loadsave_invoke_callback(sint32 result, const utf8 * path) From 3b697c071d4489d5067cbfb02f1c0f00fa707da5 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Thu, 22 Mar 2018 22:09:37 +0100 Subject: [PATCH 4/5] Only append default extension when none is provided This should give Linux the same behaviour as Windows. It requires testing, I don't have access to a Linux machine. --- src/openrct2-ui/UiContext.Linux.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/openrct2-ui/UiContext.Linux.cpp b/src/openrct2-ui/UiContext.Linux.cpp index 2fa859d8f4..af47284af7 100644 --- a/src/openrct2-ui/UiContext.Linux.cpp +++ b/src/openrct2-ui/UiContext.Linux.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -169,13 +170,13 @@ namespace OpenRCT2 { namespace Ui // array must be carefully populated, at least the first element. std::string pattern = desc.Filters[0].Pattern; std::string defaultExtension = pattern.substr(pattern.find_last_of('.')); - int dotPosition = output.size() - defaultExtension.size(); - // Add the default extension if no extension is specified - if (output.substr(dotPosition, defaultExtension.size()).compare(defaultExtension) == 0) - { - result = output; - } - else + + const utf8 * filename = Path::GetFileName(output.c_str()); + + // If there is no extension, append the pattern + const utf8 * extension = Path::GetExtension(filename); + result = output; + if (extension[0] == '\0' && !defaultExtension.empty()) { result = output.append(defaultExtension); } From 9ddda9ac77e8871681d42b81ec054638706f4d70 Mon Sep 17 00:00:00 2001 From: Hielke Morsink Date: Sat, 24 Mar 2018 13:34:05 +0100 Subject: [PATCH 5/5] Move comment --- src/openrct2-ui/windows/LoadSave.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index 1c60366e2c..fdb0f5c71f 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -792,7 +792,8 @@ static void window_loadsave_populate_list(rct_window *w, sint32 includeNewItem, utf8 absoluteDirectory[MAX_PATH]; Path::GetAbsolute(absoluteDirectory, Util::CountOf(absoluteDirectory), directory); safe_strcpy(_directory, absoluteDirectory, Util::CountOf(_directory)); - if (_extension != extension) // Note: This compares the pointers, not values + // Note: This compares the pointers, not values + if (_extension != extension) { safe_strcpy(_extension, extension, Util::CountOf(_extension)); }