From d54a03988a644eaa7deedda79d0065e8d9da273e Mon Sep 17 00:00:00 2001
From: Fernando Molon Toigo
<54711579+fernando-toigo-hoplon@users.noreply.github.com>
Date: Fri, 22 Nov 2019 21:47:39 -0300
Subject: [PATCH 01/44] Added virtual GetBodyHighlightStyle (#197)
---
Scripts/Editor/NodeEditor.cs | 6 +++++-
Scripts/Editor/NodeEditorGUI.cs | 4 ++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/Scripts/Editor/NodeEditor.cs b/Scripts/Editor/NodeEditor.cs
index 13440ea..eae80cd 100644
--- a/Scripts/Editor/NodeEditor.cs
+++ b/Scripts/Editor/NodeEditor.cs
@@ -100,6 +100,10 @@ namespace XNodeEditor {
return NodeEditorResources.styles.nodeBody;
}
+ public virtual GUIStyle GetBodyHighlightStyle() {
+ return NodeEditorResources.styles.nodeHighlight;
+ }
+
/// Add items for the context menu when right-clicking this node. Override to add custom menu items.
public virtual void AddContextMenuItems(GenericMenu menu) {
// Actions if only one node is selected
@@ -143,4 +147,4 @@ namespace XNodeEditor {
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs
index c41afd0..74530d8 100644
--- a/Scripts/Editor/NodeEditorGUI.cs
+++ b/Scripts/Editor/NodeEditorGUI.cs
@@ -413,7 +413,7 @@ namespace XNodeEditor {
if (selected) {
GUIStyle style = new GUIStyle(nodeEditor.GetBodyStyle());
- GUIStyle highlightStyle = new GUIStyle(NodeEditorResources.styles.nodeHighlight);
+ GUIStyle highlightStyle = new GUIStyle(nodeEditor.GetBodyHighlightStyle());
highlightStyle.padding = style.padding;
style.padding = new RectOffset();
GUI.color = nodeEditor.GetTint();
@@ -524,4 +524,4 @@ namespace XNodeEditor {
}
}
}
-}
\ No newline at end of file
+}
From 5005b5e4f9b30441ad35f90c604c642d8b95995c Mon Sep 17 00:00:00 2001
From: Andrei <51819874+Tasta@users.noreply.github.com>
Date: Sun, 15 Dec 2019 12:52:22 +0200
Subject: [PATCH 02/44] Made NodeGraphiEditor's OnGui method virtual and
protected, so it can be extended by adding additional content/widgets to be
drawn. (#214)
---
Scripts/Editor/NodeEditorGUI.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
mode change 100644 => 100755 Scripts/Editor/NodeEditorGUI.cs
diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs
old mode 100644
new mode 100755
index 74530d8..358b2e5
--- a/Scripts/Editor/NodeEditorGUI.cs
+++ b/Scripts/Editor/NodeEditorGUI.cs
@@ -17,7 +17,7 @@ namespace XNodeEditor {
public event Action onLateGUI;
private static readonly Vector3[] polyLineTempArray = new Vector3[2];
- private void OnGUI() {
+ protected virtual void OnGUI() {
Event e = Event.current;
Matrix4x4 m = GUI.matrix;
if (graph == null) return;
From ede650c36925316d111e2f8b13eaebb23bf7b0b3 Mon Sep 17 00:00:00 2001
From: Lumos
Date: Sat, 21 Dec 2019 20:33:34 +0100
Subject: [PATCH 03/44] Added a big "edit graph" button to Node and Graph
inspectors. I was very confused that this isn't a thing already.
---
Scripts/Editor/GraphAndNodeEditor.cs | 128 ++++++++++++++++++++++
Scripts/Editor/GraphAndNodeEditor.cs.meta | 11 ++
2 files changed, 139 insertions(+)
create mode 100644 Scripts/Editor/GraphAndNodeEditor.cs
create mode 100644 Scripts/Editor/GraphAndNodeEditor.cs.meta
diff --git a/Scripts/Editor/GraphAndNodeEditor.cs b/Scripts/Editor/GraphAndNodeEditor.cs
new file mode 100644
index 0000000..b2cc1c1
--- /dev/null
+++ b/Scripts/Editor/GraphAndNodeEditor.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEditor;
+using UnityEngine;
+
+namespace XNodeEditor {
+
+ [CustomEditor(typeof(XNode.NodeGraph), true)]
+ public class GlobalGraphEditor : Editor {
+ public override void OnInspectorGUI() {
+ serializedObject.Update();
+
+ var graphObject = serializedObject.targetObject as XNode.NodeGraph;
+
+ var button = GUILayout.Button("Edit graph", GUILayout.Height(40));
+ if (button && graphObject != null) {
+ NodeEditorWindow.Open(graphObject);
+ }
+
+ GUILayout.Space(EditorGUIUtility.singleLineHeight);
+ GUILayout.Label("Raw data", "BoldLabel");
+
+ DrawDefaultInspector();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+
+
+ [CustomEditor(typeof(XNode.Node), true)]
+ public class GlobalNodeEditor : Editor {
+ private SerializedProperty graph;
+
+ private void OnEnable() {
+ graph = serializedObject.FindProperty("graph");
+ }
+
+ public override void OnInspectorGUI() {
+ serializedObject.Update();
+
+ var graphObject = GetTargetObjectOfProperty(graph) as XNode.NodeGraph;
+
+ var button = GUILayout.Button("Edit graph", GUILayout.Height(40));
+ if (button && graphObject != null) {
+ NodeEditorWindow.Open(graphObject);
+ }
+
+ GUILayout.Space(EditorGUIUtility.singleLineHeight);
+ GUILayout.Label("Raw data", "BoldLabel");
+
+ // Now draw the node itself.
+ DrawDefaultInspector();
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+
+
+ // HELPER METHODS BELOW RETRIEVED FROM https://github.com/lordofduct/spacepuppy-unity-framework/blob/master/SpacepuppyBaseEditor/EditorHelper.cs
+ // BASED ON POST https://forum.unity.com/threads/get-a-general-object-value-from-serializedproperty.327098/#post-2309545
+ // AND ADJUSTED SLIGHTLY AFTERWARDS
+
+ ///
+ /// Gets the object the property represents.
+ ///
+ ///
+ ///
+ private static object GetTargetObjectOfProperty(SerializedProperty prop) {
+ if (prop == null) return null;
+
+ var path = prop.propertyPath.Replace(".Array.data[", "[");
+ object obj = prop.serializedObject.targetObject;
+ var elements = path.Split('.');
+ foreach (var element in elements) {
+ if (element.Contains("[")) {
+ var elementName = element.Substring(0, element.IndexOf("[", StringComparison.Ordinal));
+ var index = Convert.ToInt32(element.Substring(element.IndexOf("[", StringComparison.Ordinal))
+ .Replace("[", "")
+ .Replace("]", ""));
+ obj = GetValue_Imp(obj, elementName, index);
+ }
+ else {
+ obj = GetValue_Imp(obj, element);
+ }
+ }
+
+ return obj;
+ }
+
+ private static object GetValue_Imp(object source, string name) {
+ if (source == null)
+ return null;
+ var type = source.GetType();
+
+ while (type != null) {
+ var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
+ if (f != null)
+ return f.GetValue(source);
+
+ var p = type.GetProperty(name,
+ BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
+ if (p != null)
+ return p.GetValue(source, null);
+
+ type = type.BaseType;
+ }
+
+ return null;
+ }
+
+ private static object GetValue_Imp(object source, string name, int index) {
+ if (!(GetValue_Imp(source, name) is IEnumerable enumerable)) return null;
+ var enm = enumerable.GetEnumerator();
+ //while (index-- >= 0)
+ // enm.MoveNext();
+ //return enm.Current;
+
+ for (var i = 0; i <= index; i++) {
+ if (!enm.MoveNext()) return null;
+ }
+
+ return enm.Current;
+ }
+ }
+
+}
diff --git a/Scripts/Editor/GraphAndNodeEditor.cs.meta b/Scripts/Editor/GraphAndNodeEditor.cs.meta
new file mode 100644
index 0000000..5cc60df
--- /dev/null
+++ b/Scripts/Editor/GraphAndNodeEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bdd6e443125ccac4dad0665515759637
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
From 23e369d38fbcf4ce688753c2e89a6694cbd5e75a Mon Sep 17 00:00:00 2001
From: Lumos
Date: Sun, 22 Dec 2019 15:43:25 +0100
Subject: [PATCH 04/44] Fix auto-connection menu opening on invalid connections
where a target node is present
---
Scripts/Editor/NodeEditorAction.cs | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs
index 2581676..9fcc42c 100644
--- a/Scripts/Editor/NodeEditorAction.cs
+++ b/Scripts/Editor/NodeEditorAction.cs
@@ -58,10 +58,9 @@ namespace XNodeEditor {
case EventType.MouseDrag:
if (e.button == 0) {
if (IsDraggingPort) {
- if (IsHoveringPort && hoveredPort.IsInput && draggedOutput.CanConnectTo(hoveredPort)) {
- if (!draggedOutput.IsConnectedTo(hoveredPort)) {
- draggedOutputTarget = hoveredPort;
- }
+ // 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)) {
+ draggedOutputTarget = hoveredPort;
} else {
draggedOutputTarget = null;
}
@@ -205,8 +204,8 @@ namespace XNodeEditor {
if (e.button == 0) {
//Port drag release
if (IsDraggingPort) {
- //If connection is valid, save it
- if (draggedOutputTarget != null) {
+ // If connection is valid, save it
+ if (draggedOutputTarget != null && draggedOutput.CanConnectTo(draggedOutputTarget)) {
XNode.Node node = draggedOutputTarget.node;
if (graph.nodes.Count != 0) draggedOutput.Connect(draggedOutputTarget);
@@ -218,8 +217,8 @@ namespace XNodeEditor {
EditorUtility.SetDirty(graph);
}
}
- // Open context menu for auto-connection
- else if (NodeEditorPreferences.GetSettings().dragToCreate && autoConnectOutput != null) {
+ // Open context menu for auto-connection if there is no target node
+ else if (draggedOutputTarget == null && NodeEditorPreferences.GetSettings().dragToCreate && autoConnectOutput != null) {
GenericMenu menu = new GenericMenu();
graphEditor.AddContextMenuItems(menu);
menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
From 1d43244a8f1f8e0726de608dc862ec50a2fafe3c Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Mon, 23 Dec 2019 13:52:53 +0100
Subject: [PATCH 05/44] Simplified implementation
---
Scripts/Editor/GraphAndNodeEditor.cs | 101 +++------------------------
1 file changed, 10 insertions(+), 91 deletions(-)
diff --git a/Scripts/Editor/GraphAndNodeEditor.cs b/Scripts/Editor/GraphAndNodeEditor.cs
index b2cc1c1..6b4f12d 100644
--- a/Scripts/Editor/GraphAndNodeEditor.cs
+++ b/Scripts/Editor/GraphAndNodeEditor.cs
@@ -6,45 +6,33 @@ using UnityEditor;
using UnityEngine;
namespace XNodeEditor {
-
+ /// Override graph inspector to show an 'Open Graph' button at the top
[CustomEditor(typeof(XNode.NodeGraph), true)]
public class GlobalGraphEditor : Editor {
public override void OnInspectorGUI() {
serializedObject.Update();
- var graphObject = serializedObject.targetObject as XNode.NodeGraph;
-
- var button = GUILayout.Button("Edit graph", GUILayout.Height(40));
- if (button && graphObject != null) {
- NodeEditorWindow.Open(graphObject);
+ if (GUILayout.Button("Edit graph", GUILayout.Height(40))) {
+ NodeEditorWindow.Open(serializedObject.targetObject as XNode.NodeGraph);
}
-
+
GUILayout.Space(EditorGUIUtility.singleLineHeight);
GUILayout.Label("Raw data", "BoldLabel");
DrawDefaultInspector();
-
+
serializedObject.ApplyModifiedProperties();
}
}
-
[CustomEditor(typeof(XNode.Node), true)]
public class GlobalNodeEditor : Editor {
- private SerializedProperty graph;
-
- private void OnEnable() {
- graph = serializedObject.FindProperty("graph");
- }
-
public override void OnInspectorGUI() {
serializedObject.Update();
- var graphObject = GetTargetObjectOfProperty(graph) as XNode.NodeGraph;
-
- var button = GUILayout.Button("Edit graph", GUILayout.Height(40));
- if (button && graphObject != null) {
- NodeEditorWindow.Open(graphObject);
+ if (GUILayout.Button("Edit graph", GUILayout.Height(40))) {
+ SerializedProperty graphProp = serializedObject.FindProperty("graph");
+ NodeEditorWindow.Open(graphProp.objectReferenceValue as XNode.NodeGraph);
}
GUILayout.Space(EditorGUIUtility.singleLineHeight);
@@ -52,77 +40,8 @@ namespace XNodeEditor {
// Now draw the node itself.
DrawDefaultInspector();
-
+
serializedObject.ApplyModifiedProperties();
}
-
-
-
- // HELPER METHODS BELOW RETRIEVED FROM https://github.com/lordofduct/spacepuppy-unity-framework/blob/master/SpacepuppyBaseEditor/EditorHelper.cs
- // BASED ON POST https://forum.unity.com/threads/get-a-general-object-value-from-serializedproperty.327098/#post-2309545
- // AND ADJUSTED SLIGHTLY AFTERWARDS
-
- ///
- /// Gets the object the property represents.
- ///
- ///
- ///
- private static object GetTargetObjectOfProperty(SerializedProperty prop) {
- if (prop == null) return null;
-
- var path = prop.propertyPath.Replace(".Array.data[", "[");
- object obj = prop.serializedObject.targetObject;
- var elements = path.Split('.');
- foreach (var element in elements) {
- if (element.Contains("[")) {
- var elementName = element.Substring(0, element.IndexOf("[", StringComparison.Ordinal));
- var index = Convert.ToInt32(element.Substring(element.IndexOf("[", StringComparison.Ordinal))
- .Replace("[", "")
- .Replace("]", ""));
- obj = GetValue_Imp(obj, elementName, index);
- }
- else {
- obj = GetValue_Imp(obj, element);
- }
- }
-
- return obj;
- }
-
- private static object GetValue_Imp(object source, string name) {
- if (source == null)
- return null;
- var type = source.GetType();
-
- while (type != null) {
- var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
- if (f != null)
- return f.GetValue(source);
-
- var p = type.GetProperty(name,
- BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
- if (p != null)
- return p.GetValue(source, null);
-
- type = type.BaseType;
- }
-
- return null;
- }
-
- private static object GetValue_Imp(object source, string name, int index) {
- if (!(GetValue_Imp(source, name) is IEnumerable enumerable)) return null;
- var enm = enumerable.GetEnumerator();
- //while (index-- >= 0)
- // enm.MoveNext();
- //return enm.Current;
-
- for (var i = 0; i <= index; i++) {
- if (!enm.MoveNext()) return null;
- }
-
- return enm.Current;
- }
}
-
-}
+}
\ No newline at end of file
From 5597e565d124751c0c836d0b44f50644a1249a9c Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Mon, 23 Dec 2019 13:56:49 +0100
Subject: [PATCH 06/44] Added focus selected node
---
Scripts/Editor/GraphAndNodeEditor.cs | 3 ++-
Scripts/Editor/NodeEditorWindow.cs | 5 +++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/Scripts/Editor/GraphAndNodeEditor.cs b/Scripts/Editor/GraphAndNodeEditor.cs
index 6b4f12d..bfc809a 100644
--- a/Scripts/Editor/GraphAndNodeEditor.cs
+++ b/Scripts/Editor/GraphAndNodeEditor.cs
@@ -32,7 +32,8 @@ namespace XNodeEditor {
if (GUILayout.Button("Edit graph", GUILayout.Height(40))) {
SerializedProperty graphProp = serializedObject.FindProperty("graph");
- NodeEditorWindow.Open(graphProp.objectReferenceValue as XNode.NodeGraph);
+ NodeEditorWindow w = NodeEditorWindow.Open(graphProp.objectReferenceValue as XNode.NodeGraph);
+ w.Home(); // Focus selected node
}
GUILayout.Space(EditorGUIUtility.singleLineHeight);
diff --git a/Scripts/Editor/NodeEditorWindow.cs b/Scripts/Editor/NodeEditorWindow.cs
index a063410..1f64653 100644
--- a/Scripts/Editor/NodeEditorWindow.cs
+++ b/Scripts/Editor/NodeEditorWindow.cs
@@ -187,12 +187,13 @@ namespace XNodeEditor {
}
/// Open the provided graph in the NodeEditor
- public static void Open(XNode.NodeGraph graph) {
- if (!graph) return;
+ public static NodeEditorWindow Open(XNode.NodeGraph graph) {
+ if (!graph) return null;
NodeEditorWindow w = GetWindow(typeof(NodeEditorWindow), false, "xNode", true) as NodeEditorWindow;
w.wantsMouseMove = true;
w.graph = graph;
+ return w;
}
/// Repaint all open NodeEditorWindows.
From ad6e441ef282ba16d9455cdc87fe48e1f31a1330 Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Mon, 23 Dec 2019 14:16:48 +0100
Subject: [PATCH 07/44] Update CONTRIBUTING.md
---
CONTRIBUTING.md | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 33da9d3..1aa9501 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,14 +5,21 @@ If you haven't already, join our [Discord channel](https://discord.gg/qgPrHv4)!
## Pull Requests
Try to keep your pull requests relevant, neat, and manageable. If you are adding multiple features, split them into separate PRs.
-* Avoid including irellevant whitespace or formatting changes.
-* Comment your code.
-* Spell check your code / comments
-* Use consistent formatting
+These are the main points to follow:
+
+1) Use formatting which is consistent with the rest of xNode base (see below)
+2) Keep _one feature_ per PR (see below)
+3) xNode aims to be compatible with C# 4.x, do not use new language features
+4) Avoid including irellevant whitespace or formatting changes
+5) Comment your code
+6) Spell check your code / comments
+7) Use english language
## New features
xNode aims to be simple and extendible, not trying to fix all of Unity's shortcomings.
+Approved changes might be rejected if bundled with rejected changes, so keep PRs as separate as possible.
+
If your feature aims to cover something not related to editing nodes, it generally won't be accepted. If in doubt, ask on the Discord channel.
## Coding conventions
From 48bbf309ce929be153e0b36195f0145f0ea9e017 Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Mon, 23 Dec 2019 14:23:14 +0100
Subject: [PATCH 08/44] Update CONTRIBUTING.md
---
CONTRIBUTING.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1aa9501..10d780a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -13,7 +13,8 @@ These are the main points to follow:
4) Avoid including irellevant whitespace or formatting changes
5) Comment your code
6) Spell check your code / comments
-7) Use english language
+7) Use concrete types, not *var*
+8) Use english language
## New features
xNode aims to be simple and extendible, not trying to fix all of Unity's shortcomings.
From e98bd85531201803209cbcf1fa009738d1101ea7 Mon Sep 17 00:00:00 2001
From: Gahwon Lee
Date: Tue, 24 Dec 2019 10:39:36 -0600
Subject: [PATCH 09/44] better odin support in xNode editors
---
Scripts/Editor/GraphAndNodeEditor.cs | 35 ++++++++++++++++++++++++----
Scripts/Editor/NodeEditor.cs | 2 +-
2 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/Scripts/Editor/GraphAndNodeEditor.cs b/Scripts/Editor/GraphAndNodeEditor.cs
index bfc809a..c13f782 100644
--- a/Scripts/Editor/GraphAndNodeEditor.cs
+++ b/Scripts/Editor/GraphAndNodeEditor.cs
@@ -1,13 +1,24 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Reflection;
-using UnityEditor;
+using UnityEditor;
using UnityEngine;
+#if ODIN_INSPECTOR
+using Sirenix.OdinInspector.Editor;
+using Sirenix.Utilities;
+using Sirenix.Utilities.Editor;
+#endif
namespace XNodeEditor {
/// Override graph inspector to show an 'Open Graph' button at the top
[CustomEditor(typeof(XNode.NodeGraph), true)]
+#if ODIN_INSPECTOR
+ 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
public class GlobalGraphEditor : Editor {
public override void OnInspectorGUI() {
serializedObject.Update();
@@ -24,8 +35,21 @@ namespace XNodeEditor {
serializedObject.ApplyModifiedProperties();
}
}
+#endif
[CustomEditor(typeof(XNode.Node), true)]
+#if ODIN_INSPECTOR
+ 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
public class GlobalNodeEditor : Editor {
public override void OnInspectorGUI() {
serializedObject.Update();
@@ -45,4 +69,5 @@ namespace XNodeEditor {
serializedObject.ApplyModifiedProperties();
}
}
+#endif
}
\ No newline at end of file
diff --git a/Scripts/Editor/NodeEditor.cs b/Scripts/Editor/NodeEditor.cs
index eae80cd..b237a21 100644
--- a/Scripts/Editor/NodeEditor.cs
+++ b/Scripts/Editor/NodeEditor.cs
@@ -21,7 +21,7 @@ namespace XNodeEditor {
public readonly static Dictionary portPositions = new Dictionary();
#if ODIN_INSPECTOR
- internal static bool inNodeEditor = false;
+ protected internal static bool inNodeEditor = false;
#endif
public virtual void OnHeaderGUI() {
From b5260923417bb9fffe7f84c82fb4c5731226cfb8 Mon Sep 17 00:00:00 2001
From: Lumos
Date: Thu, 2 Jan 2020 19:48:36 +0100
Subject: [PATCH 10/44] Added a virtual OnRename function to base nodes,
triggered when a node gets renamed. (#225)
---
Scripts/Editor/NodeEditor.cs | 7 ++++++-
Scripts/Editor/RenamePopup.cs | 2 ++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/Scripts/Editor/NodeEditor.cs b/Scripts/Editor/NodeEditor.cs
index b237a21..edf66d6 100644
--- a/Scripts/Editor/NodeEditor.cs
+++ b/Scripts/Editor/NodeEditor.cs
@@ -129,9 +129,14 @@ namespace XNodeEditor {
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() { }
+
+
[AttributeUsage(AttributeTargets.Class)]
public class CustomNodeEditorAttribute : Attribute,
XNodeEditor.Internal.NodeEditorBase.INodeEditorAttrib {
diff --git a/Scripts/Editor/RenamePopup.cs b/Scripts/Editor/RenamePopup.cs
index 564374e..f245d4e 100644
--- a/Scripts/Editor/RenamePopup.cs
+++ b/Scripts/Editor/RenamePopup.cs
@@ -49,6 +49,7 @@ namespace XNodeEditor {
if (input == null || input.Trim() == "") {
if (GUILayout.Button("Revert to default") || (e.isKey && e.keyCode == KeyCode.Return)) {
target.name = NodeEditorUtilities.NodeDefaultName(target.GetType());
+ NodeEditor.GetEditor((XNode.Node)target, NodeEditorWindow.current).OnRename();
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
Close();
target.TriggerOnValidate();
@@ -58,6 +59,7 @@ namespace XNodeEditor {
else {
if (GUILayout.Button("Apply") || (e.isKey && e.keyCode == KeyCode.Return)) {
target.name = input;
+ NodeEditor.GetEditor((XNode.Node)target, NodeEditorWindow.current).OnRename();
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
Close();
target.TriggerOnValidate();
From ac7403b8766b53152e47294d114c594d8cf6acc8 Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Mon, 6 Jan 2020 09:12:58 +0100
Subject: [PATCH 11/44] Removed Allowmultiple from Output and Input attributes
---
Scripts/Node.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Scripts/Node.cs b/Scripts/Node.cs
index a07679a..28e389d 100644
--- a/Scripts/Node.cs
+++ b/Scripts/Node.cs
@@ -262,7 +262,7 @@ namespace XNode {
#region Attributes
/// Mark a serializable field as an input port. You can access this through
- [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
+ [AttributeUsage(AttributeTargets.Field)]
public class InputAttribute : Attribute {
public ShowBackingValue backingValue;
public ConnectionType connectionType;
@@ -285,7 +285,7 @@ namespace XNode {
}
/// Mark a serializable field as an output port. You can access this through
- [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
+ [AttributeUsage(AttributeTargets.Field)]
public class OutputAttribute : Attribute {
public ShowBackingValue backingValue;
public ConnectionType connectionType;
From 7e93ffe4b75a6cab453223d20c5e03f4d7c57f7f Mon Sep 17 00:00:00 2001
From: Lumos
Date: Tue, 21 Jan 2020 07:01:57 +0000
Subject: [PATCH 12/44] Fix for the dynamic port "serialisation desync"
problem. (#223)
* Exclude strings from array types manually to prevent them from being treated as char arrays.
---
Scripts/Editor/NodeEditorAction.cs | 4 +--
Scripts/Editor/NodeEditorGUILayout.cs | 7 +++--
Scripts/Node.cs | 6 ++--
Scripts/NodeDataCache.cs | 43 ++++++++++++++++++++++++++-
Scripts/NodePort.cs | 15 ++++++++--
5 files changed, 64 insertions(+), 11 deletions(-)
diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs
index 9fcc42c..8021a16 100644
--- a/Scripts/Editor/NodeEditorAction.cs
+++ b/Scripts/Editor/NodeEditorAction.cs
@@ -456,8 +456,8 @@ namespace XNodeEditor {
XNode.Node newNodeIn, newNodeOut;
if (substitutes.TryGetValue(inputPort.node, out newNodeIn) && substitutes.TryGetValue(outputPort.node, out newNodeOut)) {
- newNodeIn.UpdateStaticPorts();
- newNodeOut.UpdateStaticPorts();
+ newNodeIn.UpdatePorts();
+ newNodeOut.UpdatePorts();
inputPort = newNodeIn.GetInputPort(inputPort.fieldName);
outputPort = newNodeOut.GetOutputPort(outputPort.fieldName);
}
diff --git a/Scripts/Editor/NodeEditorGUILayout.cs b/Scripts/Editor/NodeEditorGUILayout.cs
index f9333db..0b8a0cd 100644
--- a/Scripts/Editor/NodeEditorGUILayout.cs
+++ b/Scripts/Editor/NodeEditorGUILayout.cs
@@ -312,6 +312,8 @@ namespace XNodeEditor {
}).Where(x => x.port != null);
List dynamicPorts = indexedPorts.OrderBy(x => x.index).Select(x => x.port).ToList();
+ node.UpdatePorts();
+
ReorderableList list = null;
Dictionary rlc;
if (reorderableListCache.TryGetValue(serializedObject.targetObject, out rlc)) {
@@ -326,6 +328,7 @@ namespace XNodeEditor {
}
list.list = dynamicPorts;
list.DoLayoutList();
+
}
private static ReorderableList CreateReorderableList(string fieldName, List dynamicPorts, SerializedProperty arrayData, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.Node.ConnectionType connectionType, XNode.Node.TypeConstraint typeConstraint, Action onCreation) {
@@ -337,7 +340,7 @@ namespace XNodeEditor {
list.drawElementCallback =
(Rect rect, int index, bool isActive, bool isFocused) => {
XNode.NodePort port = node.GetPort(fieldName + " " + index);
- if (hasArrayData) {
+ if (hasArrayData && arrayData.propertyType != SerializedPropertyType.String) {
if (arrayData.arraySize <= index) {
EditorGUI.LabelField(rect, "Array[" + index + "] data out of range");
return;
@@ -465,7 +468,7 @@ namespace XNodeEditor {
EditorUtility.SetDirty(node);
}
- if (hasArrayData) {
+ if (hasArrayData && arrayData.propertyType != SerializedPropertyType.String) {
if (arrayData.arraySize <= index) {
Debug.LogWarning("Attempted to remove array index " + index + " where only " + arrayData.arraySize + " exist - Skipped");
Debug.Log(rl.list[0]);
diff --git a/Scripts/Node.cs b/Scripts/Node.cs
index 28e389d..4103d67 100644
--- a/Scripts/Node.cs
+++ b/Scripts/Node.cs
@@ -119,12 +119,12 @@ namespace XNode {
protected void OnEnable() {
if (graphHotfix != null) graph = graphHotfix;
graphHotfix = null;
- UpdateStaticPorts();
+ UpdatePorts();
Init();
}
- /// Update static ports to reflect class fields. This happens automatically on enable.
- public void UpdateStaticPorts() {
+ /// Update static ports and dynamic ports managed by DynamicPortLists to reflect class fields. This happens automatically on enable or on redrawing a dynamic port list.
+ public void UpdatePorts() {
NodeDataCache.UpdatePorts(this, ports);
}
diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs
index 02e35a1..24458ec 100644
--- a/Scripts/NodeDataCache.cs
+++ b/Scripts/NodeDataCache.cs
@@ -9,7 +9,7 @@ namespace XNode {
private static PortDataCache portDataCache;
private static bool Initialized { get { return portDataCache != null; } }
- /// Update static ports to reflect class fields.
+ /// Update static ports and dynamic ports managed by DynamicPortLists to reflect class fields.
public static void UpdatePorts(Node node, Dictionary ports) {
if (!Initialized) BuildCache();
@@ -17,6 +17,8 @@ namespace XNode {
Dictionary> removedPorts = new Dictionary>();
System.Type nodeType = node.GetType();
+ List dynamicListPorts = new List();
+
List typePortCache;
if (portDataCache.TryGetValue(nodeType, out typePortCache)) {
for (int i = 0; i < typePortCache.Count; i++) {
@@ -25,6 +27,7 @@ namespace XNode {
}
// Cleanup port dict - Remove nonexisting static ports - update static port types
+ // AND update dynamic ports (albeit only those in lists) too, in order to enforce proper serialisation.
// Loop through current node ports
foreach (NodePort port in ports.Values.ToList()) {
// If port still exists, check it it has been changed
@@ -43,6 +46,10 @@ namespace XNode {
port.ClearConnections();
ports.Remove(port.fieldName);
}
+ // If the port is dynamic and is managed by a dynamic port list, flag it for reference updates
+ else if (IsDynamicListPort(port)) {
+ dynamicListPorts.Add(port);
+ }
}
// Add missing ports
foreach (NodePort staticPort in staticPorts.Values) {
@@ -60,8 +67,42 @@ namespace XNode {
ports.Add(staticPort.fieldName, port);
}
}
+
+ // Finally, make sure dynamic list port settings correspond to the settings of their "backing port"
+ foreach (NodePort listPort in dynamicListPorts) {
+ // At this point we know that ports here are dynamic list ports
+ // which have passed name/"backing port" checks, ergo we can proceed more safely.
+ string backingPortName = listPort.fieldName.Split(' ')[0];
+ NodePort backingPort = staticPorts[backingPortName];
+
+ // Update port constraints. Creating a new port instead will break the editor, mandating the need for setters.
+ listPort.ValueType = backingPort.ValueType;
+ listPort.direction = backingPort.direction;
+ listPort.connectionType = backingPort.connectionType;
+ listPort.typeConstraint = backingPort.typeConstraint;
+ }
}
+ /// Returns true if the given port is in a dynamic port list.
+ private static bool IsDynamicListPort(NodePort port) {
+ // Ports flagged as "dynamicPortList = true" end up having a "backing port" and a name with an index, but we have
+ // no guarantee that a dynamic port called "output 0" is an element in a list backed by a static "output" port.
+ // Thus, we need to check for attributes... (but at least we don't need to look at all fields this time)
+ string[] fieldNameParts = port.fieldName.Split(' ');
+ if (fieldNameParts.Length != 2) return false;
+
+ FieldInfo backingPortInfo = port.node.GetType().GetField(fieldNameParts[0]);
+ if (backingPortInfo == null) return false;
+
+ object[] attribs = backingPortInfo.GetCustomAttributes(true);
+ return attribs.Any(x => {
+ Node.InputAttribute inputAttribute = x as Node.InputAttribute;
+ Node.OutputAttribute outputAttribute = x as Node.OutputAttribute;
+ return inputAttribute != null && inputAttribute.dynamicPortList ||
+ outputAttribute != null && outputAttribute.dynamicPortList;
+ });
+ }
+
/// Cache node types
private static void BuildCache() {
portDataCache = new PortDataCache();
diff --git a/Scripts/NodePort.cs b/Scripts/NodePort.cs
index 58a3bd6..b2f1ad1 100644
--- a/Scripts/NodePort.cs
+++ b/Scripts/NodePort.cs
@@ -19,9 +19,18 @@ namespace XNode {
}
}
- public IO direction { get { return _direction; } }
- public Node.ConnectionType connectionType { get { return _connectionType; } }
- public Node.TypeConstraint typeConstraint { get { return _typeConstraint; } }
+ public IO direction {
+ get { return _direction; }
+ internal set { _direction = value; }
+ }
+ public Node.ConnectionType connectionType {
+ get { return _connectionType; }
+ internal set { _connectionType = value; }
+ }
+ public Node.TypeConstraint typeConstraint {
+ get { return _typeConstraint; }
+ internal set { _typeConstraint = value; }
+ }
/// Is this port connected to anytihng?
public bool IsConnected { get { return connections.Count != 0; } }
From cf8c70203b0624c7ef402bc71d5f6a392894b3cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Rey=20M=C3=A9ndez?=
Date: Sun, 2 Feb 2020 14:36:21 -0300
Subject: [PATCH 13/44] Fix stack overflow when using obsolete method
Node.AddInstanceInput (#231)
---
Scripts/Node.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Scripts/Node.cs b/Scripts/Node.cs
index 4103d67..beb5f77 100644
--- a/Scripts/Node.cs
+++ b/Scripts/Node.cs
@@ -65,7 +65,7 @@ namespace XNode {
[Obsolete("Use AddDynamicInput instead")]
public NodePort AddInstanceInput(Type type, Node.ConnectionType connectionType = Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null) {
- return AddInstanceInput(type, connectionType, typeConstraint, fieldName);
+ return AddDynamicInput(type, connectionType, typeConstraint, fieldName);
}
[Obsolete("Use AddDynamicOutput instead")]
From f9200ae6a8ef31dc9c3244e8ae0b90d63c16bb64 Mon Sep 17 00:00:00 2001
From: Lumos
Date: Thu, 13 Feb 2020 21:48:59 +0000
Subject: [PATCH 14/44] Change the serialised type of dynamic port lists
defined as lists/arrays to match the respective element type. (#232)
This is logical, given that xNode already draws such dynamic ports as belonging to the element type.
---
Scripts/NodeDataCache.cs | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs
index 24458ec..71931b1 100644
--- a/Scripts/NodeDataCache.cs
+++ b/Scripts/NodeDataCache.cs
@@ -76,13 +76,28 @@ namespace XNode {
NodePort backingPort = staticPorts[backingPortName];
// Update port constraints. Creating a new port instead will break the editor, mandating the need for setters.
- listPort.ValueType = backingPort.ValueType;
+ listPort.ValueType = GetBackingValueType(backingPort.ValueType);
listPort.direction = backingPort.direction;
listPort.connectionType = backingPort.connectionType;
listPort.typeConstraint = backingPort.typeConstraint;
}
}
+ ///
+ /// Extracts the underlying types from arrays and lists, the only collections for dynamic port lists
+ /// currently supported. If the given type is not applicable (i.e. if the dynamic list port was not
+ /// defined as an array or a list), returns the given type itself.
+ ///
+ private static System.Type GetBackingValueType(System.Type portValType) {
+ if (portValType.HasElementType) {
+ return portValType.GetElementType();
+ }
+ if (portValType.IsGenericType && portValType.GetGenericTypeDefinition() == typeof(List<>)) {
+ return portValType.GetGenericArguments()[0];
+ }
+ return portValType;
+ }
+
/// Returns true if the given port is in a dynamic port list.
private static bool IsDynamicListPort(NodePort port) {
// Ports flagged as "dynamicPortList = true" end up having a "backing port" and a name with an index, but we have
From c9e1ef1c922000b8798b2198f8fa318c44adca07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=B6khan=20Kurt?=
Date: Fri, 14 Feb 2020 01:38:17 +0300
Subject: [PATCH 15/44] Skip Microsoft assemblies while building node cache
(#234)
---
Scripts/NodeDataCache.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs
index 71931b1..ad55f7b 100644
--- a/Scripts/NodeDataCache.cs
+++ b/Scripts/NodeDataCache.cs
@@ -137,6 +137,7 @@ namespace XNode {
case "UnityEngine":
case "System":
case "mscorlib":
+ case "Microsoft":
continue;
default:
nodeTypes.AddRange(assembly.GetTypes().Where(t => !t.IsAbstract && baseType.IsAssignableFrom(t)).ToArray());
From 1ef389689307a761d0b22434cb408a65344df85c Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Tue, 25 Feb 2020 09:13:14 +0100
Subject: [PATCH 16/44] Potential fix for the main asset/rename problem in
newer versions of Unity
---
Scripts/Editor/RenamePopup.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Scripts/Editor/RenamePopup.cs b/Scripts/Editor/RenamePopup.cs
index f245d4e..5429270 100644
--- a/Scripts/Editor/RenamePopup.cs
+++ b/Scripts/Editor/RenamePopup.cs
@@ -50,9 +50,10 @@ namespace XNodeEditor {
if (GUILayout.Button("Revert to default") || (e.isKey && e.keyCode == KeyCode.Return)) {
target.name = NodeEditorUtilities.NodeDefaultName(target.GetType());
NodeEditor.GetEditor((XNode.Node)target, NodeEditorWindow.current).OnRename();
+ AssetDatabase.SetMainObject((target as XNode.Node).graph, AssetDatabase.GetAssetPath(target));
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
Close();
- target.TriggerOnValidate();
+ target.TriggerOnValidate();
}
}
// Rename asset to input text
@@ -60,9 +61,10 @@ namespace XNodeEditor {
if (GUILayout.Button("Apply") || (e.isKey && e.keyCode == KeyCode.Return)) {
target.name = input;
NodeEditor.GetEditor((XNode.Node)target, NodeEditorWindow.current).OnRename();
+ AssetDatabase.SetMainObject((target as XNode.Node).graph, AssetDatabase.GetAssetPath(target));
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
Close();
- target.TriggerOnValidate();
+ target.TriggerOnValidate();
}
}
}
From bbfc44b04fdb4c4926ee36764654ad661ef3f412 Mon Sep 17 00:00:00 2001
From: Jeff Campbell
Date: Fri, 28 Feb 2020 22:52:30 +0100
Subject: [PATCH 17/44] Added fix for duplicate node fields found
* Added fix for duplicate node fields found while iterating through base fields; on 2019.3 using .Net 20 getting the fields of the node type will return all base type fields as well. This results in the iteration up through the base classes and adding their instance fields resulting in duplicates which causes errors on node creation when assigning port information.
---
Scripts/NodeDataCache.cs | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/Scripts/NodeDataCache.cs b/Scripts/NodeDataCache.cs
index ad55f7b..ba52e1b 100644
--- a/Scripts/NodeDataCache.cs
+++ b/Scripts/NodeDataCache.cs
@@ -156,7 +156,14 @@ namespace XNode {
// GetFields doesnt return inherited private fields, so walk through base types and pick those up
System.Type tempType = nodeType;
while ((tempType = tempType.BaseType) != typeof(XNode.Node)) {
- fieldInfo.AddRange(tempType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance));
+ FieldInfo[] parentFields = tempType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
+ for (int i = 0; i < parentFields.Length; i++) {
+ // Ensure that we do not already have a member with this type and name
+ FieldInfo parentField = parentFields[i];
+ if (fieldInfo.TrueForAll(x => x.Name != parentField.Name)) {
+ fieldInfo.Add(parentField);
+ }
+ }
}
return fieldInfo;
}
From 11b7f4ac4444220d7075f9a07e387477f31d0bc7 Mon Sep 17 00:00:00 2001
From: Jeff Campbell
Date: Sat, 7 Mar 2020 21:30:46 +0100
Subject: [PATCH 18/44] Added NRE check for ValidateGraphEditor
* Added NRE check to prevent exception when NodeGraphEditor.GetEditor returns null and an existing non-null graph editor is already present.
---
Scripts/Editor/NodeEditorWindow.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Scripts/Editor/NodeEditorWindow.cs b/Scripts/Editor/NodeEditorWindow.cs
index 1f64653..4fc1136 100644
--- a/Scripts/Editor/NodeEditorWindow.cs
+++ b/Scripts/Editor/NodeEditorWindow.cs
@@ -97,7 +97,7 @@ namespace XNodeEditor {
/// Make sure the graph editor is assigned and to the right object
private void ValidateGraphEditor() {
NodeGraphEditor graphEditor = NodeGraphEditor.GetEditor(graph, this);
- if (this.graphEditor != graphEditor) {
+ if (this.graphEditor != graphEditor && graphEditor != null) {
this.graphEditor = graphEditor;
graphEditor.OnOpen();
}
From 9add4e11b29fba2086094f61c9d84c6694436727 Mon Sep 17 00:00:00 2001
From: Jeff Campbell <1663648+jeffcampbellmakesgames@users.noreply.github.com>
Date: Sun, 8 Mar 2020 12:56:57 +0100
Subject: [PATCH 19/44] Added fix for rename bug with v2 AssetDatabase (#239)
* Added fix for NodeGraph rename bug with v2 AssetDatabase where renaming a graph asset can sometimes result in it being swapped as the main asset with one of the node sub assets.
---
.../Editor/GraphRenameFixAssetProcessor.cs | 35 +++++++++++++++++++
.../GraphRenameFixAssetProcessor.cs.meta | 11 ++++++
2 files changed, 46 insertions(+)
create mode 100644 Scripts/Editor/GraphRenameFixAssetProcessor.cs
create mode 100644 Scripts/Editor/GraphRenameFixAssetProcessor.cs.meta
diff --git a/Scripts/Editor/GraphRenameFixAssetProcessor.cs b/Scripts/Editor/GraphRenameFixAssetProcessor.cs
new file mode 100644
index 0000000..264e8b1
--- /dev/null
+++ b/Scripts/Editor/GraphRenameFixAssetProcessor.cs
@@ -0,0 +1,35 @@
+using UnityEditor;
+using XNode;
+
+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.
+ ///
+ 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++) {
+ 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)) {
+ AssetDatabase.SetMainObject(nodeAsset.graph, movedAssets[i]);
+ AssetDatabase.ImportAsset(movedAssets[i]);
+
+ nodeAsset.name = NodeEditorUtilities.NodeDefaultName(nodeAsset.GetType());
+ EditorUtility.SetDirty(nodeAsset);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Scripts/Editor/GraphRenameFixAssetProcessor.cs.meta b/Scripts/Editor/GraphRenameFixAssetProcessor.cs.meta
new file mode 100644
index 0000000..77e87ee
--- /dev/null
+++ b/Scripts/Editor/GraphRenameFixAssetProcessor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 65da1ff1c50a9984a9c95fd18799e8dd
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
From 871427249bde0a04008d308691c88da134fbc661 Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Sun, 8 Mar 2020 14:07:31 +0100
Subject: [PATCH 20/44] Added .editorconfig
---
.editorconfig | 8 ++++++++
1 file changed, 8 insertions(+)
create mode 100644 .editorconfig
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..82fb8f5
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,8 @@
+root = true
+
+[*.cs]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+insert_final_newline = false
+trim_trailing_whitespace = true
From 6a69cdaf9c63890572fd35659d29953771d5b9c2 Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Fri, 3 Apr 2020 11:09:57 +0200
Subject: [PATCH 21/44] New component: SceneGraph, lets you create a graph
inside the scene which can reference scene objects.
---
Examples.meta | 8 +++
Scripts/Editor/SceneGraphEditor.cs | 76 +++++++++++++++++++++++++
Scripts/Editor/SceneGraphEditor.cs.meta | 11 ++++
Scripts/SceneGraph.cs | 23 ++++++++
Scripts/SceneGraph.cs.meta | 11 ++++
5 files changed, 129 insertions(+)
create mode 100644 Examples.meta
create mode 100644 Scripts/Editor/SceneGraphEditor.cs
create mode 100644 Scripts/Editor/SceneGraphEditor.cs.meta
create mode 100644 Scripts/SceneGraph.cs
create mode 100644 Scripts/SceneGraph.cs.meta
diff --git a/Examples.meta b/Examples.meta
new file mode 100644
index 0000000..231b3e2
--- /dev/null
+++ b/Examples.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3cfe6eabeed0aa44e8d9d54b308a461f
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Scripts/Editor/SceneGraphEditor.cs b/Scripts/Editor/SceneGraphEditor.cs
new file mode 100644
index 0000000..911f66c
--- /dev/null
+++ b/Scripts/Editor/SceneGraphEditor.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+using XNode;
+
+namespace XNodeEditor {
+ [CustomEditor(typeof(SceneGraph), true)]
+ public class SceneGraphEditor : Editor {
+ private SceneGraph sceneGraph;
+ private bool removeSafely;
+ private Type graphType;
+
+ public override void OnInspectorGUI() {
+ if (sceneGraph.graph == null) {
+ if (GUILayout.Button("New graph", GUILayout.Height(40))) {
+ if (graphType == null) {
+ Type[] graphTypes = NodeEditorReflection.GetDerivedTypes(typeof(NodeGraph));
+ GenericMenu menu = new GenericMenu();
+ for (int i = 0; i < graphTypes.Length; i++) {
+ Type graphType = graphTypes[i];
+ menu.AddItem(new GUIContent(graphType.Name), false, () => CreateGraph(graphType));
+ }
+ menu.ShowAsContext();
+ } else {
+ CreateGraph(graphType);
+ }
+ }
+ } else {
+ if (GUILayout.Button("Open graph", GUILayout.Height(40))) {
+ NodeEditorWindow.Open(sceneGraph.graph);
+ }
+ if (removeSafely) {
+ GUILayout.BeginHorizontal();
+ GUILayout.Label("Really remove graph?");
+ GUI.color = new Color(1, 0.8f, 0.8f);
+ if (GUILayout.Button("Remove")) {
+ removeSafely = false;
+ sceneGraph.graph = null;
+ }
+ GUI.color = Color.white;
+ if (GUILayout.Button("Cancel")) {
+ removeSafely = false;
+ }
+ GUILayout.EndHorizontal();
+ } else {
+ GUI.color = new Color(1, 0.8f, 0.8f);
+ if (GUILayout.Button("Remove graph")) {
+ removeSafely = true;
+ }
+ GUI.color = Color.white;
+ }
+ }
+ }
+
+ private void OnEnable() {
+ sceneGraph = target as SceneGraph;
+ Type sceneGraphType = sceneGraph.GetType();
+ if (sceneGraphType == typeof(SceneGraph)) {
+ graphType = null;
+ } else {
+ Type baseType = sceneGraphType.BaseType;
+ if (baseType.IsGenericType) {
+ graphType = sceneGraphType = baseType.GetGenericArguments() [0];
+ }
+ }
+ }
+
+ public void CreateGraph(Type type) {
+ serializedObject.Update();
+ sceneGraph.graph = ScriptableObject.CreateInstance(type) as NodeGraph;
+ serializedObject.ApplyModifiedProperties();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Scripts/Editor/SceneGraphEditor.cs.meta b/Scripts/Editor/SceneGraphEditor.cs.meta
new file mode 100644
index 0000000..e1bf0b2
--- /dev/null
+++ b/Scripts/Editor/SceneGraphEditor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: aea725adabc311f44b5ea8161360a915
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Scripts/SceneGraph.cs b/Scripts/SceneGraph.cs
new file mode 100644
index 0000000..bb2774f
--- /dev/null
+++ b/Scripts/SceneGraph.cs
@@ -0,0 +1,23 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using XNode;
+
+namespace XNode {
+ /// Lets you instantiate a node graph in the scene. This allows you to reference in-scene objects.
+ public class SceneGraph : MonoBehaviour {
+ public NodeGraph graph;
+ }
+
+ /// Derive from this class to create a SceneGraph with a specific graph type.
+ ///
+ ///
+ /// public class MySceneGraph : SceneGraph {
+ ///
+ /// }
+ ///
+ ///
+ public class SceneGraph : SceneGraph where T : NodeGraph {
+ public new T graph { get { return base.graph as T; } set { base.graph = value; } }
+ }
+}
\ No newline at end of file
diff --git a/Scripts/SceneGraph.cs.meta b/Scripts/SceneGraph.cs.meta
new file mode 100644
index 0000000..c7978b6
--- /dev/null
+++ b/Scripts/SceneGraph.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7915171fc13472a40a0162003052d2db
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
From f3b211ed83834fb237c0e40093a0367a027fbba6 Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Fri, 3 Apr 2020 11:26:12 +0200
Subject: [PATCH 22/44] Fixed error on adding nodes in scene graphs
---
Scripts/Editor/NodeGraphEditor.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Scripts/Editor/NodeGraphEditor.cs b/Scripts/Editor/NodeGraphEditor.cs
index 3a0464c..9c25911 100644
--- a/Scripts/Editor/NodeGraphEditor.cs
+++ b/Scripts/Editor/NodeGraphEditor.cs
@@ -143,7 +143,7 @@ namespace XNodeEditor {
Undo.RegisterCreatedObjectUndo(node, "Create Node");
node.position = position;
if (node.name == null || node.name.Trim() == "") node.name = NodeEditorUtilities.NodeDefaultName(type);
- AssetDatabase.AddObjectToAsset(node, target);
+ if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(target))) AssetDatabase.AddObjectToAsset(node, target);
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
NodeEditorWindow.RepaintAll();
return node;
From f899e48ee08c59443d1cd833ab8f273b0b5a11db Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Fri, 3 Apr 2020 15:01:44 +0200
Subject: [PATCH 23/44] Added undo support and default graph name to SceneGraph
---
Scripts/Editor/SceneGraphEditor.cs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Scripts/Editor/SceneGraphEditor.cs b/Scripts/Editor/SceneGraphEditor.cs
index 911f66c..9fb1c67 100644
--- a/Scripts/Editor/SceneGraphEditor.cs
+++ b/Scripts/Editor/SceneGraphEditor.cs
@@ -37,6 +37,7 @@ namespace XNodeEditor {
GUI.color = new Color(1, 0.8f, 0.8f);
if (GUILayout.Button("Remove")) {
removeSafely = false;
+ Undo.RecordObject(sceneGraph, "Removed graph");
sceneGraph.graph = null;
}
GUI.color = Color.white;
@@ -68,9 +69,9 @@ namespace XNodeEditor {
}
public void CreateGraph(Type type) {
- serializedObject.Update();
+ Undo.RecordObject(sceneGraph, "Create graph");
sceneGraph.graph = ScriptableObject.CreateInstance(type) as NodeGraph;
- serializedObject.ApplyModifiedProperties();
+ sceneGraph.graph.name = sceneGraph.name + "-graph";
}
}
}
\ No newline at end of file
From e2c7934f1e46ca098f0212aa5268eba01a8e3e35 Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Sat, 4 Apr 2020 14:01:05 +0200
Subject: [PATCH 24/44] Limit the OnDropObjects warning to only show when a
node graph editor is present
---
Scripts/Editor/NodeGraphEditor.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Scripts/Editor/NodeGraphEditor.cs b/Scripts/Editor/NodeGraphEditor.cs
index 9c25911..6089d29 100644
--- a/Scripts/Editor/NodeGraphEditor.cs
+++ b/Scripts/Editor/NodeGraphEditor.cs
@@ -133,7 +133,7 @@ namespace XNodeEditor {
/// Deal with objects dropped into the graph through DragAndDrop
public virtual void OnDropObjects(UnityEngine.Object[] objects) {
- Debug.Log("No OnDropObjects override defined for " + GetType());
+ if (GetType() != typeof(NodeGraphEditor)) Debug.Log("No OnDropObjects override defined for " + GetType());
}
/// Create a node and save it in the graph asset
From 01a5666adedc7049d690a06c7d46ef6d40fee00c Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Mon, 6 Apr 2020 22:19:10 +0200
Subject: [PATCH 25/44] Delete Examples.meta
---
Examples.meta | 8 --------
1 file changed, 8 deletions(-)
delete mode 100644 Examples.meta
diff --git a/Examples.meta b/Examples.meta
deleted file mode 100644
index 231b3e2..0000000
--- a/Examples.meta
+++ /dev/null
@@ -1,8 +0,0 @@
-fileFormatVersion: 2
-guid: 3cfe6eabeed0aa44e8d9d54b308a461f
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
From 76cf82509098ed2a2a86baea8337644aabb7d578 Mon Sep 17 00:00:00 2001
From: Simon Rodriguez
Date: Mon, 13 Apr 2020 19:35:52 +0200
Subject: [PATCH 26/44] Suggestion! A new way of drawing lines very similar to
Unitys upcoming Shader Node Editor.
---
Scripts/Editor/NodeEditorGUI.cs | 35 +++++++++++++++++++++++++
Scripts/Editor/NodeEditorPreferences.cs | 2 +-
2 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs
index 358b2e5..236091c 100755
--- a/Scripts/Editor/NodeEditorGUI.cs
+++ b/Scripts/Editor/NodeEditorGUI.cs
@@ -267,6 +267,41 @@ namespace XNodeEditor {
}
}
break;
+ case NoodlePath.ShaderLab:
+ Vector2 start = gridPoints[0];
+ Vector2 end = gridPoints[length - 1];
+ //Modify first and last point in array so we can loop trough them nicely.
+ gridPoints[0] = gridPoints[0] + Vector2.right * (20 / zoom);
+ gridPoints[length - 1] = gridPoints[length - 1] + Vector2.left * (20 / zoom);
+ //Draw first vertical lines going out from nodes
+ Handles.color = gradient.Evaluate(0f);
+ DrawAAPolyLineNonAlloc(thickness, start, gridPoints[0]);
+ Handles.color = gradient.Evaluate(1f);
+ DrawAAPolyLineNonAlloc(thickness, end, gridPoints[length - 1]);
+ for (int i = 0; i < length - 1; i++) {
+ Vector2 point_a = gridPoints[i];
+ Vector2 point_b = gridPoints[i + 1];
+ // Draws the line with the coloring.
+ Vector2 prev_point = point_a;
+ // Approximately one segment per 5 pixels
+ int segments = (int) Vector2.Distance(point_a, point_b) / 5;
+
+ int draw = 0;
+ for (int j = 0; j <= segments; j++) {
+ draw++;
+ float t = j / (float) segments;
+ Vector2 lerp = Vector2.Lerp(point_a, point_b, t);
+ if (draw > 0) {
+ if (i == length - 2) Handles.color = gradient.Evaluate(t);
+ DrawAAPolyLineNonAlloc(thickness, prev_point, lerp);
+ }
+ prev_point = lerp;
+ if (stroke == NoodleStroke.Dashed && draw >= 2) draw = -2;
+ }
+ }
+ gridPoints[0] = start;
+ gridPoints[length - 1] = end;
+ break;
}
}
diff --git a/Scripts/Editor/NodeEditorPreferences.cs b/Scripts/Editor/NodeEditorPreferences.cs
index 467318a..72eb8aa 100644
--- a/Scripts/Editor/NodeEditorPreferences.cs
+++ b/Scripts/Editor/NodeEditorPreferences.cs
@@ -5,7 +5,7 @@ using UnityEngine;
using UnityEngine.Serialization;
namespace XNodeEditor {
- public enum NoodlePath { Curvy, Straight, Angled }
+ public enum NoodlePath { Curvy, Straight, Angled, ShaderLab }
public enum NoodleStroke { Full, Dashed }
public static class NodeEditorPreferences {
From a61bb3f87ea87a4851e4524b9c5f72f8835ae28f Mon Sep 17 00:00:00 2001
From: Simon Rodriguez
Date: Tue, 14 Apr 2020 08:11:21 +0200
Subject: [PATCH 27/44] Implemented OrderBy in Add Node Menu (#247)
---
Scripts/Editor/NodeGraphEditor.cs | 15 +++++++++++++--
Scripts/Node.cs | 10 ++++++++++
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/Scripts/Editor/NodeGraphEditor.cs b/Scripts/Editor/NodeGraphEditor.cs
index 6089d29..f8e1eda 100644
--- a/Scripts/Editor/NodeGraphEditor.cs
+++ b/Scripts/Editor/NodeGraphEditor.cs
@@ -41,11 +41,22 @@ namespace XNodeEditor {
return NodeEditorUtilities.NodeDefaultPath(type);
}
+ /// The order by which the menu items are displayed.
+ public virtual int GetNodeMenuOrder(Type type) {
+ //Check if type has the CreateNodeMenuAttribute
+ XNode.Node.CreateNodeMenuAttribute attrib;
+ if (NodeEditorUtilities.GetAttrib(type, out attrib)) // Return custom path
+ return attrib.order;
+ else
+ return 0;
+ }
+
/// Add items for the context menu when right-clicking this node. Override to add custom menu items.
public virtual void AddContextMenuItems(GenericMenu menu) {
Vector2 pos = NodeEditorWindow.current.WindowToGridPosition(Event.current.mousePosition);
- for (int i = 0; i < NodeEditorReflection.nodeTypes.Length; i++) {
- Type type = NodeEditorReflection.nodeTypes[i];
+ var nodeTypes = NodeEditorReflection.nodeTypes.OrderBy(type => GetNodeMenuOrder(type)).ToArray();
+ for (int i = 0; i < nodeTypes.Length; i++) {
+ Type type = nodeTypes[i];
//Get node context menu path
string path = GetNodeMenuName(type);
diff --git a/Scripts/Node.cs b/Scripts/Node.cs
index beb5f77..9d2721b 100644
--- a/Scripts/Node.cs
+++ b/Scripts/Node.cs
@@ -317,10 +317,20 @@ namespace XNode {
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class CreateNodeMenuAttribute : Attribute {
public string menuName;
+ public int order;
/// Manually supply node class with a context menu path
/// Path to this node in the context menu. Null or empty hides it.
public CreateNodeMenuAttribute(string menuName) {
this.menuName = menuName;
+ this.order = 0;
+ }
+
+ /// Manually supply node class with a context menu path
+ /// Path to this node in the context menu. Null or empty hides it.
+ /// The order by which the menu items are displayed.
+ public CreateNodeMenuAttribute(string menuName, int order) {
+ this.menuName = menuName;
+ this.order = order;
}
}
From 049a62465c6af3588fb01fb29c43e9d4fc647cfa Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Sun, 19 Apr 2020 20:41:12 +0200
Subject: [PATCH 28/44] Made nodeEditorWindow.selectedReroutes public
---
Scripts/Editor/NodeEditorAction.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs
index 8021a16..8e840af 100644
--- a/Scripts/Editor/NodeEditorAction.cs
+++ b/Scripts/Editor/NodeEditorAction.cs
@@ -25,7 +25,7 @@ namespace XNodeEditor {
[NonSerialized] private XNode.NodePort autoConnectOutput = null;
[NonSerialized] private List draggedOutputReroutes = new List();
private RerouteReference hoveredReroute = new RerouteReference();
- private List selectedReroutes = new List();
+ public List selectedReroutes = new List();
private Vector2 dragBoxStart;
private UnityEngine.Object[] preBoxSelection;
private RerouteReference[] preBoxSelectionReroute;
From e704b97c77b4b06c6a2bc01d27bb6297f788de9f Mon Sep 17 00:00:00 2001
From: Dan Erhardt <51964473+DanErhardt@users.noreply.github.com>
Date: Mon, 20 Apr 2020 11:21:19 -0300
Subject: [PATCH 29/44] A fix for an ArgumentException error. (#250)
This is the fix proposed by nostravaganza on discord.
It works 100%. Could not reproduce the error again.
---
Scripts/Editor/NodeEditorUtilities.cs | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/Scripts/Editor/NodeEditorUtilities.cs b/Scripts/Editor/NodeEditorUtilities.cs
index 9973145..ac12e33 100644
--- a/Scripts/Editor/NodeEditorUtilities.cs
+++ b/Scripts/Editor/NodeEditorUtilities.cs
@@ -74,8 +74,10 @@ namespace XNodeEditor {
Attribute attr;
if (!typeTypes.TryGetValue(typeof(T), out attr)) {
- if (GetAttrib(classType, fieldName, out attribOut)) typeTypes.Add(typeof(T), attribOut);
- else typeTypes.Add(typeof(T), null);
+ if (GetAttrib(classType, fieldName, out attribOut)) {
+ typeTypes.Add(typeof(T), attribOut);
+ return true;
+ } else typeTypes.Add(typeof(T), null);
}
if (attr == null) {
@@ -261,4 +263,4 @@ namespace XNodeEditor {
}
}
}
-}
\ No newline at end of file
+}
From bbdbee90a169778d1a8a4b45f2362ec7c6817479 Mon Sep 17 00:00:00 2001
From: Dan Erhardt <51964473+DanErhardt@users.noreply.github.com>
Date: Mon, 20 Apr 2020 11:56:33 -0300
Subject: [PATCH 30/44] Fix to prevent division by 0 (#251)
---
Scripts/Editor/NodeEditorGUI.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs
index 236091c..7c82a12 100755
--- a/Scripts/Editor/NodeEditorGUI.cs
+++ b/Scripts/Editor/NodeEditorGUI.cs
@@ -202,6 +202,7 @@ namespace XNodeEditor {
Vector2 prev_point = point_a;
// Approximately one segment per 5 pixels
int segments = (int) Vector2.Distance(point_a, point_b) / 5;
+ segments = Math.Max(segments, 1);
int draw = 0;
for (int j = 0; j <= segments; j++) {
@@ -285,6 +286,7 @@ namespace XNodeEditor {
Vector2 prev_point = point_a;
// Approximately one segment per 5 pixels
int segments = (int) Vector2.Distance(point_a, point_b) / 5;
+ segments = Math.Max(segments, 1);
int draw = 0;
for (int j = 0; j <= segments; j++) {
From a550a87b9e26064acf14e9ac9441c37d8be2f541 Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Tue, 21 Apr 2020 15:29:24 +0200
Subject: [PATCH 31/44] Fix .editorconfig. Line endings were set as LF despite
all endings being CRLF
---
.editorconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.editorconfig b/.editorconfig
index 82fb8f5..03c2cb5 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -3,6 +3,6 @@ root = true
[*.cs]
indent_style = space
indent_size = 4
-end_of_line = lf
+end_of_line = crlf
insert_final_newline = false
trim_trailing_whitespace = true
From 8965d365e62aec3c458fca9585e2a7d6d5c0fa50 Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Tue, 21 Apr 2020 15:31:07 +0200
Subject: [PATCH 32/44] Add [DisallowMultipleNodes] for limiting how many nodes
of a certain type can exist on any graph
---
Scripts/Editor/NodeEditorAction.cs | 9 +++++++++
Scripts/Editor/NodeGraphEditor.cs | 12 +++++++++++-
Scripts/Node.cs | 10 ++++++++++
3 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs
index 8e840af..f9a81fb 100644
--- a/Scripts/Editor/NodeEditorAction.cs
+++ b/Scripts/Editor/NodeEditorAction.cs
@@ -439,6 +439,15 @@ namespace XNodeEditor {
for (int i = 0; i < nodes.Length; i++) {
XNode.Node srcNode = nodes[i];
if (srcNode == null) continue;
+
+ // Check if user is allowed to add more of given node type
+ XNode.Node.DisallowMultipleNodesAttribute disallowAttrib;
+ Type nodeType = srcNode.GetType();
+ if (NodeEditorUtilities.GetAttrib(nodeType, out disallowAttrib)) {
+ int typeCount = graph.nodes.Count(x => x.GetType() == nodeType);
+ if (typeCount >= disallowAttrib.max) continue;
+ }
+
XNode.Node newNode = graphEditor.CopyNode(srcNode);
substitutes.Add(srcNode, newNode);
newNode.position = srcNode.position + offset;
diff --git a/Scripts/Editor/NodeGraphEditor.cs b/Scripts/Editor/NodeGraphEditor.cs
index f8e1eda..3806d39 100644
--- a/Scripts/Editor/NodeGraphEditor.cs
+++ b/Scripts/Editor/NodeGraphEditor.cs
@@ -62,7 +62,17 @@ namespace XNodeEditor {
string path = GetNodeMenuName(type);
if (string.IsNullOrEmpty(path)) continue;
- menu.AddItem(new GUIContent(path), false, () => {
+ // Check if user is allowed to add more of given node type
+ XNode.Node.DisallowMultipleNodesAttribute disallowAttrib;
+ bool disallowed = false;
+ if (NodeEditorUtilities.GetAttrib(type, out disallowAttrib)) {
+ int typeCount = target.nodes.Count(x => x.GetType() == type);
+ if (typeCount >= disallowAttrib.max) disallowed = true;
+ }
+
+ // Add node entry to context menu
+ if (disallowed) menu.AddItem(new GUIContent(path), false, null);
+ else menu.AddItem(new GUIContent(path), false, () => {
XNode.Node node = CreateNode(type, pos);
NodeEditorWindow.current.AutoConnect(node);
});
diff --git a/Scripts/Node.cs b/Scripts/Node.cs
index 9d2721b..8e1a670 100644
--- a/Scripts/Node.cs
+++ b/Scripts/Node.cs
@@ -334,6 +334,16 @@ namespace XNode {
}
}
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public class DisallowMultipleNodesAttribute : Attribute {
+ public int max;
+ /// Prevents Node of the same type (or subtype) to be added more than once (configurable) to a NodeGraph
+ /// How many nodes to allow. Defaults to 1.
+ public DisallowMultipleNodesAttribute(int max = 1) {
+ this.max = max;
+ }
+ }
+
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class NodeTintAttribute : Attribute {
public Color color;
From c2a99ba2b5ea226639ec6c53903ce2e69ef4dd78 Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Tue, 21 Apr 2020 15:52:06 +0200
Subject: [PATCH 33/44] Improved commenting on attributes
---
Scripts/Node.cs | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/Scripts/Node.cs b/Scripts/Node.cs
index 8e1a670..6744cc5 100644
--- a/Scripts/Node.cs
+++ b/Scripts/Node.cs
@@ -314,6 +314,7 @@ namespace XNode {
public OutputAttribute(ShowBackingValue backingValue, ConnectionType connectionType, bool dynamicPortList) : this(backingValue, connectionType, TypeConstraint.None, dynamicPortList) { }
}
+ /// Manually supply node class with a context menu path
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class CreateNodeMenuAttribute : Attribute {
public string menuName;
@@ -334,16 +335,20 @@ namespace XNode {
}
}
+ /// Prevents Node of the same type to be added more than once (configurable) to a NodeGraph
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class DisallowMultipleNodesAttribute : Attribute {
+ // TODO: Make inheritance work in such a way that applying [DisallowMultipleNodes(1)] to type NodeBar : Node
+ // while type NodeFoo : NodeBar exists, will let you add *either one* of these nodes, but not both.
public int max;
- /// Prevents Node of the same type (or subtype) to be added more than once (configurable) to a NodeGraph
+ /// Prevents Node of the same type to be added more than once (configurable) to a NodeGraph
/// How many nodes to allow. Defaults to 1.
public DisallowMultipleNodesAttribute(int max = 1) {
this.max = max;
}
}
+ /// Specify a color for this node type
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class NodeTintAttribute : Attribute {
public Color color;
@@ -370,6 +375,7 @@ namespace XNode {
}
}
+ /// Specify a width for this node type
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class NodeWidthAttribute : Attribute {
public int width;
From ff2c1e815885f57b842187f730b0f40f95084c0c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Romain=20Th=C3=A9ry?=
Date: Thu, 23 Apr 2020 11:27:02 +0200
Subject: [PATCH 34/44] Mark CopyNode as virtual (#252)
---
Scripts/Editor/NodeGraphEditor.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Scripts/Editor/NodeGraphEditor.cs b/Scripts/Editor/NodeGraphEditor.cs
index 3806d39..7551e2f 100644
--- a/Scripts/Editor/NodeGraphEditor.cs
+++ b/Scripts/Editor/NodeGraphEditor.cs
@@ -171,7 +171,7 @@ namespace XNodeEditor {
}
/// Creates a copy of the original node in the graph
- public XNode.Node CopyNode(XNode.Node original) {
+ public virtual XNode.Node CopyNode(XNode.Node original) {
Undo.RecordObject(target, "Duplicate Node");
XNode.Node node = target.CopyNode(original);
Undo.RegisterCreatedObjectUndo(node, "Duplicate Node");
@@ -211,4 +211,4 @@ namespace XNodeEditor {
}
}
}
-}
\ No newline at end of file
+}
From c298b5ee537f53add2c5903a04c6984b7acb122e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Romain=20Th=C3=A9ry?=
Date: Thu, 23 Apr 2020 15:08:43 +0200
Subject: [PATCH 35/44] Add virtual OnWindowFocus and OnWindowFocusLost in
NodeGraphEditor(#253)
---
Scripts/Editor/NodeEditorWindow.cs | 9 ++++++++-
Scripts/Editor/NodeGraphEditor.cs | 6 ++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/Scripts/Editor/NodeEditorWindow.cs b/Scripts/Editor/NodeEditorWindow.cs
index 4fc1136..a751722 100644
--- a/Scripts/Editor/NodeEditorWindow.cs
+++ b/Scripts/Editor/NodeEditorWindow.cs
@@ -77,7 +77,14 @@ namespace XNodeEditor {
void OnFocus() {
current = this;
ValidateGraphEditor();
- if (graphEditor != null && NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
+ if (graphEditor != null) {
+ graphEditor.OnWindowFocus();
+ if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
+ }
+ }
+
+ void OnLostFocus() {
+ if (graphEditor != null) graphEditor.OnWindowFocusLost();
}
[InitializeOnLoadMethod]
diff --git a/Scripts/Editor/NodeGraphEditor.cs b/Scripts/Editor/NodeGraphEditor.cs
index 7551e2f..12b9ba1 100644
--- a/Scripts/Editor/NodeGraphEditor.cs
+++ b/Scripts/Editor/NodeGraphEditor.cs
@@ -17,6 +17,12 @@ namespace XNodeEditor {
/// Called when opened by NodeEditorWindow
public virtual void OnOpen() { }
+
+ /// Called when NodeEditorWindow gains focus
+ public virtual void OnWindowFocus() { }
+
+ /// Called when NodeEditorWindow loses focus
+ public virtual void OnWindowFocusLost() { }
public virtual Texture2D GetGridTexture() {
return NodeEditorPreferences.GetSettings().gridTexture;
From d9d90f0f7b8f240baaaf2e1d8d0b6d1fd790453f Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Fri, 24 Apr 2020 15:57:50 +0200
Subject: [PATCH 36/44] Add [RequireNode] attribute to graphs (#254)
---
Scripts/Editor/NodeEditor.cs | 16 +++++----
Scripts/Editor/NodeGraphEditor.cs | 17 +++++++++
Scripts/Editor/NodeGraphImporter.cs | 45 ++++++++++++++++++++++++
Scripts/Editor/NodeGraphImporter.cs.meta | 11 ++++++
Scripts/NodeGraph.cs | 39 ++++++++++++++++++++
5 files changed, 122 insertions(+), 6 deletions(-)
create mode 100644 Scripts/Editor/NodeGraphImporter.cs
create mode 100644 Scripts/Editor/NodeGraphImporter.cs.meta
diff --git a/Scripts/Editor/NodeEditor.cs b/Scripts/Editor/NodeEditor.cs
index edf66d6..36c3a6e 100644
--- a/Scripts/Editor/NodeEditor.cs
+++ b/Scripts/Editor/NodeEditor.cs
@@ -67,7 +67,7 @@ namespace XNodeEditor {
serializedObject.ApplyModifiedProperties();
#if ODIN_INSPECTOR
- // Call repaint so that the graph window elements respond properly to layout changes coming from Odin
+ // Call repaint so that the graph window elements respond properly to layout changes coming from Odin
if (GUIHelper.RepaintRequested) {
GUIHelper.ClearRepaintRequest();
window.Repaint();
@@ -106,17 +106,22 @@ namespace XNodeEditor {
/// Add items for the context menu when right-clicking this node. Override to add custom menu items.
public virtual void AddContextMenuItems(GenericMenu menu) {
+ bool canRemove = true;
// Actions if only one node is selected
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
XNode.Node node = Selection.activeObject as XNode.Node;
menu.AddItem(new GUIContent("Move To Top"), false, () => NodeEditorWindow.current.MoveNodeToTop(node));
menu.AddItem(new GUIContent("Rename"), false, NodeEditorWindow.current.RenameSelectedNode);
+
+ canRemove = NodeGraphEditor.GetEditor(node.graph, NodeEditorWindow.current).CanRemove(node);
}
// Add actions to any number of selected nodes
menu.AddItem(new GUIContent("Copy"), false, NodeEditorWindow.current.CopySelectedNodes);
menu.AddItem(new GUIContent("Duplicate"), false, NodeEditorWindow.current.DuplicateSelectedNodes);
- menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes);
+
+ 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 XNode.Node) {
@@ -132,11 +137,10 @@ namespace XNodeEditor {
OnRename();
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(target));
}
-
+
/// Called after this node's name has changed.
public virtual void OnRename() { }
-
-
+
[AttributeUsage(AttributeTargets.Class)]
public class CustomNodeEditorAttribute : Attribute,
XNodeEditor.Internal.NodeEditorBase.INodeEditorAttrib {
@@ -152,4 +156,4 @@ namespace XNodeEditor {
}
}
}
-}
+}
\ No newline at end of file
diff --git a/Scripts/Editor/NodeGraphEditor.cs b/Scripts/Editor/NodeGraphEditor.cs
index 12b9ba1..01de70e 100644
--- a/Scripts/Editor/NodeGraphEditor.cs
+++ b/Scripts/Editor/NodeGraphEditor.cs
@@ -187,8 +187,25 @@ namespace XNodeEditor {
return node;
}
+ /// Return false for nodes that can't be removed
+ public virtual bool CanRemove(XNode.Node node) {
+ // Check graph attributes to see if this node is required
+ Type graphType = target.GetType();
+ XNode.NodeGraph.RequireNodeAttribute[] attribs = Array.ConvertAll(
+ graphType.GetCustomAttributes(typeof(XNode.NodeGraph.RequireNodeAttribute), true), x => x as XNode.NodeGraph.RequireNodeAttribute);
+ if (attribs.Any(x => x.Requires(node.GetType()))) {
+ if (target.nodes.Count(x => x.GetType() == node.GetType()) <= 1) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/// Safely remove a node and all its connections.
public virtual void RemoveNode(XNode.Node node) {
+ if (!CanRemove(node)) return;
+
+ // Remove the node
Undo.RecordObject(node, "Delete Node");
Undo.RecordObject(target, "Delete Node");
foreach (var port in node.Ports)
diff --git a/Scripts/Editor/NodeGraphImporter.cs b/Scripts/Editor/NodeGraphImporter.cs
new file mode 100644
index 0000000..3faf54f
--- /dev/null
+++ b/Scripts/Editor/NodeGraphImporter.cs
@@ -0,0 +1,45 @@
+using System;
+using System.IO;
+using System.Linq;
+using UnityEditor;
+using UnityEditor.Experimental.AssetImporters;
+using UnityEngine;
+using XNode;
+
+namespace XNodeEditor {
+ /// Deals with modified assets
+ class NodeGraphImporter : AssetPostprocessor {
+ private static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) {
+ foreach (string path in importedAssets) {
+ // Skip processing anything without the .asset extension
+ if (Path.GetExtension(path) != ".asset") continue;
+
+ // Get the object that is requested for deletion
+ NodeGraph graph = AssetDatabase.LoadAssetAtPath(path);
+ if (graph == null) continue;
+
+ // Get attributes
+ Type graphType = graph.GetType();
+ NodeGraph.RequireNodeAttribute[] attribs = Array.ConvertAll(
+ graphType.GetCustomAttributes(typeof(NodeGraph.RequireNodeAttribute), true), x => x as NodeGraph.RequireNodeAttribute);
+
+ Vector2 position = Vector2.zero;
+ foreach (NodeGraph.RequireNodeAttribute attrib in attribs) {
+ if (attrib.type0 != null) AddRequired(graph, attrib.type0, ref position);
+ if (attrib.type1 != null) AddRequired(graph, attrib.type1, ref position);
+ if (attrib.type2 != null) AddRequired(graph, attrib.type2, ref position);
+ }
+ }
+ }
+
+ private static void AddRequired(NodeGraph graph, Type type, ref Vector2 position) {
+ if (!graph.nodes.Any(x => x.GetType() == type)) {
+ XNode.Node node = graph.AddNode(type);
+ node.position = position;
+ position.x += 200;
+ if (node.name == null || node.name.Trim() == "") node.name = NodeEditorUtilities.NodeDefaultName(type);
+ if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(graph))) AssetDatabase.AddObjectToAsset(node, graph);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Scripts/Editor/NodeGraphImporter.cs.meta b/Scripts/Editor/NodeGraphImporter.cs.meta
new file mode 100644
index 0000000..b3dd1fe
--- /dev/null
+++ b/Scripts/Editor/NodeGraphImporter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7a816f2790bf3da48a2d6d0035ebc9a0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Scripts/NodeGraph.cs b/Scripts/NodeGraph.cs
index 6a0cead..d928f94 100644
--- a/Scripts/NodeGraph.cs
+++ b/Scripts/NodeGraph.cs
@@ -81,5 +81,44 @@ namespace XNode {
// Remove all nodes prior to graph destruction
Clear();
}
+
+#region Attributes
+ /// Automatically ensures the existance of a certain node type, and prevents it from being deleted.
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
+ public class RequireNodeAttribute : Attribute {
+ public Type type0;
+ public Type type1;
+ public Type type2;
+
+ /// Automatically ensures the existance of a certain node type, and prevents it from being deleted
+ public RequireNodeAttribute(Type type) {
+ this.type0 = type;
+ this.type1 = null;
+ this.type2 = null;
+ }
+
+ /// Automatically ensures the existance of a certain node type, and prevents it from being deleted
+ public RequireNodeAttribute(Type type, Type type2) {
+ this.type0 = type;
+ this.type1 = type2;
+ this.type2 = null;
+ }
+
+ /// Automatically ensures the existance of a certain node type, and prevents it from being deleted
+ public RequireNodeAttribute(Type type, Type type2, Type type3) {
+ this.type0 = type;
+ this.type1 = type2;
+ this.type2 = type3;
+ }
+
+ public bool Requires(Type type) {
+ if (type == null) return false;
+ if (type == type0) return true;
+ else if (type == type1) return true;
+ else if (type == type2) return true;
+ return false;
+ }
+ }
+#endregion
}
}
\ No newline at end of file
From a1cf78d3fb9ac379a1ee4acffd0430c3eb35a761 Mon Sep 17 00:00:00 2001
From: Dan Erhardt <51964473+DanErhardt@users.noreply.github.com>
Date: Sun, 26 Apr 2020 12:44:46 -0300
Subject: [PATCH 37/44] Fix for AutoConnect method. (#255)
Prevents incompatible connections between node ports when creating a new node on connection drag.
---
Scripts/Editor/NodeEditorAction.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs
index f9a81fb..1a02556 100644
--- a/Scripts/Editor/NodeEditorAction.cs
+++ b/Scripts/Editor/NodeEditorAction.cs
@@ -535,8 +535,8 @@ namespace XNodeEditor {
XNode.NodePort inputPort = node.Ports.FirstOrDefault(x => x.IsInput && x.ValueType == autoConnectOutput.ValueType);
// Fallback to input port
if (inputPort == null) inputPort = node.Ports.FirstOrDefault(x => x.IsInput);
- // Autoconnect
- if (inputPort != null) autoConnectOutput.Connect(inputPort);
+ // Autoconnect if connection is compatible
+ if (inputPort != null && inputPort.CanConnectTo(autoConnectOutput)) autoConnectOutput.Connect(inputPort);
// Save changes
EditorUtility.SetDirty(graph);
@@ -544,4 +544,4 @@ namespace XNodeEditor {
autoConnectOutput = null;
}
}
-}
\ No newline at end of file
+}
From 4c6d22a15246bbb72aac724e1cdf29b0847fec88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Romain=20Th=C3=A9ry?=
Date: Thu, 7 May 2020 10:21:39 +0200
Subject: [PATCH 38/44] Improve rename popup (#256)
---
Scripts/Editor/RenamePopup.cs | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/Scripts/Editor/RenamePopup.cs b/Scripts/Editor/RenamePopup.cs
index 5429270..a43837f 100644
--- a/Scripts/Editor/RenamePopup.cs
+++ b/Scripts/Editor/RenamePopup.cs
@@ -1,9 +1,11 @@
-using UnityEditor;
+using UnityEditor;
using UnityEngine;
namespace XNodeEditor {
/// Utility for renaming assets
public class RenamePopup : EditorWindow {
+ private const string inputControlName = "nameInput";
+
public static RenamePopup current { get; private set; }
public Object target;
public string input;
@@ -19,7 +21,6 @@ namespace XNodeEditor {
window.input = target.name;
window.minSize = new Vector2(100, 44);
window.position = new Rect(0, 0, width, 44);
- GUI.FocusControl("ClearAllFocus");
window.UpdatePositionToMouse();
return window;
}
@@ -43,7 +44,9 @@ namespace XNodeEditor {
UpdatePositionToMouse();
firstFrame = false;
}
+ GUI.SetNextControlName(inputControlName);
input = EditorGUILayout.TextField(input);
+ EditorGUI.FocusTextInControl(inputControlName);
Event e = Event.current;
// If input is empty, revert name to default instead
if (input == null || input.Trim() == "") {
@@ -67,6 +70,14 @@ namespace XNodeEditor {
target.TriggerOnValidate();
}
}
+
+ if (e.isKey && e.keyCode == KeyCode.Escape) {
+ Close();
+ }
+ }
+
+ private void OnDestroy() {
+ EditorGUIUtility.editingTextField = false;
}
}
}
\ No newline at end of file
From 8046e6e0bfb17f645ad9663e805bde843aa91313 Mon Sep 17 00:00:00 2001
From: fdtdev
Date: Sat, 9 May 2020 13:21:35 +0200
Subject: [PATCH 39/44] [FIX] fix a problem when a complex class with optional
port drawing is used with NodeEditorGUILayout.DynamicPortList. By having an
item that wasn't drawing the port, the method was throwing a
KeyNotFoundException when reordering. (#262)
The fix detects if there isn't a port when swapping rects.
---
Scripts/Editor/NodeEditorGUILayout.cs | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/Scripts/Editor/NodeEditorGUILayout.cs b/Scripts/Editor/NodeEditorGUILayout.cs
index 0b8a0cd..3574ace 100644
--- a/Scripts/Editor/NodeEditorGUILayout.cs
+++ b/Scripts/Editor/NodeEditorGUILayout.cs
@@ -371,7 +371,10 @@ namespace XNodeEditor {
};
list.onReorderCallback =
(ReorderableList rl) => {
-
+ bool hasRect = false;
+ bool hasNewRect = false;
+ Rect rect = Rect.zero;
+ Rect newRect = Rect.zero;
// Move up
if (rl.index > reorderableListIndex) {
for (int i = reorderableListIndex; i < rl.index; ++i) {
@@ -380,9 +383,10 @@ namespace XNodeEditor {
port.SwapConnections(nextPort);
// Swap cached positions to mitigate twitching
- Rect rect = NodeEditorWindow.current.portConnectionPoints[port];
- NodeEditorWindow.current.portConnectionPoints[port] = NodeEditorWindow.current.portConnectionPoints[nextPort];
- NodeEditorWindow.current.portConnectionPoints[nextPort] = rect;
+ hasRect = NodeEditorWindow.current.portConnectionPoints.TryGetValue(port, out rect);
+ hasNewRect = NodeEditorWindow.current.portConnectionPoints.TryGetValue(nextPort, out newRect);
+ NodeEditorWindow.current.portConnectionPoints[port] = hasNewRect?newRect:rect;
+ NodeEditorWindow.current.portConnectionPoints[nextPort] = hasRect?rect:newRect;
}
}
// Move down
@@ -393,9 +397,10 @@ namespace XNodeEditor {
port.SwapConnections(nextPort);
// Swap cached positions to mitigate twitching
- Rect rect = NodeEditorWindow.current.portConnectionPoints[port];
- NodeEditorWindow.current.portConnectionPoints[port] = NodeEditorWindow.current.portConnectionPoints[nextPort];
- NodeEditorWindow.current.portConnectionPoints[nextPort] = rect;
+ hasRect = NodeEditorWindow.current.portConnectionPoints.TryGetValue(port, out rect);
+ hasNewRect = NodeEditorWindow.current.portConnectionPoints.TryGetValue(nextPort, out newRect);
+ NodeEditorWindow.current.portConnectionPoints[port] = hasNewRect?newRect:rect;
+ NodeEditorWindow.current.portConnectionPoints[nextPort] = hasRect?rect:newRect;
}
}
// Apply changes
From a8daac60b0bfdb913302654730151f838cac1bc9 Mon Sep 17 00:00:00 2001
From: chrisfairc
Date: Wed, 27 May 2020 07:20:20 +0100
Subject: [PATCH 40/44] Add a dragthreshold to better distunguish right clicks
and right drags (#230)
* add a drag threshold so right clicks are better distinguished from right drags especially on large screens
* ignore mac files too
* dont use less than 1 as a drag threshold
Co-authored-by: Chris Fairclough
---
.gitignore | 3 +++
Scripts/Editor/NodeEditorAction.cs | 8 ++++++--
Scripts/Editor/NodeEditorWindow.cs | 2 ++
3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/.gitignore b/.gitignore
index 64ab4c0..c75a01e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,6 @@ sysinfo.txt
.git.meta
.gitignore.meta
.gitattributes.meta
+
+# OS X only:
+.DS_Store
\ No newline at end of file
diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs
index 1a02556..b112732 100644
--- a/Scripts/Editor/NodeEditorAction.cs
+++ b/Scripts/Editor/NodeEditorAction.cs
@@ -32,6 +32,7 @@ namespace XNodeEditor {
private Rect selectionBox;
private bool isDoubleClick = false;
private Vector2 lastMousePosition;
+ private float dragThreshold = 1f;
public void Controls() {
wantsMouseMove = true;
@@ -134,8 +135,11 @@ namespace XNodeEditor {
Repaint();
}
} else if (e.button == 1 || e.button == 2) {
- panOffset += e.delta * zoom;
- isPanning = true;
+ //check drag threshold for larger screens
+ if (e.delta.magnitude > dragThreshold) {
+ panOffset += e.delta * zoom;
+ isPanning = true;
+ }
}
break;
case EventType.MouseDown:
diff --git a/Scripts/Editor/NodeEditorWindow.cs b/Scripts/Editor/NodeEditorWindow.cs
index a751722..4f0a102 100644
--- a/Scripts/Editor/NodeEditorWindow.cs
+++ b/Scripts/Editor/NodeEditorWindow.cs
@@ -81,6 +81,8 @@ namespace XNodeEditor {
graphEditor.OnWindowFocus();
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
}
+
+ dragThreshold = Math.Max(1f, Screen.width / 1000f);
}
void OnLostFocus() {
From 6c85abf9bc18998fdfcac6caafec128550e8a99d Mon Sep 17 00:00:00 2001
From: Christiaan Bloemendaal
Date: Wed, 27 May 2020 14:20:37 +0200
Subject: [PATCH 41/44] Fix handles color not being reset to original color
(#266)
Co-authored-by: Christiaan Bloemendaal
---
Scripts/Editor/NodeEditorGUI.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs
index 7c82a12..99cdecf 100755
--- a/Scripts/Editor/NodeEditorGUI.cs
+++ b/Scripts/Editor/NodeEditorGUI.cs
@@ -142,6 +142,7 @@ namespace XNodeEditor {
for (int i = 0; i < gridPoints.Count; ++i)
gridPoints[i] = GridToWindowPosition(gridPoints[i]);
+ Color originalHandlesColor = Handles.color;
Handles.color = gradient.Evaluate(0f);
int length = gridPoints.Count;
switch (path) {
@@ -305,6 +306,7 @@ namespace XNodeEditor {
gridPoints[length - 1] = end;
break;
}
+ Handles.color = originalHandlesColor;
}
/// Draws all connections
From 8ef01722c4f8297866f98ed82a69a3f8aed218a9 Mon Sep 17 00:00:00 2001
From: Thor Brigsted
Date: Fri, 29 May 2020 22:23:10 +0200
Subject: [PATCH 42/44] Updated package.json version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 91252ef..9c1ec7d 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "com.github.siccity.xnode",
"description": "xNode provides a set of APIs and an editor interface for creating and editing custom node graphs.",
- "version": "1.7.0",
+ "version": "1.8.0",
"unity": "2018.1",
"displayName": "xNode"
}
From eb4623a93947d971ab7e8c3881fe336d4b8b20a8 Mon Sep 17 00:00:00 2001
From: Favo Yang
Date: Sun, 31 May 2020 23:48:48 +0800
Subject: [PATCH 43/44] docs: add installation option via OpenUPM (#268)
---
README.md | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/README.md b/README.md
index 9907392..0207ad3 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@
[](https://github.com/Siccity/xNode/issues)
[](https://raw.githubusercontent.com/Siccity/xNode/master/LICENSE.md)
[](https://github.com/Siccity/xNode/wiki)
+[](https://openupm.com/packages/com.github.siccity.xnode/)
[Downloads](https://github.com/Siccity/xNode/releases) / [Asset Store](http://u3d.as/108S) / [Documentation](https://github.com/Siccity/xNode/wiki)
@@ -33,6 +34,7 @@ With a minimal footprint, it is ideal as a base for custom state machines, dialo
* [Examples branch](https://github.com/Siccity/xNode/tree/examples) - look at other small projects
### Installing with Unity Package Manager
+***Via Git URL***
*(Requires Unity version 2018.3.0b7 or above)*
To install this project as a [Git dependency](https://docs.unity3d.com/Manual/upm-git.html) using the Unity Package Manager,
@@ -46,6 +48,14 @@ You will need to have Git installed and available in your system's PATH.
If you are using [Assembly Definitions](https://docs.unity3d.com/Manual/ScriptCompilationAssemblyDefinitionFiles.html) in your project, you will need to add `XNode` and/or `XNodeEditor` as Assembly Definition References.
+***Via OpenUPM***
+
+The package is available on the [openupm registry](https://openupm.com). It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
+
+```
+openupm add com.github.siccity.xnode
+```
+
### Node example:
```csharp
// public classes deriving from Node are registered as nodes for use within a graph
From 60a8e89cdbf728519c8e615fcf261624a02de7c7 Mon Sep 17 00:00:00 2001
From: belivo <56844569+belivo@users.noreply.github.com>
Date: Thu, 11 Jun 2020 15:40:04 -0400
Subject: [PATCH 44/44] fix node and graph multi-edit (#273)
Co-authored-by: Israel Prince-Beliveau
---
Scripts/Editor/GraphAndNodeEditor.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Scripts/Editor/GraphAndNodeEditor.cs b/Scripts/Editor/GraphAndNodeEditor.cs
index c13f782..6859855 100644
--- a/Scripts/Editor/GraphAndNodeEditor.cs
+++ b/Scripts/Editor/GraphAndNodeEditor.cs
@@ -19,6 +19,7 @@ namespace XNodeEditor {
}
}
#else
+ [CanEditMultipleObjects]
public class GlobalGraphEditor : Editor {
public override void OnInspectorGUI() {
serializedObject.Update();
@@ -50,6 +51,7 @@ namespace XNodeEditor {
}
}
#else
+ [CanEditMultipleObjects]
public class GlobalNodeEditor : Editor {
public override void OnInspectorGUI() {
serializedObject.Update();