public void AddResponse(BasicDialResponse resp) { if (_responses.Count + 1 > MAX_OPTIONS) throw new System.Exception("To many responses to add!"); _responses.Add(resp); }
public static Conversation[] loadFromGephiGraphML(TextAsset f) { if (f == null) throw new NullReferenceException("Cannot load graph from NULL reference!"); /* load and prepare data */ XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(f.text); XmlNodeList conKeyList = xmlDoc.GetElementsByTagName("key"); XmlNodeList conNodeList = xmlDoc.GetElementsByTagName("node"); XmlNodeList conEdgeList = xmlDoc.GetElementsByTagName("edge"); Dictionary<string, BasicDialNode> dialNodes = new Dictionary<string, BasicDialNode>(); List<BasicDialNode> conStartNodes = new List<BasicDialNode>(); // store conversation starts /* get data keys */ string PlayerEventNodeId = null; string ActivationEventNodeId = null; string PlayerEventEdgeId = null; string ActivationEventEdgeId = null; string RequirementEdgeId = null; foreach (XmlNode key in conKeyList) { switch(key.Attributes["attr.name"].Value) { case "PlayerEvent": if (key.Attributes["for"].Value.Equals("node")) PlayerEventNodeId = key.Attributes["id"].Value; else PlayerEventEdgeId = key.Attributes["id"].Value; break; case "ActivationEvent": if (key.Attributes["for"].Value.Equals("node")) ActivationEventNodeId = key.Attributes["id"].Value; else ActivationEventEdgeId = key.Attributes["id"].Value; break; case "Requirement": RequirementEdgeId = key.Attributes["id"].Value; break; } } /* load nodes aka dialogue */ BasicDialNode latestNode; foreach (XmlNode node in conNodeList) { latestNode = new BasicDialNode(); latestNode.XmlID = node.Attributes["id"].Value; Debug.Assert(!dialNodes.ContainsKey(latestNode.XmlID), "Duplicated nodes entries found in XML!"); dialNodes[latestNode.XmlID] = latestNode; // get important ATTRIBUTES for this node Dictionary<string, string> nodeDic = XmlNodesToDic(node.ChildNodes, "key"); Debug.Assert(nodeDic["label"] != null, "A node should contain a label!"); latestNode.dialogueText = nodeDic["label"]; if (nodeDic.ContainsKey("notetype")) { string nodetype = nodeDic["notetype"]; switch (nodetype) { case "Start": conStartNodes.Add(latestNode); break; case "OpenUI": // doesn't do much here break; case "Exit": // doesn't do much here break; default: Debug.LogError("Unknown Node Type detected: " + nodetype + " for node: " + latestNode.XmlID); break; } } if (nodeDic.ContainsKey(PlayerEventNodeId)) { Debug.Log(nodeDic[PlayerEventNodeId] + ": Node Activation Event found!"); } if (nodeDic.ContainsKey(ActivationEventNodeId)) { Debug.Log(nodeDic[ActivationEventNodeId] + ": Node Player Event found!"); } } /* load edges aka responses */ foreach (XmlNode edge in conEdgeList) { BasicDialResponse response = new BasicDialResponse(); response.nextNode = dialNodes[edge.Attributes["target"].Value]; // set target node link dialNodes[edge.Attributes["source"].Value].AddResponse(response); // set source node link // get important ATTRIBUTES for this edge Dictionary<string, string> edgeDic = XmlNodesToDic(edge.ChildNodes, "key"); Debug.Assert(edgeDic["edgelabel"] != null, "An edge should contain a label!"); response.responseText = edgeDic["edgelabel"]; if (edgeDic.ContainsKey("edgetype")) { switch (edgeDic["edgetype"]) { case "OpenShop": response.optionType = EConOptionType.OPEN_SHOP; break; case "Exit": response.optionType = EConOptionType.EXIT; break; case "Quest": // EConOptionType.OFFER_QUEST response.optionType = EConOptionType.OFFER_QUEST; // TODO: load quest name break; default: Debug.LogError("Unknown edge type: " + edgeDic["edgetype"]); break; } } else response.optionType = EConOptionType.NORMAL; if (edgeDic.ContainsKey(PlayerEventEdgeId)) { Debug.Log(edgeDic[PlayerEventEdgeId] + ": Requirement found!"); } if (edgeDic.ContainsKey(ActivationEventEdgeId)) { Debug.Log(edgeDic[ActivationEventEdgeId] + ": Requirement found!"); } if (edgeDic.ContainsKey(RequirementEdgeId)) { Debug.Log(edgeDic[RequirementEdgeId] + ": Requirement found!"); } } // separate nodes into multiple conversations, if necessary Conversation[] newConArr = new Conversation[(conStartNodes.Count > 0) ? conStartNodes.Count : 1]; BasicDialNode[] dialNodesArr = new BasicDialNode[dialNodes.Count]; dialNodes.Values.CopyTo(dialNodesArr, 0); if (conStartNodes.Count == 0) { Debug.LogError("A valid conversion file should ALWAYS have at least 1 conversation start!"); } else { for (int i = 0; i < conStartNodes.Count; ++i) { Conversation newCon = new Conversation(); newCon.conNodes = dialNodesArr; newCon.startNode = conStartNodes[i]; newCon._currentNode = conStartNodes[i]; newConArr[i] = newCon; } } return newConArr; }
/** * func: loads a conversion saved as a graphml file * the expected graphml syntax is as follows: * * - allows 1 dimensional grouping inside the graph. Stacked grouping may cause unexpected behaviour * - a group is considered a separate conversation, but edge can connect them * @graphmlFile: Asset reference to a valid graphml file */ public static Conversation[] loadFromYedGraphml(TextAsset graphmlFile) { if (!graphmlFile) throw new NullReferenceException("no xmlFile given!"); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(graphmlFile.text); XmlNodeList conNodeList = xmlDoc.GetElementsByTagName("node"); XmlNodeList conEdgeList = xmlDoc.GetElementsByTagName("edge"); Dictionary<string, BasicDialNode> dialNodes = new Dictionary<string, BasicDialNode>(); List<string> groupNodes = new List<string>(); // may have some use later on List<string> groupLabel = new List<string>(); List<BasicDialNode> conStartNodes = new List<BasicDialNode>(); // store conversation starts // LOAD NODES ~> ANSWERES/QUESTIONS BasicDialNode lastNode; foreach (XmlNode node in conNodeList) { // grouping nodes only indicate string grpLabel = GetGroupNodeLabel(node); if (grpLabel != null) { Debug.Log("Group node found!"); groupNodes.Add(node.Attributes["id"].Value); groupLabel.Add(grpLabel); continue; // TODO: we may grab the group label later on. Do this in here! } // normal dialogue node lastNode = new BasicDialNode(); lastNode.XmlID = node.Attributes["id"].Value; Debug.Assert(!dialNodes.ContainsKey(lastNode.XmlID), "Duplicated nodes entries found in XML!"); dialNodes[lastNode.XmlID] = lastNode; // get important ATTRIBUTES for this node foreach (XmlNode i in node.ChildNodes) { if (i.Attributes["key"] != null) { if (i.Attributes["key"].Value.Equals(NODE_GRAPHICS_KEY)) { if (i.HasChildNodes && i.ChildNodes[0].Name.Equals("y:ShapeNode")) { bool labelFound = false; foreach (XmlNode n in i.ChildNodes[0].ChildNodes) { if (n.Name.Equals("y:NodeLabel")) { labelFound = true; lastNode.dialogueText = n.InnerText; // TODE: set up multi dialogue texts HERE! } else if (n.Name.Equals("y:Fill")) { if (n.Attributes["color"].Value.Equals(START_NODE_COLOR)) conStartNodes.Add(lastNode); // found a conversation start node } } Debug.Assert(labelFound, "Found a response edge, but no response message??"); } } if (i.Attributes["key"].Value.Equals(NODE_ACTIVATION_EVENT_KEY)) { Debug.Log(node.Attributes["id"].Value + ": Node Activation Event found!"); } if (i.Attributes["key"].Value.Equals(NODE_PLAYER_EVENT_KEY)) { Debug.Log(node.Attributes["id"].Value + ": Node Player Event found!"); } } } } // LOAD EDGE ~> RESPONSES foreach (XmlNode edge in conEdgeList) { BasicDialResponse response = new BasicDialResponse(); response.nextNode = dialNodes[edge.Attributes["target"].Value]; // set target node link dialNodes[edge.Attributes["source"].Value].AddResponse(response); // set source node link foreach (XmlNode i in edge.ChildNodes) { // get the label -> response string if (i.Attributes["key"].Value.Equals(EDGE_GRAPHICS_KEY)) { XmlNode PolyLineEdge = i.ChildNodes[0]; Debug.Assert(PolyLineEdge.Name.Equals("y:PolyLineEdge"), "Unexpected edge structure!"); bool labelFound = false; foreach (XmlNode n in PolyLineEdge.ChildNodes) if (n.Name.Equals("y:LineStyle")) { if (n.Attributes["color"].Value.Equals(OPENSHOP_EDGE_COLOR)) response.optionType = EConOptionType.OPEN_SHOP; } else if (n.Name.Equals("y:EdgeLabel")) { labelFound = true; response.responseText = n.InnerText; // TODO: set up multi response texts HERE } Debug.Assert(labelFound, "Found a response edge, but no response message??"); } if (i.Attributes["key"].Value.Equals(EDGE_REQUIREMENT_KEY)) { Debug.Log(edge.Attributes["id"].Value + ": Requirement found!"); } if (i.Attributes["key"].Value.Equals(EDGE_ACTIVATION_EVENT)) { Debug.Log(edge.Attributes["id"].Value + ": Requirement found!"); } if (i.Attributes["key"].Value.Equals(EDGE_PLAYER_EVENT)) { Debug.Log(edge.Attributes["id"].Value + ": Requirement found!"); } } } // separate nodes into multiple conversations, if necessary Conversation[] newConArr = new Conversation[(conStartNodes.Count > 0) ? conStartNodes.Count : 1]; BasicDialNode[] dialNodesArr = new BasicDialNode[dialNodes.Values.Count]; dialNodes.Values.CopyTo(dialNodesArr, 0); // TODO: may split it up later on if (conStartNodes.Count == 0) { Debug.LogError("A valid conversion file should ALWAYS have at least 1 conversation start!"); } else { for (int i=0; i<conStartNodes.Count; ++i) { Conversation newCon = new Conversation(); newCon.conNodes = dialNodesArr; newCon.startNode = conStartNodes[i]; newCon._currentNode = conStartNodes[i]; newConArr[i] = newCon; } } return newConArr; }