From 4730f6a0df4c53de3dbcc10f62ad472c9f2a2540 Mon Sep 17 00:00:00 2001 From: Jeroen van de Haterd Date: Thu, 10 Jan 2019 21:15:23 +0100 Subject: [PATCH] Added comments --- Scripts/Editor/NodeEditorAction.cs | 115 +++++++++++- Scripts/Editor/NodeEditorGUI.cs | 171 +++++++++++++++++- Scripts/Editor/NodeEditorResources.cs | 17 +- Scripts/Editor/NodeEditorWindow.cs | 40 ++++ Scripts/Editor/NodeGraphEditor.cs | 57 ++++++ Scripts/Editor/Resources/xnode_comment.png | Bin 0 -> 999 bytes .../Editor/Resources/xnode_comment.png.meta | 98 ++++++++++ .../Resources/xnode_node_comment_workfile.psd | Bin 0 -> 34708 bytes .../xnode_node_comment_workfile.psd.meta | 88 +++++++++ Scripts/NodeGraph.cs | 26 +++ Scripts/NodeGraphComment.cs | 14 ++ Scripts/NodeGraphComment.cs.meta | 11 ++ 12 files changed, 628 insertions(+), 9 deletions(-) create mode 100644 Scripts/Editor/Resources/xnode_comment.png create mode 100644 Scripts/Editor/Resources/xnode_comment.png.meta create mode 100644 Scripts/Editor/Resources/xnode_node_comment_workfile.psd create mode 100644 Scripts/Editor/Resources/xnode_node_comment_workfile.psd.meta create mode 100644 Scripts/NodeGraphComment.cs create mode 100644 Scripts/NodeGraphComment.cs.meta diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs index f3ebde4..9424155 100644 --- a/Scripts/Editor/NodeEditorAction.cs +++ b/Scripts/Editor/NodeEditorAction.cs @@ -6,7 +6,7 @@ using UnityEngine; namespace XNodeEditor { public partial class NodeEditorWindow { - public enum NodeActivity { Idle, HoldNode, DragNode, HoldGrid, DragGrid } + public enum NodeActivity { Idle, HoldNode, DragNode, HoldGrid, DragGrid, HoldComment, ResizeComment } public static NodeActivity currentActivity = NodeActivity.Idle; public static bool isPanning { get; private set; } public static Vector2[] dragOffset; @@ -15,11 +15,17 @@ namespace XNodeEditor { private bool IsHoveringPort { get { return hoveredPort != null; } } private bool IsHoveringNode { get { return hoveredNode != null; } } private bool IsHoveringReroute { get { return hoveredReroute.port != null; } } + private bool IsHoveringComment { get { return hoveredComment != null; } } + private bool IsResizingComment { get { return resizingComment != null; } } private XNode.Node hoveredNode = null; [NonSerialized] private XNode.NodePort hoveredPort = null; [NonSerialized] private XNode.NodePort draggedOutput = null; [NonSerialized] private XNode.NodePort draggedOutputTarget = null; [NonSerialized] private List draggedOutputReroutes = new List(); + [NonSerialized] private XNode.NodeGraphComment hoveredComment = null; + [NonSerialized] private XNode.NodeGraphComment resizingComment = null; + public enum NodeGraphCommentSide { Top, TopRight, Right, BottomRight, Bottom, BottomLeft, Left, TopLeft } + public static NodeGraphCommentSide resizingCommentSide; private RerouteReference hoveredReroute = new RerouteReference(); private List selectedReroutes = new List(); private Rect nodeRects; @@ -68,7 +74,7 @@ namespace XNodeEditor { draggedOutputTarget = null; } Repaint(); - } else if (currentActivity == NodeActivity.HoldNode) { + } else if (currentActivity == NodeActivity.HoldNode || currentActivity == NodeActivity.HoldComment) { RecalculateDragOffsets(e); currentActivity = NodeActivity.DragNode; Repaint(); @@ -110,6 +116,15 @@ namespace XNodeEditor { } } } + else if(Selection.objects[i] is XNode.NodeGraphComment) { + XNode.NodeGraphComment comment = Selection.objects[i] as XNode.NodeGraphComment; + Vector2 initial = comment.position; + comment.position = mousePos + dragOffset[i]; + if (gridSnap) { + comment.position.x = (Mathf.Round((comment.position.x + 8) / 16) * 16) - 8; + comment.position.y = (Mathf.Round((comment.position.y + 8) / 16) * 16) - 8; + } + } } // Move selected reroutes with offset for (int i = 0; i < selectedReroutes.Count; i++) { @@ -133,6 +148,44 @@ namespace XNodeEditor { 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 (currentActivity == NodeActivity.ResizeComment) { + switch (resizingCommentSide) { + case NodeGraphCommentSide.Top: + resizingComment.size.y -= e.delta.y; + resizingComment.position.y += e.delta.y; + break; + case NodeGraphCommentSide.TopRight: + resizingComment.size.y -= e.delta.y; + resizingComment.position.y += e.delta.y; + resizingComment.size.x += e.delta.x; + break; + case NodeGraphCommentSide.Right: + resizingComment.size.x += e.delta.x; + break; + case NodeGraphCommentSide.BottomRight: + resizingComment.size += e.delta; + break; + case NodeGraphCommentSide.Bottom: + resizingComment.size.y += e.delta.y; + break; + case NodeGraphCommentSide.BottomLeft: + resizingComment.size.x -= e.delta.x; + resizingComment.position.x += e.delta.x; + resizingComment.size.y += e.delta.y; + break; + case NodeGraphCommentSide.Left: + resizingComment.size.x -= e.delta.x; + resizingComment.position.x += e.delta.x; + break; + case NodeGraphCommentSide.TopLeft: + resizingComment.size.x -= e.delta.x; + resizingComment.position.x += e.delta.x; + resizingComment.size.y -= e.delta.y; + resizingComment.position.y += e.delta.y; + break; + } + Repaint(); } } else if (e.button == 1 || e.button == 2) { @@ -191,8 +244,33 @@ namespace XNodeEditor { e.Use(); currentActivity = NodeActivity.HoldNode; } + else if (IsHoveringComment && !IsHoveringNode) { + if (!Selection.Contains(hoveredComment)) { + if (e.shift) { + SelectComment(hoveredComment, true); + SelectNodesInComment(hoveredComment); + } + else SelectComment(hoveredComment, e.control || e.shift); + } + else if (e.control || e.shift) { + DeselectComment(hoveredComment); + if (e.shift) + { + DeselectNodesInComment(hoveredComment); + } + } else SelectComment(hoveredComment, false); + + e.Use(); + currentActivity = NodeActivity.HoldComment; + } else if (IsResizingComment && !e.control && !e.shift) { + selectedReroutes.Clear(); + Selection.activeObject = null; + + e.Use(); + currentActivity = NodeActivity.ResizeComment; + } // If mousedown on grid background, deselect all - else if (!IsHoveringNode) { + else if (!IsHoveringNode && !IsHoveringComment) { currentActivity = NodeActivity.HoldGrid; if (!e.control && !e.shift) { selectedReroutes.Clear(); @@ -227,7 +305,7 @@ namespace XNodeEditor { IEnumerable nodes = Selection.objects.Where(x => x is XNode.Node).Select(x => x as XNode.Node); foreach (XNode.Node node in nodes) EditorUtility.SetDirty(node); if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); - } else if (!IsHoveringNode) { + } else if (!IsHoveringNode && !IsHoveringComment && !IsResizingComment) { // If click outside node, release field focus if (!isPanning) { EditorGUI.FocusTextInControl(null); @@ -265,6 +343,11 @@ namespace XNodeEditor { GenericMenu menu = new GenericMenu(); NodeEditor.GetEditor(hoveredNode).AddContextMenuItems(menu); menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); + } else if (IsHoveringComment && !IsHoveringNode) { + if (!Selection.Contains(hoveredComment)) SelectComment(hoveredComment, false); + GenericMenu menu = new GenericMenu(); + graphEditor.AddCommentContextMenuItems(menu); + menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero)); } else if (!IsHoveringNode) { GenericMenu menu = new GenericMenu(); graphEditor.AddContextMenuItems(menu); @@ -315,6 +398,11 @@ namespace XNodeEditor { XNode.Node node = Selection.objects[i] as XNode.Node; dragOffset[i] = node.position - WindowToGridPosition(current.mousePosition); } + else if (Selection.objects[i] is XNode.NodeGraphComment) + { + XNode.NodeGraphComment comment = Selection.objects[i] as XNode.NodeGraphComment; + dragOffset[i] = comment.position - WindowToGridPosition(current.mousePosition); + } } // Selected reroutes @@ -342,6 +430,10 @@ namespace XNodeEditor { XNode.Node node = item as XNode.Node; graphEditor.RemoveNode(node); } + else if (item is XNode.NodeGraphComment) { + XNode.NodeGraphComment comment = item as XNode.NodeGraphComment; + graphEditor.RemoveComment(comment); + } } } @@ -353,6 +445,15 @@ namespace XNodeEditor { } } + /// Initiate a rename on the currently selected comment + public void RenameSelectedComment() + { + if (Selection.objects.Length == 1 && Selection.activeObject is XNode.NodeGraphComment) + { + renamingComment = Selection.activeObject as XNode.NodeGraphComment; + } + } + /// Draw this node on top of other nodes by placing it last in the graph.nodes list public void MoveNodeToTop(XNode.Node node) { int index; @@ -374,6 +475,12 @@ namespace XNodeEditor { substitutes.Add(srcNode, newNode); newNode.position = srcNode.position + new Vector2(30, 30); newNodes[i] = newNode; + } else if (Selection.objects[i] is XNode.NodeGraphComment) { + XNode.NodeGraphComment srcComment = Selection.objects[i] as XNode.NodeGraphComment; + if (srcComment.graph != graph) continue; // ignore comments selected in another graph + XNode.NodeGraphComment newComment = graphEditor.CopyComment(srcComment); + newComment.position = srcComment.position + new Vector2(30, 30); + newNodes[i] = newComment; } } diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs index 9f48f0e..9d0663b 100644 --- a/Scripts/Editor/NodeEditorGUI.cs +++ b/Scripts/Editor/NodeEditorGUI.cs @@ -13,6 +13,8 @@ namespace XNodeEditor { private int topPadding { get { return isDocked() ? 19 : 22; } } /// Executed after all other window GUI. Useful if Zoom is ruining your day. Automatically resets after being run. public event Action onLateGUI; + public XNode.NodeGraphComment renamingComment; + public bool renamingStarted = false; private void OnGUI() { Event e = Event.current; @@ -23,7 +25,13 @@ namespace XNodeEditor { Controls(); + if (e.type == EventType.Layout) + { + selectionCache = new List(Selection.objects); + } + DrawGrid(position, zoom, panOffset); + DrawComments(); DrawConnections(); DrawDraggedConnection(); DrawNodes(); @@ -237,9 +245,6 @@ namespace XNodeEditor { private void DrawNodes() { Event e = Event.current; - if (e.type == EventType.Layout) { - selectionCache = new List(Selection.objects); - } //Active node is hashed before and after node GUI to detect changes int nodeHash = 0; @@ -419,5 +424,165 @@ namespace XNodeEditor { Repaint(); } } + + private void DrawComments() + { + Event e = Event.current; + + BeginZoomed(position, zoom, topPadding); + Vector2 mousePos = Event.current.mousePosition; + + if (e.type != EventType.Layout) { + hoveredComment = null; + if (currentActivity != NodeActivity.ResizeComment) resizingComment = null; + } + + List preSelection = preBoxSelection != null ? new List(preBoxSelection) : new List(); + + Vector2 boxStartPos = GridToWindowPositionNoClipped(dragBoxStart); + Vector2 boxSize = mousePos - 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); } + Rect selectionBox = new Rect(boxStartPos, boxSize); + + for (int n = 0; n < graph.comments.Count; n++) { + XNode.NodeGraphComment comment = graph.comments[n]; + if (comment == null) continue; + + Vector2 commentPos = GridToWindowPositionNoClipped(comment.position); + GUILayout.BeginArea(new Rect(commentPos, new Vector2(comment.size.x, comment.size.y))); + + bool selected = selectionCache.Contains(comment); + + if (selected) { + GUIStyle style = new GUIStyle(NodeEditorResources.styles.commentBody); + GUIStyle highlightStyle = new GUIStyle(NodeEditorResources.styles.nodeHighlight); + highlightStyle.padding = style.padding; + style.padding = new RectOffset(); + GUI.color = Color.white; + GUILayout.BeginVertical(style); + GUI.color = NodeEditorPreferences.GetSettings().highlightColor; + GUILayout.BeginVertical(new GUIStyle(highlightStyle)); + } else { + GUIStyle style = new GUIStyle(NodeEditorResources.styles.commentBody); + GUI.color = Color.white; + GUILayout.BeginVertical(style); + } + + if (renamingComment == comment) { + if (Selection.Contains(renamingComment)) { + int controlID = EditorGUIUtility.GetControlID(FocusType.Keyboard) + 1; + if (!renamingStarted) { + EditorGUIUtility.keyboardControl = controlID; + EditorGUIUtility.editingTextField = true; + renamingStarted = true; + } + comment.comment = EditorGUILayout.TextField(comment.comment, NodeEditorResources.styles.commentHeader, GUILayout.Height(26)); + if (!EditorGUIUtility.editingTextField) { + Debug.Log("Finish renaming"); + renamingComment = null; + renamingStarted = false; + } + } + else { + // Selection changed, so stop renaming. + GUILayout.Label(comment.comment, NodeEditorResources.styles.commentHeader, GUILayout.Height(26)); + renamingComment = null; + renamingStarted = false; + } + } else { + GUIStyle blackStyle = new GUIStyle(NodeEditorResources.styles.commentHeader); + blackStyle.normal.textColor = new Color(0.2f, 0.2f, 0.2f); + + GUILayout.Label(comment.comment, blackStyle, GUILayout.Height(26)); + + Rect lastRect = GUILayoutUtility.GetLastRect(); + lastRect.x -= 0.5f; + lastRect.y -= 1; + GUI.Label(lastRect, comment.comment, NodeEditorResources.styles.commentHeader); + } + + + GUILayout.FlexibleSpace(); + + GUILayout.EndVertical(); + + if (selected) GUILayout.EndVertical(); + + if (e.type != EventType.Layout && currentActivity != NodeActivity.ResizeComment) { + //Check if we are hovering this node + Vector2 commentSize = GUILayoutUtility.GetLastRect().size; + Rect windowRect = new Rect(commentPos, commentSize); + + float padding = 12; + + // Resizing areas + // Follows the NodeGraphCommentSide order + Rect[] resizeRects = new[] { + new Rect(padding, 0, commentSize.x - padding * 2, padding), + new Rect(commentSize.x - padding, 0, padding, padding), + new Rect(commentSize.x - padding, padding, padding, commentSize.y - padding * 2), + new Rect(commentSize.x - padding, commentSize.y - padding, padding, padding), + new Rect(padding, commentSize.y - padding, commentSize.x - padding * 2, padding), + new Rect(0, commentSize.y - padding, padding, padding), + new Rect(0, padding, padding, commentSize.y - padding * 2), + new Rect(0, 0, padding, padding), + }; + + // Icons for the resize area list + MouseCursor[] resizeIcons = new[] { + MouseCursor.ResizeVertical, + MouseCursor.ResizeUpRight, + MouseCursor.ResizeHorizontal, + MouseCursor.ResizeUpLeft, + MouseCursor.ResizeVertical, + MouseCursor.ResizeUpRight, + MouseCursor.ResizeHorizontal, + MouseCursor.ResizeUpLeft, + }; + + for (int i = 0; i < resizeRects.Length; i++) { + EditorGUIUtility.AddCursorRect(resizeRects[i], resizeIcons[i]); + + // Transform the locations now to gui space locations + resizeRects[i].position += commentPos; + } + + if (windowRect.Contains(mousePos)) { + //If dragging a selection box, add nodes inside to selection + if (currentActivity == NodeActivity.DragGrid) { + if (windowRect.Overlaps(selectionBox)) preSelection.Add(comment); + } else { + // Check if we should resize or select + bool resizeAreaClicked = false; + for (int i = 0; i < resizeRects.Length; i++) { + if (resizeRects[i].Contains(mousePos)) { + resizingComment = comment; + // i can be cast to NodeGraphCommentSide as resizeRects + // has one element per NodeGraphCommentSide value and + // uses the same order + resizingCommentSide = (NodeGraphCommentSide)i; + resizeAreaClicked = true; + + break; + } + } + + if (!resizeAreaClicked) hoveredComment = comment; + } + } + + //If dragging a selection box, add nodes inside to selection + if (currentActivity == NodeActivity.DragGrid) { + if (windowRect.Overlaps(selectionBox)) preSelection.Add(comment); + } + } + + GUILayout.EndArea(); + } + + if (e.type != EventType.Layout && currentActivity == NodeActivity.DragGrid) Selection.objects = preSelection.ToArray(); + EndZoomed(position, zoom, topPadding); + } } } \ No newline at end of file diff --git a/Scripts/Editor/NodeEditorResources.cs b/Scripts/Editor/NodeEditorResources.cs index 0a84e0a..18e803b 100644 --- a/Scripts/Editor/NodeEditorResources.cs +++ b/Scripts/Editor/NodeEditorResources.cs @@ -12,14 +12,16 @@ namespace XNodeEditor { private static Texture2D _nodeBody; public static Texture2D nodeHighlight { get { return _nodeHighlight != null ? _nodeHighlight : _nodeHighlight = Resources.Load("xnode_node_highlight"); } } private static Texture2D _nodeHighlight; + public static Texture2D commentBody { get { return _commentBody != null ? _commentBody : _commentBody = Resources.Load("xnode_comment"); } } + private static Texture2D _commentBody; // Styles public static Styles styles { get { return _styles != null ? _styles : _styles = new Styles(); } } public static Styles _styles = null; public static GUIStyle OutputPort { get { return new GUIStyle(EditorStyles.label) { alignment = TextAnchor.UpperRight }; } } public class Styles { - public GUIStyle inputPort, nodeHeader, nodeBody, tooltip, nodeHighlight; - + public GUIStyle inputPort, nodeHeader, nodeBody, tooltip, nodeHighlight, commentHeader, commentBody; + public Styles() { GUIStyle baseStyle = new GUIStyle("Label"); baseStyle.fixedHeight = 18; @@ -44,6 +46,17 @@ namespace XNodeEditor { tooltip = new GUIStyle("helpBox"); tooltip.alignment = TextAnchor.MiddleCenter; + + commentHeader = new GUIStyle(); + commentHeader.alignment = TextAnchor.MiddleCenter; + commentHeader.fontStyle = FontStyle.Bold; + commentHeader.fontSize = 20; + commentHeader.normal.textColor = new Color(0.93f, 0.93f, 0.93f); + + commentBody = new GUIStyle(); + commentBody.normal.background = NodeEditorResources.commentBody; + commentBody.border = new RectOffset(32, 32, 32, 32); + commentBody.padding = new RectOffset(16, 16, 4, 16); } } diff --git a/Scripts/Editor/NodeEditorWindow.cs b/Scripts/Editor/NodeEditorWindow.cs index 72fd4ce..829377b 100644 --- a/Scripts/Editor/NodeEditorWindow.cs +++ b/Scripts/Editor/NodeEditorWindow.cs @@ -142,6 +142,46 @@ namespace XNodeEditor { Selection.objects = selection.ToArray(); } + public void SelectComment(XNode.NodeGraphComment comment, bool add) { + if (add) { + List selection = new List(Selection.objects); + selection.Add(comment); + Selection.objects = selection.ToArray(); + } else Selection.objects = new Object[] { comment }; + } + + public void DeselectComment(XNode.NodeGraphComment comment) { + List selection = new List(Selection.objects); + selection.Remove(comment); + Selection.objects = selection.ToArray(); + } + + public void SelectNodesInComment(XNode.NodeGraphComment comment) { + Rect commentRect = new Rect(comment.position, comment.size); + for (int i = 0; i < graph.nodes.Count; i++) { + XNode.Node node = graph.nodes[i]; + if (!node) continue; + + if (commentRect.Contains(node.position)) SelectNode(node, true); + } + } + + public void DeselectNodesInComment(XNode.NodeGraphComment comment) + { + List selection = new List(Selection.objects); + + + Rect commentRect = new Rect(comment.position, comment.size); + for (int i = 0; i < graph.nodes.Count; i++) { + XNode.Node node = graph.nodes[i]; + if (!node) continue; + + if (commentRect.Contains(node.position)) selection.Remove(node); + } + + Selection.objects = selection.ToArray(); + } + [OnOpenAsset(0)] public static bool OnOpen(int instanceID, int line) { XNode.NodeGraph nodeGraph = EditorUtility.InstanceIDToObject(instanceID) as XNode.NodeGraph; diff --git a/Scripts/Editor/NodeGraphEditor.cs b/Scripts/Editor/NodeGraphEditor.cs index 20f5657..db76c51 100644 --- a/Scripts/Editor/NodeGraphEditor.cs +++ b/Scripts/Editor/NodeGraphEditor.cs @@ -53,10 +53,41 @@ namespace XNodeEditor { }); } menu.AddSeparator(""); + menu.AddItem(new GUIContent("Add comment"), false, () => CreateComment(pos)); + menu.AddSeparator(""); menu.AddItem(new GUIContent("Preferences"), false, () => NodeEditorWindow.OpenPreferences()); NodeEditorWindow.AddCustomContextMenuItems(menu, target); } + /// Add items for the context menu when right-clicking this node. Override to add custom menu items. + public virtual void AddCommentContextMenuItems(GenericMenu menu) { + Vector2 pos = NodeEditorWindow.current.WindowToGridPosition(Event.current.mousePosition); + for (int i = 0; i < NodeEditorWindow.nodeTypes.Length; i++) { + Type type = NodeEditorWindow.nodeTypes[i]; + + //Get node context menu path + string path = GetNodeMenuName(type); + if (string.IsNullOrEmpty(path)) continue; + + menu.AddItem(new GUIContent(path), false, () => { + CreateNode(type, pos); + }); + } + + menu.AddSeparator(""); + menu.AddItem(new GUIContent("Add comment"), false, () => CreateComment(pos)); + menu.AddSeparator(""); + // Actions if only one node is selected + if (Selection.objects.Length == 1 && Selection.activeObject is XNode.NodeGraphComment) { + XNode.NodeGraphComment comment = Selection.activeObject as XNode.NodeGraphComment; + menu.AddItem(new GUIContent("Rename"), false, NodeEditorWindow.current.RenameSelectedComment); + } + + // Add actions to any number of selected nodes + menu.AddItem(new GUIContent("Duplicate"), false, NodeEditorWindow.current.DuplicateSelectedNodes); + menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes); + } + public virtual Color GetTypeColor(Type type) { return NodeEditorPreferences.GetTypeColor(type); } @@ -87,6 +118,32 @@ namespace XNodeEditor { if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); } + /// Create a comment and save it in the graph asset + public void CreateComment(Vector2 position) { + XNode.NodeGraphComment comment = target.AddComment(); + comment.position = position; + comment.comment = "New comment"; + AssetDatabase.AddObjectToAsset(comment, target); + if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); + NodeEditorWindow.RepaintAll(); + } + + /// Creates a copy of the original comment in the graph + public XNode.NodeGraphComment CopyComment(XNode.NodeGraphComment original) { + XNode.NodeGraphComment comment = target.CopyComment(original); + comment.name = original.name; + AssetDatabase.AddObjectToAsset(comment, target); + if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); + return comment; + } + + /// Safely remove a comment + public void RemoveComment(XNode.NodeGraphComment comment) { + UnityEngine.Object.DestroyImmediate(comment, true); + target.RemoveComment(comment); + if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets(); + } + [AttributeUsage(AttributeTargets.Class)] public class CustomNodeGraphEditorAttribute : Attribute, XNodeEditor.Internal.NodeEditorBase.INodeEditorAttrib { diff --git a/Scripts/Editor/Resources/xnode_comment.png b/Scripts/Editor/Resources/xnode_comment.png new file mode 100644 index 0000000000000000000000000000000000000000..f9284e3521e962fc08e9f9f9cbaa183ebd8d6769 GIT binary patch literal 999 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=EX7WqAsj$Z!;#Vfxlq$-qD7NjaT1_T%~FmTL#?B##fTlbVtn1;qF|I=qYp9V27CkyKddkcFn zc41~_=4R$FFflMNW0~aUu+1_=<01p=45=BBvm|Fr&SEy~IM2%9u}$Qp)fHzW1_owh zPZ!6KiaBp*+xp*jkU0LoyzaEL(xFbP05J)zi(LDh_Pc0@3MNl4p=~m61oRFlx^YsG>j*pH3+4Gj%@wd|a)cvKt&Mtn4m{g>3!(-01g#XgcJ11|w9Plgx8>SDob&u&=AHT; zfkW?0tW3{;w#&=O*|YxoYkS5yj2wcU5|7jvYtqxx3rkDCHm64VU*?*lwl?hb>u=w_ z&2DaPKF?6c_~OAVmUR}>L$#(JG7;xzFg7;szMAzlc4bHuQvgfC<6ExgBG09wqoc1n zE&QPMc0%T33%|m;x_R<)a&?RadSx^1!7?NKyC$o_F`c9PRvtFsVRn#fXf|Z^c~$@CeuARZ=eDeB z4<-vCxd$Okay(HCr3_hH7+x`4$zZ&~xZ)zy3g&>ttO4u`+_)F;IrNGxxG~S7-R|ie z@oZ&Uy7Q=*YIW#SFYLUOOCA7ucJdKcDWkv@JFA zt^&uLEzZk2A6qas$TLJS`~o_v+F@e^Pwe&F$Z1!(n-W$%XO}(x@=>3y!>naD&p-dX zP@w7Nw!6VH=At~G$|o4Gy{Koz=`IJ^1}WVJD+W`92Q*kcG*zGfsh=tL-r4Z#`WpQU zZ_8%SDVE&+Wz$mb=P}!EzcqGYa=XT>!CEoz`OIaSJck8(Hm(#sATjy)@#D*PykULJ z84(}4yGeyH{_4>Yin!kCF>|J zO<_17;rypMs53wM{`ctW>gxG6=d%^7)CKhC?|g7fRGDGT&6_vxJbU&mXlG2^i4-Ga zCyrna!;?(E&Zb>ne>H3Q?%liZH!FM)6uo~?mi0*YQXdy>T^XMG0-KdWkACmzU-5w9 zV%0)9A-03JyE?c{1v)#r=YM(LzT<-3qC>*$4her&pAfpGqAWbiZL#E2{$C${eG!@= Sd=;2e89ZJ6T-G@yGywn}HK6$b literal 0 HcmV?d00001 diff --git a/Scripts/Editor/Resources/xnode_comment.png.meta b/Scripts/Editor/Resources/xnode_comment.png.meta new file mode 100644 index 0000000..f49a081 --- /dev/null +++ b/Scripts/Editor/Resources/xnode_comment.png.meta @@ -0,0 +1,98 @@ +fileFormatVersion: 2 +guid: 043280fd1ad23004487ead415d2b11dd +timeCreated: 1507454532 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + 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 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Android + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: WebGL + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Editor/Resources/xnode_node_comment_workfile.psd b/Scripts/Editor/Resources/xnode_node_comment_workfile.psd new file mode 100644 index 0000000000000000000000000000000000000000..e439523feaefc1b8e16abb536b7047ca710db44f GIT binary patch literal 34708 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 a0z?9;6P*)sH?Ee7FP(BF& literal 0 HcmV?d00001 diff --git a/Scripts/Editor/Resources/xnode_node_comment_workfile.psd.meta b/Scripts/Editor/Resources/xnode_node_comment_workfile.psd.meta new file mode 100644 index 0000000..930c2e6 --- /dev/null +++ b/Scripts/Editor/Resources/xnode_node_comment_workfile.psd.meta @@ -0,0 +1,88 @@ +fileFormatVersion: 2 +guid: 18f697c0521665f48b9b797ec72852e8 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 7 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + 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 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/NodeGraph.cs b/Scripts/NodeGraph.cs index 6b95fc2..5abf274 100644 --- a/Scripts/NodeGraph.cs +++ b/Scripts/NodeGraph.cs @@ -10,6 +10,9 @@ namespace XNode { /// All nodes in the graph. /// See: [SerializeField] public List nodes = new List(); + /// All comments in the graph. + /// See: + [SerializeField] public List comments = new List(); /// Add a node to the graph by type public T AddNode() where T : Node { @@ -53,6 +56,29 @@ namespace XNode { nodes.Clear(); } + /// Add a comment to the graph + public NodeGraphComment AddComment() { + NodeGraphComment comment = ScriptableObject.CreateInstance(); + comment.graph = this; + comments.Add(comment); + + return comment; + } + + /// Creates a copy of the comment node in the graph + public virtual NodeGraphComment CopyComment(NodeGraphComment original) { + NodeGraphComment comment = ScriptableObject.Instantiate(original); + comment.graph = this; + comments.Add(comment); + return comment; + } + + /// Safely remove a comment + public void RemoveComment(NodeGraphComment comment) { + comments.Remove(comment); + if (Application.isPlaying) Destroy(comment); + } + /// Create a new deep copy of this graph public XNode.NodeGraph Copy() { // Instantiate a new nodegraph instance diff --git a/Scripts/NodeGraphComment.cs b/Scripts/NodeGraphComment.cs new file mode 100644 index 0000000..47ae11b --- /dev/null +++ b/Scripts/NodeGraphComment.cs @@ -0,0 +1,14 @@ +using System; +using UnityEngine; + +namespace XNode +{ + [Serializable] + public class NodeGraphComment : ScriptableObject + { + [SerializeField] public NodeGraph graph; + [SerializeField] public Vector2 position; + [SerializeField] public Vector2 size = new Vector2(200, 300); + [SerializeField] public string comment; + } +} \ No newline at end of file diff --git a/Scripts/NodeGraphComment.cs.meta b/Scripts/NodeGraphComment.cs.meta new file mode 100644 index 0000000..d0f4740 --- /dev/null +++ b/Scripts/NodeGraphComment.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c8a458777eab4f84287de1d8a542972c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: