public void DetachNodes(int knobID, QD_KnobType type) { QD_Knob knob = selectedNode.GetKnob(type, knobID); List <int> keys = new List <int>(); if (knob.Connections.Count > 0) { foreach (KeyValuePair <int, List <int> > connection in knob.Connections.dictionary) { int connectionCount = connection.Value.Count; QD_Node conn = db.GetNode(connection.Key); for (int j = 0; j < connectionCount; ++j) { conn.DisconnectNode(selectedNode.ID, connection.Value[j], type == QD_KnobType.Input ? QD_KnobType.Output : QD_KnobType.Input); } keys.Add(connection.Key); } } int keyCount = keys.Count; for (int j = 0; j < keyCount; ++j) { selectedNode.DisconnectNode(keys[j], knobID, type); } }
/// <summary> /// Disconnects a node's knob from a knob. /// </summary> /// <param name="connectionID">The id of the connected node.</param> /// <param name="connectionKnobID">The id of the connected knob.</param> /// <param name="knobID">The id of the knob.</param> /// <param name="knobType">The type of the knob.</param> public void DisconnectNode(int connectionID, int connectionKnobID, int knobID, QD_KnobType knobType) { QD_Knob knob = GetKnob(knobType, knobID); knob.Disconnect(connectionID, connectionKnobID); OnDisconnect(QD_DialogueEditor.db.DataDB, QD_DialogueEditor.db.GetNode(connectionID).Type, connectionID, connectionKnobID, knobID, knobType); }
/// <summary> /// Connects a knob from one node to a knob on this node. /// </summary> /// <param name="connectionID">The id of the connecting node.</param> /// <param name="connectionKnobID">The id of the connecting knob.</param> /// <param name="knobID">The id of this node's knob.</param> /// <param name="knobType">The type of this node's knob.</param> public void ConnectNode(int connectionID, int connectionKnobID, int knobID, QD_KnobType knobType) { QD_Knob knob = GetKnob(knobType, knobID); if (!knob.AllowMultipleConnections && knob.Connections.Count > 0) { return; } if (!knob.Connections.ContainsKey(connectionID)) { knob.Connections.Add(connectionID, new List <int> { connectionKnobID }); } else if (!knob.Connections.Get(connectionID).Contains(connectionKnobID)) { knob.Connections.Get(connectionID).Add(connectionKnobID); } OnConnect(QD_DialogueEditor.db.DataDB, QD_DialogueEditor.db.GetNode(connectionID).Type, connectionID, connectionKnobID, knobID, knobType); }
/// <summary> /// The function called to modify the node's data whenever a node connects. /// </summary> /// <param name="dialogue">The dialogue data.</param> /// <param name="connectionType">The type of the connecting node.</param> /// <param name="connectionID">The id of the connecting node.</param> /// <param name="connectionKnobID">The id of the connecting knob.</param> /// <param name="knobID">The id of this node's knob.</param> /// <param name="knobType">The type of this node's knob.</param> public override void OnConnect(QD_Dialogue dialogue, QD_NodeType connectionType, int connectionID, int connectionKnobID, int knobID, QD_KnobType knobType) { Data.OnConnect(dialogue, connectionType, connectionID, connectionKnobID, knobID, knobType); QD_DialogueEditor.db.DataDB.SetMessage(Data.ID, Data); if (connectionType == QD_NodeType.Speaker && knobID == 0 && knobType == QD_KnobType.Input) { QD_Node message = QD_DialogueEditor.db.GetNode(ID); QD_Knob messageKnob = message.GetKnob(QD_KnobType.Output, 0); int nextMessageID = messageKnob.Connections.Count > 0 ? messageKnob.Connections.keys[0] : -1; QD_Message nextMessage = nextMessageID != -1 ? dialogue.GetMessage(nextMessageID) : null; while (nextMessageID != -1 && nextMessage != null) { nextMessage.Speaker = connectionID; nextMessage.SpeakerName = dialogue.GetSpeaker(connectionID).Name; QD_DialogueEditor.db.DataDB.SetMessage(nextMessage.ID, nextMessage); message = QD_DialogueEditor.db.GetNode(nextMessageID); messageKnob = message.GetKnob(QD_KnobType.Output, 0); nextMessageID = messageKnob.Connections.Count > 0 ? messageKnob.Connections.keys[0] : -1; nextMessage = nextMessageID != -1 ? dialogue.GetMessage(nextMessageID) : null; } } }
private void OnGUI() { if (!editor) { editor = this; } SelectDB(); skin = Resources.Load <GUISkin>("Node Editor Skin"); GUI.skin = skin; float eWidth = editor.position.width; float eHeight = editor.position.height; if (!db) { EditorGUILayout.HelpBox("Select an object with a QD_NodeDB script.", MessageType.Info); } else { Event e = Event.current; mouse = e.mousePosition; int nodeCount = db.Nodes.Count; // Mouse click events, taken from https://forum.unity.com/threads/simple-node-editor.189230/ if (e.type == EventType.MouseDown && e.button == 1 && !connectingNodes) { bool clicked = false; int selectedIndex = -1; bool knobClicked = false; int knobSelectedIndex = -1; for (int i = 0; i < nodeCount; ++i) { QD_Node node = db.Nodes[i]; if (node.Window.Contains(mouse + scroll)) { selectedIndex = i; clicked = true; break; } else { int inputCount = node.Inputs.Count; for (int j = 0; j < inputCount; ++j) { if (node.InputKnob(j).Contains(mouse + scroll)) { selectedIndex = i; clicked = true; knobSelectedIndex = j; knobClicked = true; knobType = QD_KnobType.Input; selectedKnob = j; break; } } if (knobClicked) { break; } int outputCount = node.Outputs.Count; for (int j = 0; j < outputCount; ++j) { if (node.OutputKnob(j).Contains(mouse + scroll)) { selectedIndex = i; clicked = true; knobSelectedIndex = j; knobClicked = true; knobType = QD_KnobType.Output; selectedKnob = j; break; } } if (knobClicked) { break; } } } if (!clicked) { GenericMenu menu = new GenericMenu(); menu.AddItem(new GUIContent("Add Conversation"), false, ContextCallback, "Add Conversation"); menu.AddItem(new GUIContent("Add Speaker"), false, ContextCallback, "Add Speaker"); menu.AddItem(new GUIContent("Add Message"), false, ContextCallback, "Add Message"); menu.AddItem(new GUIContent("Add Choice"), false, ContextCallback, "Add Choice"); menu.ShowAsContext(); e.Use(); } else { GenericMenu menu = new GenericMenu(); if (!knobClicked) { menu.AddItem(new GUIContent("Detach All Connected Nodes"), false, ContextCallback, "Detach All Connected Nodes"); menu.AddItem(new GUIContent("Delete Node"), false, ContextCallback, "Delete Node"); } else { menu.AddItem(new GUIContent("Attach to Node"), false, ContextCallback, "Attach to Node"); menu.AddItem(new GUIContent("Detach Connected Nodes"), false, ContextCallback, "Detach Connected Nodes"); } menu.ShowAsContext(); e.Use(); selectedNode = db.Nodes[selectedIndex]; } } else if (e.type == EventType.MouseDown && e.button == 0 && connectingNodes) { bool clicked = false; int selectedIndex = -1; bool knobClicked = false; int knobSelectedIndex = -1; QD_KnobType clickedKnobType = QD_KnobType.Input; for (int i = 0; i < nodeCount; ++i) { QD_Node node = db.Nodes[i]; int inputCount = node.Inputs.Count; for (int j = 0; j < inputCount; ++j) { if (node.InputKnob(j).Contains(mouse + scroll)) { selectedIndex = i; clicked = true; knobSelectedIndex = j; knobClicked = true; clickedKnobType = QD_KnobType.Input; break; } } if (knobClicked) { break; } int outputCount = node.Outputs.Count; for (int j = 0; j < outputCount; ++j) { if (node.OutputKnob(j).Contains(mouse + scroll)) { selectedIndex = i; clicked = true; knobSelectedIndex = j; knobClicked = true; clickedKnobType = QD_KnobType.Output; break; } } if (knobClicked) { break; } } if (clicked) { EditorUtility.SetDirty(db); if (knobType == QD_KnobType.Input && clickedKnobType == QD_KnobType.Output) { QD_Node outputNode = db.Nodes[selectedIndex]; QD_Knob input = selectedNode.Inputs[selectedKnob]; QD_Knob output = outputNode.Outputs[knobSelectedIndex]; if (selectedNode.ID != outputNode.ID && (!output.Connections.ContainsKey(selectedNode.ID) || !output.Connections.Get(selectedNode.ID).Contains(selectedKnob)) && (!input.Connections.ContainsKey(outputNode.ID) || !input.Connections.Get(outputNode.ID).Contains(knobSelectedIndex)) && (output.AllowMultipleConnections || output.Connections.Count == 0) && (input.AllowMultipleConnections || input.Connections.Count == 0) && selectedNode.CanConnect(knobType, selectedKnob, outputNode.Type, QD_KnobType.Output, knobSelectedIndex) ) { selectedNode.ConnectNode(outputNode.ID, knobSelectedIndex, selectedKnob, QD_KnobType.Input); outputNode.ConnectNode(selectedNode.ID, selectedKnob, knobSelectedIndex, QD_KnobType.Output); } } else if (knobType == QD_KnobType.Output && clickedKnobType == QD_KnobType.Input) { QD_Node inputNode = db.Nodes[selectedIndex]; QD_Knob input = inputNode.Inputs[knobSelectedIndex]; QD_Knob output = selectedNode.Outputs[selectedKnob]; if (selectedNode.ID != inputNode.ID && (!output.Connections.ContainsKey(inputNode.ID) || !output.Connections.Get(inputNode.ID).Contains(knobSelectedIndex)) && (!input.Connections.ContainsKey(selectedNode.ID) || !input.Connections.Get(selectedNode.ID).Contains(selectedKnob)) && (output.AllowMultipleConnections || output.Connections.Count == 0) && (input.AllowMultipleConnections || input.Connections.Count == 0) && selectedNode.CanConnect(knobType, selectedKnob, inputNode.Type, QD_KnobType.Input, knobSelectedIndex) ) { selectedNode.ConnectNode(inputNode.ID, knobSelectedIndex, selectedKnob, QD_KnobType.Output); inputNode.ConnectNode(selectedNode.ID, selectedKnob, knobSelectedIndex, QD_KnobType.Input); } } } connectingNodes = false; selectedNode = null; knobClicked = false; selectedKnob = -1; e.Use(); } if (connectingNodes && selectedNode != null) { Rect mouseRect = new Rect(e.mousePosition.x, e.mousePosition.y, 10, 10); Rect knobRect = knobType == QD_KnobType.Input ? selectedNode.InputKnob(selectedKnob) : selectedNode.OutputKnob(selectedKnob); knobRect.position += new Vector2(knobRect.width / 2, knobRect.height / 2) - scroll; DrawNodeCurve(knobType == QD_KnobType.Output ? knobRect : mouseRect, knobType == QD_KnobType.Output ? mouseRect : knobRect, false); Repaint(); } GUILayout.BeginArea(new Rect(-scroll, new Vector2(5000, 5000))); for (int i = 0; i < nodeCount; ++i) { QD_Node node = db.Nodes[i]; int outputCount = node.Outputs.Count; for (int j = 0; j < outputCount; ++j) { QD_Knob output = node.Outputs[j]; if (output.Connections.Count > 0) { foreach (KeyValuePair <int, List <int> > connection in output.Connections.dictionary) { int connectionCount = connection.Value.Count; for (int k = 0; k < connectionCount; ++k) { DrawNodeCurve(node.OutputKnob(j), db.GetNode(connection.Key).InputKnob(connection.Value[k]), true); } } } } } BeginWindows(); for (int i = 0; i < nodeCount; ++i) { QD_Node node = db.Nodes[i]; if (node.Type == QD_NodeType.Speaker) { QD_SpeakerNode realNode = db.GetSpeakerNode(node.ID); node.Window = GUI.Window(node.ID, node.Window, realNode.DrawWindow, realNode.WindowTitle); } else if (node.Type == QD_NodeType.Message) { QD_MessageNode realNode = db.GetMessageNode(node.ID); node.Window = GUI.Window(node.ID, node.Window, realNode.DrawWindow, realNode.WindowTitle); } else if (node.Type == QD_NodeType.Conversation) { QD_ConversationNode realNode = db.GetConversationNode(node.ID); node.Window = GUI.Window(node.ID, node.Window, realNode.DrawWindow, realNode.WindowTitle); } else if (node.Type == QD_NodeType.Choice) { QD_ChoiceNode realNode = db.GetChoiceNode(node.ID); node.Window = GUI.Window(node.ID, node.Window, realNode.DrawWindow, realNode.WindowTitle); } node.DrawKnobs(); } EndWindows(); GUILayout.EndArea(); scroll = new Vector2( GUI.HorizontalScrollbar(new Rect(0, eHeight - 15, eWidth - 15, eHeight - 5), scroll.x, eHeight, 0, 5000), GUI.VerticalScrollbar(new Rect(eWidth - 15, 0, eWidth - 5, eHeight - 15), scroll.y, eHeight, 0, 5000) ); } }