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; } public virtual string Title() { return "xNode"; } /// Add a node to the graph by type public virtual Node AddNode(Type type) { Node.graphHotfix = this; Node node = CreateInstance(type) as Node; node.UniqueID = node.GetInstanceID(); 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++) // { // DestroyImmediate(nodes[i], false); // } // } // // 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]) 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(); } #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 } }