Created
January 17, 2022 20:13
-
-
Save redxdev/eef7050fafcd23b82bb8d2c6e6d5bf98 to your computer and use it in GitHub Desktop.
Editor functions that allow exporting save games to json and then importing them again. Meant to be used in an editor module that depends on Json and JsonUtilities. Use it from an editor utility widget.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "SaveGameEditorUtilities.h" | |
#include "GameFramework/SaveGame.h" | |
#include "DesktopPlatformModule.h" | |
#include "JsonObjectConverter.h" | |
#include "Kismet/GameplayStatics.h" | |
#include "Logging/MessageLog.h" | |
#include "Misc/FileHelper.h" | |
#define LOCTEXT_NAMESPACE "SaveGameEditorUtilities" | |
bool USaveGameEditorUtilities::ExportSaveGameToJsonFile(const FString& SlotName, int32 UserIndex) | |
{ | |
if (!UGameplayStatics::DoesSaveGameExist(SlotName, UserIndex)) | |
{ | |
FMessageLog("EditorErrors").Error(FText::Format(LOCTEXT("SaveGameDoesNotExit", "Save game '{0}' does not exist, cannot export save game"), FText::FromString(SlotName))); | |
FMessageLog("EditorErrors").Notify(LOCTEXT("ExportFailNotification", "Failed to export save game")); | |
return false; | |
} | |
USaveGame* SaveGame = UGameplayStatics::LoadGameFromSlot(SlotName, UserIndex); | |
if (!SaveGame) | |
{ | |
FMessageLog("EditorErrors").Error(FText::Format(LOCTEXT("SaveGameFailedToLoad", "Save game '{0}' failed to load, cannot export save game"), FText::FromString(SlotName))); | |
FMessageLog("EditorErrors").Notify(LOCTEXT("ExportFailNotification", "Failed to export save game")); | |
return false; | |
} | |
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get(); | |
if (!DesktopPlatform) | |
{ | |
FMessageLog("EditorErrors").Error(LOCTEXT("ExportBadDesktopPlatform", "Unable to retrieve IDesktopPlatform, cannot export save game")); | |
FMessageLog("EditorErrors").Notify(LOCTEXT("ExportFailNotification", "Failed to export save game")); | |
return false; | |
} | |
TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().GetActiveTopLevelWindow(); | |
void* ParentWindowHandle = (ParentWindow.IsValid() && ParentWindow->GetNativeWindow().IsValid()) | |
? ParentWindow->GetNativeWindow()->GetOSWindowHandle() | |
: nullptr; | |
TArray<FString> SelectedFiles; | |
bool Result = DesktopPlatform->SaveFileDialog( | |
ParentWindowHandle, | |
TEXT("Export Save Game"), | |
FPaths::ProjectDir(), | |
FString::Printf(TEXT("%s.json"), SlotName), | |
TEXT("JSON Files|*.json"), | |
EFileDialogFlags::None, | |
SelectedFiles); | |
if (!Result || SelectedFiles.Num() == 0) | |
{ | |
return false; | |
} | |
FString JsonString; | |
if (!ExportSaveGameToJson(SaveGame, JsonString)) | |
{ | |
FMessageLog("EditorErrors").Error(LOCTEXT("ExportSaveFailedJson", "Failed to export save, json error")); | |
FMessageLog("EditorErrors").Notify(LOCTEXT("ExportFailNotification", "Failed to export save game")); | |
} | |
if (!FFileHelper::SaveStringToFile(JsonString, *SelectedFiles[0])) | |
{ | |
FMessageLog("EditorErrors").Error(FText::Format(LOCTEXT("ExportSaveFailed", "Failed to export save to '{0}'"), FText::FromString(SelectedFiles[0]))); | |
FMessageLog("EditorErrors").Notify(LOCTEXT("ExportFailNotification", "Failed to export save game")); | |
return false; | |
} | |
return true; | |
} | |
bool USaveGameEditorUtilities::ImportSaveGameFromJsonFile(const FString& SlotName, int32 UserIndex) | |
{ | |
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get(); | |
if (!DesktopPlatform) | |
{ | |
FMessageLog("EditorErrors").Error(LOCTEXT("ImportBadDesktopPlatform", "Unable to retrieve IDesktopPlatform, cannot import save game")); | |
FMessageLog("EditorErrors").Notify(LOCTEXT("ImportFailNotification", "Failed to import save game")); | |
return false; | |
} | |
TSharedPtr<SWindow> ParentWindow = FSlateApplication::Get().GetActiveTopLevelWindow(); | |
void* ParentWindowHandle = (ParentWindow.IsValid() && ParentWindow->GetNativeWindow().IsValid()) | |
? ParentWindow->GetNativeWindow()->GetOSWindowHandle() | |
: nullptr; | |
TArray<FString> SelectedFiles; | |
bool Result = DesktopPlatform->OpenFileDialog( | |
ParentWindowHandle, | |
TEXT("Import Save Game"), | |
FPaths::ProjectDir(), | |
TEXT(""), | |
TEXT("JSON Files|*.json"), | |
EFileDialogFlags::None, | |
SelectedFiles); | |
if (!Result || SelectedFiles.Num() == 0) | |
{ | |
return false; | |
} | |
FString JsonString; | |
if (!FFileHelper::LoadFileToString(JsonString, *SelectedFiles[0])) | |
{ | |
FMessageLog("EditorErrors").Error(FText::Format(LOCTEXT("ImportFileFailed", "Failed to import save from '{0}'"), FText::FromString(SelectedFiles[0]))); | |
FMessageLog("EditorErrors").Notify(LOCTEXT("ImportFailNotification", "Failed to import save game")); | |
return false; | |
} | |
USaveGame* SaveGame = ImportSaveGameFromJson(JsonString); | |
if (!SaveGame) | |
{ | |
FMessageLog("EditorErrors").Error(FText::Format(LOCTEXT("ImportSaveFileFailed", "Failed to import save from '{0}', possible parse error"), FText::FromString(SelectedFiles[0]))); | |
FMessageLog("EditorErrors").Notify(LOCTEXT("ImportFailNotification", "Failed to import save game")); | |
return false; | |
} | |
if (!UGameplayStatics::SaveGameToSlot(SaveGame, SlotName, UserIndex)) | |
{ | |
FMessageLog("EditorErrors").Error(FText::Format(LOCTEXT("UnableToSaveImport", "Failed to save imported save game to slot '{0}'"), FText::FromString(SlotName))); | |
FMessageLog("EditorErrors").Notify(LOCTEXT("ImportFailNotification", "Failed to import save game")); | |
return false; | |
} | |
return true; | |
} | |
bool USaveGameEditorUtilities::ExportSaveGameToJson(USaveGame* Save, FString& OutJsonString) | |
{ | |
if (!IsValid(Save)) | |
{ | |
return false; | |
} | |
FExportedSaveGame Export; | |
Export.SaveGame = Save; | |
return FJsonObjectConverter::UStructToJsonObjectString(Export, OutJsonString); | |
} | |
USaveGame* USaveGameEditorUtilities::ImportSaveGameFromJson(const FString& JsonString) | |
{ | |
FExportedSaveGame Import; | |
if (!FJsonObjectConverter::JsonObjectStringToUStruct(JsonString, &Import, 0, 0)) | |
{ | |
return nullptr; | |
} | |
return Import.SaveGame; | |
} | |
#undef LOCTEXT_NAMESPACE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "CoreMinimal.h" | |
#include "SaveGameEditorUtilities.generated.h" | |
class USaveGame; | |
USTRUCT() | |
struct FExportedSaveGame | |
{ | |
GENERATED_BODY() | |
FExportedSaveGame() | |
{ | |
SaveGame = nullptr; | |
} | |
UPROPERTY(Instanced) | |
USaveGame* SaveGame; | |
}; | |
UCLASS() | |
class MYGAMEEDITOR_API USaveGameEditorUtilities : public UBlueprintFunctionLibrary | |
{ | |
GENERATED_BODY() | |
public: | |
UFUNCTION(BlueprintCallable, Category = "Game|SaveData|Editor") | |
static bool ExportSaveGameToJsonFile(const FString& SlotName, int32 UserIndex); | |
UFUNCTION(BlueprintCallable, Category = "Game|SaveData|Editor") | |
static bool ImportSaveGameFromJsonFile(const FString& SlotName, int32 UserIndex); | |
static bool ExportSaveGameToJson(USaveGame* Save, FString& OutJsonString); | |
static USaveGame* ImportSaveGameFromJson(const FString& JsonString); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment