diff --git a/Examples/NodeToy/NodeGraphExample.asset b/Examples/NodeToy/NodeGraphExample.asset
index 595fa1a..c44ea50 100644
Binary files a/Examples/NodeToy/NodeGraphExample.asset and b/Examples/NodeToy/NodeGraphExample.asset differ
diff --git a/Examples/NodeToy/NodeGraphExample.asset.meta b/Examples/NodeToy/NodeGraphExample.asset.meta
index 1af7b94..d3a3583 100644
--- a/Examples/NodeToy/NodeGraphExample.asset.meta
+++ b/Examples/NodeToy/NodeGraphExample.asset.meta
@@ -1,6 +1,6 @@
fileFormatVersion: 2
-guid: 2e27fbb85ccd5994e932fd8a6d34e4b3
-timeCreated: 1506790922
+guid: ce9064d2750a8344784c005788637f15
+timeCreated: 1507333474
licenseType: Free
NativeFormatImporter:
mainObjectFileID: 11400000
diff --git a/Scripts/Editor/NodeEditorAction.cs b/Scripts/Editor/NodeEditorAction.cs
index 536f759..aaf5b93 100644
--- a/Scripts/Editor/NodeEditorAction.cs
+++ b/Scripts/Editor/NodeEditorAction.cs
@@ -93,6 +93,8 @@ public partial class NodeEditorWindow {
//If connection is valid, save it
if (draggedOutputTarget != null) {
if (graph.nodes.Count != 0) draggedOutput.Connect(draggedOutputTarget);
+ EditorUtility.SetDirty(graph);
+ AssetDatabase.SaveAssets();
}
//Release dragged connection
draggedOutput = null;
diff --git a/Scripts/Node.cs b/Scripts/Node.cs
index e972308..d563231 100644
--- a/Scripts/Node.cs
+++ b/Scripts/Node.cs
@@ -5,23 +5,24 @@ using System;
/// Base class for all nodes
[Serializable]
-public abstract class Node {
+public abstract class Node : ScriptableObject {
/// Name of the node
- [SerializeField] public string name = "";
- [SerializeField] public NodeGraph graph;
+ [NonSerialized] public NodeGraph graph;
[SerializeField] public Rect rect = new Rect(0,0,200,200);
/// Input s. It is recommended not to modify these at hand. Instead, see
- [SerializeField] public NodePort[] inputs = new NodePort[0];
+ [SerializeField] public List inputs = new List();
/// Output s. It is recommended not to modify these at hand. Instead, see
[SerializeField] public NodePort[] outputs = new NodePort[0];
- public int InputCount { get { return inputs.Length; } }
+ public int InputCount { get { return inputs.Count; } }
public int OutputCount { get { return outputs.Length; } }
- /// Constructor
protected Node() {
CachePorts(); //Cache the ports at creation time so we don't have to use reflection at runtime
+ }
+
+ protected void OnEnable() {
Init();
}
@@ -33,7 +34,7 @@ public abstract class Node {
public virtual void OnCreateConnection(NodePort from, NodePort to) { }
public int GetInputId(NodePort input) {
- for (int i = 0; i < inputs.Length; i++) {
+ for (int i = 0; i < inputs.Count; i++) {
if (input == inputs[i]) return i;
}
@@ -55,7 +56,7 @@ public abstract class Node {
}
public void ClearConnections() {
- for (int i = 0; i < inputs.Length; i++) {
+ for (int i = 0; i < inputs.Count; i++) {
inputs[i].ClearConnections();
}
for (int i = 0; i < outputs.Length; i++) {
@@ -99,7 +100,7 @@ public abstract class Node {
else if (outputAttrib != null) outputPorts.Add(new NodePort(fieldInfo[i].Name, fieldInfo[i].FieldType, this, NodePort.IO.Output));
}
- inputs = inputPorts.ToArray();
+ inputs = inputPorts;
outputs = outputPorts.ToArray();
}
}
diff --git a/Scripts/NodeGraph.cs b/Scripts/NodeGraph.cs
index 128add7..d61ec99 100644
--- a/Scripts/NodeGraph.cs
+++ b/Scripts/NodeGraph.cs
@@ -5,7 +5,8 @@ using System;
/// Base class for all node graphs
[Serializable]
-public abstract class NodeGraph : ScriptableObject {
+public abstract class NodeGraph : ScriptableObject, ISerializationCallbackReceiver {
+
/// All nodes in the graph.
/// See:
[SerializeField] public List nodes = new List();
@@ -15,7 +16,10 @@ public abstract class NodeGraph : ScriptableObject {
}
public virtual Node AddNode(Type type) {
- Node node = (Node)Activator.CreateInstance(type);
+ Node node = ScriptableObject.CreateInstance(type) as Node;
+#if UNITY_EDITOR
+ UnityEditor.AssetDatabase.AddObjectToAsset(node, this);
+#endif
nodes.Add(node);
node.graph = this;
return node;
@@ -32,5 +36,14 @@ public abstract class NodeGraph : ScriptableObject {
public void Clear() {
nodes.Clear();
}
+
+ public void OnBeforeSerialize() {
+ }
+
+ public void OnAfterDeserialize() {
+ for (int i = 0; i < nodes.Count; i++) {
+ nodes[i].graph = this;
+ }
+ }
}
diff --git a/Scripts/NodePort.cs b/Scripts/NodePort.cs
index bf626e5..c0df2bb 100644
--- a/Scripts/NodePort.cs
+++ b/Scripts/NodePort.cs
@@ -9,9 +9,7 @@ public class NodePort {
public int ConnectionCount { get { return connections.Count; } }
/// Return the first connection
- public NodePort Connection { get { return connections.Count > 0 ? connections[0] : null; } }
- /// Returns a copy of the connections list
- public List Connections { get { return new List(connections); } }
+ public NodePort Connection { get { return connections.Count > 0 ? connections[0].Port : null; } }
public IO direction { get { return _direction; } }
/// Is this port connected to anytihng?
@@ -20,11 +18,13 @@ public class NodePort {
public bool IsOutput { get { return direction == IO.Output; } }
public Node node { get; private set; }
- public string name { get { return _name; } set { _name = value; } }
+ public string name { get { return _name; } }
public bool enabled { get { return _enabled; } set { _enabled = value; } }
+ public string id { get { return _id; } }
- [SerializeField] private List connections = new List();
-
+ [SerializeField] private List connections = new List();
+ [SerializeField] private string asdf;
+ [SerializeField] private string _id;
[SerializeField] public Type type;
[SerializeField] private string _name;
[SerializeField] private bool _enabled = true;
@@ -35,39 +35,75 @@ public class NodePort {
this.type = type;
this.node = node;
_direction = direction;
+ _id = node.GetInstanceID() + _name;
}
/// Connect this to another
/// The to connect to
public void Connect(NodePort port) {
- if (connections == null) connections = new List();
+ if (connections == null) connections = new List();
if (port == null) { Debug.LogWarning("Cannot connect to null port"); return; }
if (port == this) { Debug.LogWarning("Attempting to connect port to self."); return; }
- if (connections.Contains(port)) { Debug.LogWarning("Port already connected. "); return; }
+ if (IsConnectedTo(port)) { Debug.LogWarning("Port already connected. "); return; }
if (direction == port.direction) { Debug.LogWarning("Cannot connect two " + (direction == IO.Input ? "input" : "output") + " connections"); return; }
- connections.Add(port);
- port.connections.Add(this);
+ connections.Add(new PortConnection(port));
+ if (port.connections == null) port.connections = new List();
+ port.connections.Add(new PortConnection(this));
node.OnCreateConnection(this, port);
port.node.OnCreateConnection(this, port);
}
public NodePort GetConnection(int i) {
- return connections[i];
+ return connections[i].Port;
}
public bool IsConnectedTo(NodePort port) {
- return connections.Contains(port);
+ for (int i = 0; i < connections.Count; i++) {
+ if (connections[i].Port == port) return true;
+ }
+ return false;
}
public void Disconnect(NodePort port) {
- connections.Remove(port);
- port.connections.Remove(this);
+ for (int i = 0; i < connections.Count; i++) {
+ if (connections[i].Port == port) {
+ connections.RemoveAt(i);
+ }
+ }
+ for (int i = 0; i < port.connections.Count; i++) {
+ if (port.connections[i].Port == this) {
+ port.connections.RemoveAt(i);
+ }
+ }
}
public void ClearConnections() {
for (int i = 0; i < connections.Count; i++) {
- connections[i].connections.Remove(this);
+ Disconnect(connections[i].Port);
+ }
+ }
+
+ [Serializable]
+ public class PortConnection {
+ [SerializeField] public Node node;
+ [SerializeField] public string portID;
+ public NodePort Port { get { return port != null ? port : port = GetPort(); } }
+ [NonSerialized] private NodePort port;
+
+ public PortConnection(NodePort port) {
+ this.port = port;
+ node = port.node;
+ portID = port.id;
+ }
+
+ private NodePort GetPort() {
+ for (int i = 0; i < node.OutputCount; i++) {
+ if (node.outputs[i].id == portID) return node.outputs[i];
+ }
+ for (int i = 0; i < node.InputCount; i++) {
+ if (node.inputs[i].id == portID) return node.inputs[i];
+ }
+ return null;
}
- connections.Clear();
}
}