using System; using System.Collections.Generic; using UnityEngine; namespace XNode { /// Base class for all node graphs [Serializable] public abstract class NodeGraph : ScriptableObject, INodeGraph { /// All nodes in the graph. /// See: [SerializeField] public List nodes = new List(); #region Interface implementation IEnumerable INodeGraph.Nodes { get { foreach (Node node in nodes) yield return node; } } UnityEngine.Object INodeGraph.Object { get { return this; } } INode INodeGraph.AddNode(Type type) { return AddNode(type); } void INodeGraph.MoveNodeToTop(INode node) { MoveNodeToTop(node as Node); } INode INodeGraph.CopyNode(INode original) { return CopyNode(original as Node); } void INodeGraph.RemoveNode(INode node) { RemoveNode(node as Node); } #endregion /// Add a node to the graph by type (convenience method - will call the System.Type version) public T AddNode() where T : Node { return AddNode(typeof(T)) as T; } /// Draw this node on top of other nodes by placing it last in the graph.nodes list public void MoveNodeToTop(XNode.Node node) { int index; while ((index = nodes.IndexOf(node as Node)) != nodes.Count - 1) { nodes[index] = nodes[index + 1]; nodes[index + 1] = node as Node; } } /// Add a node to the graph by type public virtual Node AddNode(Type type) { Node.graphHotfix = this; Node node = ScriptableObject.CreateInstance(type) as Node; node.graph = this; nodes.Add(node); return node; } /// Creates a copy of the original node in the graph public virtual Node CopyNode(Node original) { Node.graphHotfix = this; Node node = ScriptableObject.Instantiate(original); node.graph = this; node.ClearConnections(); nodes.Add(node); return node; } /// Safely remove a node and all its connections /// The node to remove public virtual void RemoveNode(Node node) { node.ClearConnections(); nodes.Remove(node); if (Application.isPlaying) Destroy(node); } /// Remove all nodes and connections from the graph public virtual void Clear() { if (Application.isPlaying) { for (int i = 0; i < nodes.Count; i++) { Destroy(nodes[i]); } } nodes.Clear(); } /// Create a new deep copy of this graph public virtual XNode.NodeGraph Copy() { // Instantiate a new nodegraph instance NodeGraph graph = Instantiate(this); // Instantiate all nodes inside the graph for (int i = 0; i < nodes.Count; i++) { if (nodes[i] == null) continue; Node.graphHotfix = graph; Node node = Instantiate(nodes[i]) as Node; node.graph = graph; graph.nodes[i] = node; } // Redirect all connections for (int i = 0; i < graph.nodes.Count; i++) { if (graph.nodes[i] == null) continue; foreach (NodePort port in graph.nodes[i].Ports) { port.Redirect(nodes, graph.nodes); } } return graph; } protected virtual void OnDestroy() { // Remove all nodes prior to graph destruction Clear(); } } }