From 5d113de554baed378d8c7c64ef44b20ebd177932 Mon Sep 17 00:00:00 2001 From: Thor Brigsted Date: Mon, 22 Jan 2018 18:06:50 +0100 Subject: [PATCH] Added multinode selection --- Scripts/Editor/NodeEditorAction.cs | 87 ++++++++++++++---- Scripts/Editor/NodeEditorGUI.cs | 76 ++++++++++----- Scripts/Editor/NodeEditorResources.cs | 12 ++- Scripts/Editor/NodeEditorWindow.cs | 14 ++- .../Editor/Resources/xnode_node_highlight.png | Bin 0 -> 20433 bytes .../Resources/xnode_node_highlight.png.meta | 87 ++++++++++++++++++ 6 files changed, 228 insertions(+), 48 deletions(-) create mode 100644 Scripts/Editor/Resources/xnode_node_highlight.png create mode 100644 Scripts/Editor/Resources/xnode_node_highlight.png.meta diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs index 409eea8..6d0cc7c 100644 --- a/Scripts/Editor/NodeEditorAction.cs +++ b/Scripts/Editor/NodeEditorAction.cs @@ -6,22 +6,20 @@ namespace XNodeEditor { public partial class NodeEditorWindow { public static bool isPanning { get; private set; } - public static Vector2 dragOffset; + public static Vector2[] dragOffset; - private bool IsDraggingNode { get { return draggedNode != null; } } + //private bool IsDraggingNode { get { return draggedNode != null; } } private bool IsDraggingPort { get { return draggedOutput != null; } } private bool IsHoveringPort { get { return hoveredPort != null; } } private bool IsHoveringNode { get { return hoveredNode != null; } } - private bool HasSelectedNode { get { return selectedNode != null; } } - + public bool CanDragNodeHeader { get; private set; } + public bool DidDragNodeHeader { get; private set; } private XNode.Node hoveredNode = null; - [NonSerialized] private XNode.Node selectedNode = null; - [NonSerialized] private XNode.Node draggedNode = null; + //[NonSerialized] private XNode.Node draggedNode = null; [NonSerialized] private XNode.NodePort hoveredPort = null; [NonSerialized] private XNode.NodePort draggedOutput = null; [NonSerialized] private XNode.NodePort draggedOutputTarget = null; - private Rect nodeRects; public void Controls() { @@ -45,12 +43,18 @@ namespace XNodeEditor { draggedOutputTarget = null; } Repaint(); - } else if (IsDraggingNode) { - draggedNode.position = WindowToGridPosition(e.mousePosition) + dragOffset; - if (NodeEditorPreferences.gridSnap) { - draggedNode.position.x = (Mathf.Round((draggedNode.position.x + 8) / 16) * 16) - 8; - draggedNode.position.y = (Mathf.Round((draggedNode.position.y + 8) / 16) * 16) - 8; + } else if (CanDragNodeHeader) { + for (int i = 0; i < Selection.objects.Length; i++) { + if (Selection.objects[i] is XNode.Node) { + XNode.Node node = Selection.objects[i] as XNode.Node; + node.position = WindowToGridPosition(e.mousePosition) + dragOffset[i]; + if (NodeEditorPreferences.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; + } + } } + DidDragNodeHeader = true; Repaint(); } } else if (e.button == 1 || e.button == 2) { @@ -66,7 +70,11 @@ namespace XNodeEditor { case EventType.MouseDown: Repaint(); if (e.button == 0) { - SelectNode(hoveredNode); + + if (hoveredNode == null) Selection.activeObject = null; + else if (!Selection.Contains(hoveredNode)) SelectNode(hoveredNode, e.control || e.shift); + else if (e.control || e.shift) DeselectNode(hoveredNode); + if (IsHoveringPort) { if (hoveredPort.IsOutput) { draggedOutput = hoveredPort; @@ -82,8 +90,15 @@ namespace XNodeEditor { } } } else if (IsHoveringNode && IsHoveringTitle(hoveredNode)) { - draggedNode = hoveredNode; - dragOffset = hoveredNode.position - WindowToGridPosition(e.mousePosition); + DidDragNodeHeader = false; + CanDragNodeHeader = true; + dragOffset = new Vector2[Selection.objects.Length]; + for (int i = 0; i < dragOffset.Length; i++) { + if (Selection.objects[i] is XNode.Node) { + XNode.Node node = Selection.objects[i] as XNode.Node; + dragOffset[i] = node.position - WindowToGridPosition(e.mousePosition); + } + } } } break; @@ -104,16 +119,22 @@ namespace XNodeEditor { EditorUtility.SetDirty(graph); Repaint(); AssetDatabase.SaveAssets(); - } else if (IsDraggingNode) { - draggedNode = null; + } else if (CanDragNodeHeader) { + CanDragNodeHeader = false; AssetDatabase.SaveAssets(); } else if (GUIUtility.hotControl != 0) { AssetDatabase.SaveAssets(); } + + if (IsHoveringNode && !DidDragNodeHeader && !e.control) { + SelectNode(hoveredNode, false); + Repaint(); + } } else if (e.button == 1) { if (!isPanning) { if (IsHoveringNode && IsHoveringTitle(hoveredNode)) { - ShowNodeContextMenu(hoveredNode); + if (!Selection.Contains(hoveredNode)) SelectNode(hoveredNode,false); + ShowNodeContextMenu(); } else if (!IsHoveringNode) { ShowGraphContextMenu(); } @@ -121,6 +142,11 @@ namespace XNodeEditor { isPanning = false; } break; + case EventType.KeyDown: + if (e.keyCode == KeyCode.Delete) RemoveSelectedNodes(); + else if (e.keyCode == KeyCode.D && e.control) DublicateSelectedNodes(); + Repaint(); + break; } } @@ -136,6 +162,31 @@ namespace XNodeEditor { Repaint(); } + /// Remove nodes in the graph in Selection.objects + public void RemoveSelectedNodes() { + foreach (UnityEngine.Object item in Selection.objects) { + if (item is XNode.Node) { + XNode.Node node = item as XNode.Node; + graph.RemoveNode(node); + } + } + } + + // Dublicate selected nodes and select the dublicates + public void DublicateSelectedNodes() { + UnityEngine.Object[] newNodes = new UnityEngine.Object[Selection.objects.Length]; + for (int i = 0; i < Selection.objects.Length; i++) { + if (Selection.objects[i] is XNode.Node) { + XNode.Node node = Selection.objects[i] as XNode.Node; + if (node.graph != graph) continue; // ignore nodes selected in another graph + XNode.Node n = graph.CopyNode(node); + n.position = node.position + new Vector2(30, 30); + newNodes[i] = n; + } + } + Selection.objects = newNodes; + } + /// Draw a connection as we are dragging it public void DrawDraggedConnection() { if (IsDraggingPort) { diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs index f8ab6d5..0153965 100644 --- a/Scripts/Editor/NodeEditorGUI.cs +++ b/Scripts/Editor/NodeEditorGUI.cs @@ -6,7 +6,8 @@ using UnityEngine; namespace XNodeEditor { /// Contains GUI methods public partial class NodeEditorWindow { - NodeGraphEditor currentGraphEditor; + private NodeGraphEditor currentGraphEditor; + private List selectionCache; private void OnGUI() { Event e = Event.current; @@ -74,23 +75,30 @@ namespace XNodeEditor { return GUILayout.Button(name, EditorStyles.toolbarDropDown, GUILayout.Width(width)); } - /// Show right-click context menu for a node - public void ShowNodeContextMenu(XNode.Node node) { + /// Show right-click context menu for selected nodes + public void ShowNodeContextMenu() { GenericMenu contextMenu = new GenericMenu(); - contextMenu.AddItem(new GUIContent("Move To Top"), false, () => { - int index; - while ((index = graph.nodes.IndexOf(node)) != graph.nodes.Count - 1) { - graph.nodes[index] = graph.nodes[index + 1]; - graph.nodes[index + 1] = node; - } - }); - contextMenu.AddItem(new GUIContent("Duplicate"), false, () => { - XNode.Node n = graph.CopyNode(node); - n.position = node.position + new Vector2(30, 30); - }); - contextMenu.AddItem(new GUIContent("Remove"), false, () => graph.RemoveNode(node)); + // If only one node is selected + if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { + XNode.Node node = Selection.activeObject as XNode.Node; + contextMenu.AddItem(new GUIContent("Move To Top"), false, () => { + int index; + while ((index = graph.nodes.IndexOf(node)) != graph.nodes.Count - 1) { + graph.nodes[index] = graph.nodes[index + 1]; + graph.nodes[index + 1] = node; + } + }); + } + + contextMenu.AddItem(new GUIContent("Duplicate"), false, DublicateSelectedNodes); + contextMenu.AddItem(new GUIContent("Remove"), false, RemoveSelectedNodes); + + // If only one node is selected + if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) { + XNode.Node node = Selection.activeObject as XNode.Node; + AddCustomContextMenuItems(contextMenu, node); + } - AddCustomContextMenuItems(contextMenu, node); contextMenu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); } @@ -168,17 +176,20 @@ namespace XNodeEditor { private void DrawNodes() { Event e = Event.current; + if (e.type == EventType.Layout) { + selectionCache = new List(Selection.objects); + } if (e.type == EventType.Repaint) { portConnectionPoints.Clear(); nodeWidths.Clear(); } - //Selected node is hashed before and after node GUI to detect changes + //Active node is hashed before and after node GUI to detect changes int nodeHash = 0; System.Reflection.MethodInfo onValidate = null; - if (selectedNode != null) { - onValidate = selectedNode.GetType().GetMethod("OnValidate"); - if (onValidate != null) nodeHash = selectedNode.GetHashCode(); + if (Selection.activeObject != null && Selection.activeObject is XNode.Node) { + onValidate = Selection.activeObject.GetType().GetMethod("OnValidate"); + if (onValidate != null) nodeHash = Selection.activeObject.GetHashCode(); } BeginZoomed(position, zoom); @@ -206,9 +217,23 @@ namespace XNodeEditor { GUILayout.BeginArea(new Rect(nodePos, new Vector2(nodeEditor.GetWidth(), 4000))); - GUIStyle style = NodeEditorResources.styles.nodeBody; - GUI.color = nodeEditor.GetTint(); - GUILayout.BeginVertical(new GUIStyle(style)); + bool selected = selectionCache.Contains(graph.nodes[n]); + + if (selected) { + GUIStyle style = new GUIStyle(NodeEditorResources.styles.nodeBody); + GUIStyle highlightStyle = new GUIStyle(NodeEditorResources.styles.nodeHighlight); + highlightStyle.padding = style.padding; + style.padding = new RectOffset(); + GUI.color = nodeEditor.GetTint(); + GUILayout.BeginVertical(new GUIStyle(style)); + GUI.color = Color.white; + GUILayout.BeginVertical(new GUIStyle(highlightStyle)); + } else { + GUIStyle style = NodeEditorResources.styles.nodeBody; + GUI.color = nodeEditor.GetTint(); + GUILayout.BeginVertical(new GUIStyle(style)); + } + GUI.color = guiColor; EditorGUI.BeginChangeCheck(); @@ -235,6 +260,7 @@ namespace XNodeEditor { } GUILayout.EndVertical(); + if (selected) GUILayout.EndVertical(); if (e.type != EventType.Layout) { //Check if we are hovering this node @@ -267,8 +293,8 @@ namespace XNodeEditor { //If a change in hash is detected in the selected node, call OnValidate method. //This is done through reflection because OnValidate is only relevant in editor, //and thus, the code should not be included in build. - if (selectedNode != null) { - if (onValidate != null && nodeHash != selectedNode.GetHashCode()) onValidate.Invoke(selectedNode, null); + if (nodeHash != 0) { + if (onValidate != null && nodeHash != Selection.activeObject.GetHashCode()) onValidate.Invoke(Selection.activeObject, null); } } diff --git a/Scripts/Editor/NodeEditorResources.cs b/Scripts/Editor/NodeEditorResources.cs index 490743b..9b55c8f 100644 --- a/Scripts/Editor/NodeEditorResources.cs +++ b/Scripts/Editor/NodeEditorResources.cs @@ -9,13 +9,15 @@ namespace XNodeEditor { private static Texture2D _dotOuter; public static Texture2D nodeBody { get { return _nodeBody != null ? _nodeBody : _nodeBody = Resources.Load("xnode_node"); } } private static Texture2D _nodeBody; + public static Texture2D nodeHighlight { get { return _nodeHighlight != null ? _nodeHighlight : _nodeHighlight = Resources.Load("xnode_node_highlight"); } } + private static Texture2D _nodeHighlight; // Styles public static Styles styles { get { return _styles != null ? _styles : _styles = new Styles(); } } public static Styles _styles = null; public class Styles { - public GUIStyle inputPort, outputPort, nodeHeader, nodeBody, tooltip; + public GUIStyle inputPort, outputPort, nodeHeader, nodeBody, tooltip, nodeHighlight; public Styles() { GUIStyle baseStyle = new GUIStyle("Label"); @@ -39,6 +41,10 @@ namespace XNodeEditor { nodeBody.border = new RectOffset(32, 32, 32, 32); nodeBody.padding = new RectOffset(16, 16, 4, 16); + nodeHighlight = new GUIStyle(); + nodeHighlight.normal.background = NodeEditorResources.nodeHighlight; + nodeHighlight.border = new RectOffset(32, 32, 32, 32); + tooltip = new GUIStyle("helpBox"); tooltip.alignment = TextAnchor.MiddleCenter; } @@ -50,8 +56,8 @@ namespace XNodeEditor { for (int y = 0; y < 64; y++) { for (int x = 0; x < 64; x++) { Color col = bg; - if (y % 16 == 0 || x % 16 == 0) col = Color.Lerp(line,bg,0.65f); - if (y == 63 || x == 63) col = Color.Lerp(line,bg,0.35f); + if (y % 16 == 0 || x % 16 == 0) col = Color.Lerp(line, bg, 0.65f); + if (y == 63 || x == 63) col = Color.Lerp(line, bg, 0.35f); cols[(y * 64) + x] = col; } } diff --git a/Scripts/Editor/NodeEditorWindow.cs b/Scripts/Editor/NodeEditorWindow.cs index 3c79e71..7761a8f 100644 --- a/Scripts/Editor/NodeEditorWindow.cs +++ b/Scripts/Editor/NodeEditorWindow.cs @@ -77,8 +77,18 @@ namespace XNodeEditor { return new Vector2(xOffset, yOffset); } - public void SelectNode(XNode.Node node) { - selectedNode = node; + public void SelectNode(XNode.Node node, bool add) { + if (add) { + List selection = new List(Selection.objects); + selection.Add(node); + Selection.objects = selection.ToArray(); + } else Selection.activeObject = node; + } + + public void DeselectNode(XNode.Node node) { + List selection = new List(Selection.objects); + selection.Remove(node); + Selection.objects = selection.ToArray(); } [OnOpenAsset(0)] diff --git a/Scripts/Editor/Resources/xnode_node_highlight.png b/Scripts/Editor/Resources/xnode_node_highlight.png new file mode 100644 index 0000000000000000000000000000000000000000..f1bb27f7ff99d83ad32c177e417bab7884ea956e GIT binary patch literal 20433 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 MSz%pd<+tsB0L%jEQ~&?~ literal 0 HcmV?d00001 diff --git a/Scripts/Editor/Resources/xnode_node_highlight.png.meta b/Scripts/Editor/Resources/xnode_node_highlight.png.meta new file mode 100644 index 0000000..21b6034 --- /dev/null +++ b/Scripts/Editor/Resources/xnode_node_highlight.png.meta @@ -0,0 +1,87 @@ +fileFormatVersion: 2 +guid: 2ab2b92d7e1771b47bba0a46a6f0f6d5 +timeCreated: 1516610730 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapU: 1 + wrapV: 1 + wrapW: -1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: