public void NextNode(int i) { if (tree == null) { return; } OCRootNode rootNode = tree.rootNodes[tree.currentRoot]; OCNode node = rootNode.GetNode(currentNode); // Force output 0 on smalltalk nodes, just in case if (node.speak != null && node.speak.smalltalk) { i = 0; } // Check for range if (i < node.connectedTo.Length) { currentNode = node.connectedTo[i]; DisplayNode(); } else { Debug.LogError("OCManager | Node index '" + i + "' out of range (0-" + (node.connectedTo.Length - 1) + ")"); EndConversation(); } }
public void SelectOption(int i) { eventHandler.OnSelectOption(i); OCNode node = tree.rootNodes[tree.currentRoot].GetNode(currentNode); node.speak.index = i; StartCoroutine(PlayLineAudio(node)); }
public OCNode AddNode() { List <OCNode> tmpNodes = new List <OCNode> (nodes); OCNode newNode = new OCNode(); newNode.SetType(OCNodeType.Speak, true); tmpNodes.Add(newNode); nodes = tmpNodes.ToArray(); return(newNode); }
public void NextNode() { OCRootNode rootNode = tree.rootNodes[tree.currentRoot]; OCNode node = rootNode.GetNode(currentNode); if (node.speak != null && node.speak.choice) { NextNode(node.speak.index); } else { NextNode(0); } }
private IEnumerator PlayLineAudio(OCNode node) { // Make sure no other conversation audio is playing if (currentAudioSource) { currentAudioSource.Stop(); currentAudioSource = null; } // With audio if (speaker.gameObject.audio && node.speak.lines[node.speak.index].audio) { speaker.gameObject.audio.clip = node.speak.lines[node.speak.index].audio; speaker.gameObject.audio.loop = false; speaker.gameObject.audio.Play(); currentAudioSource = speaker.gameObject.audio; // Wait for speech duration float duration = speaker.gameObject.audio.clip.length; yield return(new WaitForSeconds(duration)); // If we already continued manually, or the conversation has ended, abort if (node.id == currentNode && tree != null) { yield return(new WaitForSeconds(0.5f)); NextNode(node.speak.index); } // Without audio } else { // For smalltalk, estimate the duration of the sentence if (node.speak.smalltalk) { float words = node.speak.lines[node.speak.index].text.Split(" "[0]).Length; float wordsPerMinute = 130; yield return(new WaitForSeconds((words / wordsPerMinute) * 60f)); NextNode(); } else { yield return(null); } } }
public void OnGUI() { placedInputs.Clear(); title = "Tree Editor"; distance.x = 220; distance.y = 100; List <string> tmpStr = new List <string> (); List <OCRootNode> tmpRoot = new List <OCRootNode> (); OCRootNode thisRoot = null; OCRootNode thatRoot = null; if (!target) { EditorGUI.LabelField(new Rect(position.width / 2 - 42, position.height / 2 - 10, 84, 20), "No target tree!", EditorStyles.boldLabel); return; } if (target.rootNodes.Length < 1) { target.AddRootNode(); } if (currentRoot > target.rootNodes.Length - 1) { currentRoot = target.rootNodes.Length - 1; } // Inspector Rect inspectorRect = new Rect(position.width - 300, 0, 300, position.height); Rect innerInspectorRect = new Rect(inspectorRect.x + 10, inspectorRect.y + 10, inspectorRect.width - 20, inspectorRect.height - 20); GUILayout.BeginArea(innerInspectorRect); int i; GUILayout.Label("Tree (" + target.gameObject.name + ")", EditorStyles.largeLabel); GUILayout.Box("", GUILayout.Height(1), GUILayout.Width(270)); // ^ Speaker names if (target.speakers.Length < 1) { tmpStr = new List <string> (target.speakers); tmpStr.Add("Speaker"); target.speakers = tmpStr.ToArray(); } GUILayout.Label("Speaker names", EditorStyles.boldLabel); for (i = 0; i < target.speakers.Length; i++) { GUILayout.BeginHorizontal(); GUI.backgroundColor = speakerColors[i]; target.speakers[i] = GUILayout.TextField(target.speakers[i]); GUI.backgroundColor = Color.white; GUI.color = Color.red; if (target.speakers.Length > 1 && GUILayout.Button("x", GUILayout.Height(16), GUILayout.Width(32))) { tmpStr = new List <string> (target.speakers); tmpStr.RemoveAt(i); target.speakers = tmpStr.ToArray(); return; } GUI.color = Color.white; GUILayout.EndHorizontal(); } GUI.color = Color.green; if (target.speakers.Length < 10 && GUILayout.Button("+", GUILayout.Height(16), GUILayout.Width(32))) { tmpStr = new List <string> (target.speakers); tmpStr.Add("Speaker"); target.speakers = tmpStr.ToArray(); } GUI.color = Color.white; GUILayout.Space(20); GUILayout.Label("Root", EditorStyles.largeLabel); GUILayout.Box("", GUILayout.Height(1), GUILayout.Width(270)); // ^ Tags string[] tags = target.rootNodes[currentRoot].tags; string tagString = ""; for (i = 0; i < tags.Length; i++) { tagString += tags[i]; if (i < tags.Length - 1) { tagString += ","; } } GUILayout.Label("Tags", EditorStyles.boldLabel); tagString = GUILayout.TextField(tagString); target.rootNodes[currentRoot].tags = tagString.Split(","[0]); GUILayout.Space(20); // ^ Node GUILayout.Label("Node", EditorStyles.largeLabel); GUILayout.Box("", GUILayout.Height(1), GUILayout.Width(270)); inspectorScrollPosition = GUILayout.BeginScrollView(inspectorScrollPosition); if (node != null) { DrawInspector(); } GUILayout.EndScrollView(); GUILayout.EndArea(); scrollRect = new Rect(0, 0, position.width - inspectorRect.width, position.height); GUI.Box(scrollRect, ""); // Tree editor scrollPosition = GUI.BeginScrollView(scrollRect, scrollPosition, innerScrollRect); Vector2 center = scrollRect.center; float right = center.x - ((target.rootNodes.Length * 1.0f) / 2f) * 32f; // ^ Root navigation if (currentRoot > 0 && GUI.Button(new Rect(right + (currentRoot - 1) * 32 - 16, 8, 32, 16), "<")) { tmpRoot = new List <OCRootNode> (target.rootNodes); thisRoot = tmpRoot [currentRoot]; thatRoot = tmpRoot [currentRoot - 1]; tmpRoot [currentRoot] = thatRoot; tmpRoot [currentRoot - 1] = thisRoot; target.rootNodes = tmpRoot.ToArray(); currentRoot--; } GUI.color = Color.red; if (GUI.Button(new Rect(right + currentRoot * 32 - 16, 8, 32, 16), "x")) { target.RemoveRootNode(currentRoot); return; } GUI.color = Color.white; if (currentRoot < target.rootNodes.Length - 1 && GUI.Button(new Rect(right + (currentRoot + 1) * 32 - 16, 8, 32, 16), ">")) { tmpRoot = new List <OCRootNode> (target.rootNodes); thisRoot = tmpRoot [currentRoot]; thatRoot = tmpRoot [currentRoot + 1]; tmpRoot [currentRoot] = thatRoot; tmpRoot [currentRoot + 1] = thisRoot; target.rootNodes = tmpRoot.ToArray(); currentRoot++; } // ^ Root display for (i = 0; i < target.rootNodes.Length; i++) { if (i == currentRoot) { GUI.color = Color.white; } else { GUI.color = Color.grey; } if (GUI.Button(new Rect(right + i * 32 - 16, 32, 32, 16), i.ToString())) { currentRoot = i; innerScrollRect.width = scrollRect.width; innerScrollRect.height = scrollRect.height; innerScrollRect.x = 0; innerScrollRect.y = 0; } GUI.color = Color.white; } // ^ Add root node GUI.color = Color.green; if (GUI.Button(new Rect(right + i * 32 - 16, 32, 32, 16), "+")) { target.AddRootNode(); } GUI.color = Color.white; // ^ Node display GUI.color = Color.green; if (GUI.Button(new Rect(right + currentRoot * 32 - 12, 56, 24, 12), "+")) { OCNode newNode = target.rootNodes [currentRoot].AddNode(); OCNode firstNode = target.rootNodes [currentRoot].GetFirstNode(); if (firstNode.connectedTo [i] > 0) { newNode.connectedTo [0] = firstNode.connectedTo [i]; } firstNode.connectedTo [i] = newNode.id; node = newNode; } GUI.color = Color.white; if (target.rootNodes[currentRoot].nodes.Length < 1) { target.rootNodes[currentRoot].AddFirstNode(); } DrawLine(new Vector2(right + currentRoot * 32, 48), new Vector2(center.x, 96)); DrawNode(target.rootNodes[currentRoot].GetNode(target.rootNodes[currentRoot].firstNode), center.x, 96); GUI.EndScrollView(); if (Event.current.type == EventType.MouseDown) { OCNode cNode = target.rootNodes [currentRoot].GetNode(connectingNode); if (cNode != null) { cNode.connectedTo[connectingOutput] = 0; } connectingNode = 0; connectingOutput = 0; } if (connectingNode > 0) { Repaint(); } if (innerScrollRect.width < scrollRect.width) { innerScrollRect.width = scrollRect.width; } if (innerScrollRect.height < scrollRect.height) { innerScrollRect.height = scrollRect.height; } if (GUI.changed) { target.CleanUp(); } }
private void DrawNode(OCNode n, float x, float y) { string nodeText = ""; Color nodeColor = Color.white; if (x - 70 < 0) { innerScrollRect.xMin = x - 70; } else if (x + 70 > innerScrollRect.xMax) { innerScrollRect.xMax = x + 70; } if (y + 60 > innerScrollRect.yMax) { innerScrollRect.yMax = y + 60; } switch (n.type) { case OCNodeType.Speak: nodeColor = speakerColors [n.speak.speaker]; if (n.speak.lines.Length == 1) { nodeText = n.speak.lines[0].text; if (nodeText.Length < 1) { nodeText = "..."; } else if (nodeText.Length > 16) { nodeText = nodeText.Substring(0, 13) + "..."; } } else { if (n.speak.smalltalk) { nodeText = "(smalltalk)"; } else { nodeText = "(choice)"; } } break; case OCNodeType.Event: nodeText = "(event)"; break; case OCNodeType.End: nodeText = "(end)"; break; case OCNodeType.Jump: nodeText = "(jump)"; break; case OCNodeType.SetQuest: nodeText = "(set quest)"; break; case OCNodeType.GetQuest: nodeText = "(get quest)"; break; case OCNodeType.SetFlag: nodeText = "(set flag)"; break; case OCNodeType.GetFlag: nodeText = "(get flag)"; break; } GUI.backgroundColor = nodeColor; if (GUI.Button(new Rect(x - 50, y, 100, 40), nodeText)) { if (connectingNode > 0) { OCNode fromNode = target.rootNodes [currentRoot].GetNode(connectingNode); if (fromNode != null) { fromNode.connectedTo[connectingOutput] = n.id; connectingNode = 0; connectingOutput = 0; return; } } node = n; } GUI.backgroundColor = Color.white; GUI.color = Color.red; if (GUI.Button(new Rect(x + 30, y - 6, 24, 12), "x")) { n.id = 0; return; } GUI.color = Color.white; // Input Rect inputRect = new Rect(x - 6, y - 6, 12, 12); placedInputs.Add(n.id, inputRect); if (GUI.Button(inputRect, "")) { } for (int i = 0; i < n.connectedTo.Length; i++) { int nextId = n.connectedTo[i]; float xPos = x; float nodeXPos = xPos; if (n.connectedTo.Length > 1) { float span = distance.x; float segment = span / (n.connectedTo.Length - 1); xPos = x - span / 2 + i * segment; nodeXPos = x - 100 / 2 + i * (100 / (n.connectedTo.Length - 1)); } GUI.color = Color.green; if (GUI.Button(new Rect(nodeXPos - 12, y + 50, 24, 12), "+")) { OCNode newNode = target.rootNodes [currentRoot].AddNode(); if (n.connectedTo [i] > 0) { newNode.connectedTo [0] = n.connectedTo [i]; } n.connectedTo [i] = newNode.id; node = newNode; } GUI.color = Color.white; Rect outputRect; if (n.type == OCNodeType.GetFlag || n.type == OCNodeType.GetQuest) { string bString = i == 0 ? "false" : "true"; outputRect = new Rect(nodeXPos - 24, y + 32, 48, 14); if (GUI.Button(outputRect, bString)) { connectingNode = n.id; connectingOutput = i; } } else { outputRect = new Rect(nodeXPos - 6, y + 34, 12, 12); if (GUI.Button(outputRect, "")) { connectingNode = n.id; connectingOutput = i; } } if (nextId > 0) { OCNode nextNode = target.rootNodes[currentRoot].GetNode(nextId); if (nextNode == null) { n.connectedTo[i] = 0; return; } if (placedInputs.ContainsKey(nextId)) { DrawLine(new Vector2(nodeXPos, y + 40), placedInputs[nextId].center); } else { DrawLine(new Vector2(nodeXPos, y + 40), new Vector2(xPos, y + distance.y)); DrawNode(nextNode, xPos, y + distance.y); } } if (connectingNode == n.id && connectingOutput == i) { DrawLine(outputRect.center, Event.current.mousePosition); } } }
public void DisplayNode() { OCNode node = tree.rootNodes[tree.currentRoot].GetNode(currentNode); bool wait = false; bool exit = false; int nextNode = 0; switch (node.type) { case OCNodeType.Jump: tree.currentRoot = node.jump.rootNode; nextNode = tree.rootNodes[tree.currentRoot].firstNode; break; case OCNodeType.Speak: speaker = speakers [node.speak.speaker]; wait = true; break; case OCNodeType.Event: // Send the event message to the target object if (node.evt.obj != null && node.evt.eventToTarget) { if (!string.IsNullOrEmpty(node.evt.argument)) { node.evt.obj.SendMessage(node.evt.message, node.evt.argument, SendMessageOptions.DontRequireReceiver); } else { node.evt.obj.SendMessage(node.evt.message, tree, SendMessageOptions.DontRequireReceiver); } // Send the message to the event handler } else if (eventHandler) { if (!string.IsNullOrEmpty(node.evt.argument)) { eventHandler.Event(node.evt.message, node.evt.argument); } else if (node.evt.obj != null) { eventHandler.Event(node.evt.message, node.evt.obj); } else { eventHandler.Event(node.evt.message, tree); } } nextNode = node.connectedTo[0]; break; case OCNodeType.SetFlag: flags.Set(node.setFlag.flag, node.setFlag.b); nextNode = node.connectedTo[0]; break; case OCNodeType.GetFlag: if (flags.Get(node.getFlag.flag)) { nextNode = node.connectedTo[1]; } else { nextNode = node.connectedTo[0]; } break; case OCNodeType.SetQuest: OCQuests.Quest quest = quests.GetUserQuest(node.setQuest.quest); if (quest == null) { quest = quests.GetPotentialQuest(node.setQuest.quest); if (quest != null) { quests.AddUserQuest(quest); } } if (quest != null) { OCQuests.Objective objective = quest.objectives [node.setQuest.objective]; objective.completed = node.setQuest.completed; } else { Debug.LogWarning("OCManager | Quest is null!"); } nextNode = node.connectedTo[0]; break; case OCNodeType.GetQuest: quest = quests.GetUserQuest(node.getQuest.quest); if ((!node.getQuest.completed && quest != null) || (quest != null && node.getQuest.objective < quest.objectives.Length && quest.objectives[node.getQuest.objective].completed)) { nextNode = node.connectedTo[1]; } else { nextNode = node.connectedTo[0]; } break; case OCNodeType.End: tree.currentRoot = node.end.rootNode; exit = true; break; } // Meta nodes if (exit) { EndConversation(); } else if (!wait) { currentNode = nextNode; DisplayNode(); // OCSpeak nodes } else if (node != null && node.speak != null) { eventHandler.OnSetSpeaker(speaker, node.speak); if (!node.speak.choice) { StartCoroutine(PlayLineAudio(node)); if (node.speak.smalltalk) { if (node.speak.index < node.speak.lines.Length - 1) { node.speak.index++; } } } } }
public void AddFirstNode() { OCNode newNode = AddNode(); firstNode = newNode.id; }