diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs
index 3a70848..41bb196 100644
--- a/Scripts/Editor/NodeEditorAction.cs
+++ b/Scripts/Editor/NodeEditorAction.cs
@@ -4,25 +4,21 @@ using UnityEngine;
namespace XNodeEditor {
public partial class NodeEditorWindow {
-
+ public enum NodeActivity { Idle, HoldHeader, DragHeader, HoldGrid, DragGrid }
+ public static NodeActivity currentActivity = NodeActivity.Idle;
public static bool isPanning { get; private set; }
- public static Vector2 dragOffset;
+ public static Vector2[] dragOffset;
- private bool IsDraggingNode { get { return draggedNode != null; } }
private bool IsDraggingPort { get { return draggedOutput != null; } }
private bool IsHoveringPort { get { return hoveredPort != null; } }
private bool IsHoveringNode { get { return hoveredNode != null; } }
- private bool HasSelectedNode { get { return selectedNode != null; } }
-
private XNode.Node hoveredNode = null;
-
- [NonSerialized] private XNode.Node selectedNode = null;
- [NonSerialized] private XNode.Node draggedNode = null;
[NonSerialized] private XNode.NodePort hoveredPort = null;
[NonSerialized] private XNode.NodePort draggedOutput = null;
[NonSerialized] private XNode.NodePort draggedOutputTarget = null;
-
private Rect nodeRects;
+ private Vector2 dragBoxStart;
+ private UnityEngine.Object[] preBoxSelection;
public void Controls() {
wantsMouseMove = true;
@@ -45,23 +41,44 @@ namespace XNodeEditor {
draggedOutputTarget = null;
}
Repaint();
- } else if (IsDraggingNode) {
- draggedNode.position = WindowToGridPosition(e.mousePosition) + dragOffset;
- if (NodeEditorPreferences.gridSnap) {
- draggedNode.position.x = (Mathf.Round((draggedNode.position.x + 8) / 16) * 16) - 8;
- draggedNode.position.y = (Mathf.Round((draggedNode.position.y + 8) / 16) * 16) - 8;
+ } else if (currentActivity == NodeActivity.HoldHeader || currentActivity == NodeActivity.DragHeader) {
+ for (int i = 0; i < Selection.objects.Length; i++) {
+ if (Selection.objects[i] is XNode.Node) {
+ XNode.Node node = Selection.objects[i] as XNode.Node;
+ node.position = WindowToGridPosition(e.mousePosition) + dragOffset[i];
+ if (NodeEditorPreferences.GridSnap) {
+ node.position.x = (Mathf.Round((node.position.x + 8) / 16) * 16) - 8;
+ node.position.y = (Mathf.Round((node.position.y + 8) / 16) * 16) - 8;
+ }
+ }
+ }
+ currentActivity = NodeActivity.DragHeader;
+ Repaint();
+ } else if (currentActivity == NodeActivity.HoldGrid) {
+ currentActivity = NodeActivity.DragGrid;
+ preBoxSelection = Selection.objects;
+ dragBoxStart = WindowToGridPosition(e.mousePosition);
+ Repaint();
+ } else if (currentActivity == NodeActivity.DragGrid) {
+ foreach (XNode.Node node in graph.nodes) {
+
}
Repaint();
}
} else if (e.button == 1 || e.button == 2) {
- panOffset += e.delta * zoom;
+ Vector2 tempOffset = panOffset;
+ tempOffset += e.delta * zoom;
+ // Round value to increase crispyness of UI text
+ tempOffset.x = Mathf.Round(tempOffset.x);
+ tempOffset.y = Mathf.Round(tempOffset.y);
+ panOffset = tempOffset;
isPanning = true;
}
break;
case EventType.MouseDown:
Repaint();
if (e.button == 0) {
- SelectNode(hoveredNode);
+
if (IsHoveringPort) {
if (hoveredPort.IsOutput) {
draggedOutput = hoveredPort;
@@ -77,8 +94,23 @@ namespace XNodeEditor {
}
}
} else if (IsHoveringNode && IsHoveringTitle(hoveredNode)) {
- draggedNode = hoveredNode;
- dragOffset = hoveredNode.position - WindowToGridPosition(e.mousePosition);
+ // If mousedown on node header, select or deselect
+ if (!Selection.Contains(hoveredNode)) SelectNode(hoveredNode, e.control || e.shift);
+ else if (e.control || e.shift) DeselectNode(hoveredNode);
+ e.Use();
+ currentActivity = NodeActivity.HoldHeader;
+ dragOffset = new Vector2[Selection.objects.Length];
+ for (int i = 0; i < dragOffset.Length; i++) {
+ if (Selection.objects[i] is XNode.Node) {
+ XNode.Node node = Selection.objects[i] as XNode.Node;
+ dragOffset[i] = node.position - WindowToGridPosition(e.mousePosition);
+ }
+ }
+ }
+ // If mousedown on grid background, deselect all
+ else if (!IsHoveringNode) {
+ currentActivity = NodeActivity.HoldGrid;
+ if (!e.control && !e.shift) Selection.activeObject = null;
}
}
break;
@@ -97,18 +129,30 @@ namespace XNodeEditor {
draggedOutput = null;
draggedOutputTarget = null;
EditorUtility.SetDirty(graph);
- Repaint();
AssetDatabase.SaveAssets();
- } else if (IsDraggingNode) {
- draggedNode = null;
+ } else if (currentActivity == NodeActivity.DragHeader) {
AssetDatabase.SaveAssets();
- } else if (GUIUtility.hotControl != 0) {
+ } else if (!IsHoveringNode) {
+ // If click outside node, release field focus
+ if (!isPanning) {
+ GUIUtility.hotControl = 0;
+ GUIUtility.keyboardControl = 0;
+ }
AssetDatabase.SaveAssets();
}
+
+ // If click node header, select single node.
+ if (currentActivity == NodeActivity.HoldHeader && !(e.control || e.shift)) {
+ SelectNode(hoveredNode, false);
+ }
+
+ Repaint();
+ currentActivity = NodeActivity.Idle;
} else if (e.button == 1) {
if (!isPanning) {
if (IsHoveringNode && IsHoveringTitle(hoveredNode)) {
- ShowNodeContextMenu(hoveredNode);
+ if (!Selection.Contains(hoveredNode)) SelectNode(hoveredNode, false);
+ ShowNodeContextMenu();
} else if (!IsHoveringNode) {
ShowGraphContextMenu();
}
@@ -116,6 +160,18 @@ namespace XNodeEditor {
isPanning = false;
}
break;
+ case EventType.KeyDown:
+ if (e.keyCode == KeyCode.Delete) RemoveSelectedNodes();
+ else if (e.keyCode == KeyCode.D && e.control) DublicateSelectedNodes();
+ Repaint();
+ break;
+ case EventType.Ignore:
+ // If release mouse outside window
+ if (e.rawType == EventType.MouseUp && currentActivity == NodeActivity.DragGrid) {
+ Repaint();
+ currentActivity = NodeActivity.Idle;
+ }
+ break;
}
}
@@ -131,6 +187,31 @@ namespace XNodeEditor {
Repaint();
}
+ /// Remove nodes in the graph in Selection.objects
+ public void RemoveSelectedNodes() {
+ foreach (UnityEngine.Object item in Selection.objects) {
+ if (item is XNode.Node) {
+ XNode.Node node = item as XNode.Node;
+ graph.RemoveNode(node);
+ }
+ }
+ }
+
+ // Dublicate selected nodes and select the dublicates
+ public void DublicateSelectedNodes() {
+ UnityEngine.Object[] newNodes = new UnityEngine.Object[Selection.objects.Length];
+ for (int i = 0; i < Selection.objects.Length; i++) {
+ if (Selection.objects[i] is XNode.Node) {
+ XNode.Node node = Selection.objects[i] as XNode.Node;
+ if (node.graph != graph) continue; // ignore nodes selected in another graph
+ XNode.Node n = graph.CopyNode(node);
+ n.position = node.position + new Vector2(30, 30);
+ newNodes[i] = n;
+ }
+ }
+ Selection.objects = newNodes;
+ }
+
/// Draw a connection as we are dragging it
public void DrawDraggedConnection() {
if (IsDraggingPort) {
diff --git a/Scripts/Editor/NodeEditorGUI.cs b/Scripts/Editor/NodeEditorGUI.cs
index f8ab6d5..e3f8c4c 100644
--- a/Scripts/Editor/NodeEditorGUI.cs
+++ b/Scripts/Editor/NodeEditorGUI.cs
@@ -6,7 +6,8 @@ using UnityEngine;
namespace XNodeEditor {
/// Contains GUI methods
public partial class NodeEditorWindow {
- NodeGraphEditor currentGraphEditor;
+ private NodeGraphEditor currentGraphEditor;
+ private List selectionCache;
private void OnGUI() {
Event e = Event.current;
@@ -20,6 +21,7 @@ namespace XNodeEditor {
DrawConnections();
DrawDraggedConnection();
DrawNodes();
+ DrawBox();
DrawTooltip();
GUI.matrix = m;
@@ -70,27 +72,45 @@ namespace XNodeEditor {
GUI.DrawTextureWithTexCoords(rect, crossTex, new Rect(tileOffset + new Vector2(0.5f, 0.5f), tileAmount));
}
+ public void DrawBox() {
+ if (currentActivity == NodeActivity.DragGrid) {
+ Vector2 curPos = WindowToGridPosition(Event.current.mousePosition);
+ Vector2 size = curPos - dragBoxStart;
+ Rect r = new Rect(dragBoxStart, size);
+ r.position = GridToWindowPosition(r.position);
+ r.size /= zoom;
+ Handles.DrawSolidRectangleWithOutline(r, new Color(0, 0, 0, 0.1f), new Color(1, 1, 1, 0.6f));
+ }
+ }
+
public static bool DropdownButton(string name, float width) {
return GUILayout.Button(name, EditorStyles.toolbarDropDown, GUILayout.Width(width));
}
- /// Show right-click context menu for a node
- public void ShowNodeContextMenu(XNode.Node node) {
+ /// Show right-click context menu for selected nodes
+ public void ShowNodeContextMenu() {
GenericMenu contextMenu = new GenericMenu();
- contextMenu.AddItem(new GUIContent("Move To Top"), false, () => {
- int index;
- while ((index = graph.nodes.IndexOf(node)) != graph.nodes.Count - 1) {
- graph.nodes[index] = graph.nodes[index + 1];
- graph.nodes[index + 1] = node;
- }
- });
- contextMenu.AddItem(new GUIContent("Duplicate"), false, () => {
- XNode.Node n = graph.CopyNode(node);
- n.position = node.position + new Vector2(30, 30);
- });
- contextMenu.AddItem(new GUIContent("Remove"), false, () => graph.RemoveNode(node));
+ // If only one node is selected
+ if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
+ XNode.Node node = Selection.activeObject as XNode.Node;
+ contextMenu.AddItem(new GUIContent("Move To Top"), false, () => {
+ int index;
+ while ((index = graph.nodes.IndexOf(node)) != graph.nodes.Count - 1) {
+ graph.nodes[index] = graph.nodes[index + 1];
+ graph.nodes[index + 1] = node;
+ }
+ });
+ }
+
+ contextMenu.AddItem(new GUIContent("Duplicate"), false, DublicateSelectedNodes);
+ contextMenu.AddItem(new GUIContent("Remove"), false, RemoveSelectedNodes);
+
+ // If only one node is selected
+ if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
+ XNode.Node node = Selection.activeObject as XNode.Node;
+ AddCustomContextMenuItems(contextMenu, node);
+ }
- AddCustomContextMenuItems(contextMenu, node);
contextMenu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
}
@@ -168,17 +188,20 @@ namespace XNodeEditor {
private void DrawNodes() {
Event e = Event.current;
+ if (e.type == EventType.Layout) {
+ selectionCache = new List(Selection.objects);
+ }
if (e.type == EventType.Repaint) {
portConnectionPoints.Clear();
nodeWidths.Clear();
}
- //Selected node is hashed before and after node GUI to detect changes
+ //Active node is hashed before and after node GUI to detect changes
int nodeHash = 0;
System.Reflection.MethodInfo onValidate = null;
- if (selectedNode != null) {
- onValidate = selectedNode.GetType().GetMethod("OnValidate");
- if (onValidate != null) nodeHash = selectedNode.GetHashCode();
+ if (Selection.activeObject != null && Selection.activeObject is XNode.Node) {
+ onValidate = Selection.activeObject.GetType().GetMethod("OnValidate");
+ if (onValidate != null) nodeHash = Selection.activeObject.GetHashCode();
}
BeginZoomed(position, zoom);
@@ -190,6 +213,8 @@ namespace XNodeEditor {
hoveredPort = null;
}
+ List preSelection = new List(preBoxSelection);
+
//Save guiColor so we can revert it
Color guiColor = GUI.color;
for (int n = 0; n < graph.nodes.Count; n++) {
@@ -206,9 +231,23 @@ namespace XNodeEditor {
GUILayout.BeginArea(new Rect(nodePos, new Vector2(nodeEditor.GetWidth(), 4000)));
- GUIStyle style = NodeEditorResources.styles.nodeBody;
- GUI.color = nodeEditor.GetTint();
- GUILayout.BeginVertical(new GUIStyle(style));
+ bool selected = selectionCache.Contains(graph.nodes[n]);
+
+ if (selected) {
+ GUIStyle style = new GUIStyle(NodeEditorResources.styles.nodeBody);
+ GUIStyle highlightStyle = new GUIStyle(NodeEditorResources.styles.nodeHighlight);
+ highlightStyle.padding = style.padding;
+ style.padding = new RectOffset();
+ GUI.color = nodeEditor.GetTint();
+ GUILayout.BeginVertical(new GUIStyle(style));
+ GUI.color = NodeEditorPreferences.HighlightColor;
+ GUILayout.BeginVertical(new GUIStyle(highlightStyle));
+ } else {
+ GUIStyle style = NodeEditorResources.styles.nodeBody;
+ GUI.color = nodeEditor.GetTint();
+ GUILayout.BeginVertical(new GUIStyle(style));
+ }
+
GUI.color = guiColor;
EditorGUI.BeginChangeCheck();
@@ -235,6 +274,7 @@ namespace XNodeEditor {
}
GUILayout.EndVertical();
+ if (selected) GUILayout.EndVertical();
if (e.type != EventType.Layout) {
//Check if we are hovering this node
@@ -242,6 +282,16 @@ namespace XNodeEditor {
Rect windowRect = new Rect(nodePos, nodeSize);
if (windowRect.Contains(mousePos)) hoveredNode = node;
+ //If dragging a selection box, add nodes inside to selection
+ if (currentActivity == NodeActivity.DragGrid) {
+ Vector2 startPos = GridToWindowPositionNoClipped(dragBoxStart);
+ Vector2 size = mousePos - startPos;
+ if (size.x < 0) { startPos.x += size.x; size.x = Mathf.Abs(size.x); }
+ if (size.y < 0) { startPos.y += size.y; size.y = Mathf.Abs(size.y); }
+ Rect r = new Rect(startPos, size);
+ if (windowRect.Overlaps(r)) preSelection.Add(node);
+ }
+
//Check if we are hovering any of this nodes ports
//Check input ports
foreach (XNode.NodePort input in node.Inputs) {
@@ -262,13 +312,14 @@ namespace XNodeEditor {
GUILayout.EndArea();
}
+ if (e.type != EventType.Layout && currentActivity == NodeActivity.DragGrid) Selection.objects = preSelection.ToArray();
EndZoomed(position, zoom);
//If a change in hash is detected in the selected node, call OnValidate method.
//This is done through reflection because OnValidate is only relevant in editor,
//and thus, the code should not be included in build.
- if (selectedNode != null) {
- if (onValidate != null && nodeHash != selectedNode.GetHashCode()) onValidate.Invoke(selectedNode, null);
+ if (nodeHash != 0) {
+ if (onValidate != null && nodeHash != Selection.activeObject.GetHashCode()) onValidate.Invoke(Selection.activeObject, null);
}
}
diff --git a/Scripts/Editor/NodeEditorPreferences.cs b/Scripts/Editor/NodeEditorPreferences.cs
index 910d426..0df1ad2 100644
--- a/Scripts/Editor/NodeEditorPreferences.cs
+++ b/Scripts/Editor/NodeEditorPreferences.cs
@@ -9,7 +9,7 @@ namespace XNodeEditor {
public static Texture2D gridTexture {
get {
VerifyLoaded();
- if (_gridTexture == null) _gridTexture = NodeEditorResources.GenerateGridTexture(_gridLineColor, _gridBgColor);
+ if (_gridTexture == null) _gridTexture = NodeEditorResources.GenerateGridTexture(settings.gridLineColor, settings.gridBgColor);
return _gridTexture;
}
}
@@ -17,27 +17,53 @@ namespace XNodeEditor {
public static Texture2D crossTexture {
get {
VerifyLoaded();
- if (_crossTexture == null) _crossTexture = NodeEditorResources.GenerateCrossTexture(_gridLineColor);
+ if (_crossTexture == null) _crossTexture = NodeEditorResources.GenerateCrossTexture(settings.gridLineColor);
return _crossTexture;
}
}
private static Texture2D _crossTexture;
- /// Have we loaded the prefs yet
- private static bool prefsLoaded = false;
+ public static bool GridSnap { get { VerifyLoaded(); return settings.gridSnap; } }
+ public static Color HighlightColor { get { VerifyLoaded(); return settings.highlightColor; } }
+
+ private static Dictionary typeColors = new Dictionary();
+ private static Settings settings;
+
+ [System.Serializable]
+ private class Settings : ISerializationCallbackReceiver {
+ public Color32 gridLineColor = new Color(0.45f, 0.45f, 0.45f);
+ public Color32 gridBgColor = new Color(0.18f, 0.18f, 0.18f);
+ public Color32 highlightColor = new Color32(255, 223, 255, 255);
+ public bool gridSnap = true;
+ public string typeColorsData = "";
+ public Dictionary typeColors = new Dictionary();
+
+ public void OnAfterDeserialize() {
+ // Deserialize typeColorsData
+ typeColors = new Dictionary();
+ string[] data = typeColorsData.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
+ for (int i = 0; i < data.Length; i += 2) {
+ Color col;
+ if (ColorUtility.TryParseHtmlString("#" + data[i + 1], out col)) {
+ typeColors.Add(data[i], col);
+ }
+ }
+ }
+
+ public void OnBeforeSerialize() {
+ // Serialize typeColors
+ typeColorsData = "";
+ foreach (var item in typeColors) {
+ typeColorsData += item.Key + "," + ColorUtility.ToHtmlStringRGB(item.Value) + ",";
+ }
+ }
+ }
- private static Dictionary typeColors;
- private static Dictionary generatedTypeColors;
- public static bool gridSnap { get { VerifyLoaded(); return _gridSnap; } }
- private static bool _gridSnap = true;
- public static Color gridLineColor { get { VerifyLoaded(); return _gridLineColor; } }
- private static Color _gridLineColor;
- public static Color gridBgColor { get { VerifyLoaded(); return _gridBgColor; } }
- private static Color _gridBgColor;
[PreferenceItem("Node Editor")]
private static void PreferencesGUI() {
VerifyLoaded();
+ NodeSettingsGUI();
GridSettingsGUI();
TypeColorsGUI();
if (GUILayout.Button(new GUIContent("Set Default", "Reset all values to default"), GUILayout.Width(120))) {
@@ -48,15 +74,25 @@ namespace XNodeEditor {
private static void GridSettingsGUI() {
//Label
EditorGUILayout.LabelField("Grid", EditorStyles.boldLabel);
- _gridSnap = EditorGUILayout.Toggle("Snap", _gridSnap);
+ settings.gridSnap = EditorGUILayout.Toggle("Snap", settings.gridSnap);
- //EditorGUIUtility.labelWidth = 30;
- _gridLineColor = EditorGUILayout.ColorField("Color", _gridLineColor);
- _gridBgColor = EditorGUILayout.ColorField(" ", _gridBgColor);
+ settings.gridLineColor = EditorGUILayout.ColorField("Color", settings.gridLineColor);
+ settings.gridBgColor = EditorGUILayout.ColorField(" ", settings.gridBgColor);
+ if (GUI.changed) {
+ SavePrefs();
+ _gridTexture = NodeEditorResources.GenerateGridTexture(settings.gridLineColor, settings.gridBgColor);
+ _crossTexture = NodeEditorResources.GenerateCrossTexture(settings.gridLineColor);
+ NodeEditorWindow.RepaintAll();
+ }
+ EditorGUILayout.Space();
+ }
+
+ private static void NodeSettingsGUI() {
+ //Label
+ EditorGUILayout.LabelField("Node", EditorStyles.boldLabel);
+ settings.highlightColor = EditorGUILayout.ColorField("Selection", settings.highlightColor);
if (GUI.changed) {
SavePrefs();
- _gridTexture = NodeEditorResources.GenerateGridTexture(_gridLineColor, _gridBgColor);
- _crossTexture = NodeEditorResources.GenerateCrossTexture(_gridLineColor);
NodeEditorWindow.RepaintAll();
}
EditorGUILayout.Space();
@@ -64,100 +100,54 @@ namespace XNodeEditor {
private static void TypeColorsGUI() {
//Label
- EditorGUILayout.LabelField("Type colors", EditorStyles.boldLabel);
+ EditorGUILayout.LabelField("Types", EditorStyles.boldLabel);
- //Get saved type keys
- string[] typeKeys = new string[typeColors.Count];
- typeColors.Keys.CopyTo(typeKeys, 0);
- //Display saved type colors
- foreach (var key in typeKeys) {
- EditorGUILayout.BeginHorizontal();
- if (!EditorGUILayout.Toggle(new GUIContent(key, key), true)) {
- typeColors.Remove(key);
- SavePrefs();
- EditorGUILayout.EndHorizontal();
- continue;
- }
+ //Display type colors. Save them if they are edited by the user
+ List keys = new List(typeColors.Keys);
+ foreach (string key in keys) {
Color col = typeColors[key];
- col = EditorGUILayout.ColorField(col);
- typeColors[key] = col;
- EditorGUILayout.EndHorizontal();
- }
- if (GUI.changed) {
- SavePrefs();
- NodeEditorWindow.RepaintAll();
- }
-
- //Get generated type keys
- string[] generatedTypeKeys = new string[generatedTypeColors.Count];
- generatedTypeColors.Keys.CopyTo(generatedTypeKeys, 0);
- //Display generated type colors
- foreach (var key in generatedTypeKeys) {
+ EditorGUI.BeginChangeCheck();
EditorGUILayout.BeginHorizontal();
- if (EditorGUILayout.Toggle(new GUIContent(key, key), false)) {
- typeColors.Add(key, generatedTypeColors[key]);
- generatedTypeColors.Remove(key);
- SavePrefs();
- EditorGUILayout.EndHorizontal();
- continue;
- }
- Color col = generatedTypeColors[key];
- EditorGUI.BeginDisabledGroup(true);
- col = EditorGUILayout.ColorField(col);
- EditorGUI.EndDisabledGroup();
-
+ col = EditorGUILayout.ColorField(key, col);
EditorGUILayout.EndHorizontal();
+ if (EditorGUI.EndChangeCheck()) {
+ typeColors[key] = col;
+ if (settings.typeColors.ContainsKey(key)) settings.typeColors[key] = col;
+ else settings.typeColors.Add(key, col);
+ SavePrefs();
+ NodeEditorWindow.RepaintAll();
+ }
}
}
- private static void LoadPrefs() {
- //Load type colors
- generatedTypeColors = new Dictionary();
+ private static Settings LoadPrefs() {
+ // Remove obsolete editorprefs
+ if (EditorPrefs.HasKey("xnode_typecolors")) EditorPrefs.DeleteKey("xnode_typecolors");
+ if (EditorPrefs.HasKey("xnode_gridcolor0")) EditorPrefs.DeleteKey("xnode_gridcolor0");
+ if (EditorPrefs.HasKey("xnode_gridcolor1")) EditorPrefs.DeleteKey("xnode_gridcolor1");
+ if (EditorPrefs.HasKey("xnode_gridsnap")) EditorPrefs.DeleteKey("xnode_gridcolor1");
- if (!EditorPrefs.HasKey("xnode_typecolors")) EditorPrefs.SetString("xnode_typecolors", "");
- string[] data = EditorPrefs.GetString("xnode_typecolors").Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- typeColors = new Dictionary();
- for (int i = 0; i < data.Length; i += 2) {
- Color col;
- if (ColorUtility.TryParseHtmlString("#" + data[i + 1], out col)) {
- typeColors.Add(data[i], col);
- }
- }
-
- //Load grid colors
- if (!EditorPrefs.HasKey("xnode_gridcolor0")) EditorPrefs.SetString("xnode_gridcolor0", ColorUtility.ToHtmlStringRGB(new Color(0.45f, 0.45f, 0.45f)));
- ColorUtility.TryParseHtmlString("#" + EditorPrefs.GetString("xnode_gridcolor0"), out _gridLineColor);
- if (!EditorPrefs.HasKey("xnode_gridcolor1")) EditorPrefs.SetString("xnode_gridcolor1", ColorUtility.ToHtmlStringRGB(new Color(0.18f, 0.18f, 0.18f)));
- ColorUtility.TryParseHtmlString("#" + EditorPrefs.GetString("xnode_gridcolor1"), out _gridBgColor);
-
- //Load snap option
- if (EditorPrefs.HasKey("xnode_gridsnap")) _gridSnap = EditorPrefs.GetBool("xnode_gridsnap");
-
- NodeEditorWindow.RepaintAll();
- prefsLoaded = true;
+ if (!EditorPrefs.HasKey("xNode.Settings")) EditorPrefs.SetString("xNode.Settings", JsonUtility.ToJson(new Settings()));
+ return JsonUtility.FromJson(EditorPrefs.GetString("xNode.Settings"));
}
/// Delete all prefs
public static void ResetPrefs() {
- if (EditorPrefs.HasKey("xnode_typecolors")) EditorPrefs.DeleteKey("xnode_typecolors");
- if (EditorPrefs.HasKey("xnode_gridcolor0")) EditorPrefs.DeleteKey("xnode_gridcolor0");
- if (EditorPrefs.HasKey("xnode_gridcolor1")) EditorPrefs.DeleteKey("xnode_gridcolor1");
- LoadPrefs();
+ if (EditorPrefs.HasKey("xNode.Settings")) EditorPrefs.DeleteKey("xNode.Settings");
+
+ settings = LoadPrefs();
+ typeColors = new Dictionary();
+ _gridTexture = NodeEditorResources.GenerateGridTexture(settings.gridLineColor, settings.gridBgColor);
+ _crossTexture = NodeEditorResources.GenerateCrossTexture(settings.gridLineColor);
+ NodeEditorWindow.RepaintAll();
}
private static void SavePrefs() {
- string s = "";
- foreach (var item in typeColors) {
- s += item.Key + "," + ColorUtility.ToHtmlStringRGB(item.Value) + ",";
- }
- EditorPrefs.SetString("xnode_typecolors", s);
- EditorPrefs.SetString("xnode_gridcolor0", ColorUtility.ToHtmlStringRGB(_gridLineColor));
- EditorPrefs.SetString("xnode_gridcolor1", ColorUtility.ToHtmlStringRGB(_gridBgColor));
- EditorPrefs.SetBool("xnode_gridsnap", _gridSnap);
+ EditorPrefs.SetString("xNode.Settings", JsonUtility.ToJson(settings));
}
private static void VerifyLoaded() {
- if (!prefsLoaded) LoadPrefs();
+ if (settings == null) settings = LoadPrefs();
}
/// Return color based on type
@@ -165,15 +155,18 @@ namespace XNodeEditor {
VerifyLoaded();
if (type == null) return Color.gray;
string typeName = type.PrettyName();
- if (typeColors.ContainsKey(typeName)) return typeColors[typeName];
- if (generatedTypeColors.ContainsKey(typeName)) return generatedTypeColors[typeName];
- #if UNITY_5_4_OR_NEWER
- UnityEngine.Random.InitState(typeName.GetHashCode());
- #else
- UnityEngine.Random.seed = typeName.GetHashCode();
- #endif
- generatedTypeColors.Add(typeName, new Color(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value));
- return generatedTypeColors[typeName];
+ if (!typeColors.ContainsKey(typeName)) {
+ if (settings.typeColors.ContainsKey(typeName)) typeColors.Add(typeName, settings.typeColors[typeName]);
+ else {
+#if UNITY_5_4_OR_NEWER
+ UnityEngine.Random.InitState(typeName.GetHashCode());
+#else
+ UnityEngine.Random.seed = typeName.GetHashCode();
+#endif
+ typeColors.Add(typeName, new Color(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value));
+ }
+ }
+ return typeColors[typeName];
}
}
}
\ No newline at end of file
diff --git a/Scripts/Editor/NodeEditorResources.cs b/Scripts/Editor/NodeEditorResources.cs
index 490743b..9b55c8f 100644
--- a/Scripts/Editor/NodeEditorResources.cs
+++ b/Scripts/Editor/NodeEditorResources.cs
@@ -9,13 +9,15 @@ namespace XNodeEditor {
private static Texture2D _dotOuter;
public static Texture2D nodeBody { get { return _nodeBody != null ? _nodeBody : _nodeBody = Resources.Load("xnode_node"); } }
private static Texture2D _nodeBody;
+ public static Texture2D nodeHighlight { get { return _nodeHighlight != null ? _nodeHighlight : _nodeHighlight = Resources.Load("xnode_node_highlight"); } }
+ private static Texture2D _nodeHighlight;
// Styles
public static Styles styles { get { return _styles != null ? _styles : _styles = new Styles(); } }
public static Styles _styles = null;
public class Styles {
- public GUIStyle inputPort, outputPort, nodeHeader, nodeBody, tooltip;
+ public GUIStyle inputPort, outputPort, nodeHeader, nodeBody, tooltip, nodeHighlight;
public Styles() {
GUIStyle baseStyle = new GUIStyle("Label");
@@ -39,6 +41,10 @@ namespace XNodeEditor {
nodeBody.border = new RectOffset(32, 32, 32, 32);
nodeBody.padding = new RectOffset(16, 16, 4, 16);
+ nodeHighlight = new GUIStyle();
+ nodeHighlight.normal.background = NodeEditorResources.nodeHighlight;
+ nodeHighlight.border = new RectOffset(32, 32, 32, 32);
+
tooltip = new GUIStyle("helpBox");
tooltip.alignment = TextAnchor.MiddleCenter;
}
@@ -50,8 +56,8 @@ namespace XNodeEditor {
for (int y = 0; y < 64; y++) {
for (int x = 0; x < 64; x++) {
Color col = bg;
- if (y % 16 == 0 || x % 16 == 0) col = Color.Lerp(line,bg,0.65f);
- if (y == 63 || x == 63) col = Color.Lerp(line,bg,0.35f);
+ if (y % 16 == 0 || x % 16 == 0) col = Color.Lerp(line, bg, 0.65f);
+ if (y == 63 || x == 63) col = Color.Lerp(line, bg, 0.35f);
cols[(y * 64) + x] = col;
}
}
diff --git a/Scripts/Editor/NodeEditorWindow.cs b/Scripts/Editor/NodeEditorWindow.cs
index 3c79e71..cf35616 100644
--- a/Scripts/Editor/NodeEditorWindow.cs
+++ b/Scripts/Editor/NodeEditorWindow.cs
@@ -77,8 +77,18 @@ namespace XNodeEditor {
return new Vector2(xOffset, yOffset);
}
- public void SelectNode(XNode.Node node) {
- selectedNode = node;
+ public void SelectNode(XNode.Node node, bool add) {
+ if (add) {
+ List