private void RefreshAnimList(ComboBox comboBoxMood, ComboBox comboBoxAnim) { string animset = comboBoxMood.SelectedValue as string; var anims = new Dictionary <string, string>(); if (EditorCore.Animations.ContainsKey(animset)) { try { anims.Add("", "<Auto>"); anims = anims.Concat(EditorCore.Animations[animset].ToDictionary(item => item)) .ToDictionary(item => item.Key, item => item.Value); } catch (System.ArgumentException) { EditorCore.LogError(String.Format("Animset \"{0}\" contains duplicate animation names", animset)); } comboBoxAnim.DataSource = new BindingSource(anims, null); comboBoxAnim.ValueMember = "Key"; comboBoxAnim.DisplayMember = "Value"; comboBoxAnim.Enabled = true; } else { comboBoxAnim.DataSource = null; comboBoxAnim.Enabled = false; } }
public void ResyncFile(Dialogue dialogue, Package previousPackage, bool focus) { if (dialogue == null) { return; } if (previousPackage != null) { TreeNode[] nodePackages = tree.Nodes.Find(GetPackageKey(previousPackage.Name), false); if (nodePackages.Count() > 0) { TreeNode nodeParent = nodePackages[0]; TreeNode[] nodeChildren = nodeParent.Nodes.Find(dialogue.GetFileName(), true); if (nodeChildren.Count() > 0) { TreeNode nodeDialogue = nodeChildren[0]; TreeNode nodeFolder = nodeDialogue.Parent; nodeDialogue.Remove(); DeleteIfEmptyFolder(nodeFolder); } } else { EditorCore.LogError("Unable to update a Dialogue with unknown Package in project explorer : " + dialogue.GetName() + " in " + previousPackage.Name); } } ResyncFile(dialogue, focus); }
static private bool DeserializeFromFile <T>(string path, T value) { //var jObject = Newtonsoft.Json.Linq.JObject.Parse(File.ReadAllText(path)); //int version = jObject.GetValue("Version"); try { JsonSerializerSettings settings = new JsonSerializerSettings(); settings.TypeNameHandling = TypeNameHandling.Auto; //default settings.NullValueHandling = NullValueHandling.Include; //default settings.ObjectCreationHandling = ObjectCreationHandling.Replace; //not default settings.PreserveReferencesHandling = PreserveReferencesHandling.None; //default settings.Binder = EditorCore.SerializationBinder; JsonConvert.PopulateObject(File.ReadAllText(path), value, settings); } catch (Newtonsoft.Json.JsonReaderException e) { EditorCore.LogError("A malformed file could not be loaded : " + path); EditorCore.LogError("> exception : " + e.Message); return(false); } catch (Newtonsoft.Json.JsonSerializationException e) { //TODO: Here I could plug additionnal handlers with older versions of the SerializationBinder EditorCore.LogError("A file containing unknown serialization bindings could not be loaded : " + path); EditorCore.LogError("> exception : " + e.Message); return(false); } return(true); }
public void ResyncFile(Dialogue dialogue, bool focus) { if (dialogue == null) { return; } if (dialogue.Package == null) { EditorCore.LogError("Unable to show a Dialogue without Package in project explorer : " + dialogue.GetName()); return; } TreeNode[] nodePackages = tree.Nodes.Find(GetPackageKey(dialogue.Package.Name), false); if (nodePackages.Count() > 0) { TreeNode nodeParent = nodePackages[0]; string path = dialogue.GetFilePath(); string[] folders = path.Split(new char[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); string folderPath = ""; foreach (string folder in folders) { folderPath = Path.Combine(folderPath, folder); TreeNode[] nodeFolders = nodeParent.Nodes.Find(folder, false); if (nodeFolders.Count() > 0) { nodeParent = nodeFolders[0]; } else { nodeParent = nodeParent.Nodes.Add(folder, folder); nodeParent.Tag = new Folder() { Path = folderPath }; nodeParent.ContextMenuStrip = menuFolder; EditorHelper.SetNodeIcon(nodeParent, ENodeIcon.Folder); } } TreeNode nodeDialogue = nodeParent.Nodes.Add(dialogue.GetFileName(), dialogue.GetName()); nodeDialogue.ContextMenuStrip = menuDocument; EditorHelper.SetNodeIcon(nodeDialogue, ENodeIcon.Dialogue); nodeDialogue.Tag = dialogue; if (focus) { nodeDialogue.EnsureVisible(); } } else { EditorCore.LogError("Unable to show a Dialogue with unknown Package in project explorer : " + dialogue.GetName() + " in " + dialogue.Package.Name); } }
public Language GetDefaultLanguage() { if (ListLanguages.Count > 0) { return(ListLanguages[0]); } EditorCore.LogError("No Default language found"); return(null); }
public Package GetDefaultPackage() { if (ListPackages.Count > 0) { return(ListPackages[0]); } EditorCore.LogError("No Default package found"); return(null); }
public override Type BindToType(string assemblyName, string typeName) { if (Bindings.ContainsKey(typeName)) { return(Bindings[typeName]); } EditorCore.LogError("Unknown type on deserialization : " + typeName); return(null); }
public override void BindToName(Type type, out string assemblyName, out string typeName) { if (!Bindings.Values.Contains(type)) { EditorCore.LogError("Unknown type on serialization : " + type); } assemblyName = null; typeName = Bindings.Single(item => item.Value == type).Key; }
//-------------------------------------------------------------------------------------------------------------- // static private bool CheckDialogueNameAvailable(string path, string name, bool logErrorIfNotAvailable) { if (!dialogues.ContainsKey(name)) { return(true); } if (logErrorIfNotAvailable) { EditorCore.LogError("Dialogue already exists (ignored) : " + name + " at \"" + path + "\" and \"" + dialogues[name].Dialogue.GetFilePath() + "\""); } return(false); }
//-------------------------------------------------------------------------------------------------------------- // static public bool AddDialogue(Dialogue dialogue) { string name = dialogue.GetName(); if (!dialogues.ContainsKey(name)) { dialogues.Add(name, new ResourceHolder { Dialogue = dialogue }); return(true); } EditorCore.LogError("Dialogue already exists (ignored) : " + name + " at \"" + dialogue.GetFilePath() + "\" and \"" + dialogues[name].Dialogue.GetFilePath() + "\""); return(false); }
//-------------------------------------------------------------------------------------------------------------- // Imports static public bool ImportFromCsv() { var project = ResourcesHandler.Project; string projectDirectory = EditorHelper.GetProjectDirectory(); string importPath = Path.Combine(projectDirectory, EditorCore.Settings.DirectoryExportDialogues); var dialog = new DialogImport(importPath); DialogResult result = dialog.ShowDialog(); if (result == DialogResult.Cancel) { return(false); } bool resultConstants = false; if (dialog.ImportConstants) { resultConstants = ImportConstantsFromCsv(dialog.ImportPathConstants, dialog.ListLanguages, true, false, false); if (resultConstants) { EditorCore.LogInfo("Import Constants Finished"); } else { EditorCore.LogError("Import Constants Failed"); } } bool resultDialogues = false; if (dialog.ImportLocalization || dialog.ImportWorkstring || dialog.ImportInformation) { resultDialogues = ImportDialoguesFromCsv(dialog.ImportPathDialogues, dialog.ListPackages, dialog.ListLanguages, dialog.ImportLocalization, dialog.ImportWorkstring, dialog.ImportInformation); if (resultDialogues) { EditorCore.LogInfo("Import Dialogues Finished"); } else { EditorCore.LogError("Import Dialogues Failed"); } } return(resultConstants || resultDialogues); }
public void PostLoad(Project project) { //Resolve links with package Package = project.GetPackage(PackageName); if (Package == null) { EditorCore.LogError("Loading a Dialogue without Package (forcing default) : " + GetName(), this); Package = project.GetDefaultPackage(); } //Resolve links between nodes RootNode = GetNodeByID(RootNodeID) as DialogueNodeRoot; foreach (DialogueNode node in ListNodes) { node.Next = GetNodeByID(node.NextID); if (node is DialogueNodeChoice) { DialogueNodeChoice nodeChoice = node as DialogueNodeChoice; foreach (int replyID in nodeChoice.RepliesIDs) { DialogueNodeReply nodeReply = GetNodeByID(replyID) as DialogueNodeReply; if (nodeReply != null) { nodeChoice.Replies.Add(nodeReply); } } } else if (node is DialogueNodeGoto) { DialogueNodeGoto nodeGoto = node as DialogueNodeGoto; nodeGoto.Goto = GetNodeByID(nodeGoto.GotoID); } else if (node is DialogueNodeBranch) { DialogueNodeBranch nodebranch = node as DialogueNodeBranch; nodebranch.Branch = GetNodeByID(nodebranch.BranchID); } } EditorCore.OnDialoguePostLoad?.Invoke(this); }
static private bool DeserializeFromString <T>(T value, string content) { try { JsonSerializerSettings settings = new JsonSerializerSettings(); settings.TypeNameHandling = TypeNameHandling.Auto; //default settings.NullValueHandling = NullValueHandling.Include; //default settings.ObjectCreationHandling = ObjectCreationHandling.Replace; //not default settings.PreserveReferencesHandling = PreserveReferencesHandling.None; //default settings.Binder = EditorCore.SerializationBinder; JsonConvert.PopulateObject(content, value, settings); } catch (Newtonsoft.Json.JsonSerializationException) { EditorCore.LogError("Errors occured when parsing a file (will not be loaded)"); return(false); } return(true); }
static public bool ImportDialoguesFromCsv(string importPath, List <Package> packages, List <Language> languages, bool importLocalization, bool importWorkstring, bool importInformation) { var project = ResourcesHandler.Project; //Dialogue, Node ID, Timestamp, Voicing ID, Index, Package, SceneType, Context, Voicing, Voicing Intensity, Speaker, Workstring Text, Words, ...Languages..., comments var headerRedirects = new Dictionary <string, string>(); headerRedirects.Add("ID", "Node ID"); headerRedirects.Add("Workstring", "Workstring Text"); if (importPath == String.Empty) { EditorCore.LogError("Import Localization failed : no file specified"); return(false); } if (!File.Exists(importPath)) { EditorCore.LogError("Import Localization failed : file not found"); return(false); } while (Utility.IsFileLocked(importPath)) { EditorCore.LogError("Import Localization failed : file is locked"); var dialogLocked = new DialogLockedFile(importPath); DialogResult eResult = dialogLocked.ShowDialog(); if (eResult == DialogResult.Cancel) { return(false); } } DateTime currentTime = Utility.GetCurrentTime(); using (System.IO.StreamReader file = new System.IO.StreamReader(importPath, Encoding.UTF8)) { ExporterCsv.CsvFileReader reader = new ExporterCsv.CsvFileReader(); if (reader.ParseHeaders(file, headerRedirects)) { while (reader.ParseNextLine()) { Dialogue dialogue = ResourcesHandler.GetDialogue(reader.GetCell("Dialogue")); if (dialogue != null) { if (!packages.Contains(dialogue.Package)) { continue; } int id = TranslationTable.GetNodeIDFromPrefixedString(reader.GetCell("ID")); DialogueNode node = dialogue.GetNodeByID(id); if (node == null) { continue; } if (node is DialogueNodeRoot) { var dialogueNodeRoot = node as DialogueNodeRoot; if (importInformation) { //Import general Dialogue informations dialogue.Package = project.GetPackage(reader.GetCell("Package")); dialogue.SceneType = reader.GetCell("Scene Type"); dialogue.Context = reader.GetCell("Context"); } } else { DateTime timestampLoca = reader.GetCellAsDate("Timestamp"); DateTime timestampWorkstring; if (node is DialogueNodeSentence) { var dialogueNodeSentence = node as DialogueNodeSentence; if (importWorkstring) { //The current workstring is more recent than the modified workstring if (dialogueNodeSentence.LastEditDate > timestampLoca) { //TODO: popup or option to choose what to do here EditorCore.LogWarning(String.Format("{0} {1} - New workstring older than currently registered workstring, but updated anyway", dialogue.GetName(), id), dialogue, node); } dialogueNodeSentence.Sentence = reader.GetCell("Workstring"); dialogueNodeSentence.LastEditDate = currentTime; timestampLoca = currentTime; } if (importInformation) { //Import Sentence informations (Voicing, Context, Speaker..) string context = reader.GetCell("Context"); dialogueNodeSentence.Context = context; string voicing = reader.GetCell("Voicing"); dialogueNodeSentence.Comment = voicing; string voiceIntensity = reader.GetCell("Voice Intensity"); dialogueNodeSentence.VoiceIntensity = voiceIntensity; string speakerID = ResourcesHandler.Project.GetActorID(reader.GetCell("Speaker")); dialogueNodeSentence.SpeakerID = speakerID; } timestampWorkstring = dialogueNodeSentence.LastEditDate; } else { var dialogueNodeReply = node as DialogueNodeReply; if (importWorkstring) { //The current workstring is more recent than the modified workstring if (dialogueNodeReply.LastEditDate > timestampLoca) { //TODO: popup or option to choose what to do here EditorCore.LogWarning(String.Format("{0} {1} - New workstring older than currently registered workstring, but updated anyway", dialogue.GetName(), id), dialogue, node); } dialogueNodeReply.Reply = reader.GetCell("Workstring"); dialogueNodeReply.LastEditDate = currentTime; timestampLoca = currentTime; } timestampWorkstring = dialogueNodeReply.LastEditDate; } if (importLocalization) { foreach (var language in languages) { //TODO: extract this part in a function, to be used from other importers ETranslationResult translationResult = dialogue.Translations.AddOrUpdateNodeEntry( id, language, timestampLoca, reader.GetCell(language.Name + " Text") ); if (translationResult == ETranslationResult.Accepted || translationResult == ETranslationResult.Accepted_IdenticalTimestamp || translationResult == ETranslationResult.Accepted_IdenticalText) { //The current workstring is more recent than the localized entry if (timestampWorkstring > timestampLoca) { EditorCore.LogWarning(String.Format("{0} {1} - [{2}] Translation accepted but based on an outdated workstring, will be re-exported", dialogue.GetName(), id, language.Name), dialogue, node); } else { //EditorCore.LogInfo(String.Format("{0} {1} - Translation accepted", dialogue.GetName(), id), dialogue.GetName(), id); } } if (translationResult == ETranslationResult.Accepted_IdenticalTimestamp) { EditorCore.LogWarning(String.Format("{0} {1} - [{2}] Translation accepted but with an identical timestamp as the previous entry", dialogue.GetName(), id, language.Name), dialogue, node); } else if (translationResult == ETranslationResult.Accepted_IdenticalText) { EditorCore.LogWarning(String.Format("{0} {1} - [{2}] Translation accepted but with an identical text as the previous entry", dialogue.GetName(), id, language.Name), dialogue, node); } else if (translationResult == ETranslationResult.Refused_EmptyText) { EditorCore.LogWarning(String.Format("{0} {1} - [{2}] Translation refused : empty text", dialogue.GetName(), id, language.Name), dialogue, node); } else if (translationResult == ETranslationResult.Refused_Outdated) { EditorCore.LogWarning(String.Format("{0} {1} - [{2}] Translation refused : outdated timestamp", dialogue.GetName(), id, language.Name), dialogue, node); } else if (translationResult == ETranslationResult.Refused_Identical) { //ignored } } } } } ResourcesHandler.SetDirty(dialogue); } ResourcesHandler.SaveAllDirty(); if (EditorCore.MainWindow != null) { EditorCore.MainWindow.RefreshDirtyFlags(); } EditorCore.ProjectExplorer.ResyncAllFiles(); } } return(true); }
static public bool ImportConstantsFromCsv(string importPath, List <Language> languages, bool importLocalization, bool importWorkstring, bool importInformation) { var project = ResourcesHandler.Project; if (importPath == String.Empty) { EditorCore.LogError("Import Constants failed : no file specified"); return(false); } if (!File.Exists(importPath)) { EditorCore.LogError("Import Constants failed : file not found"); return(false); } while (Utility.IsFileLocked(importPath)) { EditorCore.LogError("Import Constants failed : file is locked"); var dialogLocked = new DialogLockedFile(importPath); DialogResult eResult = dialogLocked.ShowDialog(); if (eResult == DialogResult.Cancel) { return(false); } } DateTime currentTime = Utility.GetCurrentTime(); using (System.IO.StreamReader file = new System.IO.StreamReader(importPath, Encoding.UTF8)) { ExporterCsv.CsvFileReader reader = new ExporterCsv.CsvFileReader(); if (reader.ParseHeaders(file)) { while (reader.ParseNextLine()) { string id = reader.GetCell("ID"); Constant constant = project.ListConstants.Find(item => item.ID == id); if (constant != null) { DateTime timestampLoca = reader.GetCellAsDate("Timestamp"); DateTime timestampWorkstring; if (importWorkstring) { //The current workstring is more recent than the modified workstring if (constant.LastEditDate > timestampLoca) { //TODO: popup or option to choose what to do here EditorCore.LogWarning(String.Format("Constant {0} - New workstring older than currently registered workstring, but updated anyway", id)); } constant.Workstring = reader.GetCell("Workstring"); constant.LastEditDate = currentTime; timestampLoca = currentTime; } if (importInformation) { string voicing = reader.GetCell("Comment"); constant.Comment = voicing; } timestampWorkstring = constant.LastEditDate; if (importLocalization) { foreach (var language in languages) { //TODO: extract this part in a function, to be used from other importers ETranslationResult translationResult = project.Translations.AddOrUpdateEntry( id, language, timestampLoca, reader.GetCell(language.Name + " Text") ); if (translationResult == ETranslationResult.Accepted || translationResult == ETranslationResult.Accepted_IdenticalTimestamp || translationResult == ETranslationResult.Accepted_IdenticalText) { //The current workstring is more recent than the localized entry if (timestampWorkstring > timestampLoca) { EditorCore.LogWarning(String.Format("Constant {0} - [{1}] Translation accepted but based on an outdated workstring, will be re-exported", id, language.Name)); } else { //EditorCore.LogInfo(String.Format("{0} {1} - Translation accepted", dialogue.GetName(), id), dialogue.GetName(), id); } } if (translationResult == ETranslationResult.Accepted_IdenticalTimestamp) { EditorCore.LogWarning(String.Format("Constant {0} - [{1}] Translation accepted but with an identical timestamp as the previous entry", id, language.Name)); } else if (translationResult == ETranslationResult.Accepted_IdenticalText) { EditorCore.LogWarning(String.Format("Constant {0} - [{1}] Translation accepted but with an identical text as the previous entry", id, language.Name)); } else if (translationResult == ETranslationResult.Refused_EmptyText) { EditorCore.LogWarning(String.Format("Constant {0} - [{1}] Translation refused : empty text", id, language.Name)); } else if (translationResult == ETranslationResult.Refused_Outdated) { EditorCore.LogWarning(String.Format("Constant {0} - [{1}] Translation refused : outdated timestamp", id, language.Name)); } else if (translationResult == ETranslationResult.Refused_Identical) { //ignored } } } } } ResourcesHandler.SaveProject(); if (EditorCore.MainWindow != null) { EditorCore.MainWindow.RefreshDirtyFlags(); } } } return(true); }
public void PreSave(Project project) { //Prepare File VersionProject = EditorCore.VersionProject; VersionEditor = EditorVersion.GetVersion(); if (Package == null) { EditorCore.LogError("Saving a Dialogue without Package (forcing default) : " + GetName(), this); Package = project.GetDefaultPackage(); } if (Package != null) { PackageName = Package.Name; } //Sanitize texts //dialogue.Comment = EditorCore.SanitizeText(dialogue.Comment); //Prepare nodes links RootNodeID = (RootNode != null) ? RootNode.ID : DialogueNode.ID_NULL; foreach (DialogueNode node in ListNodes) { node.NextID = (node.Next != null) ? node.Next.ID : DialogueNode.ID_NULL; if (node is DialogueNodeSentence) { //Generate ID DialogueNodeSentence nodeSentence = node as DialogueNodeSentence; nodeSentence.VoicingID = EditorHelper.GetPrettyNodeVoicingID(this, nodeSentence); //Sanitize texts nodeSentence.Sentence = EditorHelper.SanitizeText(nodeSentence.Sentence); //nodeSentence.Comment = EditorHelper.SanitizeText(nodeSentence.Comment); } else if (node is DialogueNodeChoice) { DialogueNodeChoice nodeChoice = node as DialogueNodeChoice; //Sanitize texts nodeChoice.Choice = EditorHelper.SanitizeText(nodeChoice.Choice); nodeChoice.RepliesIDs.Clear(); foreach (DialogueNodeReply nodeReply in nodeChoice.Replies) { //Sanitize texts nodeReply.Reply = EditorHelper.SanitizeText(nodeReply.Reply); nodeChoice.RepliesIDs.Add(nodeReply.ID); } } else if (node is DialogueNodeGoto) { DialogueNodeGoto nodeGoto = node as DialogueNodeGoto; nodeGoto.GotoID = (nodeGoto.Goto != null) ? nodeGoto.Goto.ID : DialogueNode.ID_NULL; } else if (node is DialogueNodeBranch) { DialogueNodeBranch nodeBranch = node as DialogueNodeBranch; nodeBranch.BranchID = (nodeBranch.Branch != null) ? nodeBranch.Branch.ID : DialogueNode.ID_NULL; } } }
public static void CheckDialogueErrors(Dialogue dialogue) { Project project = ResourcesHandler.Project; if (!EditorCore.CustomLists["SceneTypes"].ContainsKey(dialogue.SceneType)) { EditorCore.LogError(String.Format("{0} - Unknown Scene Type : {1}", dialogue.GetName(), dialogue.SceneType), dialogue); } if (!EditorCore.CustomLists["Cameras"].ContainsKey(dialogue.Camera)) { EditorCore.LogError(String.Format("{0} - Unknown Camera : {1}", dialogue.GetName(), dialogue.Camera), dialogue); } var usedIDs = new HashSet <int>(); foreach (DialogueNode node in dialogue.ListNodes) { if (usedIDs.Contains(node.ID)) { EditorCore.LogError(String.Format("{0} - Identical ID between two nodes : {1}", dialogue.GetName(), node.ID), dialogue, node); } else { usedIDs.Add(node.ID); } if (node is DialogueNodeSentence) { var nodeSentence = node as DialogueNodeSentence; bool validSpeaker = false; if (nodeSentence.SpeakerID == "") { EditorCore.LogError(String.Format("{0} {1} - Sentence has no Speaker", dialogue.GetName(), node.ID), dialogue, node); } else { if (project.GetActorFromID(nodeSentence.SpeakerID) == null) { EditorCore.LogError(String.Format("{0} {1} - Sentence has an invalid Speaker : {2}", dialogue.GetName(), node.ID, nodeSentence.SpeakerID), dialogue, node); } else { validSpeaker = true; } } if (nodeSentence.ListenerID != "") { if (project.GetActorFromID(nodeSentence.ListenerID) == null) { EditorCore.LogError(String.Format("{0} {1} - Sentence has an invalid Listener : {2}", dialogue.GetName(), node.ID, nodeSentence.ListenerID), dialogue, node); } else if (validSpeaker) { var speaker = project.GetActorFromID(nodeSentence.SpeakerID); var listener = project.GetActorFromID(nodeSentence.ListenerID); if (speaker == listener) { EditorCore.LogError(String.Format("{0} {1} - Listener is also Speaker", dialogue.GetName(), node.ID), dialogue, node); } else { if (speaker.VoiceKit != String.Empty) { if (speaker.VoiceKit == listener.VoiceKit) { EditorCore.LogWarning(String.Format("{0} {1} - Speaker and Listener have the same Voice Kit", dialogue.GetName(), node.ID), dialogue, node); } else if (project.GetVoiceActorNameFromKit(speaker.VoiceKit) == project.GetVoiceActorNameFromKit(listener.VoiceKit)) { EditorCore.LogWarning(String.Format("{0} {1} - Speaker and Listener have the same Voice Actor", dialogue.GetName(), node.ID), dialogue, node); } } } } } if (nodeSentence.Sentence.Length > project.MaxLengthSentence) { EditorCore.LogWarning(String.Format("{0} {1} - Sentence has too many characters", dialogue.GetName(), node.ID), dialogue, node); } } else if (node is DialogueNodeChoice) { var nodeChoice = node as DialogueNodeChoice; if (nodeChoice.Replies.Count == 0) { EditorCore.LogError(String.Format("{0} {1} - Choice has no Reply", dialogue.GetName(), node.ID), dialogue, node); } } else if (node is DialogueNodeReply) { var nodeReply = node as DialogueNodeReply; if (nodeReply.Reply.Length > project.MaxLengthReply) { EditorCore.LogWarning(String.Format("{0} {1} - Reply has too many characters", dialogue.GetName(), node.ID), dialogue, node); } } else if (node is DialogueNodeGoto) { var nodeGoto = node as DialogueNodeGoto; if (nodeGoto.Goto == null) { EditorCore.LogError(String.Format("{0} {1} - Goto has no Target", dialogue.GetName(), node.ID), dialogue, node); } } else if (node is DialogueNodeBranch) { var nodeBranch = node as DialogueNodeBranch; if (nodeBranch.Branch == null) { EditorCore.LogError(String.Format("{0} {1} - Branch has no Target", dialogue.GetName(), node.ID), dialogue, node); } } } if (EditorCore.OnCheckDialogueErrors != null) { EditorCore.OnCheckDialogueErrors(dialogue); } }