// ^^^^^ LOAD STORY EDITOR ^^^^^ // // vvvvv SAVE STORY EDITOR vvvvv // // returns if it completed the save or not public static bool SaveItems(bool saveAs) { // use event regardless of outcome to prevent unexpected event pass-through Event.current.Use(); if (mainEditor == null) { Debug.Log("Cannot Save: Story Editor reference unhooked!"); return(false); } // open the file explorer save window if on a new file // otherwise, save to the current file string path; if (saveAs || (!saveAs && string.IsNullOrEmpty(mainEditor.fileName))) { path = EditorUtility.SaveFilePanel("Save Story Entry", ProjectPathManager.LastExportPath, "entry", "sdexml"); mainEditor.fileName = path; } else { path = mainEditor.fileName; } if (string.IsNullOrEmpty(path)) { Debug.Log("canceled save"); return(false); } EditorStoryNodeEntry storyEntry = new EditorStoryNodeEntry(); List <EditorNodeEntry> nodes = GenerateNodeEntries(mainEditor.nodes); List <string> flags = new List <string>(); foreach (TextArea flag in mainEditor.localFlagsMenu.items) { flags.Add(flag.text); } // assign nodes/flags storyEntry.nodes = nodes; storyEntry.localFlags = flags; storyEntry.offset = mainEditor.offset; // write to disk XmlSerializer serializer = new XmlSerializer(typeof(EditorStoryNodeEntry)); Encoding encoding = Encoding.GetEncoding("UTF-8"); using (StreamWriter stream = new StreamWriter(path, false, encoding)) { serializer.Serialize(stream, storyEntry); } ProjectPathManager.LastExportPath = path; return(true); }
/* * InitializeNodes() is a helper function for loading Story Dialog Editor data. * * Returns the mapping of input connection points and their associated output connection points */ private static Dictionary <int, List <int> > InitializeNodes(EditorStoryNodeEntry storyEntry, Dictionary <int, ConnectionPoint> connectionPointMap) { // the map of input points and their associated output points Dictionary <int, List <int> > connectionMap = new Dictionary <int, List <int> >(); // generate nodes and data from entries Node tempNode; foreach (EditorNodeEntry entry in storyEntry.nodes) { tempNode = NodeManager.AddNodeAt(new Vector2(entry.rect.x, entry.rect.y), entry.nodeType, markHistory: false, center: false); connectionPointMap[entry.inPoint.CPEID] = tempNode.inPoint; connectionMap[entry.inPoint.CPEID] = entry.inPoint.linkedCPEIDs; // add flag data if set local/global if (entry.nodeType == NodeType.SetLocalFlag || entry.nodeType == NodeType.CheckLocalFlag) { tempNode.localFlagDropdown.selectedItem = mainEditor.localFlagsMenu.GetTextArea(entry.selectedFlag); } else if (entry.nodeType == NodeType.SetGlobalFlag || entry.nodeType == NodeType.CheckGlobalFlag) { tempNode.globalItemDropdown.selectedItem = entry.selectedFlag; } else if (entry.nodeType == NodeType.SetGlobalVariable || entry.nodeType == NodeType.CheckGlobalVariable) { tempNode.globalItemDropdown.selectedItem = entry.selectedFlag; tempNode.globalVariableField.text = entry.globalVariableValue; } // map Node outpoint/splitter depending on NodeType if (entry.nodeType == NodeType.SetLocalFlag || entry.nodeType == NodeType.SetGlobalFlag || entry.nodeType == NodeType.SetGlobalVariable || entry.nodeType == NodeType.Interrupt) { // add outpoint entry if available if (tempNode.outPoint != null && entry.outPoint != null) { connectionPointMap[entry.outPoint.CPEID] = tempNode.outPoint; } } else if (entry.nodeType == NodeType.CheckLocalFlag || entry.nodeType == NodeType.CheckGlobalFlag || entry.nodeType == NodeType.CheckGlobalVariable) { // add splitter entries if available if (tempNode.splitter != null && entry.outPos != null && entry.outNeg != null) { connectionPointMap[entry.outPos.CPEID] = tempNode.splitter.positiveOutpoint; connectionPointMap[entry.outNeg.CPEID] = tempNode.splitter.negativeOutpoint; } } // record child container outpoints depending on NodeType and populate fields if (entry.nodeType == NodeType.Dialog || entry.nodeType == NodeType.Decision) { DBox child = tempNode.childContainer as DBox; SDEContainerEntry childEntry = entry.childContainer; while (childEntry != null) { // set text and outpoint mapping for the child container child.textArea.text = childEntry.text; connectionPointMap[childEntry.outPoint.CPEID] = child.outPoint; childEntry = childEntry.child; // generate the child's child if there needs to be one if (childEntry != null) { switch (entry.nodeType) { case NodeType.Dialog: child.child = ScriptableObject.CreateInstance <DialogBox>(); ((DialogBox)child.child).Init(child, ""); break; case NodeType.Decision: child.child = ScriptableObject.CreateInstance <DecisionBox>(); ((DecisionBox)child.child).Init(child, ""); break; } } child = child.child as DBox; } } else if (entry.nodeType == NodeType.Interrupt) { tempNode.SetBottomLevelInterrupt(entry.bottomLevel); DialogInterrupt child; SDEContainerEntry childEntry = entry.childContainer; if (childEntry != null) { // create the first child of the parent node tempNode.childContainer = ScriptableObject.CreateInstance <DialogInterrupt>(); tempNode.childContainer.Init(tempNode); ((DialogInterrupt)tempNode.childContainer).label.text = childEntry.text; // record the connection point connectionPointMap[childEntry.outPoint.CPEID] = tempNode.childContainer.outPoint; child = tempNode.childContainer as DialogInterrupt; childEntry = childEntry.child; while (childEntry != null) { // generate the child interrupt and populate it child.child = ScriptableObject.CreateInstance <DialogInterrupt>(); ((DialogInterrupt)child.child).Init(child); ((DialogInterrupt)child.child).label.text = childEntry.text; // record the connection point connectionPointMap[childEntry.outPoint.CPEID] = child.child.outPoint; child = child.child as DialogInterrupt; childEntry = childEntry.child; } } } } return(connectionMap); }
// vvvvv LOAD STORY EDITOR vvvvv // public static void LoadItems(string path) { if (mainEditor == null) { // open a new window if it's unhooked Debug.Log("Window not found, opening new Story Dialog Editor window."); StoryDialogEditor.OpenWindow(); } else if (HistoryManager.needsSave) { // create dialog entry to warn user that they have unsaved changes if (!EditorUtility.DisplayDialog("Load new entry", "Are you sure you want to open a new entry and close the current one?", "yes", "no")) { return; } } Debug.Log("attempting to load: " + path); EditorStoryNodeEntry storyEntry = new EditorStoryNodeEntry(); XmlSerializer serializer = new XmlSerializer(typeof(EditorStoryNodeEntry)); Encoding encoding = Encoding.GetEncoding("UTF-8"); using (StreamReader stream = new StreamReader(path, encoding)) { storyEntry = serializer.Deserialize(stream) as EditorStoryNodeEntry; } // destroy the scene before populating it mainEditor.DestroyScene(); // set the editor's offset to match the saved entry mainEditor.offset = storyEntry.offset; // load flags foreach (string entry in storyEntry.localFlags) { mainEditor.localFlagsMenu.AddItem(entry, markHistory: false); } // CPEID maps to ConnectionPoint to generate connections later Dictionary <int, ConnectionPoint> connectionPointMap = new Dictionary <int, ConnectionPoint>(); // initialize all the nodes and generate the connection map Dictionary <int, List <int> > connectionMap = InitializeNodes(storyEntry, connectionPointMap); // create all the connections foreach (int inCPEID in connectionMap.Keys) { ConnectionManager.selectedInPoint = connectionPointMap[inCPEID]; bool deletable = true; if (((Node)ConnectionManager.selectedInPoint.parent).nodeType == NodeType.Interrupt) { deletable = false; } foreach (int outCPEID in connectionMap[inCPEID]) { ConnectionManager.selectedOutPoint = connectionPointMap[outCPEID]; ConnectionManager.CreateConnection(deletable, markHistory: false); } } ConnectionManager.ClearConnectionSelection(); Debug.Log("loaded: " + path); mainEditor.fileName = path; }