diff --git a/Scripts/Editor/NodeEditor.cs b/Scripts/Editor/NodeEditor.cs
index 09bed80..e03973a 100644
--- a/Scripts/Editor/NodeEditor.cs
+++ b/Scripts/Editor/NodeEditor.cs
@@ -24,7 +24,6 @@ namespace XNodeEditor
/// Fires every whenever a node was modified through the editor
public static Action onUpdateNode;
public static readonly Dictionary portPositions = new Dictionary();
- private Vector2 _lastClickPos;
#if ODIN_INSPECTOR
protected internal static bool inNodeEditor = false;
@@ -32,18 +31,6 @@ namespace XNodeEditor
public virtual void OnHeaderGUI()
{
- Event e = Event.current;
- if (e.type == EventType.MouseDown)
- {
- if ((_lastClickPos - e.mousePosition).sqrMagnitude <= 5 * 5 && e.clickCount > 1)
- {
- Debug.Log("Renaming time!");
- return;
- }
-
- _lastClickPos = e.mousePosition;
- }
-
GUILayout.Label(target.name, NodeEditorResources.styles.nodeHeader, GUILayout.Height(30));
}
diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs
index 50c6432..e694477 100644
--- a/Scripts/Editor/NodeEditorAction.cs
+++ b/Scripts/Editor/NodeEditorAction.cs
@@ -20,7 +20,8 @@ namespace XNodeEditor
HoldNode,
DragNode,
HoldGrid,
- DragGrid
+ DragGrid,
+ Renaming
}
public static NodeActivity currentActivity = NodeActivity.Idle;
public static bool isPanning { get; private set; }
@@ -32,6 +33,8 @@ namespace XNodeEditor
public bool IsHoveringPort => hoveredPort != null;
public bool IsHoveringNode => hoveredNode != null;
public bool IsHoveringReroute => hoveredReroute.port != null;
+ public bool IsSelectingRenamingObject =>
+ currentActivity == NodeActivity.Renaming && IsHoveringNode && Selection.Contains(hoveredNode);
/// Return the dragged port or null if not exist
public NodePort DraggedOutputPort
@@ -135,6 +138,7 @@ namespace XNodeEditor
else if (currentActivity == NodeActivity.HoldNode)
{
RecalculateDragOffsets(e);
+ isDoubleClick = false;
currentActivity = NodeActivity.DragNode;
Repaint();
}
@@ -277,8 +281,14 @@ namespace XNodeEditor
}
}
}
+
+ if (currentActivity == NodeActivity.Renaming)
+ {
+ currentActivity = NodeActivity.Idle;
+ }
}
- else if (IsHoveringNode && IsHoveringTitle(hoveredNode))
+ else if (IsHoveringNode && IsHoveringTitle(hoveredNode) &&
+ (currentActivity != NodeActivity.Renaming || !IsSelectingRenamingObject))
{
// If mousedown on node header, select or deselect
if (!Selection.Contains(hoveredNode))
@@ -415,19 +425,30 @@ namespace XNodeEditor
}
// If click node header, select it.
- if (currentActivity == NodeActivity.HoldNode && !(e.control || e.shift))
+ if ((currentActivity == NodeActivity.HoldNode || !IsSelectingRenamingObject) &&
+ !(e.control || e.shift))
{
selectedReroutes.Clear();
SelectNode(hoveredNode, false);
- // Double click to center node
+ // Double click to rename node
if (isDoubleClick)
{
- Vector2 nodeDimension = nodeSizes.ContainsKey(hoveredNode)
- ? nodeSizes[hoveredNode] / 2
- : Vector2.zero;
- panOffset = -hoveredNode.position - nodeDimension;
+ RenameSelectedNodeTextField();
+ currentActivity = NodeActivity.Renaming;
+ // Vector2 nodeDimension = nodeSizes.ContainsKey(hoveredNode)
+ // ? nodeSizes[hoveredNode] / 2
+ // : Vector2.zero;
+ // panOffset = -hoveredNode.position - nodeDimension;
}
+ else
+ {
+ currentActivity = NodeActivity.HoldNode;
+ }
+ }
+ else if (currentActivity != NodeActivity.Renaming)
+ {
+ currentActivity = NodeActivity.Idle;
}
// If click reroute, select it.
@@ -438,7 +459,6 @@ namespace XNodeEditor
}
Repaint();
- currentActivity = NodeActivity.Idle;
}
else if (e.button == 1 || e.button == 2)
{
@@ -483,6 +503,11 @@ namespace XNodeEditor
graphEditor.AddContextMenuItems(menu);
menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
}
+
+ if (currentActivity == NodeActivity.Renaming)
+ {
+ currentActivity = NodeActivity.Idle;
+ }
}
isPanning = false;
@@ -604,6 +629,11 @@ namespace XNodeEditor
break;
}
+
+ if (currentActivity != NodeActivity.Renaming && RenameTextField.IsActive)
+ {
+ RenameTextField.current.SaveAndClose();
+ }
}
private void RecalculateDragOffsets(Event current)
@@ -686,6 +716,24 @@ namespace XNodeEditor
}
}
+
+ public void RenameSelectedNodeTextField()
+ {
+ if (Selection.objects.Length == 1 && Selection.activeObject is Node)
+ {
+ Node node = Selection.activeObject as Node;
+ Vector2 size;
+ if (nodeSizes.TryGetValue(node, out size))
+ {
+ RenameTextField.Show(Selection.activeObject, size.x);
+ }
+ else
+ {
+ RenameTextField.Show(Selection.activeObject);
+ }
+ }
+ }
+
/// Draw this node on top of other nodes by placing it last in the graph.nodes list
public void MoveNodeToTop(Node node)
{
diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs
index 479ef02..18d46d6 100755
--- a/Scripts/Editor/NodeEditorGUI.cs
+++ b/Scripts/Editor/NodeEditorGUI.cs
@@ -156,7 +156,7 @@ namespace XNodeEditor
}
else
{
- graphEditor.AddContextMenuItems(contextMenu, hoveredPort.ValueType, NodePort.IO.Input);
+ graphEditor.AddContextMenuItems(contextMenu, hoveredPort.ValueType);
}
}
@@ -681,7 +681,15 @@ namespace XNodeEditor
EditorGUI.BeginChangeCheck();
//Draw node contents
- nodeEditor.OnHeaderGUI();
+ if (currentActivity == NodeActivity.Renaming && Selection.activeObject == node)
+ {
+ RenameTextField.current.DrawRenameTextField();
+ }
+ else
+ {
+ nodeEditor.OnHeaderGUI();
+ }
+
nodeEditor.OnBodyGUI();
//If user changed a value, notify other scripts through onUpdateNode
diff --git a/Scripts/Editor/NodeEditorResources.cs b/Scripts/Editor/NodeEditorResources.cs
index e70a785..cc963e8 100644
--- a/Scripts/Editor/NodeEditorResources.cs
+++ b/Scripts/Editor/NodeEditorResources.cs
@@ -25,7 +25,7 @@ namespace XNodeEditor
public static GUIStyle OutputPort => new GUIStyle(EditorStyles.label) { alignment = TextAnchor.UpperRight };
public class Styles
{
- public GUIStyle inputPort, outputPort, nodeHeader, nodeBody, tooltip, nodeHighlight;
+ public GUIStyle inputPort, outputPort, nodeHeader, nodeHeaderRename, nodeBody, tooltip, nodeHighlight;
public Styles()
{
@@ -49,6 +49,13 @@ namespace XNodeEditor
nodeHeader.fontStyle = FontStyle.Bold;
nodeHeader.normal.textColor = Color.white;
+ nodeHeaderRename = new GUIStyle(GUI.skin.textField);
+ nodeHeaderRename.alignment = TextAnchor.MiddleCenter;
+ nodeHeaderRename.fontStyle = FontStyle.Bold;
+ nodeHeaderRename.normal.textColor = Color.white;
+ nodeHeaderRename.fixedHeight = 18;
+ nodeHeaderRename.margin = new RectOffset(5, 5, 10, 8);
+
nodeBody = new GUIStyle();
nodeBody.normal.background = NodeEditorResources.nodeBody;
nodeBody.border = new RectOffset(32, 32, 32, 32);
@@ -63,6 +70,20 @@ namespace XNodeEditor
}
}
+ public static Texture2D GenerateSolidColorTexture(int width, int height, Color col)
+ {
+ var pix = new Color[width * height];
+ for (int i = 0; i < pix.Length; ++i)
+ {
+ pix[i] = col;
+ }
+
+ Texture2D result = new Texture2D(width, height);
+ result.SetPixels(pix);
+ result.Apply();
+ return result;
+ }
+
public static Texture2D GenerateGridTexture(Color line, Color bg)
{
Texture2D tex = new Texture2D(64, 64);
diff --git a/Scripts/Editor/RenameTextField.cs b/Scripts/Editor/RenameTextField.cs
new file mode 100644
index 0000000..ceb64fc
--- /dev/null
+++ b/Scripts/Editor/RenameTextField.cs
@@ -0,0 +1,98 @@
+using UnityEditor;
+using UnityEngine;
+using XNode;
+
+namespace XNodeEditor
+{
+ /// Utility for renaming assets
+ public class RenameTextField
+ {
+ private const string inputControlName = "nameInput";
+
+ public static RenameTextField current { get; private set; }
+ public static bool IsActive => current != null;
+ public Object target;
+ public string input;
+
+ private bool firstFrame = true;
+
+ /// Show a rename text field for an asset in the node header. Will trigger reimport of the asset on apply.
+ public static RenameTextField Show(Object target, float width = 200)
+ {
+ RenameTextField textField = new RenameTextField();
+ if (current != null)
+ {
+ current = null;
+ }
+
+ current = textField;
+ textField.target = target;
+ textField.input = target.name;
+
+ return textField;
+ }
+
+ public void DrawRenameTextField()
+ {
+ GUI.SetNextControlName(inputControlName);
+ input = GUILayout.TextField(input, NodeEditorResources.styles.nodeHeaderRename);
+ EditorGUI.FocusTextInControl(inputControlName);
+
+ if (firstFrame)
+ {
+ TextEditor textEditor =
+ (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl);
+ textEditor.SelectAll();
+ firstFrame = false;
+ }
+
+ Event e = Event.current;
+ // If input is empty, revert name to default instead
+ if (input == null || input.Trim() == "")
+ {
+ if (e.isKey && e.keyCode == KeyCode.Return)
+ {
+ SaveAndClose();
+ }
+ }
+ // Rename asset to input text
+ else
+ {
+ if (e.isKey && e.keyCode == KeyCode.Return)
+ {
+ SaveAndClose();
+ }
+ }
+
+ if (e.isKey && e.keyCode == KeyCode.Escape)
+ {
+ Close();
+ }
+ }
+
+ public void SaveAndClose()
+ {
+ target.name = input;
+ NodeEditor.GetEditor((Node)target, NodeEditorWindow.current).OnRename();
+ if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(target)))
+ {
+ AssetDatabase.SetMainObject((target as Node).graph, AssetDatabase.GetAssetPath(target));
+ AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
+ }
+
+ Close();
+ target.TriggerOnValidate();
+ }
+
+ public void Close()
+ {
+ firstFrame = true;
+ current = null;
+ NodeEditorWindow.current.Repaint();
+ if (NodeEditorWindow.currentActivity == NodeEditorWindow.NodeActivity.Renaming)
+ {
+ NodeEditorWindow.currentActivity = NodeEditorWindow.NodeActivity.Idle;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Scripts/Editor/RenameTextField.cs.meta b/Scripts/Editor/RenameTextField.cs.meta
new file mode 100644
index 0000000..29f40c9
--- /dev/null
+++ b/Scripts/Editor/RenameTextField.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: e19c9bf223d748e895841425ac714280
+timeCreated: 1696534896
\ No newline at end of file