using System; using System.Collections.Generic; using UnityEngine; namespace XNode { /// Base class for all node graphs [Serializable] public abstract class NodeGraph : ScriptableObject { /// /// All nodes in the graph. /// /// See: /// [SerializeField] public List nodes = new List(); /// 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; } /// Add a node to the graph by type public virtual Node AddNode(Type type) { Node.graphHotfix = this; Node node = 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 = 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++) { if (nodes[i] != null) { Destroy(nodes[i]); } } } nodes.Clear(); } /// Create a new deep copy of this graph public virtual 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]); 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(); } #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) { type0 = type; type1 = null; type2 = null; } /// Automatically ensures the existance of a certain node type, and prevents it from being deleted public RequireNodeAttribute(Type type, Type type2) { type0 = type; 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) { type0 = type; type1 = type2; this.type2 = type3; } public bool Requires(Type type) { if (type == null) { return false; } if (type == type0) { return true; } if (type == type1) { return true; } if (type == type2) { return true; } return false; } } #endregion } }