How would you go about changing the color of the selected node, for easer identification?
Thank you!
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
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);
}
}
}
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
);
}
}
}
Actually very good idea!