Dialogue node: how to change color of selected node?

How would you go about changing the color of the selected node, for easer identification?

Thank you!

What I did was to assign an alternate background if the node was currently assigned, much like you change the background between player and speaker. So in my case, I have four background images

speaker
speakerSelected
player
playerSelected

1 Like

I managed to do this, this is my code (should be use at the end of the Dialogue Editor section):

public class DialogueEditor : EditorWindow
   {
       Dialogue selectedDialogue = null;
       Vector2 scrollPostion;

       [NonSerialized] GUIStyle speakerNodeStyle;
       [NonSerialized] GUIStyle speakerNodeSelectedStyle;
       [NonSerialized] GUIStyle playerNodeStyle;
       [NonSerialized] GUIStyle playerNodeSelectedStyle;
       [NonSerialized] DialogueNode draggingNode = null;
       [NonSerialized] DialogueNode selectedNode = null;
       [NonSerialized] Vector2 draggingOffset = Vector2.zero;
       [NonSerialized] DialogueNode creatingNode = null;
       [NonSerialized] DialogueNode deletingNode = null;
       [NonSerialized] DialogueNode linkingParentNode = null;
       [NonSerialized] bool draggingCanvas = false;
       [NonSerialized] Vector2 dragginCanvasOffset;

       const float canvasSize = 4000;
       const float backgroundSize = 50;
       const int rectOffsetPadding = 15;
       const int rectOffsetBorder = 12;

       bool isSelected = false;

       [MenuItem("Dialogue/Dialogue Editor")]
       public static void ShowEditorWindow()
       {
           GetWindow(typeof(DialogueEditor), false, "Dialogue Editor");
       }

       [OnOpenAsset(1)]
       public static bool OnDoubleClickedAsset(int instaceId, int line)
       {
           Dialogue dialogue = EditorUtility.InstanceIDToObject(instaceId) as Dialogue;

           if (dialogue != null)
           {
               ShowEditorWindow();
               return true;
           }

           return false;
       }

       private void OnEnable()
       {
           Selection.selectionChanged += OnSelectionChanged;

           speakerNodeStyle = new GUIStyle();
           speakerNodeStyle.normal.background = EditorGUIUtility.Load("node0") as Texture2D;
           speakerNodeStyle.padding = new RectOffset(rectOffsetPadding, rectOffsetPadding, rectOffsetPadding, rectOffsetPadding);
           speakerNodeStyle.border = new RectOffset(rectOffsetBorder, rectOffsetBorder, rectOffsetBorder, rectOffsetBorder);

           speakerNodeSelectedStyle = new GUIStyle();
           speakerNodeSelectedStyle.normal.background = EditorGUIUtility.Load("node3") as Texture2D;
           speakerNodeSelectedStyle.padding = new RectOffset(rectOffsetPadding, rectOffsetPadding, rectOffsetPadding, rectOffsetPadding);
           speakerNodeSelectedStyle.border = new RectOffset(rectOffsetBorder, rectOffsetBorder, rectOffsetBorder, rectOffsetBorder);

           playerNodeStyle = new GUIStyle();
           playerNodeStyle.normal.background = EditorGUIUtility.Load("node1") as Texture2D;
           playerNodeStyle.padding = new RectOffset(rectOffsetPadding, rectOffsetPadding, rectOffsetPadding, rectOffsetPadding);
           playerNodeStyle.border = new RectOffset(rectOffsetBorder, rectOffsetBorder, rectOffsetBorder, rectOffsetBorder);

           playerNodeSelectedStyle = new GUIStyle();
           playerNodeSelectedStyle.normal.background = EditorGUIUtility.Load("node2") as Texture2D;
           playerNodeSelectedStyle.padding = new RectOffset(rectOffsetPadding, rectOffsetPadding, rectOffsetPadding, rectOffsetPadding);
           playerNodeSelectedStyle.border = new RectOffset(rectOffsetBorder, rectOffsetBorder, rectOffsetBorder, rectOffsetBorder);
       }

       private void OnSelectionChanged()
       {
           Dialogue newDialogue = Selection.activeObject as Dialogue;

           if (newDialogue != null)
           {
               selectedDialogue = newDialogue;
               Repaint();

           }
       }

       private void OnGUI()
       {

           if (selectedDialogue == null)
           {
               EditorGUILayout.LabelField("No dialogue selected");
           }
           else
           {
               ProcessEvents();

               scrollPostion = EditorGUILayout.BeginScrollView(scrollPostion);

               Rect canvas = GUILayoutUtility.GetRect(canvasSize, canvasSize);
               Texture2D backgroundTexture = Resources.Load("DialogueCanvas_Background") as Texture2D;

               Rect textCoords = new Rect(0, 0, canvasSize / backgroundSize, canvasSize / backgroundSize);
               GUI.DrawTextureWithTexCoords(canvas, backgroundTexture, textCoords);

               foreach (DialogueNode node in selectedDialogue.GetAllNodes())
               {
                   DrawConnections(node);
               }

               foreach (DialogueNode node in selectedDialogue.GetAllNodes())
               {
                   DrawNode(node);
               }


               EditorGUILayout.EndScrollView();

               if (creatingNode != null)
               {
                   selectedDialogue.CreateNode(creatingNode);
                   creatingNode = null;
               }

               if (deletingNode != null)
               {
                   selectedDialogue.DeleteNode(deletingNode);
                   deletingNode = null;
               }
           }

       }

       private void ProcessEvents()
       {
           if (Event.current.type == EventType.MouseDown && draggingNode == null)
           {
               draggingNode = GetNodeAtPoint(Event.current.mousePosition + scrollPostion);
               selectedNode = draggingNode;

               if (draggingNode != null)
               {
                   draggingOffset = draggingNode.Rect.position - Event.current.mousePosition;
                   Selection.activeObject = draggingNode;
               }
               else
               {
                   draggingCanvas = true;
                   isSelected = false;
                   dragginCanvasOffset = Event.current.mousePosition + scrollPostion;
                   Selection.activeObject = selectedDialogue;
               }
           }
           else if (Event.current.type == EventType.MouseDrag && draggingNode != null)
           {
               draggingNode.SetPosition(Event.current.mousePosition + draggingOffset);

               GUI.changed = true;
           }
           else if (Event.current.type == EventType.MouseDrag && draggingCanvas)
           {
               scrollPostion = dragginCanvasOffset - Event.current.mousePosition;

               GUI.changed = true;
           }
           else if (Event.current.type == EventType.MouseUp && draggingNode != null)
           {
               draggingNode = null;

           }
           else if (Event.current.type == EventType.MouseUp && draggingCanvas)
           {
               draggingCanvas = false;
           }

           if (selectedNode == null)
           {
               isSelected = false;
           }
       }


       private void DrawNode(DialogueNode node)
       {
           GUIStyle style = speakerNodeStyle;

           if (node.IsPlayerSpeaking && !node.IsSelected)
           {
               style = playerNodeStyle;
               Repaint();
           }
           else if (node.IsPlayerSpeaking && node.IsSelected && isSelected)
           {
               style = playerNodeSelectedStyle;
               Repaint();
           }

           if (!node.IsPlayerSpeaking && !node.IsSelected)
           {
               style = speakerNodeStyle;
               Repaint();
           }
           else if (!node.IsPlayerSpeaking && node.IsSelected && isSelected)
           {
               style = speakerNodeSelectedStyle;
               Repaint();
           }

           if (!isSelected || selectedNode.name != node.name)
           {
               node.IsSelected = false;
           }

           GUILayout.BeginArea(node.Rect, style);
           node.SetSentence(EditorGUILayout.TextField(node.Sentence));

           GUILayout.BeginHorizontal();

           if (GUILayout.Button("Add"))
           {
               creatingNode = node;
           }

           DrawLinkingButtons(node);

           if (GUILayout.Button("Delete"))
           {
               deletingNode = node;
           }

           GUILayout.EndHorizontal();

           GUILayout.EndArea();
       }

       private void DrawLinkingButtons(DialogueNode node)
       {
           if (linkingParentNode == null)
           {
               if (GUILayout.Button("Link"))
               {
                   linkingParentNode = node;
               }
           }
           else if (linkingParentNode == node)
           {
               if (GUILayout.Button("Cancel"))
               {
                   linkingParentNode = null;
               }
           }
           else if (linkingParentNode.Children.Contains(node.name))
           {
               if (GUILayout.Button("Unlink"))
               {
                   linkingParentNode.RemoveChild(node.name);
                   linkingParentNode = null;
               }
           }
           else
           {
               if (GUILayout.Button("Child"))
               {
                   linkingParentNode.AddChild(node.name);
                   linkingParentNode = null;
               }
           }
       }

       private DialogueNode GetNodeAtPoint(Vector2 point)
       {
           DialogueNode foundNode = null;

           foreach (DialogueNode node in selectedDialogue.GetAllNodes())
           {
               if (node.Rect.Contains(point))
               {
                   foundNode = node;
                   node.IsSelected = true;
                   isSelected = true;
               }

           }

           return foundNode;
       }

       private void DrawConnections(DialogueNode node)
       {
           Vector3 startPosition = new Vector2(node.Rect.xMax, node.Rect.center.y);

           foreach (DialogueNode childNode in selectedDialogue.GetAllChildren(node))
           {
               Vector3 endPosition = new Vector2(childNode.Rect.xMin, childNode.Rect.center.y);
               Vector3 controlPointOffset = endPosition - startPosition;
               controlPointOffset.y = 0;
               controlPointOffset.x *= 0.8f;
               Handles.DrawBezier(startPosition, endPosition, startPosition + controlPointOffset, endPosition - controlPointOffset, Color.white, null, 6f);
           }
       }

   }
1 Like

I just get the node’s name to see if the node im drawing is the selected one.
I only posting the relevant code as i modified some code…

public class DialogueEditor : EditorWindow
{
    [NonSerialized] GUIStyle selectedNodeStyle; // Style of the selected node
    string selectedDialogueNodeName = null;     // Name (id) of the selected node
    ...

    private void OnEnable() {
        ...
        
        // Add a new style for the selected node
        selectedNodeStyle = new GUIStyle();
        selectedNodeStyle.normal.background = EditorGUIUtility.Load("node0 on") as Texture2D;
    }

    private void ProcessEvents()
    {
        if (Event.current.type == EventType.MouseDown && draggingNode == null)
        {
            draggingNode = GetNodeAtPoint(Event.current.mousePosition + scrollPosition);

            if (draggingNode != null)
            {
                // When click on a node
                ...
                
                // Assign the name of the node when click on it
                selectedDialogueNodeName = draggingNode.name;
            }
            else
            {
                // When click on the Canvas
                ...

                // Assign null when clicked outside the node
                selectedDialogueNodeName = null;
            }
        }

        ...
    }
    
    private void DrawNode(DialogueNode node)
    {
        // Set the style if selected Node
        if (node.name == selectedDialogueNodeName)
        {
            GUILayout.BeginArea(node.rect, selectedNodeStyle);
        }
        // Set the style if unselected Node
        else
        {
            GUILayout.BeginArea(node.rect, nodeStyle);
        }

        ...
    }

    private void DrawConnections(DialogueNode node)
    {
        ...

        // Connection if selected node
        if (node.name == selectedDialogueNodeName)
        {
            Handles.DrawBezier(
                startPosition, endPosition,
                startPosition + controlPointOffset,
                endPosition - controlPointOffset,
                Color.white, null, 4f
            );
        }
        // Connection if unselected node
        else
        {
            Handles.DrawBezier(
                startPosition, endPosition,
                startPosition + controlPointOffset,
                endPosition - controlPointOffset,
                Color.gray, null, 4f
            );
        }
    }
}
2 Likes

Actually very good idea! :smiley:

Privacy & Terms