diff --git a/src/openrct2-ui/WindowManager.cpp b/src/openrct2-ui/WindowManager.cpp index 703511e4a4..fa9891bc20 100644 --- a/src/openrct2-ui/WindowManager.cpp +++ b/src/openrct2-ui/WindowManager.cpp @@ -236,8 +236,10 @@ public: loadsave_callback callback = reinterpret_cast( intent->GetPointerExtra(INTENT_EXTRA_CALLBACK)); TrackDesign* trackDesign = static_cast(intent->GetPointerExtra(INTENT_EXTRA_TRACK_DESIGN)); - rct_window* w = window_loadsave_open(type, defaultName.c_str(), callback, trackDesign); - + auto* w = window_loadsave_open( + type, defaultName, + [callback](int32_t result, std::string_view path) { callback(result, std::string(path).c_str()); }, + trackDesign); return w; } case WC_MANAGE_TRACK_DESIGN: diff --git a/src/openrct2-ui/scripting/ScTitleSequence.hpp b/src/openrct2-ui/scripting/ScTitleSequence.hpp index 7e5d0da5e3..7ad050d932 100644 --- a/src/openrct2-ui/scripting/ScTitleSequence.hpp +++ b/src/openrct2-ui/scripting/ScTitleSequence.hpp @@ -173,6 +173,13 @@ namespace OpenRCT2::Scripting return result; } + void addPark(const std::string& path, const std::string& fileName) + { + auto titleSeq = LoadTitleSequence(_path); + TitleSequenceAddPark(*titleSeq, path.c_str(), fileName.c_str()); + TitleSequenceSave(*titleSeq); + } + std::shared_ptr clone(const std::string& name) const { auto copyIndex = GetManagerIndex(); @@ -206,6 +213,7 @@ namespace OpenRCT2::Scripting dukglue_register_property(ctx, &ScTitleSequence::isDirectory_get, nullptr, "isDirectory"); dukglue_register_property(ctx, &ScTitleSequence::isReadOnly_get, nullptr, "isReadOnly"); dukglue_register_property(ctx, &ScTitleSequence::parks_get, nullptr, "parks"); + dukglue_register_method(ctx, &ScTitleSequence::addPark, "addPark"); dukglue_register_method(ctx, &ScTitleSequence::clone, "clone"); dukglue_register_method(ctx, &ScTitleSequence::delete_, "delete"); } diff --git a/src/openrct2-ui/scripting/ScUi.hpp b/src/openrct2-ui/scripting/ScUi.hpp index 2b42fa270f..3f870f7a6b 100644 --- a/src/openrct2-ui/scripting/ScUi.hpp +++ b/src/openrct2-ui/scripting/ScUi.hpp @@ -210,6 +210,46 @@ namespace OpenRCT2::Scripting } } + void showFileBrowse(const DukValue& desc) + { + try + { + auto plugin = _scriptEngine.GetExecInfo().GetCurrentPlugin(); + auto type = desc["type"].as_string(); + auto fileType = desc["fileType"].as_string(); + auto defaultPath = AsOrDefault(desc["defaultPath"], ""); + auto callback = desc["callback"]; + + int32_t loadSaveType{}; + if (type == "load") + loadSaveType = LOADSAVETYPE_LOAD; + else + throw DukException(); + + if (fileType == "game") + loadSaveType |= LOADSAVETYPE_GAME; + else if (fileType == "heightmap") + loadSaveType |= LOADSAVETYPE_HEIGHTMAP; + else + throw DukException(); + + window_loadsave_open( + loadSaveType, defaultPath, + [this, plugin, callback](int32_t result, std::string_view path) { + if (result == MODAL_RESULT_OK) + { + auto dukValue = ToDuk(_scriptEngine.GetContext(), path); + _scriptEngine.ExecutePluginCall(plugin, callback, { dukValue }, false); + } + }, + nullptr); + } + catch (const DukException&) + { + duk_error(_scriptEngine.GetContext(), DUK_ERR_ERROR, "Invalid parameters."); + } + } + void activateTool(const DukValue& desc) { InitialiseCustomTool(_scriptEngine, desc); @@ -237,6 +277,7 @@ namespace OpenRCT2::Scripting dukglue_register_method(ctx, &ScUi::getWindow, "getWindow"); dukglue_register_method(ctx, &ScUi::showError, "showError"); dukglue_register_method(ctx, &ScUi::showTextInput, "showTextInput"); + dukglue_register_method(ctx, &ScUi::showFileBrowse, "showFileBrowse"); dukglue_register_method(ctx, &ScUi::activateTool, "activateTool"); dukglue_register_method(ctx, &ScUi::registerMenuItem, "registerMenuItem"); } diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index 3ad1ccdb4e..467acdb730 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -126,7 +126,7 @@ struct LoadSaveListItem bool loaded; }; -static loadsave_callback _loadSaveCallback; +static std::function _loadSaveCallback; static TrackDesign* _trackDesign; static std::vector _listItems; @@ -134,7 +134,7 @@ static char _directory[MAX_PATH]; static char _shortenedDirectory[MAX_PATH]; static char _parentDirectory[MAX_PATH]; static char _extension[256]; -static char _defaultName[MAX_PATH]; +static std::string _defaultPath; static int32_t _type; static int32_t maxDateWidth = 0; @@ -234,17 +234,14 @@ static int32_t window_loadsave_get_dir(const int32_t type, char* path, size_t pa static bool browse(bool isSave, char* path, size_t pathSize); -rct_window* window_loadsave_open(int32_t type, const char* defaultName, loadsave_callback callback, TrackDesign* trackDesign) +rct_window* window_loadsave_open( + int32_t type, std::string_view defaultPath, std::function callback, + TrackDesign* trackDesign) { _loadSaveCallback = callback; _trackDesign = trackDesign; _type = type; - _defaultName[0] = '\0'; - - if (!str_is_null_or_empty(defaultName)) - { - safe_strcpy(_defaultName, defaultName, sizeof(_defaultName)); - } + _defaultPath = defaultPath; bool isSave = (type & 0x01) == LOADSAVETYPE_SAVE; char path[MAX_PATH]; @@ -394,9 +391,9 @@ static bool browse(bool isSave, char* path, size_t pathSize) if (isSave) { // The file browser requires a file path instead of just a directory - if (String::SizeOf(_defaultName) > 0) + if (!_defaultPath.empty()) { - safe_strcat_path(path, _defaultName, pathSize); + safe_strcat_path(path, _defaultPath.c_str(), pathSize); } else { @@ -454,7 +451,7 @@ static void window_loadsave_mouseup(rct_window* w, rct_widgetindex widgetIndex) case WIDX_NEW_FILE: window_text_input_open( w, WIDX_NEW_FILE, STR_NONE, STR_FILEBROWSER_FILE_NAME_PROMPT, STR_STRING, - reinterpret_cast(&_defaultName), 64); + reinterpret_cast(_defaultPath.c_str()), 64); break; case WIDX_NEW_FOLDER: diff --git a/src/openrct2-ui/windows/Window.h b/src/openrct2-ui/windows/Window.h index d7c1a067ac..906615aaed 100644 --- a/src/openrct2-ui/windows/Window.h +++ b/src/openrct2-ui/windows/Window.h @@ -109,7 +109,9 @@ rct_window* window_scenarioselect_open(scenarioselect_callback callback, bool ti rct_window* window_error_open(rct_string_id title, rct_string_id message, const class Formatter& formatter); rct_window* window_error_open(std::string_view title, std::string_view message); struct TrackDesign; -rct_window* window_loadsave_open(int32_t type, const char* defaultName, loadsave_callback callback, TrackDesign* t6Exporter); +rct_window* window_loadsave_open( + int32_t type, std::string_view defaultPath, std::function callback, + TrackDesign* trackDesign); rct_window* window_track_place_open(const struct track_design_file_ref* tdFileRef); rct_window* window_track_manage_open(struct track_design_file_ref* tdFileRef);