using System; using System.Collections.Generic; using UnityEngine; /// Base class for all nodes [Serializable] public abstract class Node : ScriptableObject { public enum ShowBackingValue { /// Never show the backing value Never, /// Show the backing value only when the port does not have any active connections Unconnected, /// Always show the backing value Always } /// Parent [SerializeField] public NodeGraph graph; /// Position on the [SerializeField] public Vector2 position; /// Input s. It is recommended not to modify these at hand. Instead, see [SerializeField] public List inputs = new List(); /// Output s. It is recommended not to modify these at hand. Instead, see [SerializeField] public List outputs = new List(); public int InputCount { get { return inputs.Count; } } public int OutputCount { get { return outputs.Count; } } protected void OnEnable() { NodeDataCache.UpdatePorts(this, inputs, outputs); Init(); } /// Checks all connections for invalid references, and removes them. public void VerifyConnections() { for (int i = 0; i < InputCount; i++) { inputs[i].VerifyConnections(); } for (int i = 0; i < OutputCount; i++) { outputs[i].VerifyConnections(); } } /// Returns input or output port which matches fieldName public NodePort GetPortByFieldName(string fieldName) { NodePort port = GetOutputByFieldName(fieldName); if (port != null) return port; else return GetInputByFieldName(fieldName); } /// Returns output port which matches fieldName. Returns null if none found. public NodePort GetOutputByFieldName(string fieldName) { for (int i = 0; i < OutputCount; i++) { if (outputs[i].fieldName == fieldName) return outputs[i]; } return null; } /// Returns input port which matches fieldName. Returns null if none found. public NodePort GetInputByFieldName(string fieldName) { for (int i = 0; i < InputCount; i++) { if (inputs[i].fieldName == fieldName) return inputs[i]; } return null; } /// Return input value for a specified port. Returns fallback value if no ports are connected /// Field name of requested input port /// If no ports are connected, this value will be returned public T GetInputByFieldName(string fieldName, T fallback = default(T)) { NodePort port = GetInputByFieldName(fieldName); if (port != null && port.IsConnected) return port.GetInputValue(); else return fallback; } /// Return all input values for a specified port. Returns fallback value if no ports are connected /// Field name of requested input port /// If no ports are connected, this value will be returned public T[] GetInputsByFieldName(string fieldName, params T[] fallback) { NodePort port = GetInputByFieldName(fieldName); if (port != null && port.IsConnected) return port.GetInputValues(); else return fallback; } /// Returns a value based on requested port output. Should be overridden before used. /// The requested port. public virtual object GetValue(NodePort port) { Debug.LogWarning("No GetValue(NodePort port) override defined for " + GetType()); return null; } /// Initialize node. Called on creation. protected virtual void Init() { name = GetType().Name; } /// Called whenever a connection is being made between two s /// Output Input public virtual void OnCreateConnection(NodePort from, NodePort to) { } /// Disconnect everything from this node public void ClearConnections() { for (int i = 0; i < inputs.Count; i++) { inputs[i].ClearConnections(); } for (int i = 0; i < outputs.Count; i++) { outputs[i].ClearConnections(); } } public override int GetHashCode() { return JsonUtility.ToJson(this).GetHashCode(); } /// Mark a serializable field as an input port. You can access this through [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] public class InputAttribute : Attribute { public ShowBackingValue backingValue; /// Mark a serializable field as an input port. You can access this through /// Should we display the backing value for this port as an editor field? public InputAttribute(ShowBackingValue backingValue = ShowBackingValue.Unconnected) { this.backingValue = backingValue; } } /// Mark a serializable field as an output port. You can access this through [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] public class OutputAttribute : Attribute { /// Mark a serializable field as an output port. You can access this through public OutputAttribute() { } } }