5#include "HAL/PlatformFilemanager.h"
6#include "GenericPlatform/GenericPlatformFile.h"
7#include "UObject/Package.h"
8#include "FileHelpers.h"
30 ShowErrorCount =
true;
35 UE_LOG(LogDlgHumanReadableTextCommandlet, Display, TEXT(
"Starting"));
36 Settings = GetDefault<UDlgSystemSettings>();
39 TArray<FString> Tokens;
40 TArray<FString> Switches;
41 TMap<FString, FString> ParamVals;
42 UCommandlet::ParseCommandLine(*Params, Tokens, Switches, ParamVals);
45 const FString* OutputInputDirectoryVal = ParamVals.Find(FString(TEXT(
"OutputInputDirectory")));
46 if (OutputInputDirectoryVal ==
nullptr)
48 UE_LOG(LogDlgHumanReadableTextCommandlet,
Error, TEXT(
"Did not provide argument -OutputInputDirectory=<Path>"));
55 UE_LOG(LogDlgHumanReadableTextCommandlet,
Error, TEXT(
"OutputInputDirectory is empty, please provide a non empty one with -OutputInputDirectory=<Path>"));
65 if (Switches.Contains(TEXT(
"SaveAllDialogues")))
69 else if (Switches.Contains(TEXT(
"NoSaveAllDialogues")))
74 if (Switches.Contains(TEXT(
"Export")))
78 else if (Switches.Contains(
"Import"))
84 UE_LOG(LogDlgHumanReadableTextCommandlet,
Error, TEXT(
"Did not choose any operationg. Either -export OR -import"));
89 IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
92 UE_LOG(LogDlgHumanReadableTextCommandlet, Display, TEXT(
"Creating OutputInputDirectory = `%s`"), *
OutputInputDirectory);
107 UE_LOG(LogDlgHumanReadableTextCommandlet, Display, TEXT(
"Exporting to = `%s`"), *
OutputInputDirectory);
115 IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
119 UPackage* Package =
Dialogue->GetOutermost();
121 const FString OriginalDialoguePath = Package->GetPathName();
122 FString DialoguePath = OriginalDialoguePath;
127 UE_LOG(LogDlgHumanReadableTextCommandlet,
Warning, TEXT(
"Dialogue = `%s` is not in the game directory, ignoring"), *DialoguePath);
131 verify(DialoguePath.RemoveFromStart(TEXT(
"/Game")));
132 const FString FileName = FPaths::GetBaseFilename(DialoguePath);
133 const FString Directory = FPaths::GetPath(DialoguePath);
137 if (!PlatformFile.DirectoryExists(*FileSystemDirectoryPath) && PlatformFile.CreateDirectoryTree(*FileSystemDirectoryPath))
139 UE_LOG(LogDlgHumanReadableTextCommandlet, Display, TEXT(
"Creating directory = `%s`"), *FileSystemDirectoryPath);
149 JsonWriter.
Write(FDlgDialogue_FormatHumanReadable::StaticStruct(), &ExportFormat);
151 const FString FileSystemFilePath = FileSystemDirectoryPath / FileName +
FileExtension;
154 UE_LOG(LogDlgHumanReadableTextCommandlet, Display, TEXT(
"Writing file = `%s` for Dialogue = `%s` "), *FileSystemFilePath, *OriginalDialoguePath);
158 UE_LOG(LogDlgHumanReadableTextCommandlet,
Error, TEXT(
"FAILED to write file = `%s` for Dialogue = `%s`"), *FileSystemFilePath, *OriginalDialoguePath);
167 UE_LOG(LogDlgHumanReadableTextCommandlet, Display, TEXT(
"Importing from = `%s`"), *
OutputInputDirectory);
171 IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
174 TArray<FString> FoundFiles;
176 if (FoundFiles.Num() == 0)
178 UE_LOG(LogDlgHumanReadableTextCommandlet,
Error, TEXT(
"FAILED import, could not find any files with the extension = `%s` inside the directory = `%s`"),
FileExtension, *
OutputInputDirectory);
182 for (
const FString& File : FoundFiles)
184 UE_LOG(LogDlgHumanReadableTextCommandlet, Display, TEXT(
"Reading file = `%s` "), *File);
190 UE_LOG(LogDlgHumanReadableTextCommandlet,
Error, TEXT(
"FAILED to read file = `%s`"), *File);
195 JsonParser.
ReadAllProperty(FDlgDialogue_FormatHumanReadable::StaticStruct(), &HumanFormat);
198 UE_LOG(LogDlgHumanReadableTextCommandlet,
Error, TEXT(
"File = `%s` is not a valid JSON file"), *File);
205 if (DialoguePtr ==
nullptr)
207 UE_LOG(LogDlgHumanReadableTextCommandlet,
209 TEXT(
"Can't find Dialogue for GUID = `%s`, DialogueName = `%s` from File = `%s`"),
222 return UEditorLoadingAndSavingUtils::SavePackages(
PackagesToSave,
false) ==
true ? 0 : -1;
238 const TArray<UDlgNode*>& Nodes =
Dialogue.GetNodes();
239 for (int32 NodeIndex = 0; NodeIndex < Nodes.Num(); NodeIndex++)
241 const UDlgNode* Node = Nodes[NodeIndex];
247 ExportNode.
Speaker = NodeSpeech->GetNodeParticipantName();
248 ExportNode.
Text = NodeSpeech->GetNodeUnformattedText();
260 ExportNode.
Speaker = NodeSpeechSequence->GetNodeParticipantName();
266 ExportEntry.
EdgeText = Entry.EdgeText;
267 ExportEntry.
Text = Entry.Text;
268 ExportEntry.
Speaker = Entry.Speaker;
269 ExportNode.
Sequence.Add(ExportEntry);
284 GraphNode->CheckAll();
299 if (GraphNode ==
nullptr)
305 if (DialogueGraphNode ==
nullptr)
334 ExportEdge.
Text = Edge.GetUnformattedText();
335 OutEdges.Add(ExportEdge);
343 bool bModified =
false;
346 UE_LOG(LogDlgHumanReadableTextCommandlet,
Warning, TEXT(
"ImportHumanReadableFormatIntoDialogue: No data to import for Dialogue = `%s`"), *
Dialogue->GetPathName());
353 if (!HumanNode.IsValid())
359 const bool bIsRootNode = HumanNode.NodeIndex ==
RootNodeIndex;
362 UDlgNode* Node = bIsRootNode ?
Dialogue->GetMutableStartNode() :
Dialogue->GetMutableNodeFromIndex(HumanNode.NodeIndex);
365 UE_LOG(LogDlgHumanReadableTextCommandlet,
Warning, TEXT(
"Invalid node index = %d, in Dialogue = `%s`. Ignoring."), HumanNode.NodeIndex, *
Dialogue->GetPathName());
372 if (NodeSpeech ==
nullptr)
374 UE_LOG(LogDlgHumanReadableTextCommandlet,
Warning, TEXT(
"Node index = %d is not a UDlgNode_Speech, in Dialogue = `%s`. Ignoring."), HumanNode.NodeIndex, *
Dialogue->GetPathName());
394 if (GraphNode ==
nullptr)
396 UE_LOG(LogDlgHumanReadableTextCommandlet,
Warning, TEXT(
"Invalid UDialogueGraphNode for Node index = %d in Dialogue = `%s`. Ignoring."), HumanNode.NodeIndex, *
Dialogue->GetPathName());
411 if (!HumanSpeechSequence.IsValid())
417 UDlgNode* Node =
Dialogue->GetMutableNodeFromIndex(HumanSpeechSequence.NodeIndex);
420 UE_LOG(LogDlgHumanReadableTextCommandlet,
422 TEXT(
"Invalid node speech sequence index = %d, in Dialogue = `%s`. Ignoring."),
423 HumanSpeechSequence.NodeIndex, *
Dialogue->GetPathName());
428 if (NodeSpeechSequence ==
nullptr)
430 UE_LOG(LogDlgHumanReadableTextCommandlet,
432 TEXT(
"Node node speech sequence index = %d is not a UDlgNode_SpeechSequence, in Dialogue = `%s`. Ignoring."),
433 HumanSpeechSequence.NodeIndex, *
Dialogue->GetPathName());
438 if (!NodeSpeechSequence->
GetNodeParticipantName().IsEqual(HumanSpeechSequence.Speaker, ENameCase::CaseSensitive))
446 for (int32 SequenceIndex = 0; SequenceIndex < SequenceArray.Num() && SequenceIndex < HumanSpeechSequence.Sequence.Num(); SequenceIndex++)
451 if (!SequenceArray[SequenceIndex].EdgeText.EqualTo(HumanSequence.
EdgeText))
458 if (!SequenceArray[SequenceIndex].Speaker.IsEqual(HumanSequence.
Speaker, ENameCase::CaseSensitive))
460 SequenceArray[SequenceIndex].Speaker = HumanSequence.
Speaker;
465 if (!SequenceArray[SequenceIndex].Text.EqualTo(HumanSequence.
Text))
467 SequenceArray[SequenceIndex].Text = HumanSequence.
Text;
473 if (GraphNode ==
nullptr)
475 UE_LOG(LogDlgHumanReadableTextCommandlet,
Warning, TEXT(
"Invalid UDialogueGraphNode for Node index = %d in Dialogue = `%s`. Ignoring."), HumanSpeechSequence.NodeIndex, *
Dialogue->GetPathName());
498 bool bModified =
false;
505 UE_LOG(LogDlgHumanReadableTextCommandlet,
507 TEXT(
"Invalid EdgeIndex = %d for Node index = %d in Dialogue = `%s`. Ignoring."),
508 HumanEdge.TargetNodeIndex, NodeIndex, *
Dialogue->GetPathName());
513 if (!GraphNode->
GetDialogueNode().GetNodeChildren()[EdgeIndex].GetUnformattedText().EqualTo(HumanEdge.Text))
DEFINE_LOG_CATEGORY(LogDlgHumanReadableTextCommandlet)
static bool SaveAllDialogues()
static FORCEINLINE bool IsPathInProjectDirectory(const FString &Path)
The DlgJsonParser class mostly adapted for Dialogues, copied from FJsonObjectConverter See IDlgParser...
bool IsValidFile() const override
void ReadAllProperty(const UStruct *ReferenceClass, void *TargetObject, UObject *DefaultObjectOuter=nullptr) override
void InitializeParser(const FString &FilePath) override
The DlgJsonWriter class mostly adapted for Dialogues, copied from FJsonObjectConverter See IDlgWriter...
bool ExportToFile(const FString &FileName) override
void Write(const UStruct *StructDefinition, const void *ContainerPtr) override
int32 GetChildEdgeIndexForChildNodeIndex(int32 ChildNodeIndex) const
void SetEdgeTextAt(int32 EdgeIndex, const FText &NewText)
TArray< UDialogueGraphNode * > GetChildNodes() const
TArray< UDialogueGraphNode * > GetParentNodes() const
int32 NodeIndex
UPROPERTY(VisibleAnywhere, Category = DialogueGraphNode)
const DlgNodeType & GetDialogueNode() const
void CheckAll() const override
UCLASS(BlueprintType, Meta = (DisplayThumbnail = "true"))
const UDlgSystemSettings * Settings
bool IsEdgeTextDefault(const FText &EdgeText)
int32 Main(const FString &Params) override
FString OutputInputDirectory
static bool ExportNodeToContext(const UDlgNode *Node, FDlgNodeContext_FormatHumanReadable &OutContext)
static const TCHAR * FileExtension
UDlgHumanReadableTextCommandlet()
static void ExportNodeEdgesToHumanReadableFormat(const TArray< FDlgEdge > &Edges, TArray< FDlgEdge_FormatHumanReadable > &OutEdges)
static constexpr int32 RootNodeIndex
TArray< UPackage * > PackagesToSave
bool ImportHumanReadableFormatIntoDialogue(const FDlgDialogue_FormatHumanReadable &Format, UDlgDialogue *Dialogue)
static bool SetGraphNodesNewEdgesText(UDialogueGraphNode *GraphNode, const TArray< FDlgEdge_FormatHumanReadable > &Edges, int32 NodeIndex, const UDlgDialogue *Dialogue)
bool ExportDialogueToHumanReadableFormat(const UDlgDialogue &Dialogue, FDlgDialogue_FormatHumanReadable &OutFormat)
static TMap< FGuid, UDlgDialogue * > GetAllDialoguesGUIDsMap()
static int32 LoadAllDialoguesIntoMemory(bool bAsync=false)
static TArray< UDlgDialogue * > GetAllDialoguesFromMemory()
UCLASS(BlueprintType, ClassGroup = "Dialogue")
virtual void SetNodeText(const FText &InText)
const FText & GetNodeUnformattedText() const override
UFUNCTION(BlueprintPure, Category = "Dialogue|Node")
UCLASS(BlueprintType, ClassGroup = "Dialogue")
FName GetNodeParticipantName() const override
UFUNCTION(BlueprintPure, Category = "Dialogue|Node")
TArray< FDlgSpeechSequenceEntry > * GetMutableNodeSpeechSequence()
UCLASS(BlueprintType, Abstract, EditInlineNew, ClassGroup = "Dialogue")
virtual const TArray< FDlgEdge > & GetNodeChildren() const
Gets this nodes children (edges) as a const/mutable array.
virtual FName GetNodeParticipantName() const
UFUNCTION(BlueprintPure, Category = "Dialogue|Node")
virtual void SetNodeParticipantName(FName InName)
TArray< int32 > ChildNodeIndices
UPROPERTY()
TArray< int32 > ParentNodeIndices
UPROPERTY()
FText EdgeText
UPROPERTY()