public override void DrawWindow(int id)
        {
            QD_Node node = QD_DialogueEditor.db.GetNode(ID);

            EditorGUI.BeginChangeCheck();
            List <string> fChoices = new List <string>();

            foreach (var choice in Data.Choices)
            {
                fChoices.Add(choice);
            }

            int count = Data.Choices.Count;

            if (GUI.Button(new Rect(140, 40 + count * 30, 20, 20), "+", QD_DialogueEditor.skin.button) && Data.Choices.Count < 6)
            {
                EditorUtility.SetDirty(QD_DialogueEditor.db);
                EditorUtility.SetDirty(QD_DialogueEditor.db.DataDB);
                int num = node.Outputs.Count;
                node.Outputs.Add(new QD_Knob(num, "Choice " + (num + 1), QD_KnobType.Output, 45 + num * 30, false));
                node.AllowedOutputs.Add(new QD_ConnectionRule(QD_NodeType.Message, 1, QD_NodeType.Choice, num));
                node.Window.height += 30;
                Data.Choices.Add("");
                fChoices.Add("");
                Data.NextMessages.Add(-1);
                QD_DialogueEditor.db.DataDB.SetChoice(Data.ID, Data);
            }

            for (int i = count - 1; i >= 0; --i)
            {
                EditorGUI.LabelField(new Rect(5, 40 + i * 30, 65, 20), "Choice " + (i + 1), QD_DialogueEditor.skin.label);
                fChoices[i] = EditorGUI.TextField(new Rect(75, 40 + i * 30, 195, 20), fChoices[i], QD_DialogueEditor.skin.textField);

                if (i == count - 1)
                {
                    if (GUI.Button(new Rect(275, 42.5f + i * 30, 20, 20), "-", QD_DialogueEditor.skin.button))
                    {
                        EditorUtility.SetDirty(QD_DialogueEditor.db);
                        EditorUtility.SetDirty(QD_DialogueEditor.db.DataDB);
                        fChoices.RemoveAt(i);
                        QD_DialogueEditor.editor.selectedNode = node;
                        QD_DialogueEditor.editor.DetachNodes(i, QD_KnobType.Output);
                        Data.NextMessages.RemoveAt(i);
                        node.Outputs.RemoveAt(i);
                        node.Window.height -= 30;
                        QD_DialogueEditor.db.DataDB.SetChoice(Data.ID, Data);
                    }
                }
            }

            if (EditorGUI.EndChangeCheck())
            {
                EditorUtility.SetDirty(QD_DialogueEditor.db);
                EditorUtility.SetDirty(QD_DialogueEditor.db.DataDB);
                Data.Choices = fChoices;
                QD_DialogueEditor.db.DataDB.SetChoice(Data.ID, Data);
            }

            GUI.DragWindow();
        }
        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>
        /// 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;
                }
            }
        }
        public void ContextCallback(object obj)
        {
            string command = obj.ToString();

            EditorUtility.SetDirty(db);
            EditorUtility.SetDirty(db.DataDB);

            if (command == "Add Conversation")
            {
                db.CreateNode(QD_NodeType.Conversation, mouse + scroll);
            }
            else if (command == "Add Speaker")
            {
                db.CreateNode(QD_NodeType.Speaker, mouse + scroll);
            }
            else if (command == "Add Message")
            {
                db.CreateNode(QD_NodeType.Message, mouse + scroll);
            }
            else if (command == "Add Choice")
            {
                db.CreateNode(QD_NodeType.Choice, mouse + scroll);
            }
            else if (command == "Attach to Node")
            {
                connectingNodes = true;
            }
            else if (command == "Detach All Connected Nodes")
            {
                DetachNodes();
            }
            else if (command == "Detach Connected Nodes")
            {
                DetachNodes(selectedKnob, knobType);
            }
            else if (command == "Delete Node")
            {
                DetachNodes();

                int     i    = db.GetNodeIndex(selectedNode.ID);
                QD_Node node = db.Nodes[i];
                if (node.Type == QD_NodeType.Speaker)
                {
                    db.SpeakerNodes.RemoveAt(db.GetSpeakerNodeIndex(selectedNode.ID));
                }
                else if (node.Type == QD_NodeType.Message)
                {
                    db.MessageNodes.RemoveAt(db.GetMessageNodeIndex(selectedNode.ID));
                }
                else if (node.Type == QD_NodeType.Conversation)
                {
                    db.ConversationNodes.RemoveAt(db.GetConversationNodeIndex(selectedNode.ID));
                }
                else if (node.Type == QD_NodeType.Choice)
                {
                    db.ChoiceNodes.RemoveAt(db.GetChoiceNodeIndex(selectedNode.ID));
                }
                db.Nodes.RemoveAt(i);
                if (node.Type == QD_NodeType.Speaker)
                {
                    foreach (var n in db.Nodes)
                    {
                        if (n.Type == QD_NodeType.Message)
                        {
                            QD_MessageNode messageNode = db.GetMessageNode(n.ID);
                            if (messageNode.Data.Speaker == node.ID)
                            {
                                messageNode.Data.Speaker     = -1;
                                messageNode.Data.SpeakerName = "";
                            }
                        }
                    }

                    i = db.DataDB.GetSpeakerIndex(selectedNode.ID);
                    db.DataDB.Speakers.RemoveAt(i);
                }
                else if (node.Type == QD_NodeType.Message)
                {
                    i = db.DataDB.GetMessageIndex(selectedNode.ID);
                    db.DataDB.Messages.RemoveAt(i);
                }
                else if (node.Type == QD_NodeType.Conversation)
                {
                    i = db.DataDB.GetConversationIndex(selectedNode.ID);
                    db.DataDB.Conversations.RemoveAt(i);
                }
                else if (node.Type == QD_NodeType.Choice)
                {
                    i = db.DataDB.GetChoiceIndex(selectedNode.ID);
                    db.DataDB.Choices.RemoveAt(i);
                }
                if (db.Nodes.Count == 0)
                {
                    db.NextID = 0;
                }
            }
        }
        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)
                    );
            }
        }
Exemple #6
0
        /// <summary>
        /// Creates a new node of the given type at the given position.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="position"></param>
        public void CreateNode(QD_NodeType type, Vector2 position)
        {
            int id   = NextID++;
            var node = new QD_Node(id, type, position.x, position.y);

            if (type == QD_NodeType.Speaker)
            {
                var speakerNode = new QD_SpeakerNode(id, type, position.x, position.y);

                node.Window.width   = speakerNode.Window.width;
                node.Window.height  = speakerNode.Window.height;
                node.Inputs         = speakerNode.CloneKnobs(QD_KnobType.Input);
                node.Outputs        = speakerNode.CloneKnobs(QD_KnobType.Output);
                node.AllowedInputs  = speakerNode.AllowedInputs;
                node.AllowedOutputs = speakerNode.AllowedOutputs;

                var speakerData = new QD_Speaker(id);
                DataDB.Speakers.Add(speakerData);
                speakerNode.Data = speakerData;

                SpeakerNodes.Add(speakerNode);
            }
            else if (type == QD_NodeType.Message)
            {
                var messageNode = new QD_MessageNode(id, type, position.x, position.y);

                node.Window.width   = messageNode.Window.width;
                node.Window.height  = messageNode.Window.height;
                node.Inputs         = messageNode.CloneKnobs(QD_KnobType.Input);
                node.Outputs        = messageNode.CloneKnobs(QD_KnobType.Output);
                node.AllowedInputs  = messageNode.AllowedInputs;
                node.AllowedOutputs = messageNode.AllowedOutputs;

                var messageData = new QD_Message(id);
                DataDB.Messages.Add(messageData);
                messageNode.Data = messageData;

                MessageNodes.Add(messageNode);
            }
            else if (type == QD_NodeType.Conversation)
            {
                var conversationNode = new QD_ConversationNode(id, type, position.x, position.y);

                node.Window.width   = conversationNode.Window.width;
                node.Window.height  = conversationNode.Window.height;
                node.Inputs         = conversationNode.CloneKnobs(QD_KnobType.Input);
                node.Outputs        = conversationNode.CloneKnobs(QD_KnobType.Output);
                node.AllowedInputs  = conversationNode.AllowedInputs;
                node.AllowedOutputs = conversationNode.AllowedOutputs;

                var conversationData = new QD_Conversation(id);
                DataDB.Conversations.Add(conversationData);
                conversationNode.Data = conversationData;

                ConversationNodes.Add(conversationNode);
            }
            else if (type == QD_NodeType.Choice)
            {
                var choiceNode = new QD_ChoiceNode(id, type, position.x, position.y);

                node.Window.width   = choiceNode.Window.width;
                node.Window.height  = choiceNode.Window.height;
                node.Inputs         = choiceNode.CloneKnobs(QD_KnobType.Input);
                node.Outputs        = choiceNode.CloneKnobs(QD_KnobType.Output);
                node.AllowedInputs  = choiceNode.AllowedInputs;
                node.AllowedOutputs = choiceNode.AllowedOutputs;

                var choiceData = new QD_Choice(id);
                DataDB.Choices.Add(choiceData);
                choiceNode.Data = choiceData;

                ChoiceNodes.Add(choiceNode);
            }

            Nodes.Add(node);
        }