diff --git a/Scripts/Editor/GraphAndNodeEditor.cs b/Scripts/Editor/GraphAndNodeEditor.cs
index 6bbb865..257ea54 100644
--- a/Scripts/Editor/GraphAndNodeEditor.cs
+++ b/Scripts/Editor/GraphAndNodeEditor.cs
@@ -1,30 +1,39 @@
using UnityEditor;
using UnityEngine;
+using XNode;
#if ODIN_INSPECTOR
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities;
using Sirenix.Utilities.Editor;
#endif
-namespace XNodeEditor {
+namespace XNodeEditor
+{
/// Override graph inspector to show an 'Open Graph' button at the top
[CustomEditor(typeof(NodeGraph), true)]
#if ODIN_INSPECTOR
- public class GlobalGraphEditor : OdinEditor {
- public override void OnInspectorGUI() {
- if (GUILayout.Button("Edit graph", GUILayout.Height(40))) {
+ public class GlobalGraphEditor : OdinEditor
+ {
+ public override void OnInspectorGUI()
+ {
+ if (GUILayout.Button("Edit graph", GUILayout.Height(40)))
+ {
NodeEditorWindow.Open(serializedObject.targetObject as XNode.NodeGraph);
}
+
base.OnInspectorGUI();
}
}
#else
[CanEditMultipleObjects]
- public class GlobalGraphEditor : Editor {
- public override void OnInspectorGUI() {
+ public class GlobalGraphEditor : Editor
+ {
+ public override void OnInspectorGUI()
+ {
serializedObject.Update();
- if (GUILayout.Button("Edit graph", GUILayout.Height(40))) {
+ if (GUILayout.Button("Edit graph", GUILayout.Height(40)))
+ {
NodeEditorWindow.Open(serializedObject.targetObject as NodeGraph);
}
@@ -40,23 +49,30 @@ namespace XNodeEditor {
[CustomEditor(typeof(Node), true)]
#if ODIN_INSPECTOR
- public class GlobalNodeEditor : OdinEditor {
- public override void OnInspectorGUI() {
- if (GUILayout.Button("Edit graph", GUILayout.Height(40))) {
+ public class GlobalNodeEditor : OdinEditor
+ {
+ public override void OnInspectorGUI()
+ {
+ if (GUILayout.Button("Edit graph", GUILayout.Height(40)))
+ {
SerializedProperty graphProp = serializedObject.FindProperty("graph");
NodeEditorWindow w = NodeEditorWindow.Open(graphProp.objectReferenceValue as XNode.NodeGraph);
w.Home(); // Focus selected node
}
+
base.OnInspectorGUI();
}
}
#else
[CanEditMultipleObjects]
- public class GlobalNodeEditor : Editor {
- public override void OnInspectorGUI() {
+ public class GlobalNodeEditor : Editor
+ {
+ public override void OnInspectorGUI()
+ {
serializedObject.Update();
- if (GUILayout.Button("Edit graph", GUILayout.Height(40))) {
+ if (GUILayout.Button("Edit graph", GUILayout.Height(40)))
+ {
SerializedProperty graphProp = serializedObject.FindProperty("graph");
NodeEditorWindow w = NodeEditorWindow.Open(graphProp.objectReferenceValue as NodeGraph);
w.Home(); // Focus selected node
diff --git a/Scripts/Editor/GraphRenameFixAssetProcessor.cs b/Scripts/Editor/GraphRenameFixAssetProcessor.cs
index cf5ec93..21e2c2e 100644
--- a/Scripts/Editor/GraphRenameFixAssetProcessor.cs
+++ b/Scripts/Editor/GraphRenameFixAssetProcessor.cs
@@ -1,27 +1,33 @@
using UnityEditor;
+using XNode;
-namespace XNodeEditor {
+namespace XNodeEditor
+{
///
- /// This asset processor resolves an issue with the new v2 AssetDatabase system present on 2019.3 and later. When
- /// renaming a asset, it appears that sometimes the v2 AssetDatabase will swap which asset
- /// is the main asset (present at top level) between the and one of its
- /// sub-assets. As a workaround until Unity fixes this, this asset processor checks all renamed assets and if it
- /// finds a case where a has been made the main asset it will swap it back to being a sub-asset
- /// and rename the node to the default name for that node type.
+ /// This asset processor resolves an issue with the new v2 AssetDatabase system present on 2019.3 and later. When
+ /// renaming a asset, it appears that sometimes the v2 AssetDatabase will swap which asset
+ /// is the main asset (present at top level) between the and one of its
+ /// sub-assets. As a workaround until Unity fixes this, this asset processor checks all renamed assets and if it
+ /// finds a case where a has been made the main asset it will swap it back to being a sub-asset
+ /// and rename the node to the default name for that node type.
///
- internal sealed class GraphRenameFixAssetProcessor : AssetPostprocessor {
+ internal sealed class GraphRenameFixAssetProcessor : AssetPostprocessor
+ {
private static void OnPostprocessAllAssets(
string[] importedAssets,
string[] deletedAssets,
string[] movedAssets,
- string[] movedFromAssetPaths) {
- for (int i = 0; i < movedAssets.Length; i++) {
+ string[] movedFromAssetPaths)
+ {
+ for (int i = 0; i < movedAssets.Length; i++)
+ {
Node nodeAsset = AssetDatabase.LoadMainAssetAtPath(movedAssets[i]) as Node;
// If the renamed asset is a node graph, but the v2 AssetDatabase has swapped a sub-asset node to be its
// main asset, reset the node graph to be the main asset and rename the node asset back to its default
// name.
- if (nodeAsset != null && AssetDatabase.IsMainAsset(nodeAsset)) {
+ if (nodeAsset != null && AssetDatabase.IsMainAsset(nodeAsset))
+ {
AssetDatabase.SetMainObject(nodeAsset.graph, movedAssets[i]);
AssetDatabase.ImportAsset(movedAssets[i]);
diff --git a/Scripts/Editor/Internal/RerouteReference.cs b/Scripts/Editor/Internal/RerouteReference.cs
index 995b1dd..4d1b01f 100644
--- a/Scripts/Editor/Internal/RerouteReference.cs
+++ b/Scripts/Editor/Internal/RerouteReference.cs
@@ -1,20 +1,39 @@
using UnityEngine;
+using XNode;
-namespace XNodeEditor.Internal {
- public struct RerouteReference {
- public NodePort port;
- public int connectionIndex;
- public int pointIndex;
+namespace XNodeEditor.Internal
+{
+ public struct RerouteReference
+ {
+ public NodePort port;
+ public int connectionIndex;
+ public int pointIndex;
- public RerouteReference(NodePort port, int connectionIndex, int pointIndex) {
- this.port = port;
- this.connectionIndex = connectionIndex;
- this.pointIndex = pointIndex;
- }
+ public RerouteReference(NodePort port, int connectionIndex, int pointIndex)
+ {
+ this.port = port;
+ this.connectionIndex = connectionIndex;
+ this.pointIndex = pointIndex;
+ }
- public void InsertPoint(Vector2 pos) { port.GetReroutePoints(connectionIndex).Insert(pointIndex, pos); }
- public void SetPoint(Vector2 pos) { port.GetReroutePoints(connectionIndex) [pointIndex] = pos; }
- public void RemovePoint() { port.GetReroutePoints(connectionIndex).RemoveAt(pointIndex); }
- public Vector2 GetPoint() { return port.GetReroutePoints(connectionIndex) [pointIndex]; }
- }
+ public void InsertPoint(Vector2 pos)
+ {
+ port.GetReroutePoints(connectionIndex).Insert(pointIndex, pos);
+ }
+
+ public void SetPoint(Vector2 pos)
+ {
+ port.GetReroutePoints(connectionIndex)[pointIndex] = pos;
+ }
+
+ public void RemovePoint()
+ {
+ port.GetReroutePoints(connectionIndex).RemoveAt(pointIndex);
+ }
+
+ public Vector2 GetPoint()
+ {
+ return port.GetReroutePoints(connectionIndex)[pointIndex];
+ }
+ }
}
\ No newline at end of file
diff --git a/Scripts/Editor/NodeEditor.cs b/Scripts/Editor/NodeEditor.cs
index 4c57611..09bed80 100644
--- a/Scripts/Editor/NodeEditor.cs
+++ b/Scripts/Editor/NodeEditor.cs
@@ -3,34 +3,53 @@ using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
+using XNode;
+using XNodeEditor.Internal;
#if ODIN_INSPECTOR
using Sirenix.OdinInspector.Editor;
using Sirenix.Utilities;
using Sirenix.Utilities.Editor;
#endif
+
#if UNITY_2019_1_OR_NEWER && USE_ADVANCED_GENERIC_MENU
using GenericMenu = XNodeEditor.AdvancedGenericMenu;
#endif
-namespace XNodeEditor {
+namespace XNodeEditor
+{
/// Base class to derive custom Node editors from. Use this to create your own custom inspectors and editors for your nodes.
[CustomNodeEditor(typeof(Node))]
- public class NodeEditor : XNodeEditor.Internal.NodeEditorBase {
-
+ public class NodeEditor : NodeEditorBase
+ {
/// Fires every whenever a node was modified through the editor
public static Action onUpdateNode;
- public readonly static Dictionary portPositions = new Dictionary();
+ public static readonly Dictionary portPositions = new Dictionary();
+ private Vector2 _lastClickPos;
#if ODIN_INSPECTOR
protected internal static bool inNodeEditor = false;
#endif
- public virtual void OnHeaderGUI() {
+ 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));
}
/// Draws standard field editors for all public fields
- public virtual void OnBodyGUI() {
+ public virtual void OnBodyGUI()
+ {
#if ODIN_INSPECTOR
inNodeEditor = true;
#endif
@@ -45,12 +64,12 @@ namespace XNodeEditor {
try
{
#if ODIN_INSPECTOR_3
- objectTree.BeginDraw( true );
+ objectTree.BeginDraw(true);
#else
InspectorUtilities.BeginDrawPropertyTree(objectTree, true);
#endif
}
- catch ( ArgumentNullException )
+ catch (ArgumentNullException)
{
#if ODIN_INSPECTOR_3
objectTree.EndDraw();
@@ -61,8 +80,8 @@ namespace XNodeEditor {
return;
}
- GUIHelper.PushLabelWidth( 84 );
- objectTree.Draw( true );
+ GUIHelper.PushLabelWidth(84);
+ objectTree.Draw(true);
#if ODIN_INSPECTOR_3
objectTree.EndDraw();
#else
@@ -74,16 +93,26 @@ namespace XNodeEditor {
// Iterate through serialized properties and draw them like the Inspector (But with ports)
SerializedProperty iterator = serializedObject.GetIterator();
bool enterChildren = true;
- while (iterator.NextVisible(enterChildren)) {
+ while (iterator.NextVisible(enterChildren))
+ {
enterChildren = false;
- if (excludes.Contains(iterator.name)) continue;
- NodeEditorGUILayout.PropertyField(iterator, true);
+ if (excludes.Contains(iterator.name))
+ {
+ continue;
+ }
+
+ NodeEditorGUILayout.PropertyField(iterator);
}
#endif
// Iterate through dynamic ports and draw them in the order in which they are serialized
- foreach (NodePort dynamicPort in target.DynamicPorts) {
- if (NodeEditorGUILayout.IsDynamicPortListPort(dynamicPort)) continue;
+ foreach (NodePort dynamicPort in target.DynamicPorts)
+ {
+ if (NodeEditorGUILayout.IsDynamicPortListPort(dynamicPort))
+ {
+ continue;
+ }
+
NodeEditorGUILayout.PortField(dynamicPort);
}
@@ -91,7 +120,8 @@ namespace XNodeEditor {
#if ODIN_INSPECTOR
// Call repaint so that the graph window elements respond properly to layout changes coming from Odin
- if (GUIHelper.RepaintRequested) {
+ if (GUIHelper.RepaintRequested)
+ {
GUIHelper.ClearRepaintRequest();
window.Repaint();
}
@@ -102,41 +132,56 @@ namespace XNodeEditor {
#endif
}
- public virtual int GetWidth() {
+ public virtual int GetWidth()
+ {
Type type = target.GetType();
int width;
- if (type.TryGetAttributeWidth(out width)) return width;
- else return 208;
+ if (type.TryGetAttributeWidth(out width))
+ {
+ return width;
+ }
+
+ return 208;
}
/// Returns color for target node
- public virtual Color GetTint() {
+ public virtual Color GetTint()
+ {
// Try get color from [NodeTint] attribute
Type type = target.GetType();
Color color;
- if (type.TryGetAttributeTint(out color)) return color;
+ if (type.TryGetAttributeTint(out color))
+ {
+ return color;
+ }
// Return default color (grey)
- else return NodeEditorPreferences.GetSettings().tintColor;
+
+ return NodeEditorPreferences.GetSettings().tintColor;
}
- public virtual GUIStyle GetBodyStyle() {
+ public virtual GUIStyle GetBodyStyle()
+ {
return NodeEditorResources.styles.nodeBody;
}
- public virtual GUIStyle GetBodyHighlightStyle() {
+ public virtual GUIStyle GetBodyHighlightStyle()
+ {
return NodeEditorResources.styles.nodeHighlight;
}
/// Override to display custom node header tooltips
- public virtual string GetHeaderTooltip() {
+ public virtual string GetHeaderTooltip()
+ {
return null;
}
/// Add items for the context menu when right-clicking this node. Override to add custom menu items.
- public virtual void AddContextMenuItems(GenericMenu menu) {
+ public virtual void AddContextMenuItems(GenericMenu menu)
+ {
bool canRemove = true;
// Actions if only one node is selected
- if (Selection.objects.Length == 1 && Selection.activeObject is Node) {
+ if (Selection.objects.Length == 1 && Selection.activeObject is Node)
+ {
Node node = Selection.activeObject as Node;
menu.AddItem(new GUIContent("Move To Top"), false, () => NodeEditorWindow.current.MoveNodeToTop(node));
menu.AddItem(new GUIContent("Rename"), false, NodeEditorWindow.current.RenameSelectedNode);
@@ -148,38 +193,54 @@ namespace XNodeEditor {
menu.AddItem(new GUIContent("Copy"), false, NodeEditorWindow.current.CopySelectedNodes);
menu.AddItem(new GUIContent("Duplicate"), false, NodeEditorWindow.current.DuplicateSelectedNodes);
- if (canRemove) menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes);
- else menu.AddItem(new GUIContent("Remove"), false, null);
+ if (canRemove)
+ {
+ menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes);
+ }
+ else
+ {
+ menu.AddItem(new GUIContent("Remove"), false, null);
+ }
// Custom sctions if only one node is selected
- if (Selection.objects.Length == 1 && Selection.activeObject is Node) {
+ if (Selection.objects.Length == 1 && Selection.activeObject is Node)
+ {
Node node = Selection.activeObject as Node;
menu.AddCustomContextMenuItems(node);
}
}
/// Rename the node asset. This will trigger a reimport of the node.
- public void Rename(string newName) {
- if (newName == null || newName.Trim() == "") newName = NodeEditorUtilities.NodeDefaultName(target.GetType());
+ public void Rename(string newName)
+ {
+ if (newName == null || newName.Trim() == "")
+ {
+ newName = NodeEditorUtilities.NodeDefaultName(target.GetType());
+ }
+
target.name = newName;
OnRename();
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
}
/// Called after this node's name has changed.
- public virtual void OnRename() { }
+ public virtual void OnRename() {}
[AttributeUsage(AttributeTargets.Class)]
public class CustomNodeEditorAttribute : Attribute,
- XNodeEditor.Internal.NodeEditorBase.INodeEditorAttrib {
- private Type inspectedType;
+ INodeEditorAttrib
+ {
+ private readonly Type inspectedType;
+
/// Tells a NodeEditor which Node type it is an editor for
/// Type that this editor can edit
- public CustomNodeEditorAttribute(Type inspectedType) {
+ public CustomNodeEditorAttribute(Type inspectedType)
+ {
this.inspectedType = inspectedType;
}
- public Type GetInspectedType() {
+ public Type GetInspectedType()
+ {
return inspectedType;
}
}
diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs
index fb81194..50c6432 100644
--- a/Scripts/Editor/NodeEditorAction.cs
+++ b/Scripts/Editor/NodeEditorAction.cs
@@ -3,60 +3,96 @@ using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
+using XNode;
using XNodeEditor.Internal;
+using Object = UnityEngine.Object;
#if UNITY_2019_1_OR_NEWER && USE_ADVANCED_GENERIC_MENU
using GenericMenu = XNodeEditor.AdvancedGenericMenu;
#endif
-namespace XNodeEditor {
- public partial class NodeEditorWindow {
- public enum NodeActivity { Idle, HoldNode, DragNode, HoldGrid, DragGrid }
+namespace XNodeEditor
+{
+ public partial class NodeEditorWindow
+ {
+ public enum NodeActivity
+ {
+ Idle,
+ HoldNode,
+ DragNode,
+ HoldGrid,
+ DragGrid
+ }
public static NodeActivity currentActivity = NodeActivity.Idle;
public static bool isPanning { get; private set; }
public static Vector2[] dragOffset;
- public static Node[] copyBuffer = null;
+ public static Node[] copyBuffer;
- public bool IsDraggingPort { get { return draggedOutput != null; } }
- public bool IsHoveringPort { get { return hoveredPort != null; } }
- public bool IsHoveringNode { get { return hoveredNode != null; } }
- public bool IsHoveringReroute { get { return hoveredReroute.port != null; } }
+ public bool IsDraggingPort => draggedOutput != null;
+ public bool IsHoveringPort => hoveredPort != null;
+ public bool IsHoveringNode => hoveredNode != null;
+ public bool IsHoveringReroute => hoveredReroute.port != null;
/// Return the dragged port or null if not exist
- public NodePort DraggedOutputPort { get { NodePort result = draggedOutput; return result; } }
+ public NodePort DraggedOutputPort
+ {
+ get
+ {
+ NodePort result = draggedOutput;
+ return result;
+ }
+ }
/// Return the Hovered port or null if not exist
- public NodePort HoveredPort { get { NodePort result = hoveredPort; return result; } }
+ public NodePort HoveredPort
+ {
+ get
+ {
+ NodePort result = hoveredPort;
+ return result;
+ }
+ }
/// Return the Hovered node or null if not exist
- public Node HoveredNode { get { Node result = hoveredNode; return result; } }
+ public Node HoveredNode
+ {
+ get
+ {
+ Node result = hoveredNode;
+ return result;
+ }
+ }
- private Node hoveredNode = null;
+ private Node hoveredNode;
[NonSerialized] public NodePort hoveredPort = null;
- [NonSerialized] private NodePort draggedOutput = null;
- [NonSerialized] private NodePort draggedOutputTarget = null;
- [NonSerialized] private NodePort autoConnectOutput = null;
+ [NonSerialized] private NodePort draggedOutput;
+ [NonSerialized] private NodePort draggedOutputTarget;
+ [NonSerialized] private NodePort autoConnectOutput;
[NonSerialized] private List draggedOutputReroutes = new List();
- private RerouteReference hoveredReroute = new RerouteReference();
+ private RerouteReference hoveredReroute;
public List selectedReroutes = new List();
private Vector2 dragBoxStart;
- private UnityEngine.Object[] preBoxSelection;
+ private Object[] preBoxSelection;
private RerouteReference[] preBoxSelectionReroute;
private Rect selectionBox;
- private bool isDoubleClick = false;
+ private bool isDoubleClick;
private Vector2 lastMousePosition;
private float dragThreshold = 1f;
- public void Controls() {
+ public void Controls()
+ {
wantsMouseMove = true;
Event e = Event.current;
- switch (e.type) {
+ switch (e.type)
+ {
case EventType.DragUpdated:
case EventType.DragPerform:
DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
- if (e.type == EventType.DragPerform) {
+ if (e.type == EventType.DragPerform)
+ {
DragAndDrop.AcceptDrag();
graphEditor.OnDropObjects(DragAndDrop.objectReferences);
}
+
break;
case EventType.MouseMove:
//Keyboard commands will not get correct mouse position from Event
@@ -64,57 +100,89 @@ namespace XNodeEditor {
break;
case EventType.ScrollWheel:
float oldZoom = zoom;
- if (e.delta.y > 0) zoom += 0.1f * zoom;
- else zoom -= 0.1f * zoom;
- if (NodeEditorPreferences.GetSettings().zoomToMouse) panOffset += (1 - oldZoom / zoom) * (WindowToGridPosition(e.mousePosition) + panOffset);
+ if (e.delta.y > 0)
+ {
+ zoom += 0.1f * zoom;
+ }
+ else
+ {
+ zoom -= 0.1f * zoom;
+ }
+
+ if (NodeEditorPreferences.GetSettings().zoomToMouse)
+ {
+ panOffset += (1 - oldZoom / zoom) * (WindowToGridPosition(e.mousePosition) + panOffset);
+ }
+
break;
case EventType.MouseDrag:
- if (e.button == 0) {
- if (IsDraggingPort) {
+ if (e.button == 0)
+ {
+ if (IsDraggingPort)
+ {
// Set target even if we can't connect, so as to prevent auto-conn menu from opening erroneously
- if (IsHoveringPort && hoveredPort.IsInput && !draggedOutput.IsConnectedTo(hoveredPort)) {
+ if (IsHoveringPort && hoveredPort.IsInput && !draggedOutput.IsConnectedTo(hoveredPort))
+ {
draggedOutputTarget = hoveredPort;
- } else {
+ }
+ else
+ {
draggedOutputTarget = null;
}
+
Repaint();
- } else if (currentActivity == NodeActivity.HoldNode) {
+ }
+ else if (currentActivity == NodeActivity.HoldNode)
+ {
RecalculateDragOffsets(e);
currentActivity = NodeActivity.DragNode;
Repaint();
}
- if (currentActivity == NodeActivity.DragNode) {
+
+ if (currentActivity == NodeActivity.DragNode)
+ {
// Holding ctrl inverts grid snap
bool gridSnap = NodeEditorPreferences.GetSettings().gridSnap;
- if (e.control) gridSnap = !gridSnap;
+ if (e.control)
+ {
+ gridSnap = !gridSnap;
+ }
Vector2 mousePos = WindowToGridPosition(e.mousePosition);
// Move selected nodes with offset
- for (int i = 0; i < Selection.objects.Length; i++) {
- if (Selection.objects[i] is Node) {
+ for (int i = 0; i < Selection.objects.Length; i++)
+ {
+ if (Selection.objects[i] is Node)
+ {
Node node = Selection.objects[i] as Node;
Undo.RecordObject(node, "Moved Node");
Vector2 initial = node.position;
node.position = mousePos + dragOffset[i];
- if (gridSnap) {
- node.position.x = (Mathf.Round((node.position.x + 8) / 16) * 16) - 8;
- node.position.y = (Mathf.Round((node.position.y + 8) / 16) * 16) - 8;
+ if (gridSnap)
+ {
+ node.position.x = Mathf.Round((node.position.x + 8) / 16) * 16 - 8;
+ node.position.y = Mathf.Round((node.position.y + 8) / 16) * 16 - 8;
}
// Offset portConnectionPoints instantly if a node is dragged so they aren't delayed by a frame.
Vector2 offset = node.position - initial;
- if (offset.sqrMagnitude > 0) {
- foreach (NodePort output in node.Outputs) {
+ if (offset.sqrMagnitude > 0)
+ {
+ foreach (NodePort output in node.Outputs)
+ {
Rect rect;
- if (portConnectionPoints.TryGetValue(output, out rect)) {
+ if (portConnectionPoints.TryGetValue(output, out rect))
+ {
rect.position += offset;
portConnectionPoints[output] = rect;
}
}
- foreach (NodePort input in node.Inputs) {
+ foreach (NodePort input in node.Inputs)
+ {
Rect rect;
- if (portConnectionPoints.TryGetValue(input, out rect)) {
+ if (portConnectionPoints.TryGetValue(input, out rect))
+ {
rect.position += offset;
portConnectionPoints[input] = rect;
}
@@ -122,51 +190,80 @@ namespace XNodeEditor {
}
}
}
+
// Move selected reroutes with offset
- for (int i = 0; i < selectedReroutes.Count; i++) {
+ for (int i = 0; i < selectedReroutes.Count; i++)
+ {
Vector2 pos = mousePos + dragOffset[Selection.objects.Length + i];
- if (gridSnap) {
- pos.x = (Mathf.Round(pos.x / 16) * 16);
- pos.y = (Mathf.Round(pos.y / 16) * 16);
+ if (gridSnap)
+ {
+ pos.x = Mathf.Round(pos.x / 16) * 16;
+ pos.y = Mathf.Round(pos.y / 16) * 16;
}
+
selectedReroutes[i].SetPoint(pos);
}
+
Repaint();
- } else if (currentActivity == NodeActivity.HoldGrid) {
+ }
+ else if (currentActivity == NodeActivity.HoldGrid)
+ {
currentActivity = NodeActivity.DragGrid;
preBoxSelection = Selection.objects;
preBoxSelectionReroute = selectedReroutes.ToArray();
dragBoxStart = WindowToGridPosition(e.mousePosition);
Repaint();
- } else if (currentActivity == NodeActivity.DragGrid) {
+ }
+ else if (currentActivity == NodeActivity.DragGrid)
+ {
Vector2 boxStartPos = GridToWindowPosition(dragBoxStart);
Vector2 boxSize = e.mousePosition - boxStartPos;
- if (boxSize.x < 0) { boxStartPos.x += boxSize.x; boxSize.x = Mathf.Abs(boxSize.x); }
- if (boxSize.y < 0) { boxStartPos.y += boxSize.y; boxSize.y = Mathf.Abs(boxSize.y); }
+ if (boxSize.x < 0)
+ {
+ boxStartPos.x += boxSize.x;
+ boxSize.x = Mathf.Abs(boxSize.x);
+ }
+
+ if (boxSize.y < 0)
+ {
+ boxStartPos.y += boxSize.y;
+ boxSize.y = Mathf.Abs(boxSize.y);
+ }
+
selectionBox = new Rect(boxStartPos, boxSize);
Repaint();
}
- } else if (e.button == 1 || e.button == 2) {
+ }
+ else if (e.button == 1 || e.button == 2)
+ {
//check drag threshold for larger screens
- if (e.delta.magnitude > dragThreshold) {
+ if (e.delta.magnitude > dragThreshold)
+ {
panOffset += e.delta * zoom;
isPanning = true;
}
}
+
break;
case EventType.MouseDown:
Repaint();
- if (e.button == 0) {
+ if (e.button == 0)
+ {
draggedOutputReroutes.Clear();
- if (IsHoveringPort) {
- if (hoveredPort.IsOutput) {
+ if (IsHoveringPort)
+ {
+ if (hoveredPort.IsOutput)
+ {
draggedOutput = hoveredPort;
autoConnectOutput = hoveredPort;
- } else {
+ }
+ else
+ {
hoveredPort.VerifyConnections();
autoConnectOutput = null;
- if (hoveredPort.IsConnected) {
+ if (hoveredPort.IsConnected)
+ {
Node node = hoveredPort.node;
NodePort output = hoveredPort.Connection;
int outputConnectionIndex = output.GetConnectionIndex(hoveredPort);
@@ -174,233 +271,397 @@ namespace XNodeEditor {
hoveredPort.Disconnect(output);
draggedOutput = output;
draggedOutputTarget = hoveredPort;
- if (NodeEditor.onUpdateNode != null) NodeEditor.onUpdateNode(node);
+ if (NodeEditor.onUpdateNode != null)
+ {
+ NodeEditor.onUpdateNode(node);
+ }
}
}
- } else if (IsHoveringNode && IsHoveringTitle(hoveredNode)) {
+ }
+ else if (IsHoveringNode && IsHoveringTitle(hoveredNode))
+ {
// If mousedown on node header, select or deselect
- if (!Selection.Contains(hoveredNode)) {
+ if (!Selection.Contains(hoveredNode))
+ {
SelectNode(hoveredNode, e.control || e.shift);
- if (!e.control && !e.shift) selectedReroutes.Clear();
- } else if (e.control || e.shift) DeselectNode(hoveredNode);
+ if (!e.control && !e.shift)
+ {
+ selectedReroutes.Clear();
+ }
+ }
+ else if (e.control || e.shift)
+ {
+ DeselectNode(hoveredNode);
+ }
// Cache double click state, but only act on it in MouseUp - Except ClickCount only works in mouseDown.
- isDoubleClick = (e.clickCount == 2);
+ isDoubleClick = e.clickCount == 2;
e.Use();
currentActivity = NodeActivity.HoldNode;
- } else if (IsHoveringReroute) {
+ }
+ else if (IsHoveringReroute)
+ {
// If reroute isn't selected
- if (!selectedReroutes.Contains(hoveredReroute)) {
+ if (!selectedReroutes.Contains(hoveredReroute))
+ {
// Add it
- if (e.control || e.shift) selectedReroutes.Add(hoveredReroute);
+ if (e.control || e.shift)
+ {
+ selectedReroutes.Add(hoveredReroute);
+ }
// Select it
- else {
- selectedReroutes = new List() { hoveredReroute };
+ else
+ {
+ selectedReroutes = new List { hoveredReroute };
Selection.activeObject = null;
}
-
}
// Deselect
- else if (e.control || e.shift) selectedReroutes.Remove(hoveredReroute);
+ else if (e.control || e.shift)
+ {
+ selectedReroutes.Remove(hoveredReroute);
+ }
+
e.Use();
currentActivity = NodeActivity.HoldNode;
}
// If mousedown on grid background, deselect all
- else if (!IsHoveringNode) {
+ else if (!IsHoveringNode)
+ {
currentActivity = NodeActivity.HoldGrid;
- if (!e.control && !e.shift) {
+ if (!e.control && !e.shift)
+ {
selectedReroutes.Clear();
Selection.activeObject = null;
}
}
}
+
break;
case EventType.MouseUp:
- if (e.button == 0) {
+ if (e.button == 0)
+ {
//Port drag release
- if (IsDraggingPort) {
+ if (IsDraggingPort)
+ {
// If connection is valid, save it
- if (draggedOutputTarget != null && graphEditor.CanConnect(draggedOutput, draggedOutputTarget)) {
+ if (draggedOutputTarget != null &&
+ graphEditor.CanConnect(draggedOutput, draggedOutputTarget))
+ {
Node node = draggedOutputTarget.node;
- if (graph.nodes.Count != 0) draggedOutput.Connect(draggedOutputTarget);
+ if (graph.nodes.Count != 0)
+ {
+ draggedOutput.Connect(draggedOutputTarget);
+ }
// ConnectionIndex can be -1 if the connection is removed instantly after creation
int connectionIndex = draggedOutput.GetConnectionIndex(draggedOutputTarget);
- if (connectionIndex != -1) {
+ if (connectionIndex != -1)
+ {
draggedOutput.GetReroutePoints(connectionIndex).AddRange(draggedOutputReroutes);
- if (NodeEditor.onUpdateNode != null) NodeEditor.onUpdateNode(node);
+ if (NodeEditor.onUpdateNode != null)
+ {
+ NodeEditor.onUpdateNode(node);
+ }
+
EditorUtility.SetDirty(graph);
}
}
// Open context menu for auto-connection if there is no target node
- else if (draggedOutputTarget == null && NodeEditorPreferences.GetSettings().dragToCreate && autoConnectOutput != null) {
+ else if (draggedOutputTarget == null && NodeEditorPreferences.GetSettings().dragToCreate &&
+ autoConnectOutput != null)
+ {
GenericMenu menu = new GenericMenu();
graphEditor.AddContextMenuItems(menu, draggedOutput.ValueType);
menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
}
+
//Release dragged connection
draggedOutput = null;
draggedOutputTarget = null;
EditorUtility.SetDirty(graph);
- if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
- } else if (currentActivity == NodeActivity.DragNode) {
- IEnumerable nodes = Selection.objects.Where(x => x is Node).Select(x => x as Node);
- foreach (Node node in nodes) EditorUtility.SetDirty(node);
- if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
- } else if (!IsHoveringNode) {
+ if (NodeEditorPreferences.GetSettings().autoSave)
+ {
+ AssetDatabase.SaveAssets();
+ }
+ }
+ else if (currentActivity == NodeActivity.DragNode)
+ {
+ var nodes = Selection.objects.Where(x => x is Node).Select(x => x as Node);
+ foreach (Node node in nodes)
+ {
+ EditorUtility.SetDirty(node);
+ }
+
+ if (NodeEditorPreferences.GetSettings().autoSave)
+ {
+ AssetDatabase.SaveAssets();
+ }
+ }
+ else if (!IsHoveringNode)
+ {
// If click outside node, release field focus
- if (!isPanning) {
+ if (!isPanning)
+ {
EditorGUI.FocusTextInControl(null);
EditorGUIUtility.editingTextField = false;
}
- if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
+
+ if (NodeEditorPreferences.GetSettings().autoSave)
+ {
+ AssetDatabase.SaveAssets();
+ }
}
// If click node header, select it.
- if (currentActivity == NodeActivity.HoldNode && !(e.control || e.shift)) {
+ if (currentActivity == NodeActivity.HoldNode && !(e.control || e.shift))
+ {
selectedReroutes.Clear();
SelectNode(hoveredNode, false);
// Double click to center node
- if (isDoubleClick) {
- Vector2 nodeDimension = nodeSizes.ContainsKey(hoveredNode) ? nodeSizes[hoveredNode] / 2 : Vector2.zero;
+ if (isDoubleClick)
+ {
+ Vector2 nodeDimension = nodeSizes.ContainsKey(hoveredNode)
+ ? nodeSizes[hoveredNode] / 2
+ : Vector2.zero;
panOffset = -hoveredNode.position - nodeDimension;
}
}
// If click reroute, select it.
- if (IsHoveringReroute && !(e.control || e.shift)) {
- selectedReroutes = new List() { hoveredReroute };
+ if (IsHoveringReroute && !(e.control || e.shift))
+ {
+ selectedReroutes = new List { hoveredReroute };
Selection.activeObject = null;
}
Repaint();
currentActivity = NodeActivity.Idle;
- } else if (e.button == 1 || e.button == 2) {
- if (!isPanning) {
- if (IsDraggingPort) {
+ }
+ else if (e.button == 1 || e.button == 2)
+ {
+ if (!isPanning)
+ {
+ if (IsDraggingPort)
+ {
draggedOutputReroutes.Add(WindowToGridPosition(e.mousePosition));
- } else if (currentActivity == NodeActivity.DragNode && Selection.activeObject == null && selectedReroutes.Count == 1) {
+ }
+ else if (currentActivity == NodeActivity.DragNode && Selection.activeObject == null &&
+ selectedReroutes.Count == 1)
+ {
selectedReroutes[0].InsertPoint(selectedReroutes[0].GetPoint());
- selectedReroutes[0] = new RerouteReference(selectedReroutes[0].port, selectedReroutes[0].connectionIndex, selectedReroutes[0].pointIndex + 1);
- } else if (IsHoveringReroute) {
+ selectedReroutes[0] = new RerouteReference(selectedReroutes[0].port,
+ selectedReroutes[0].connectionIndex, selectedReroutes[0].pointIndex + 1);
+ }
+ else if (IsHoveringReroute)
+ {
ShowRerouteContextMenu(hoveredReroute);
- } else if (IsHoveringPort) {
+ }
+ else if (IsHoveringPort)
+ {
ShowPortContextMenu(hoveredPort);
- } else if (IsHoveringNode && IsHoveringTitle(hoveredNode)) {
- if (!Selection.Contains(hoveredNode)) SelectNode(hoveredNode, false);
+ }
+ else if (IsHoveringNode && IsHoveringTitle(hoveredNode))
+ {
+ if (!Selection.Contains(hoveredNode))
+ {
+ SelectNode(hoveredNode, false);
+ }
+
autoConnectOutput = null;
GenericMenu menu = new GenericMenu();
NodeEditor.GetEditor(hoveredNode, this).AddContextMenuItems(menu);
menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
e.Use(); // Fixes copy/paste context menu appearing in Unity 5.6.6f2 - doesn't occur in 2018.3.2f1 Probably needs to be used in other places.
- } else if (!IsHoveringNode) {
+ }
+ else if (!IsHoveringNode)
+ {
autoConnectOutput = null;
GenericMenu menu = new GenericMenu();
graphEditor.AddContextMenuItems(menu);
menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
}
}
+
isPanning = false;
}
+
// Reset DoubleClick
isDoubleClick = false;
break;
case EventType.KeyDown:
- if (EditorGUIUtility.editingTextField || GUIUtility.keyboardControl != 0) break;
- else if (e.keyCode == KeyCode.F) Home();
- if (NodeEditorUtilities.IsMac()) {
- if (e.keyCode == KeyCode.Return) RenameSelectedNode();
- } else {
- if (e.keyCode == KeyCode.F2) RenameSelectedNode();
+ if (EditorGUIUtility.editingTextField || GUIUtility.keyboardControl != 0)
+ {
+ break;
}
- if (e.keyCode == KeyCode.A) {
- if (Selection.objects.Any(x => graph.nodes.Contains(x as Node))) {
- foreach (Node node in graph.nodes) {
+
+ if (e.keyCode == KeyCode.F)
+ {
+ Home();
+ }
+
+ if (NodeEditorUtilities.IsMac())
+ {
+ if (e.keyCode == KeyCode.Return)
+ {
+ RenameSelectedNode();
+ }
+ }
+ else
+ {
+ if (e.keyCode == KeyCode.F2)
+ {
+ RenameSelectedNode();
+ }
+ }
+
+ if (e.keyCode == KeyCode.A)
+ {
+ if (Selection.objects.Any(x => graph.nodes.Contains(x as Node)))
+ {
+ foreach (Node node in graph.nodes)
+ {
DeselectNode(node);
}
- } else {
- foreach (Node node in graph.nodes) {
+ }
+ else
+ {
+ foreach (Node node in graph.nodes)
+ {
SelectNode(node, true);
}
}
+
Repaint();
}
+
break;
case EventType.ValidateCommand:
case EventType.ExecuteCommand:
- if (e.commandName == "SoftDelete") {
- if (e.type == EventType.ExecuteCommand) RemoveSelectedNodes();
- e.Use();
- } else if (NodeEditorUtilities.IsMac() && e.commandName == "Delete") {
- if (e.type == EventType.ExecuteCommand) RemoveSelectedNodes();
- e.Use();
- } else if (e.commandName == "Duplicate") {
- if (e.type == EventType.ExecuteCommand) DuplicateSelectedNodes();
- e.Use();
- } else if (e.commandName == "Copy") {
- if (!EditorGUIUtility.editingTextField) {
- if (e.type == EventType.ExecuteCommand) CopySelectedNodes();
- e.Use();
+ if (e.commandName == "SoftDelete")
+ {
+ if (e.type == EventType.ExecuteCommand)
+ {
+ RemoveSelectedNodes();
}
- } else if (e.commandName == "Paste") {
- if (!EditorGUIUtility.editingTextField) {
- if (e.type == EventType.ExecuteCommand) PasteNodes(WindowToGridPosition(lastMousePosition));
+
+ e.Use();
+ }
+ else if (NodeEditorUtilities.IsMac() && e.commandName == "Delete")
+ {
+ if (e.type == EventType.ExecuteCommand)
+ {
+ RemoveSelectedNodes();
+ }
+
+ e.Use();
+ }
+ else if (e.commandName == "Duplicate")
+ {
+ if (e.type == EventType.ExecuteCommand)
+ {
+ DuplicateSelectedNodes();
+ }
+
+ e.Use();
+ }
+ else if (e.commandName == "Copy")
+ {
+ if (!EditorGUIUtility.editingTextField)
+ {
+ if (e.type == EventType.ExecuteCommand)
+ {
+ CopySelectedNodes();
+ }
+
e.Use();
}
}
+ else if (e.commandName == "Paste")
+ {
+ if (!EditorGUIUtility.editingTextField)
+ {
+ if (e.type == EventType.ExecuteCommand)
+ {
+ PasteNodes(WindowToGridPosition(lastMousePosition));
+ }
+
+ e.Use();
+ }
+ }
+
Repaint();
break;
case EventType.Ignore:
// If release mouse outside window
- if (e.rawType == EventType.MouseUp && currentActivity == NodeActivity.DragGrid) {
+ if (e.rawType == EventType.MouseUp && currentActivity == NodeActivity.DragGrid)
+ {
Repaint();
currentActivity = NodeActivity.Idle;
}
+
break;
}
}
- private void RecalculateDragOffsets(Event current) {
+ private void RecalculateDragOffsets(Event current)
+ {
dragOffset = new Vector2[Selection.objects.Length + selectedReroutes.Count];
// Selected nodes
- for (int i = 0; i < Selection.objects.Length; i++) {
- if (Selection.objects[i] is Node) {
+ for (int i = 0; i < Selection.objects.Length; i++)
+ {
+ if (Selection.objects[i] is Node)
+ {
Node node = Selection.objects[i] as Node;
dragOffset[i] = node.position - WindowToGridPosition(current.mousePosition);
}
}
// Selected reroutes
- for (int i = 0; i < selectedReroutes.Count; i++) {
- dragOffset[Selection.objects.Length + i] = selectedReroutes[i].GetPoint() - WindowToGridPosition(current.mousePosition);
+ for (int i = 0; i < selectedReroutes.Count; i++)
+ {
+ dragOffset[Selection.objects.Length + i] =
+ selectedReroutes[i].GetPoint() - WindowToGridPosition(current.mousePosition);
}
}
/// Puts all selected nodes in focus. If no nodes are present, resets view and zoom to to origin
- public void Home() {
+ public void Home()
+ {
var nodes = Selection.objects.Where(o => o is Node).Cast().ToList();
- if (nodes.Count > 0) {
- Vector2 minPos = nodes.Select(x => x.position).Aggregate((x, y) => new Vector2(Mathf.Min(x.x, y.x), Mathf.Min(x.y, y.y)));
- Vector2 maxPos = nodes.Select(x => x.position + (nodeSizes.ContainsKey(x) ? nodeSizes[x] : Vector2.zero)).Aggregate((x, y) => new Vector2(Mathf.Max(x.x, y.x), Mathf.Max(x.y, y.y)));
+ if (nodes.Count > 0)
+ {
+ Vector2 minPos = nodes.Select(x => x.position)
+ .Aggregate((x, y) => new Vector2(Mathf.Min(x.x, y.x), Mathf.Min(x.y, y.y)));
+ Vector2 maxPos = nodes
+ .Select(x => x.position + (nodeSizes.ContainsKey(x) ? nodeSizes[x] : Vector2.zero))
+ .Aggregate((x, y) => new Vector2(Mathf.Max(x.x, y.x), Mathf.Max(x.y, y.y)));
panOffset = -(minPos + (maxPos - minPos) / 2f);
- } else {
+ }
+ else
+ {
zoom = 2;
panOffset = Vector2.zero;
}
}
/// Remove nodes in the graph in Selection.objects
- public void RemoveSelectedNodes() {
+ public void RemoveSelectedNodes()
+ {
// We need to delete reroutes starting at the highest point index to avoid shifting indices
selectedReroutes = selectedReroutes.OrderByDescending(x => x.pointIndex).ToList();
- for (int i = 0; i < selectedReroutes.Count; i++) {
+ for (int i = 0; i < selectedReroutes.Count; i++)
+ {
selectedReroutes[i].RemovePoint();
}
+
selectedReroutes.Clear();
- foreach (UnityEngine.Object item in Selection.objects) {
- if (item is Node) {
+ foreach (Object item in Selection.objects)
+ {
+ if (item is Node)
+ {
Node node = item as Node;
graphEditor.RemoveNode(node);
}
@@ -408,64 +669,93 @@ namespace XNodeEditor {
}
/// Initiate a rename on the currently selected node
- public void RenameSelectedNode() {
- if (Selection.objects.Length == 1 && Selection.activeObject is Node) {
+ public void RenameSelectedNode()
+ {
+ if (Selection.objects.Length == 1 && Selection.activeObject is Node)
+ {
Node node = Selection.activeObject as Node;
Vector2 size;
- if (nodeSizes.TryGetValue(node, out size)) {
+ if (nodeSizes.TryGetValue(node, out size))
+ {
RenamePopup.Show(Selection.activeObject, size.x);
- } else {
+ }
+ else
+ {
RenamePopup.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) {
+ public void MoveNodeToTop(Node node)
+ {
int index;
- while ((index = graph.nodes.IndexOf(node)) != graph.nodes.Count - 1) {
+ while ((index = graph.nodes.IndexOf(node)) != graph.nodes.Count - 1)
+ {
graph.nodes[index] = graph.nodes[index + 1];
graph.nodes[index + 1] = node;
}
}
/// Duplicate selected nodes and select the duplicates
- public void DuplicateSelectedNodes() {
+ public void DuplicateSelectedNodes()
+ {
// Get selected nodes which are part of this graph
- Node[] selectedNodes = Selection.objects.Select(x => x as Node).Where(x => x != null && x.graph == graph).ToArray();
- if (selectedNodes == null || selectedNodes.Length == 0) return;
+ var selectedNodes = Selection.objects.Select(x => x as Node).Where(x => x != null && x.graph == graph)
+ .ToArray();
+ if (selectedNodes == null || selectedNodes.Length == 0)
+ {
+ return;
+ }
+
// Get top left node position
- Vector2 topLeftNode = selectedNodes.Select(x => x.position).Aggregate((x, y) => new Vector2(Mathf.Min(x.x, y.x), Mathf.Min(x.y, y.y)));
+ Vector2 topLeftNode = selectedNodes.Select(x => x.position)
+ .Aggregate((x, y) => new Vector2(Mathf.Min(x.x, y.x), Mathf.Min(x.y, y.y)));
InsertDuplicateNodes(selectedNodes, topLeftNode + new Vector2(30, 30));
}
- public void CopySelectedNodes() {
+ public void CopySelectedNodes()
+ {
copyBuffer = Selection.objects.Select(x => x as Node).Where(x => x != null && x.graph == graph).ToArray();
}
- public void PasteNodes(Vector2 pos) {
+ public void PasteNodes(Vector2 pos)
+ {
InsertDuplicateNodes(copyBuffer, pos);
}
- private void InsertDuplicateNodes(Node[] nodes, Vector2 topLeft) {
- if (nodes == null || nodes.Length == 0) return;
+ private void InsertDuplicateNodes(Node[] nodes, Vector2 topLeft)
+ {
+ if (nodes == null || nodes.Length == 0)
+ {
+ return;
+ }
// Get top-left node
- Vector2 topLeftNode = nodes.Select(x => x.position).Aggregate((x, y) => new Vector2(Mathf.Min(x.x, y.x), Mathf.Min(x.y, y.y)));
+ Vector2 topLeftNode = nodes.Select(x => x.position)
+ .Aggregate((x, y) => new Vector2(Mathf.Min(x.x, y.x), Mathf.Min(x.y, y.y)));
Vector2 offset = topLeft - topLeftNode;
- UnityEngine.Object[] newNodes = new UnityEngine.Object[nodes.Length];
- Dictionary substitutes = new Dictionary();
- for (int i = 0; i < nodes.Length; i++) {
+ var newNodes = new Object[nodes.Length];
+ var substitutes = new Dictionary();
+ for (int i = 0; i < nodes.Length; i++)
+ {
Node srcNode = nodes[i];
- if (srcNode == null) continue;
+ if (srcNode == null)
+ {
+ continue;
+ }
// Check if user is allowed to add more of given node type
Node.DisallowMultipleNodesAttribute disallowAttrib;
Type nodeType = srcNode.GetType();
- if (NodeEditorUtilities.GetAttrib(nodeType, out disallowAttrib)) {
+ if (NodeEditorUtilities.GetAttrib(nodeType, out disallowAttrib))
+ {
int typeCount = graph.nodes.Count(x => x.GetType() == nodeType);
- if (typeCount >= disallowAttrib.max) continue;
+ if (typeCount >= disallowAttrib.max)
+ {
+ continue;
+ }
}
Node newNode = graphEditor.CopyNode(srcNode);
@@ -475,91 +765,141 @@ namespace XNodeEditor {
}
// Walk through the selected nodes again, recreate connections, using the new nodes
- for (int i = 0; i < nodes.Length; i++) {
+ for (int i = 0; i < nodes.Length; i++)
+ {
Node srcNode = nodes[i];
- if (srcNode == null) continue;
- foreach (NodePort port in srcNode.Ports) {
- for (int c = 0; c < port.ConnectionCount; c++) {
+ if (srcNode == null)
+ {
+ continue;
+ }
+
+ foreach (NodePort port in srcNode.Ports)
+ {
+ for (int c = 0; c < port.ConnectionCount; c++)
+ {
NodePort inputPort = port.direction == NodePort.IO.Input ? port : port.GetConnection(c);
NodePort outputPort = port.direction == NodePort.IO.Output ? port : port.GetConnection(c);
Node newNodeIn, newNodeOut;
- if (substitutes.TryGetValue(inputPort.node, out newNodeIn) && substitutes.TryGetValue(outputPort.node, out newNodeOut)) {
+ if (substitutes.TryGetValue(inputPort.node, out newNodeIn) &&
+ substitutes.TryGetValue(outputPort.node, out newNodeOut))
+ {
newNodeIn.UpdatePorts();
newNodeOut.UpdatePorts();
inputPort = newNodeIn.GetInputPort(inputPort.fieldName);
outputPort = newNodeOut.GetOutputPort(outputPort.fieldName);
}
- if (!inputPort.IsConnectedTo(outputPort)) inputPort.Connect(outputPort);
+
+ if (!inputPort.IsConnectedTo(outputPort))
+ {
+ inputPort.Connect(outputPort);
+ }
}
}
}
+
EditorUtility.SetDirty(graph);
// Select the new nodes
Selection.objects = newNodes;
}
/// Draw a connection as we are dragging it
- public void DrawDraggedConnection() {
- if (IsDraggingPort) {
+ public void DrawDraggedConnection()
+ {
+ if (IsDraggingPort)
+ {
Gradient gradient = graphEditor.GetNoodleGradient(draggedOutput, null);
float thickness = graphEditor.GetNoodleThickness(draggedOutput, null);
NoodlePath path = graphEditor.GetNoodlePath(draggedOutput, null);
NoodleStroke stroke = graphEditor.GetNoodleStroke(draggedOutput, null);
Rect fromRect;
- if (!_portConnectionPoints.TryGetValue(draggedOutput, out fromRect)) return;
- List gridPoints = new List();
+ if (!portConnectionPoints.TryGetValue(draggedOutput, out fromRect))
+ {
+ return;
+ }
+
+ var gridPoints = new List();
gridPoints.Add(fromRect.center);
- for (int i = 0; i < draggedOutputReroutes.Count; i++) {
+ for (int i = 0; i < draggedOutputReroutes.Count; i++)
+ {
gridPoints.Add(draggedOutputReroutes[i]);
}
- if (draggedOutputTarget != null) gridPoints.Add(portConnectionPoints[draggedOutputTarget].center);
- else gridPoints.Add(WindowToGridPosition(Event.current.mousePosition));
+
+ if (draggedOutputTarget != null)
+ {
+ gridPoints.Add(portConnectionPoints[draggedOutputTarget].center);
+ }
+ else
+ {
+ gridPoints.Add(WindowToGridPosition(Event.current.mousePosition));
+ }
DrawNoodle(gradient, path, stroke, thickness, gridPoints);
- GUIStyle portStyle = NodeEditorWindow.current.graphEditor.GetPortStyle(draggedOutput);
+ GUIStyle portStyle = current.graphEditor.GetPortStyle(draggedOutput);
Color bgcol = Color.black;
Color frcol = gradient.colorKeys[0].color;
bgcol.a = 0.6f;
frcol.a = 0.6f;
// Loop through reroute points again and draw the points
- for (int i = 0; i < draggedOutputReroutes.Count; i++) {
+ for (int i = 0; i < draggedOutputReroutes.Count; i++)
+ {
// Draw reroute point at position
Rect rect = new Rect(draggedOutputReroutes[i], new Vector2(16, 16));
rect.position = new Vector2(rect.position.x - 8, rect.position.y - 8);
rect = GridToWindowRect(rect);
- NodeEditorGUILayout.DrawPortHandle(rect, bgcol, frcol, portStyle.normal.background, portStyle.active.background);
+ NodeEditorGUILayout.DrawPortHandle(rect, bgcol, frcol, portStyle.normal.background,
+ portStyle.active.background);
}
}
}
- bool IsHoveringTitle(Node node) {
+ private bool IsHoveringTitle(Node node)
+ {
Vector2 mousePos = Event.current.mousePosition;
//Get node position
Vector2 nodePos = GridToWindowPosition(node.position);
float width;
Vector2 size;
- if (nodeSizes.TryGetValue(node, out size)) width = size.x;
- else width = 200;
+ if (nodeSizes.TryGetValue(node, out size))
+ {
+ width = size.x;
+ }
+ else
+ {
+ width = 200;
+ }
+
Rect windowRect = new Rect(nodePos, new Vector2(width / zoom, 30 / zoom));
return windowRect.Contains(mousePos);
}
/// Attempt to connect dragged output to target node
- public void AutoConnect(Node node) {
- if (autoConnectOutput == null) return;
+ public void AutoConnect(Node node)
+ {
+ if (autoConnectOutput == null)
+ {
+ return;
+ }
// Find compatible input port
- NodePort inputPort = node.Ports.FirstOrDefault(x => x.IsInput && graphEditor.CanConnect(autoConnectOutput, x));
- if (inputPort != null) autoConnectOutput.Connect(inputPort);
+ NodePort inputPort =
+ node.Ports.FirstOrDefault(x => x.IsInput && graphEditor.CanConnect(autoConnectOutput, x));
+ if (inputPort != null)
+ {
+ autoConnectOutput.Connect(inputPort);
+ }
// Save changes
EditorUtility.SetDirty(graph);
- if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
+ if (NodeEditorPreferences.GetSettings().autoSave)
+ {
+ AssetDatabase.SaveAssets();
+ }
+
autoConnectOutput = null;
}
}
diff --git a/Scripts/Editor/NodeEditorAssetModProcessor.cs b/Scripts/Editor/NodeEditorAssetModProcessor.cs
index 82472eb..98cfdee 100644
--- a/Scripts/Editor/NodeEditorAssetModProcessor.cs
+++ b/Scripts/Editor/NodeEditorAssetModProcessor.cs
@@ -1,64 +1,98 @@
-using UnityEditor;
-using UnityEngine;
+using System;
using System.IO;
+using UnityEditor;
+using UnityEngine;
+using XNode;
+using Object = UnityEngine.Object;
-namespace XNodeEditor {
+namespace XNodeEditor
+{
/// Deals with modified assets
- class NodeEditorAssetModProcessor : UnityEditor.AssetModificationProcessor {
-
- /// Automatically delete Node sub-assets before deleting their script.
- /// This is important to do, because you can't delete null sub assets.
- /// For another workaround, see: https://gitlab.com/RotaryHeart-UnityShare/subassetmissingscriptdelete
- private static AssetDeleteResult OnWillDeleteAsset (string path, RemoveAssetOptions options) {
+ internal class NodeEditorAssetModProcessor : AssetModificationProcessor
+ {
+ ///
+ /// Automatically delete Node sub-assets before deleting their script.
+ /// This is important to do, because you can't delete null sub assets.
+ ///
+ /// For another workaround, see: https://gitlab.com/RotaryHeart-UnityShare/subassetmissingscriptdelete
+ ///
+ private static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOptions options)
+ {
// Skip processing anything without the .cs extension
- if (Path.GetExtension(path) != ".cs") return AssetDeleteResult.DidNotDelete;
-
+ if (Path.GetExtension(path) != ".cs")
+ {
+ return AssetDeleteResult.DidNotDelete;
+ }
+
// Get the object that is requested for deletion
- UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath (path);
+ Object obj = AssetDatabase.LoadAssetAtPath