Exemple #1
0
            public static IReadOnlyCollection <Guid> CheckUniqueIds(IEnumerable <MemoryStream> validStreams)
            {
                HashSet <Guid> result   = new HashSet <Guid>();
                HashSet <Guid> existing = new HashSet <Guid>();

                foreach (var stream in validStreams)
                {
                    stream.Position = 0;
                    var d    = XDocument.Load(stream);
                    var root = d.Element(Root);

                    //TODO: Make sure the docs for this function (and the call chain) clarify that unsupported versions will be silently ignored.
                    string encounteredVersion = root.Attribute("xmlversion")?.Value ?? "";
                    if (XmlVersionRead.Contains(encounteredVersion))
                    {
                        var nodeElements = root.Elements("Node");
                        foreach (var guid in nodeElements.Select(n => Id <NodeTemp> .Parse(n.Attribute("Id").Value).Guid))
                        {
                            if (!existing.Add(guid))
                            {
                                result.Add(guid);
                            }
                        }
                    }
                }
                return(result);
            }
Exemple #2
0
            public XmlGraphData <TUIRawData, TEditorData> Read(Stream stream)
            {
                object documentID = new object();

                stream.Position = 0;
                var d    = XDocument.Load(stream);
                var root = d.Element(Root);

                //TODO: Should possibly treat this as a missing file rather than crashing the editor
                string encounteredVersion = root.Attribute("xmlversion")?.Value ?? "";

                if (!XmlVersionRead.Contains(encounteredVersion))
                {
                    throw new DeserializerVersionMismatchException(string.Join(", ", XmlVersionRead), encounteredVersion);
                }

                var nodeElements  = root.Elements("Node");
                var filteredNodes = m_filter != null?nodeElements.Where(n => m_filter(ReadType(n))) : nodeElements;

                IEnumerable <Either <GraphAndUI <TUIRawData>, LoadError> > editables = filteredNodes.Select(n => ReadEditable(n, m_datasource, documentID)).Evaluate();
                var allnodes = new Dictionary <Id <NodeTemp>, GraphAndUI <TUIRawData> >();
                var errors   = new List <LoadError>();

                foreach (var editable in editables)
                {
                    editable.Do(e =>
                    {
                        allnodes[e.GraphData.NodeId] = new GraphAndUI <TUIRawData>(e.GraphData, e.UIData);
                    }, a =>
                    {
                        errors.Add(a);
                    });
                }

                var links = ReadLinks(n => allnodes.ContainsKey(n), root);

                foreach (var link in links)
                {
                    var id1 = link.Item1.Item2;
                    var id2 = link.Item2.Item2;
                    if (allnodes.ContainsKey(id1) && allnodes.ContainsKey(id2)) //If copy/pasting a piece of graph, linked nodes may not exist
                    {
                        IConversationNodeData node1 = allnodes[id1].GraphData;
                        IConversationNodeData node2 = allnodes[id2].GraphData;

                        var unknownNode1 = node1 as UnknownEditable;
                        var unknownNode2 = node2 as UnknownEditable;

                        if (unknownNode1 != null)
                        {
                            unknownNode1.AddConnector(link.Item1.Item1);
                        }
                        if (unknownNode2 != null)
                        {
                            unknownNode2.AddConnector(link.Item2.Item1);
                        }

                        Output connector1 = node1.Connectors.SingleOrDefault(c => c.Id == link.Item1.Item1);
                        Output connector2 = node2.Connectors.SingleOrDefault(c => c.Id == link.Item2.Item1);

                        if (unknownNode1 != null)
                        {
                            unknownNode1.AllowConnection(connector1, connector2);
                        }

                        if (unknownNode2 != null)
                        {
                            unknownNode2.AllowConnection(connector1, connector2);
                        }

                        if (connector1 == null || connector2 == null)
                        {
                            errors.Add(new LoadError("Connector does not exist"));
                        }
                        else
                        {
                            bool success = connector1.ConnectTo(connector2, false);
                            if (!success)
                            {
                                success = connector1.ConnectTo(connector2, true);
                                if (!success)
                                {
                                    errors.Add(new LoadError("Tried to connect two connectors that could not be connected")); //TODO: Might be better to add the connection in violation of the rule to avoid modifying the file then have an error checker
                                }
                            }
                        }
                    }
                }

                foreach (var node in root.Elements("Node"))
                {
                    Id <NodeTemp> nodeID = Id <NodeTemp> .Parse(node.Attribute("Id").Value);

                    //ID<NodeTypeTemp> nodeType = ID<NodeTypeTemp>.Parse(node.Attribute("Guid").Value);
                    int outputIndex = 0; //no idea where the output guids come from so just assume they're ordered

                    //TODO: Remove support for legacy linking
                    foreach (var output in node.Elements("Output"))
                    {
                        Id <TConnector> outputGuid = Id <TConnector> .Parse(output.Attribute("guid").Value);

                        bool legacyNodeOutput = Id <TConnector> .Parse("1583e20c-c725-48c3-944d-1ba40c3ebdf4") == outputGuid;

                        var outputConnectors = legacyNodeOutput ? allnodes[nodeID].GraphData.Connectors : allnodes[nodeID].GraphData.Connectors.ElementAt(outputIndex).Only();
                        var connectedNodes   = output.Elements("Link").Select(l => Id <NodeTemp> .Parse(l.Attribute("To").Value));
                        foreach (var connectedID in connectedNodes)
                        {
                            var  connectedNode     = allnodes[connectedID].GraphData;
                            var  orderedConnectors = connectedNode.Connectors.OrderBy(o => o.Definition.Id != ConnectorDefinitionData.InputDefinitionId); //Put any inputs at the front of the list
                            bool success           = false;
                            foreach (var connector in orderedConnectors)
                            {
                                if (success)
                                {
                                    break;
                                }
                                foreach (var outputConnector in outputConnectors)
                                {
                                    if (success)
                                    {
                                        break;
                                    }
                                    if (connector.ConnectTo(outputConnector, false))
                                    {
                                        success = true;
                                    }
                                    else
                                    {
                                        connector.ConnectTo(outputConnector, true);
                                    }
                                }
                            }
                            if (!success)
                            {
                                errors.Add(new LoadError("Could not link nodes"));
                            }
                        }
                        outputIndex++;
                    }
                }

                return(new XmlGraphData <TUIRawData, TEditorData>(allnodes.Values, m_editorDataDeserializer.Read(root), new ReadOnlyCollection <LoadError>(errors), documentID));
            }