diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 11c9717729..c26a40df11 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -7,6 +7,7 @@ - Fix: [#23743] Parks with guest goals over 32767 do not appear in the scenario list. - Fix: [#23844] Sound effects keep playing when loading another save. - Fix: [#23897] Reverse Freefall Coaster slope up to vertical track piece does not draw a vertical tunnel. +- Fix: [#23939] Incorrect assertion when trying to load heightmap. 0.4.20 (2025-02-25) ------------------------------------------------------------------------ diff --git a/src/openrct2-ui/WindowManager.cpp b/src/openrct2-ui/WindowManager.cpp index b567d2e5f6..0515971bdc 100644 --- a/src/openrct2-ui/WindowManager.cpp +++ b/src/openrct2-ui/WindowManager.cpp @@ -257,13 +257,14 @@ public: intent->GetSIntExtra(INTENT_EXTRA_RIDE_ID)); case WindowClass::Loadsave: { - uint32_t type = intent->GetUIntExtra(INTENT_EXTRA_LOADSAVE_TYPE); + auto action = intent->GetEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION); + auto type = intent->GetEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE); std::string defaultPath = intent->GetStringExtra(INTENT_EXTRA_PATH); LoadSaveCallback callback = reinterpret_cast( intent->GetCloseCallbackExtra(INTENT_EXTRA_CALLBACK)); TrackDesign* trackDesign = static_cast(intent->GetPointerExtra(INTENT_EXTRA_TRACK_DESIGN)); auto* w = FileBrowser::OpenPreferred( - type, defaultPath, + action, type, defaultPath, [callback](ModalResult result, std::string_view path) { if (callback != nullptr) { diff --git a/src/openrct2-ui/input/Shortcuts.cpp b/src/openrct2-ui/input/Shortcuts.cpp index a5decc97e7..f289401dc9 100644 --- a/src/openrct2-ui/input/Shortcuts.cpp +++ b/src/openrct2-ui/input/Shortcuts.cpp @@ -418,7 +418,8 @@ static void ShortcutQuickSaveGame() else if (gLegacyScene == LegacyScene::scenarioEditor) { auto intent = Intent(WindowClass::Loadsave); - intent.PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_SAVE | LOADSAVETYPE_LANDSCAPE); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::save); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::landscape); intent.PutExtra(INTENT_EXTRA_PATH, GetGameState().ScenarioName); ContextOpenIntent(&intent); } diff --git a/src/openrct2-ui/interface/FileBrowser.cpp b/src/openrct2-ui/interface/FileBrowser.cpp index e2453e73eb..c27a26681f 100644 --- a/src/openrct2-ui/interface/FileBrowser.cpp +++ b/src/openrct2-ui/interface/FileBrowser.cpp @@ -32,7 +32,8 @@ namespace OpenRCT2::Ui::FileBrowser { static LoadSaveCallback _loadSaveCallback; - WindowBase* OpenPreferred(int32_t type, u8string defaultPath, LoadSaveCallback callback, TrackDesign* trackDesign) + WindowBase* OpenPreferred( + LoadSaveAction action, LoadSaveType type, u8string defaultPath, LoadSaveCallback callback, TrackDesign* trackDesign) { RegisterCallback(callback); @@ -42,19 +43,19 @@ namespace OpenRCT2::Ui::FileBrowser // Open system file picker? if (config.UseNativeBrowseDialog && hasFilePicker) { - const bool isSave = (type & 0x01) == LOADSAVETYPE_SAVE; + const bool isSave = (action == LoadSaveAction::save); const auto defaultDirectory = GetDir(type); const u8string path = OpenSystemFileBrowser(isSave, type, defaultDirectory, defaultPath); if (!path.empty()) { - Select(path.c_str(), type, trackDesign); + Select(path.c_str(), action, type, trackDesign); } return nullptr; } // Use built-in load/save window - return Windows::LoadsaveOpen(type, defaultPath, callback, trackDesign); + return Windows::LoadsaveOpen(action, type, defaultPath, callback, trackDesign); } bool ListItemSort(LoadSaveListItem& a, LoadSaveListItem& b) @@ -96,20 +97,20 @@ namespace OpenRCT2::Ui::FileBrowser return Platform::IsFilenameValid(filename); } - u8string GetLastDirectoryByType(int32_t type) + u8string GetLastDirectoryByType(LoadSaveType type) { - switch (type & 0x0E) + switch (type) { - case LOADSAVETYPE_GAME: + case LoadSaveType::park: return Config::Get().general.LastSaveGameDirectory; - case LOADSAVETYPE_LANDSCAPE: + case LoadSaveType::landscape: return Config::Get().general.LastSaveLandscapeDirectory; - case LOADSAVETYPE_SCENARIO: + case LoadSaveType::scenario: return Config::Get().general.LastSaveScenarioDirectory; - case LOADSAVETYPE_TRACK: + case LoadSaveType::track: return Config::Get().general.LastSaveTrackDirectory; default: @@ -117,28 +118,28 @@ namespace OpenRCT2::Ui::FileBrowser } } - u8string GetInitialDirectoryByType(const int32_t type) + u8string GetInitialDirectoryByType(const LoadSaveType type) { std::optional subdir = std::nullopt; - switch (type & 0x0E) + switch (type) { - case LOADSAVETYPE_GAME: + case LoadSaveType::park: subdir = DIRID::SAVE; break; - case LOADSAVETYPE_LANDSCAPE: + case LoadSaveType::landscape: subdir = DIRID::LANDSCAPE; break; - case LOADSAVETYPE_SCENARIO: + case LoadSaveType::scenario: subdir = DIRID::SCENARIO; break; - case LOADSAVETYPE_TRACK: + case LoadSaveType::track: subdir = DIRID::TRACK; break; - case LOADSAVETYPE_HEIGHTMAP: + case LoadSaveType::heightmap: subdir = DIRID::HEIGHTMAP; break; } @@ -150,23 +151,23 @@ namespace OpenRCT2::Ui::FileBrowser return env->GetDirectoryPath(DIRBASE::USER); } - const char* GetFilterPatternByType(const int32_t type, const bool isSave) + const char* GetFilterPatternByType(const LoadSaveType type, const bool isSave) { - switch (type & 0x0E) + switch (type) { - case LOADSAVETYPE_GAME: + case LoadSaveType::park: return isSave ? "*.park" : "*.park;*.sv6;*.sc6;*.sc4;*.sv4;*.sv7;*.sea"; - case LOADSAVETYPE_LANDSCAPE: + case LoadSaveType::landscape: return isSave ? "*.park" : "*.park;*.sc6;*.sv6;*.sc4;*.sv4;*.sv7;*.sea"; - case LOADSAVETYPE_SCENARIO: + case LoadSaveType::scenario: return isSave ? "*.park" : "*.park;*.sc6;*.sc4"; - case LOADSAVETYPE_TRACK: + case LoadSaveType::track: return isSave ? "*.td6" : "*.td6;*.td4"; - case LOADSAVETYPE_HEIGHTMAP: + case LoadSaveType::heightmap: return "*.bmp;*.png"; default: @@ -185,7 +186,7 @@ namespace OpenRCT2::Ui::FileBrowser return u8string{ pattern }; } - u8string GetDir(const int32_t type) + u8string GetDir(const LoadSaveType type) { u8string result = GetLastDirectoryByType(type); if (result.empty() || !Path::DirectoryExists(result)) @@ -208,7 +209,7 @@ namespace OpenRCT2::Ui::FileBrowser } } - void Select(const char* path, int32_t type, TrackDesign* trackDesignPtr) + void Select(const char* path, LoadSaveAction action, LoadSaveType type, TrackDesign* trackDesignPtr) { if (!IsValidPath(path)) { @@ -227,169 +228,194 @@ namespace OpenRCT2::Ui::FileBrowser auto& gameState = GetGameState(); - switch (type & 0x0F) + switch (action) { - case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME): - SetAndSaveConfigPath(Config::Get().general.LastSaveGameDirectory, pathBuffer); - if (GetContext()->LoadParkFromFile(pathBuffer)) + case LoadSaveAction::load: + { + switch (type) { - InvokeCallback(ModalResult::ok, pathBuffer); - windowMgr->CloseByClass(WindowClass::Loadsave); - GfxInvalidateScreen(); - } - else - { - auto windowManager = GetWindowManager(); - if (!windowManager->FindByClass(WindowClass::Error)) + case (LoadSaveType::park): { - // Not the best message... - ContextShowError(STR_LOAD_GAME, STR_FAILED_TO_LOAD_FILE_CONTAINS_INVALID_DATA, {}); + SetAndSaveConfigPath(Config::Get().general.LastSaveGameDirectory, pathBuffer); + if (GetContext()->LoadParkFromFile(pathBuffer)) + { + InvokeCallback(ModalResult::ok, pathBuffer); + windowMgr->CloseByClass(WindowClass::Loadsave); + GfxInvalidateScreen(); + } + else + { + auto windowManager = GetWindowManager(); + if (!windowManager->FindByClass(WindowClass::Error)) + { + // Not the best message... + ContextShowError(STR_LOAD_GAME, STR_FAILED_TO_LOAD_FILE_CONTAINS_INVALID_DATA, {}); + } + InvokeCallback(ModalResult::fail, pathBuffer); + } + break; } - InvokeCallback(ModalResult::fail, pathBuffer); - } - break; + case (LoadSaveType::landscape): + { + SetAndSaveConfigPath(Config::Get().general.LastSaveLandscapeDirectory, pathBuffer); + if (Editor::LoadLandscape(pathBuffer)) + { + gCurrentLoadedPath = pathBuffer; + GfxInvalidateScreen(); + InvokeCallback(ModalResult::ok, pathBuffer); + } + else + { + // Not the best message... + ContextShowError(STR_LOAD_LANDSCAPE, STR_FAILED_TO_LOAD_FILE_CONTAINS_INVALID_DATA, {}); + InvokeCallback(ModalResult::fail, pathBuffer); + } + break; + } + case (LoadSaveType::scenario): + { + SetAndSaveConfigPath(Config::Get().general.LastSaveScenarioDirectory, pathBuffer); + int32_t parkFlagsBackup = gameState.Park.Flags; + gameState.Park.Flags &= ~PARK_FLAGS_SPRITES_INITIALISED; + gameState.EditorStep = EditorStep::Invalid; + gameState.ScenarioFileName = std::string(String::toStringView(pathBuffer, std::size(pathBuffer))); + int32_t success = ScenarioSave(gameState, pathBuffer, Config::Get().general.SavePluginData ? 3 : 2); + gameState.Park.Flags = parkFlagsBackup; - case (LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME): - SetAndSaveConfigPath(Config::Get().general.LastSaveGameDirectory, pathBuffer); - if (ScenarioSave(gameState, pathBuffer, Config::Get().general.SavePluginData ? 1 : 0)) - { - gScenarioSavePath = pathBuffer; - gCurrentLoadedPath = pathBuffer; - gIsAutosaveLoaded = false; - gFirstTimeSaving = false; + if (success) + { + windowMgr->CloseByClass(WindowClass::Loadsave); + InvokeCallback(ModalResult::ok, pathBuffer); - windowMgr->CloseByClass(WindowClass::Loadsave); - GfxInvalidateScreen(); - - InvokeCallback(ModalResult::ok, pathBuffer); - } - else - { - ContextShowError(STR_SAVE_GAME, STR_GAME_SAVE_FAILED, {}); - InvokeCallback(ModalResult::fail, pathBuffer); - } - break; - - case (LOADSAVETYPE_LOAD | LOADSAVETYPE_LANDSCAPE): - SetAndSaveConfigPath(Config::Get().general.LastSaveLandscapeDirectory, pathBuffer); - if (Editor::LoadLandscape(pathBuffer)) - { - gCurrentLoadedPath = pathBuffer; - GfxInvalidateScreen(); - InvokeCallback(ModalResult::ok, pathBuffer); - } - else - { - // Not the best message... - ContextShowError(STR_LOAD_LANDSCAPE, STR_FAILED_TO_LOAD_FILE_CONTAINS_INVALID_DATA, {}); - InvokeCallback(ModalResult::fail, pathBuffer); - } - break; - - case (LOADSAVETYPE_SAVE | LOADSAVETYPE_LANDSCAPE): - SetAndSaveConfigPath(Config::Get().general.LastSaveLandscapeDirectory, pathBuffer); - gameState.ScenarioFileName = std::string(String::toStringView(pathBuffer, std::size(pathBuffer))); - if (ScenarioSave(gameState, pathBuffer, Config::Get().general.SavePluginData ? 3 : 2)) - { - gCurrentLoadedPath = pathBuffer; - windowMgr->CloseByClass(WindowClass::Loadsave); - GfxInvalidateScreen(); - InvokeCallback(ModalResult::ok, pathBuffer); - } - else - { - ContextShowError(STR_SAVE_LANDSCAPE, STR_LANDSCAPE_SAVE_FAILED, {}); - InvokeCallback(ModalResult::fail, pathBuffer); - } - break; - - case (LOADSAVETYPE_SAVE | LOADSAVETYPE_SCENARIO): - { - SetAndSaveConfigPath(Config::Get().general.LastSaveScenarioDirectory, pathBuffer); - int32_t parkFlagsBackup = gameState.Park.Flags; - gameState.Park.Flags &= ~PARK_FLAGS_SPRITES_INITIALISED; - gameState.EditorStep = EditorStep::Invalid; - gameState.ScenarioFileName = std::string(String::toStringView(pathBuffer, std::size(pathBuffer))); - int32_t success = ScenarioSave(gameState, pathBuffer, Config::Get().general.SavePluginData ? 3 : 2); - gameState.Park.Flags = parkFlagsBackup; - - if (success) - { - windowMgr->CloseByClass(WindowClass::Loadsave); - InvokeCallback(ModalResult::ok, pathBuffer); - - auto* context = GetContext(); - context->SetActiveScene(context->GetTitleScene()); - } - else - { - ContextShowError(STR_FILE_DIALOG_TITLE_SAVE_SCENARIO, STR_SCENARIO_SAVE_FAILED, {}); - gameState.EditorStep = EditorStep::ObjectiveSelection; - InvokeCallback(ModalResult::fail, pathBuffer); + auto* context = GetContext(); + context->SetActiveScene(context->GetTitleScene()); + } + else + { + ContextShowError(STR_FILE_DIALOG_TITLE_SAVE_SCENARIO, STR_SCENARIO_SAVE_FAILED, {}); + gameState.EditorStep = EditorStep::ObjectiveSelection; + InvokeCallback(ModalResult::fail, pathBuffer); + } + break; + } + case (LoadSaveType::track): + { + SetAndSaveConfigPath(Config::Get().general.LastSaveTrackDirectory, pathBuffer); + auto intent = Intent(WindowClass::InstallTrack); + intent.PutExtra(INTENT_EXTRA_PATH, std::string{ pathBuffer }); + ContextOpenIntent(&intent); + windowMgr->CloseByClass(WindowClass::Loadsave); + InvokeCallback(ModalResult::ok, pathBuffer); + break; + } + case (LoadSaveType::heightmap): + { + windowMgr->CloseByClass(WindowClass::Loadsave); + InvokeCallback(ModalResult::ok, pathBuffer); + break; + } } break; } - - case (LOADSAVETYPE_LOAD | LOADSAVETYPE_TRACK): + case LoadSaveAction::save: { - SetAndSaveConfigPath(Config::Get().general.LastSaveTrackDirectory, pathBuffer); - auto intent = Intent(WindowClass::InstallTrack); - intent.PutExtra(INTENT_EXTRA_PATH, std::string{ pathBuffer }); - ContextOpenIntent(&intent); - windowMgr->CloseByClass(WindowClass::Loadsave); - InvokeCallback(ModalResult::ok, pathBuffer); - break; - } - - case (LOADSAVETYPE_SAVE | LOADSAVETYPE_TRACK): - { - SetAndSaveConfigPath(Config::Get().general.LastSaveTrackDirectory, pathBuffer); - - const auto withExtension = Path::WithExtension(pathBuffer, ".td6"); - String::set(pathBuffer, sizeof(pathBuffer), withExtension.c_str()); - - RCT2::T6Exporter t6Export{ *trackDesignPtr }; - - auto success = t6Export.SaveTrack(pathBuffer); - - if (success) + switch (type) { - windowMgr->CloseByClass(WindowClass::Loadsave); - Windows::WindowRideMeasurementsDesignCancel(); - InvokeCallback(ModalResult::ok, path); - } - else - { - ContextShowError(STR_FILE_DIALOG_TITLE_SAVE_TRACK, STR_TRACK_SAVE_FAILED, {}); - InvokeCallback(ModalResult::fail, path); + case LoadSaveType::park: + { + SetAndSaveConfigPath(Config::Get().general.LastSaveGameDirectory, pathBuffer); + if (ScenarioSave(gameState, pathBuffer, Config::Get().general.SavePluginData ? 1 : 0)) + { + gScenarioSavePath = pathBuffer; + gCurrentLoadedPath = pathBuffer; + gIsAutosaveLoaded = false; + gFirstTimeSaving = false; + + windowMgr->CloseByClass(WindowClass::Loadsave); + GfxInvalidateScreen(); + + InvokeCallback(ModalResult::ok, pathBuffer); + } + else + { + ContextShowError(STR_SAVE_GAME, STR_GAME_SAVE_FAILED, {}); + InvokeCallback(ModalResult::fail, pathBuffer); + } + break; + } + case LoadSaveType::landscape: + { + SetAndSaveConfigPath(Config::Get().general.LastSaveLandscapeDirectory, pathBuffer); + gameState.ScenarioFileName = std::string(String::toStringView(pathBuffer, std::size(pathBuffer))); + if (ScenarioSave(gameState, pathBuffer, Config::Get().general.SavePluginData ? 3 : 2)) + { + gCurrentLoadedPath = pathBuffer; + windowMgr->CloseByClass(WindowClass::Loadsave); + GfxInvalidateScreen(); + InvokeCallback(ModalResult::ok, pathBuffer); + } + else + { + ContextShowError(STR_SAVE_LANDSCAPE, STR_LANDSCAPE_SAVE_FAILED, {}); + InvokeCallback(ModalResult::fail, pathBuffer); + } + break; + } + case LoadSaveType::scenario: + { + break; + } + case LoadSaveType::track: + { + SetAndSaveConfigPath(Config::Get().general.LastSaveTrackDirectory, pathBuffer); + + const auto withExtension = Path::WithExtension(pathBuffer, ".td6"); + String::set(pathBuffer, sizeof(pathBuffer), withExtension.c_str()); + + RCT2::T6Exporter t6Export{ *trackDesignPtr }; + + auto success = t6Export.SaveTrack(pathBuffer); + + if (success) + { + windowMgr->CloseByClass(WindowClass::Loadsave); + Windows::WindowRideMeasurementsDesignCancel(); + InvokeCallback(ModalResult::ok, path); + } + else + { + ContextShowError(STR_FILE_DIALOG_TITLE_SAVE_TRACK, STR_TRACK_SAVE_FAILED, {}); + InvokeCallback(ModalResult::fail, path); + } + break; + } + case LoadSaveType::heightmap: + { + break; + } } break; } - - case (LOADSAVETYPE_LOAD | LOADSAVETYPE_HEIGHTMAP): - windowMgr->CloseByClass(WindowClass::Loadsave); - InvokeCallback(ModalResult::ok, pathBuffer); - break; } } - StringId GetTitleStringId(int32_t type, bool isSave) + StringId GetTitleStringId(LoadSaveType type, bool isSave) { - switch (type & 0x0E) + switch (type) { - case LOADSAVETYPE_GAME: + case LoadSaveType::park: return isSave ? STR_FILE_DIALOG_TITLE_SAVE_GAME : STR_FILE_DIALOG_TITLE_LOAD_GAME; - case LOADSAVETYPE_LANDSCAPE: + case LoadSaveType::landscape: return isSave ? STR_FILE_DIALOG_TITLE_SAVE_LANDSCAPE : STR_FILE_DIALOG_TITLE_LOAD_LANDSCAPE; - case LOADSAVETYPE_SCENARIO: + case LoadSaveType::scenario: return STR_FILE_DIALOG_TITLE_SAVE_SCENARIO; - case LOADSAVETYPE_TRACK: + case LoadSaveType::track: return isSave ? STR_FILE_DIALOG_TITLE_SAVE_TRACK : STR_FILE_DIALOG_TITLE_INSTALL_NEW_TRACK_DESIGN; - case LOADSAVETYPE_HEIGHTMAP: + case LoadSaveType::heightmap: return STR_FILE_DIALOG_TITLE_LOAD_HEIGHTMAP; default: @@ -397,20 +423,20 @@ namespace OpenRCT2::Ui::FileBrowser } } - static u8string GetDefaultExtensionByType(int32_t type) + static u8string GetDefaultExtensionByType(LoadSaveType type) { - switch (type & 0x0E) + switch (type) { - case LOADSAVETYPE_GAME: + case LoadSaveType::park: return u8".park"; - case LOADSAVETYPE_LANDSCAPE: + case LoadSaveType::landscape: return u8".park"; - case LOADSAVETYPE_SCENARIO: + case LoadSaveType::scenario: return u8".park"; - case LOADSAVETYPE_TRACK: + case LoadSaveType::track: return u8".td6"; default: @@ -418,23 +444,23 @@ namespace OpenRCT2::Ui::FileBrowser } } - static Ui::FileDialogDesc::Filter GetFilterForType(int32_t type, bool isSave) + static Ui::FileDialogDesc::Filter GetFilterForType(LoadSaveType type, bool isSave) { - switch (type & 0x0E) + switch (type) { - case LOADSAVETYPE_GAME: + case LoadSaveType::park: return { LanguageGetString(STR_OPENRCT2_SAVED_GAME), GetFilterPatternByType(type, isSave) }; - case LOADSAVETYPE_LANDSCAPE: + case LoadSaveType::landscape: return { LanguageGetString(STR_OPENRCT2_LANDSCAPE_FILE), GetFilterPatternByType(type, isSave) }; - case LOADSAVETYPE_SCENARIO: + case LoadSaveType::scenario: return { LanguageGetString(STR_OPENRCT2_SCENARIO_FILE), GetFilterPatternByType(type, isSave) }; - case LOADSAVETYPE_TRACK: + case LoadSaveType::track: return { LanguageGetString(STR_OPENRCT2_TRACK_DESIGN_FILE), GetFilterPatternByType(type, isSave) }; - case LOADSAVETYPE_HEIGHTMAP: + case LoadSaveType::heightmap: return { LanguageGetString(STR_OPENRCT2_HEIGHTMAP_FILE), GetFilterPatternByType(type, isSave) }; default: @@ -443,7 +469,7 @@ namespace OpenRCT2::Ui::FileBrowser } } - u8string OpenSystemFileBrowser(bool isSave, int32_t type, u8string defaultDirectory, u8string defaultPath) + u8string OpenSystemFileBrowser(bool isSave, LoadSaveType type, u8string defaultDirectory, u8string defaultPath) { u8string path = defaultDirectory; if (isSave) diff --git a/src/openrct2-ui/interface/FileBrowser.h b/src/openrct2-ui/interface/FileBrowser.h index 184fc6c69d..f577b84b15 100644 --- a/src/openrct2-ui/interface/FileBrowser.h +++ b/src/openrct2-ui/interface/FileBrowser.h @@ -15,6 +15,8 @@ #include #include +enum class LoadSaveAction : uint8_t; +enum class LoadSaveType : uint8_t; enum class ModalResult : int8_t; struct TrackDesign; @@ -50,15 +52,16 @@ namespace OpenRCT2::Ui::FileBrowser bool ListItemSort(LoadSaveListItem& a, LoadSaveListItem& b); void SetAndSaveConfigPath(u8string& config_str, u8string_view path); bool IsValidPath(const char* path); - u8string GetLastDirectoryByType(int32_t type); - u8string GetInitialDirectoryByType(const int32_t type); - const char* GetFilterPatternByType(const int32_t type, const bool isSave); + u8string GetLastDirectoryByType(LoadSaveType type); + u8string GetInitialDirectoryByType(const LoadSaveType type); + const char* GetFilterPatternByType(const LoadSaveType type, const bool isSave); u8string RemovePatternWildcard(u8string_view pattern); - u8string GetDir(const int32_t type); + u8string GetDir(const LoadSaveType type); void RegisterCallback(std::function callback); void InvokeCallback(ModalResult result, const utf8* path); - void Select(const char* path, int32_t type, TrackDesign* trackDesignPtr); - StringId GetTitleStringId(int32_t type, bool isSave); - u8string OpenSystemFileBrowser(bool isSave, int32_t type, u8string defaultDirectory, u8string defaultPath); - WindowBase* OpenPreferred(int32_t type, u8string defaultPath, LoadSaveCallback callback, TrackDesign* trackDesign); + void Select(const char* path, LoadSaveAction action, LoadSaveType type, TrackDesign* trackDesignPtr); + StringId GetTitleStringId(LoadSaveType type, bool isSave); + u8string OpenSystemFileBrowser(bool isSave, LoadSaveType type, u8string defaultDirectory, u8string defaultPath); + WindowBase* OpenPreferred( + LoadSaveAction action, LoadSaveType type, u8string defaultPath, LoadSaveCallback callback, TrackDesign* trackDesign); } // namespace OpenRCT2::Ui::FileBrowser diff --git a/src/openrct2-ui/scripting/ScUi.hpp b/src/openrct2-ui/scripting/ScUi.hpp index 0f5ed93f9d..85f2be5ca8 100644 --- a/src/openrct2-ui/scripting/ScUi.hpp +++ b/src/openrct2-ui/scripting/ScUi.hpp @@ -272,21 +272,22 @@ namespace OpenRCT2::Scripting auto defaultPath = AsOrDefault(desc["defaultPath"], ""); auto callback = desc["callback"]; - int32_t loadSaveType{}; + auto loadSaveAction = LoadSaveAction::load; if (type == "load") - loadSaveType = LOADSAVETYPE_LOAD; + loadSaveAction = LoadSaveAction::load; else throw DukException(); + LoadSaveType loadSaveType; if (fileType == "game") - loadSaveType |= LOADSAVETYPE_GAME; + loadSaveType = LoadSaveType::park; else if (fileType == "heightmap") - loadSaveType |= LOADSAVETYPE_HEIGHTMAP; + loadSaveType = LoadSaveType::heightmap; else throw DukException(); LoadsaveOpen( - loadSaveType, defaultPath, + loadSaveAction, loadSaveType, defaultPath, [this, plugin, callback](ModalResult result, std::string_view path) { if (result == ModalResult::ok) { diff --git a/src/openrct2-ui/windows/EditorBottomToolbar.cpp b/src/openrct2-ui/windows/EditorBottomToolbar.cpp index 024c7c97a0..1c21ae8c21 100644 --- a/src/openrct2-ui/windows/EditorBottomToolbar.cpp +++ b/src/openrct2-ui/windows/EditorBottomToolbar.cpp @@ -263,7 +263,8 @@ namespace OpenRCT2::Ui::Windows auto* windowMgr = Ui::GetWindowManager(); windowMgr->CloseAll(); auto intent = Intent(WindowClass::Loadsave); - intent.PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_SAVE | LOADSAVETYPE_SCENARIO); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::save); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::scenario); intent.PutExtra(INTENT_EXTRA_PATH, gameState.ScenarioName); ContextOpenIntent(&intent); } diff --git a/src/openrct2-ui/windows/EditorObjectSelection.cpp b/src/openrct2-ui/windows/EditorObjectSelection.cpp index 34030ffe42..83bcef07ae 100644 --- a/src/openrct2-ui/windows/EditorObjectSelection.cpp +++ b/src/openrct2-ui/windows/EditorObjectSelection.cpp @@ -417,7 +417,8 @@ namespace OpenRCT2::Ui::Windows Invalidate(); auto intent = Intent(WindowClass::Loadsave); - intent.PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_LOAD | LOADSAVETYPE_TRACK); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::load); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::track); ContextOpenIntent(&intent); break; } diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index e9a5b7e42f..0cfe5b9756 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -123,15 +123,17 @@ namespace OpenRCT2::Ui::Windows class LoadSaveWindow final : public Window { public: - LoadSaveWindow(int32_t loadSaveType) - : type(loadSaveType) + LoadSaveWindow(LoadSaveAction _action, LoadSaveType _type) + : action(_action) + , type(_type) { } private: int32_t maxDateWidth{ 0 }; int32_t maxTimeWidth{ 0 }; - int32_t type; + LoadSaveAction action; + LoadSaveType type; ParkPreview _preview; bool ShowPreviews() @@ -140,7 +142,7 @@ namespace OpenRCT2::Ui::Windows return config.FileBrowserShowPreviews; } - void PopulateList(bool includeNewItem, const u8string& directory, std::string_view extensionPattern) + void PopulateList(const u8string& directory, std::string_view extensionPattern) { const auto absoluteDirectory = Path::GetAbsolute(directory); String::safeUtf8Copy(_directory, absoluteDirectory.c_str(), std::size(_directory)); @@ -325,7 +327,7 @@ namespace OpenRCT2::Ui::Windows if (!ShowPreviews()) return; - if ((type & 0x0E) == LOADSAVETYPE_TRACK || (type & 0x0E) == LOADSAVETYPE_HEIGHTMAP) + if (type == LoadSaveType::track || type == LoadSaveType::heightmap) return; if (_listItems[selected_list_item].type == FileType::directory) @@ -464,8 +466,7 @@ namespace OpenRCT2::Ui::Windows widgets[WIDX_SYSTEM_BROWSER].type = WindowWidgetType::Empty; } - // TODO: Split LOADSAVETYPE_* into two proper enum classes (one for load/save, the other for the type) - const bool isSave = (type & 0x01) == LOADSAVETYPE_SAVE; + const bool isSave = action == LoadSaveAction::save; // Pause the game if not on title scene, nor in network play. if (gLegacyScene != LegacyScene::titleSequence && NetworkGetMode() == NETWORK_MODE_NONE) @@ -495,7 +496,7 @@ namespace OpenRCT2::Ui::Windows // Populate file list const char* pattern = GetFilterPatternByType(type, isSave); const auto path = GetDir(type); - PopulateList(isSave, path, pattern); + PopulateList(path, pattern); no_list_items = static_cast(_listItems.size()); selected_list_item = -1; @@ -622,7 +623,7 @@ namespace OpenRCT2::Ui::Windows widgets[WIDX_SORT_DATE].type = WindowWidgetType::Empty; } - if (type & LOADSAVETYPE_SAVE) + if (action == LoadSaveAction::save) { widgets[WIDX_SCROLL].bottom -= 18; @@ -712,7 +713,7 @@ namespace OpenRCT2::Ui::Windows widgets[WIDX_SORT_DATE], STR_DATE_COLUMN, FileBrowserSort::DateAscending, FileBrowserSort::DateDescending); // 'Filename:' label - if (type & LOADSAVETYPE_SAVE) + if (action == LoadSaveAction::save) { auto& widget = widgets[WIDX_FILENAME_TEXTBOX]; DrawTextBasic(dpi, windowPos + ScreenCoordsXY{ 5, widget.top + 2 }, STR_FILENAME_LABEL, {}, { COLOUR_GREY }); @@ -721,7 +722,7 @@ namespace OpenRCT2::Ui::Windows void OnMouseUp(WidgetIndex widgetIndex) override { - bool isSave = (type & 0x01) == LOADSAVETYPE_SAVE; + bool isSave = action == LoadSaveAction::save; switch (widgetIndex) { case WIDX_CLOSE: @@ -729,7 +730,7 @@ namespace OpenRCT2::Ui::Windows break; case WIDX_PARENT_FOLDER: - PopulateList(isSave, _parentDirectory, _extensionPattern); + PopulateList(_parentDirectory, _extensionPattern); InitScrollWidgets(); no_list_items = static_cast(_listItems.size()); break; @@ -745,12 +746,12 @@ namespace OpenRCT2::Ui::Windows u8string path = OpenSystemFileBrowser(isSave, type, _directory, _defaultPath); if (!path.empty()) { - Select(path.c_str(), type, _trackDesign); + Select(path.c_str(), action, type, _trackDesign); } else { // If user cancels file dialog, refresh list - PopulateList(isSave, _directory, _extensionPattern); + PopulateList(_directory, _extensionPattern); InitScrollWidgets(); no_list_items = static_cast(_listItems.size()); } @@ -800,7 +801,7 @@ namespace OpenRCT2::Ui::Windows break; case WIDX_DEFAULT_FOLDER: - PopulateList(isSave, GetInitialDirectoryByType(type).c_str(), _extensionPattern); + PopulateList(GetInitialDirectoryByType(type).c_str(), _extensionPattern); InitScrollWidgets(); no_list_items = static_cast(_listItems.size()); break; @@ -815,9 +816,9 @@ namespace OpenRCT2::Ui::Windows Path::Combine(_directory, _currentFilename), RemovePatternWildcard(_extensionPattern)); if (File::Exists(path)) - WindowOverwritePromptOpen(_currentFilename, path, type, _trackDesign); + WindowOverwritePromptOpen(_currentFilename, path, action, type, _trackDesign); else - Select(path.c_str(), type, _trackDesign); + Select(path.c_str(), action, type, _trackDesign); } } } @@ -912,7 +913,7 @@ namespace OpenRCT2::Ui::Windows no_list_items = 0; selected_list_item = -1; - PopulateList((type & 1) == LOADSAVETYPE_SAVE, path, _extensionPattern); + PopulateList(path, _extensionPattern); InitScrollWidgets(); no_list_items = static_cast(_listItems.size()); @@ -964,12 +965,11 @@ namespace OpenRCT2::Ui::Windows // The selected item is a folder no_list_items = 0; selected_list_item = -1; - bool includeNewItem = (type & 1) == LOADSAVETYPE_SAVE; char directory[MAX_PATH]; String::safeUtf8Copy(directory, _listItems[selectedItem].path.c_str(), sizeof(directory)); - PopulateList(includeNewItem, directory, _extensionPattern); + PopulateList(directory, _extensionPattern); InitScrollWidgets(); no_list_items = static_cast(_listItems.size()); @@ -980,10 +980,15 @@ namespace OpenRCT2::Ui::Windows String::set(_currentFilename, std::size(_currentFilename), _listItems[selectedItem].name.c_str()); InvalidateWidget(WIDX_FILENAME_TEXTBOX); - if ((type & 0x01) == LOADSAVETYPE_SAVE) - WindowOverwritePromptOpen(_listItems[selectedItem].name, _listItems[selectedItem].path, type, _trackDesign); + if (action == LoadSaveAction::save) + { + WindowOverwritePromptOpen( + _listItems[selectedItem].name, _listItems[selectedItem].path, action, type, _trackDesign); + } else - Select(_listItems[selectedItem].path.c_str(), type, _trackDesign); + { + Select(_listItems[selectedItem].path.c_str(), action, type, _trackDesign); + } } } @@ -1069,7 +1074,9 @@ namespace OpenRCT2::Ui::Windows #pragma endregion }; - WindowBase* LoadsaveOpen(int32_t type, std::string_view defaultPath, LoadSaveCallback callback, TrackDesign* trackDesign) + WindowBase* LoadsaveOpen( + LoadSaveAction action, LoadSaveType type, std::string_view defaultPath, LoadSaveCallback callback, + TrackDesign* trackDesign) { _trackDesign = trackDesign; _defaultPath = defaultPath; @@ -1094,12 +1101,12 @@ namespace OpenRCT2::Ui::Windows w = windowMgr->Create( WindowClass::Loadsave, width, height, WF_STICK_TO_FRONT | WF_RESIZABLE | WF_AUTO_POSITION | WF_CENTRE_SCREEN, - type); + action, type); } - bool isSave = (type & 0x01) == LOADSAVETYPE_SAVE; + bool isSave = action == LoadSaveAction::save; - if ((type & 0x0E) == LOADSAVETYPE_HEIGHTMAP && !isSave) + if (type == LoadSaveType::heightmap && isSave) { Guard::Fail("Cannot save images through loadsave window"); } @@ -1107,7 +1114,7 @@ namespace OpenRCT2::Ui::Windows w->widgets[WIDX_TITLE].text = GetTitleStringId(type, isSave); if (w->widgets[WIDX_TITLE].text == kStringIdNone) { - Guard::Fail("Unsupported load/save type: %d", type & 0x0F); + Guard::Fail("Unsupported load/save type: %d", EnumValue(type)); } return w; diff --git a/src/openrct2-ui/windows/MapGen.cpp b/src/openrct2-ui/windows/MapGen.cpp index 8e5d942aad..b13f2b95f4 100644 --- a/src/openrct2-ui/windows/MapGen.cpp +++ b/src/openrct2-ui/windows/MapGen.cpp @@ -929,7 +929,8 @@ namespace OpenRCT2::Ui::Windows case WIDX_HEIGHTMAP_BROWSE: { auto intent = Intent(WindowClass::Loadsave); - intent.PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_LOAD | LOADSAVETYPE_HEIGHTMAP); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::load); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::heightmap); intent.PutExtra(INTENT_EXTRA_CALLBACK, reinterpret_cast(HeightmapLoadsaveCallback)); ContextOpenIntent(&intent); return; diff --git a/src/openrct2-ui/windows/OverwritePrompt.cpp b/src/openrct2-ui/windows/OverwritePrompt.cpp index 3543935cc9..fc1dff6b32 100644 --- a/src/openrct2-ui/windows/OverwritePrompt.cpp +++ b/src/openrct2-ui/windows/OverwritePrompt.cpp @@ -43,14 +43,17 @@ namespace OpenRCT2::Ui::Windows { std::string _name; std::string _path; - int32_t _type; + LoadSaveAction _action; + LoadSaveType _type; TrackDesign* _trackDesign; public: OverwritePromptWindow( - const std::string_view name, const std::string_view path, int32_t type, TrackDesign* trackDesignPtr) + const std::string_view name, const std::string_view path, LoadSaveAction action, LoadSaveType type, + TrackDesign* trackDesignPtr) : _name(name) , _path(path) + , _action(action) , _type(type) , _trackDesign(trackDesignPtr) { @@ -67,7 +70,7 @@ namespace OpenRCT2::Ui::Windows { case WIDX_OVERWRITE_OVERWRITE: { - FileBrowser::Select(_path.c_str(), _type, _trackDesign); + FileBrowser::Select(_path.c_str(), _action, _type, _trackDesign); // As the LoadSaveWindow::Select function can change the order of the // windows we can't use WindowClose(w). @@ -97,14 +100,15 @@ namespace OpenRCT2::Ui::Windows }; WindowBase* WindowOverwritePromptOpen( - const std::string_view name, const std::string_view path, int32_t type, TrackDesign* trackDesignPtr) + const std::string_view name, const std::string_view path, LoadSaveAction action, LoadSaveType type, + TrackDesign* trackDesignPtr) { auto* windowMgr = Ui::GetWindowManager(); windowMgr->CloseByClass(WindowClass::LoadsaveOverwritePrompt); return windowMgr->Create( WindowClass::LoadsaveOverwritePrompt, OVERWRITE_WW, OVERWRITE_WH, - WF_TRANSPARENT | WF_STICK_TO_FRONT | WF_CENTRE_SCREEN, name, path, type, trackDesignPtr); + WF_TRANSPARENT | WF_STICK_TO_FRONT | WF_CENTRE_SCREEN, name, path, action, type, trackDesignPtr); } void WindowLoadSaveOverwritePromptInputKey(WindowBase* w, uint32_t keycode) diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index 5f6a9e26bb..df810c461c 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -5412,7 +5412,8 @@ namespace OpenRCT2::Ui::Windows auto trackName = ride->GetName(); auto intent = Intent(WindowClass::Loadsave); - intent.PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_SAVE | LOADSAVETYPE_TRACK); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::save); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::track); intent.PutExtra(INTENT_EXTRA_TRACK_DESIGN, _trackDesign.get()); intent.PutExtra(INTENT_EXTRA_PATH, trackName); intent.PutExtra(INTENT_EXTRA_CALLBACK, reinterpret_cast(&TrackDesignCallback)); diff --git a/src/openrct2-ui/windows/SavePrompt.cpp b/src/openrct2-ui/windows/SavePrompt.cpp index 7eb367f094..b473733aab 100644 --- a/src/openrct2-ui/windows/SavePrompt.cpp +++ b/src/openrct2-ui/windows/SavePrompt.cpp @@ -169,7 +169,8 @@ namespace OpenRCT2::Ui::Windows if (isInEditorMode()) { intent = std::make_unique(WindowClass::Loadsave); - intent->PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_SAVE | LOADSAVETYPE_LANDSCAPE); + intent->PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::save); + intent->PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::landscape); intent->PutExtra(INTENT_EXTRA_PATH, GetGameState().ScenarioName); } else diff --git a/src/openrct2-ui/windows/ServerStart.cpp b/src/openrct2-ui/windows/ServerStart.cpp index 84bb002f81..b4e45337b3 100644 --- a/src/openrct2-ui/windows/ServerStart.cpp +++ b/src/openrct2-ui/windows/ServerStart.cpp @@ -136,7 +136,8 @@ namespace OpenRCT2::Ui::Windows case WIDX_LOAD_SERVER: NetworkSetPassword(_password); auto intent = Intent(WindowClass::Loadsave); - intent.PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::load); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::park); intent.PutExtra(INTENT_EXTRA_CALLBACK, reinterpret_cast(LoadSaveCallback)); ContextOpenIntent(&intent); break; diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index 91a78d076e..8ef77c5369 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -464,7 +464,8 @@ namespace OpenRCT2::Ui::Windows if (gLegacyScene == LegacyScene::scenarioEditor) { auto intent = Intent(WindowClass::Loadsave); - intent.PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_SAVE | LOADSAVETYPE_LANDSCAPE); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::save); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::landscape); intent.PutExtra(INTENT_EXTRA_PATH, GetGameState().ScenarioName); ContextOpenIntent(&intent); } diff --git a/src/openrct2-ui/windows/Windows.h b/src/openrct2-ui/windows/Windows.h index 84e771d9a7..fda2c211b8 100644 --- a/src/openrct2-ui/windows/Windows.h +++ b/src/openrct2-ui/windows/Windows.h @@ -133,8 +133,8 @@ namespace OpenRCT2::Ui::Windows // LoadSave WindowBase* LoadsaveOpen( - int32_t type, std::string_view defaultPath, std::function callback, - TrackDesign* trackDesign); + LoadSaveAction action, LoadSaveType type, std::string_view defaultPath, + std::function callback, TrackDesign* trackDesign); void WindowLoadSaveInputKey(WindowBase* w, uint32_t keycode); // Main @@ -188,7 +188,8 @@ namespace OpenRCT2::Ui::Windows // OverwritePrompt WindowBase* WindowOverwritePromptOpen( - const std::string_view name, const std::string_view path, int32_t type, TrackDesign* trackDesignPtr); + const std::string_view name, const std::string_view path, LoadSaveAction action, LoadSaveType type, + TrackDesign* trackDesignPtr); void WindowLoadSaveOverwritePromptInputKey(WindowBase* w, uint32_t keycode); // Park diff --git a/src/openrct2/Editor.cpp b/src/openrct2/Editor.cpp index 0a95d9d7f9..c98549dcec 100644 --- a/src/openrct2/Editor.cpp +++ b/src/openrct2/Editor.cpp @@ -126,7 +126,8 @@ namespace OpenRCT2::Editor { ToolCancel(); auto intent = Intent(WindowClass::Loadsave); - intent.PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::load); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::park); intent.PutExtra(INTENT_EXTRA_CALLBACK, reinterpret_cast(ConvertSaveToScenarioCallback)); ContextOpenIntent(&intent); } diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index f7052a9d96..d93c154797 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -167,7 +167,8 @@ bool GameIsNotPaused() static void LoadLandscape() { auto intent = Intent(WindowClass::Loadsave); - intent.PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_LOAD | LOADSAVETYPE_LANDSCAPE); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::load); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::landscape); ContextOpenIntent(&intent); } @@ -498,7 +499,8 @@ std::unique_ptr CreateSaveGameAsIntent() auto name = Path::GetFileNameWithoutExtension(gScenarioSavePath); auto intent = std::make_unique(WindowClass::Loadsave); - intent->PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME); + intent->PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::save); + intent->PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::park); intent->PutExtra(INTENT_EXTRA_PATH, name); return intent; @@ -663,7 +665,8 @@ void GameLoadOrQuitNoSavePrompt() else { auto intent = Intent(WindowClass::Loadsave); - intent.PutExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_ACTION, LoadSaveAction::load); + intent.PutEnumExtra(INTENT_EXTRA_LOADSAVE_TYPE, LoadSaveType::park); intent.PutExtra(INTENT_EXTRA_CALLBACK, reinterpret_cast(GameLoadOrQuitNoSavePromptCallback)); ContextOpenIntent(&intent); } diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index 3cfc1b60c4..48d472073a 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -212,17 +212,19 @@ enum BTM_TOOLBAR_DIRTY_FLAGS BTM_TB_DIRTY_FLAG_PARK_RATING = (1 << 4) }; -// 000N_TTTL -enum +enum class LoadSaveAction : uint8_t { - LOADSAVETYPE_LOAD = 0 << 0, - LOADSAVETYPE_SAVE = 1 << 0, + load, + save, +}; - LOADSAVETYPE_GAME = 0 << 1, - LOADSAVETYPE_LANDSCAPE = 1 << 1, - LOADSAVETYPE_SCENARIO = 2 << 1, - LOADSAVETYPE_TRACK = 3 << 1, - LOADSAVETYPE_HEIGHTMAP = 4 << 1, +enum class LoadSaveType : uint8_t +{ + park, + landscape, + scenario, + track, + heightmap, }; enum class ModalResult : int8_t diff --git a/src/openrct2/windows/Intent.h b/src/openrct2/windows/Intent.h index 3439d33442..575540cd41 100644 --- a/src/openrct2/windows/Intent.h +++ b/src/openrct2/windows/Intent.h @@ -89,12 +89,24 @@ namespace OpenRCT2 uint32_t GetUIntExtra(uint32_t key) const; int32_t GetSIntExtra(uint32_t key) const; CloseCallback GetCloseCallbackExtra(uint32_t key) const; + template + TEnumType GetEnumExtra(uint32_t key) + { + static_assert(std::is_enum_v); + return static_cast(GetUIntExtra(key)); + } Intent* PutExtra(uint32_t key, uint32_t value); Intent* PutExtra(uint32_t key, void* value); Intent* PutExtra(uint32_t key, int32_t value); Intent* PutExtra(uint32_t key, std::string value); Intent* PutExtra(uint32_t key, CloseCallback value); + template + Intent* PutEnumExtra(uint32_t key, TEnumType value) + { + static_assert(std::is_enum_v); + return PutExtra(key, EnumValue(value)); + } template Intent* PutExtra(uint32_t key, const TIdentifier& value) @@ -110,6 +122,7 @@ namespace OpenRCT2 INTENT_EXTRA_RIDE_ID, INTENT_EXTRA_PATH, INTENT_EXTRA_PEEP, + INTENT_EXTRA_LOADSAVE_ACTION, INTENT_EXTRA_LOADSAVE_TYPE, INTENT_EXTRA_CALLBACK, INTENT_EXTRA_TRACK_DESIGN,