public void Export(IProject2 project, ConfigParameterString exportPath, Func <Id <LocalizedStringType>, Id <LocalizedText>, Tuple <string, DateTime> > localize, IErrorCheckerUtilities <IConversationNode> util) { if (project == null) { throw new ArgumentNullException(nameof(project)); } if (exportPath == null) { throw new ArgumentNullException(nameof(exportPath)); } using (var sfd = new SaveFileDialog()) { sfd.DefaultExt = "*.ssv"; sfd.AddExtension = true; sfd.CreatePrompt = false; sfd.InitialDirectory = exportPath.Value; sfd.OverwritePrompt = true; sfd.ValidateNames = true; sfd.Title = "Export to C# source file"; sfd.DefaultExt = ".ssv"; if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { exportPath.Value = Path.GetDirectoryName(sfd.FileName); FileStream stream = null; try { stream = new FileStream(sfd.FileName, FileMode.OpenOrCreate, FileAccess.Write); stream.SetLength(0); using (var sw = new StreamWriter(stream)) { stream = null; ExportAsSsv ssv = new ExportAsSsv((type, textId) => localize(type, textId).Item1); CsvData.WriteTitle(";", sw, true); foreach (var con in project.ConversationFilesCollection) { ssv.WriteConversation(con, sw, true, util); } } } finally { if (stream != null) { stream.Dispose(); } } } } }
public void WriteConversation(IConversationFile conversation, StreamWriter sw, bool includeName, IErrorCheckerUtilities <IConversationNode> util) { if (conversation == null) { throw new ArgumentNullException(nameof(conversation)); } var nodes = conversation.Nodes; Stack <IConversationNodeData> startNodes = new Stack <IConversationNodeData>(nodes.Where(n => Viking.Util.IsStartNode(n.Data.NodeTypeId, util)).Select(n => n.Data)); var conversationInfo = conversation.Nodes.Where(n => n.Data.NodeTypeId == CsvData.CONVERSATIONINFO).FirstOrDefault(); var playerSpeechNodes = conversation.Nodes.Where(n => n.Data.NodeTypeId == CsvData.PLAYER_SPEECH).Select(n => new { Key = n, Value = CsvData.GetPlayerSpeechData(n, conversationInfo, m_localize) }); var npcSpeechNodes = conversation.Nodes.Where(n => n.Data.NodeTypeId == CsvData.NPC_SPEECH).Select(n => new { Key = n, Value = CsvData.GetSpeechData(n, conversationInfo, m_localize) }); var radioSpeechNodes = conversation.Nodes.Where(n => n.Data.NodeTypeId == CsvData.RADIO_SPEECH).Select(n => new { Key = n, Value = CsvData.GetSpeechData(n, conversationInfo, m_localize) }); var optionNodes = conversation.Nodes.Where(n => n.Data.NodeTypeId == CsvData.OPTION).Select(n => new { Key = n, Value = CsvData.GetOptionData(n, conversationInfo, m_localize) }); var allcontent = playerSpeechNodes.Concat(npcSpeechNodes).Concat(radioSpeechNodes).Concat(optionNodes).ToDictionary(kvp => kvp.Key.Data, kvp => kvp.Value); HashSet <IConversationNodeData> processed = new HashSet <IConversationNodeData>(); //Depth first iterate through the conversation starting at start nodes while (startNodes.Any()) { var start = startNodes.Pop(); if (!processed.Contains(start)) { foreach (var output in start.Connectors.Where(c => c.Definition.Id == SpecialConnectors.Output.Id)) { foreach (var connection in output.Connections) { var connected = connection.Parent; startNodes.Push(connected); } } if (allcontent.ContainsKey(start)) { var row = allcontent[start]; row.Write(Separator, includeName ? conversation.File.File.Name : null, sw); allcontent.Remove(start); } } processed.Add(start); } //Pick up any leftover nodes that are not connected to a start node foreach (var node in nodes.Select(n => n.Data)) { if (!processed.Contains(node)) { if (allcontent.ContainsKey(node)) { var row = allcontent[node]; row.Write(Separator, includeName ? conversation.File.File.Name : null, sw); allcontent.Remove(node); } processed.Add(node); } } }