mirror of
https://github.com/Siccity/xNode.git
synced 2025-12-20 01:06:01 +08:00
Big update.
Removal of scripts now also clears dependant nodes, to avoid null objects. NodePorts now support fallback values. UI Changes. node.graph is now serialized as well.
This commit is contained in:
parent
c1db2d9e4b
commit
5e68b6bcdc
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8c47bc953732464a9bf3a76273d99ef
|
||||
timeCreated: 1507916591
|
||||
guid: 614b670274b902e44bba59ba861eb1bd
|
||||
timeCreated: 1507988229
|
||||
licenseType: Free
|
||||
NativeFormatImporter:
|
||||
mainObjectFileID: 11400000
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
[System.Serializable]
|
||||
public class ConstantValue : ExampleNodeBase {
|
||||
public float a;
|
||||
[Output] public float value;
|
||||
|
||||
protected override void Init() {
|
||||
name = "Constant Value";
|
||||
}
|
||||
|
||||
public override object GetValue(NodePort port) {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class DisplayValue : ExampleNodeBase {
|
||||
[Input] public float value;
|
||||
[Input(false)] public float value;
|
||||
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class ExampleNodeBase : Node {
|
||||
public abstract class ExampleNodeBase : Node {
|
||||
|
||||
public float GetInputFloat(string fieldName) {
|
||||
float result = 0f;
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
|
||||
[System.Serializable]
|
||||
public class MathNode : ExampleNodeBase {
|
||||
[Input] public float c;
|
||||
[Input] public float b;
|
||||
[Output] public float result;
|
||||
[Input(true)] public float a;
|
||||
[Input(true)] public float b;
|
||||
[Output(false)] public float result;
|
||||
public enum MathType { Add, Subtract, Multiply, Divide}
|
||||
public MathType mathType = MathType.Add;
|
||||
|
||||
@ -13,7 +13,7 @@ public class MathNode : ExampleNodeBase {
|
||||
}
|
||||
|
||||
public override object GetValue(NodePort port) {
|
||||
float a = GetInputFloat("c");
|
||||
float a = GetInputFloat("a");
|
||||
float b = GetInputFloat("b");
|
||||
|
||||
switch(port.fieldName) {
|
||||
|
||||
19
Example/Nodes/TestNode.cs
Normal file
19
Example/Nodes/TestNode.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class TestNode : Node {
|
||||
|
||||
public int i;
|
||||
public float f;
|
||||
public double d;
|
||||
public long l;
|
||||
public bool b;
|
||||
public string s;
|
||||
public Rect r;
|
||||
public Vector2 v2;
|
||||
public Vector3 v3;
|
||||
public Vector4 v4;
|
||||
public Color col;
|
||||
public AnimationCurve a;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 707240ce8955a0240a7c0c4177d83bf5
|
||||
timeCreated: 1505937586
|
||||
guid: 47bfd6281f41a10459bcb45bb4cd03f3
|
||||
timeCreated: 1507990362
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
@ -14,8 +14,7 @@ public class NodeEditor {
|
||||
/// <param name="portPositions">Port handle positions need to be returned to the NodeEditorWindow </param>
|
||||
public virtual void OnNodeGUI(out Dictionary<NodePort, Vector2> portPositions) {
|
||||
DrawDefaultHeaderGUI();
|
||||
DrawDefaultNodePortsGUI(out portPositions);
|
||||
DrawDefaultNodeBodyGUI();
|
||||
DrawDefaultNodeBodyGUI(out portPositions);
|
||||
}
|
||||
|
||||
protected void DrawDefaultHeaderGUI() {
|
||||
@ -23,40 +22,15 @@ public class NodeEditor {
|
||||
GUILayout.Label(target.name, NodeEditorResources.styles.nodeHeader, GUILayout.Height(30));
|
||||
}
|
||||
|
||||
/// <summary> Draws standard editors for all fields marked with <see cref="Node.InputAttribute"/> or <see cref="Node.OutputAttribute"/> </summary>
|
||||
protected void DrawDefaultNodePortsGUI(out Dictionary<NodePort, Vector2> portPositions) {
|
||||
/// <summary> Draws standard field editors for all public fields </summary>
|
||||
protected void DrawDefaultNodeBodyGUI(out Dictionary<NodePort, Vector2> portPositions) {
|
||||
portPositions = new Dictionary<NodePort, Vector2>();
|
||||
|
||||
Event e = Event.current;
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
|
||||
//Inputs
|
||||
GUILayout.BeginVertical();
|
||||
for (int i = 0; i < target.InputCount; i++) {
|
||||
Vector2 handlePoint = DrawNodePortGUI(target.inputs[i]);
|
||||
portPositions.Add(target.inputs[i], handlePoint);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
//Outputs
|
||||
GUILayout.BeginVertical();
|
||||
for (int i = 0; i < target.OutputCount; i++) {
|
||||
Vector2 handlePoint = DrawNodePortGUI(target.outputs[i]);
|
||||
portPositions.Add(target.outputs[i], handlePoint);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
/// <summary> Draws standard field editors for all public fields </summary>
|
||||
protected void DrawDefaultNodeBodyGUI() {
|
||||
FieldInfo[] fields = GetInspectorFields(target);
|
||||
for (int i = 0; i < fields.Length; i++) {
|
||||
object[] fieldAttribs = fields[i].GetCustomAttributes(false);
|
||||
if (NodeEditorUtilities.HasAttrib<Node.InputAttribute>(fieldAttribs) || NodeEditorUtilities.HasAttrib<Node.OutputAttribute>(fieldAttribs)) continue;
|
||||
DrawFieldInfoDrawerGUI(fields[i]);
|
||||
if (fields[i].Name == "graph" || fields[i].Name == "rect") continue;
|
||||
NodeEditorGUILayout.PropertyField(target, fields[i], portPositions);
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,73 +71,6 @@ public class NodeEditor {
|
||||
return node.GetType().GetFields().Where(f => f.IsPublic || f.GetCustomAttributes(typeof(SerializeField), false) != null).ToArray();
|
||||
}
|
||||
|
||||
private void DrawFieldInfoDrawerGUI(FieldInfo fieldInfo) {
|
||||
Type fieldType = fieldInfo.FieldType;
|
||||
string fieldName = fieldInfo.Name;
|
||||
string fieldPrettyName = fieldName.PrettifyCamelCase();
|
||||
object fieldValue = fieldInfo.GetValue(target);
|
||||
object[] fieldAttribs = fieldInfo.GetCustomAttributes(false);
|
||||
|
||||
HeaderAttribute headerAttrib;
|
||||
if (NodeEditorUtilities.GetAttrib(fieldAttribs, out headerAttrib)) {
|
||||
EditorGUILayout.LabelField(headerAttrib.header);
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
if (fieldType == typeof(int)) {
|
||||
fieldValue = NodeEditorGUILayout.IntField(fieldPrettyName, (int) fieldValue);
|
||||
} else if (fieldType == typeof(bool)) {
|
||||
fieldValue = EditorGUILayout.Toggle(fieldPrettyName, (bool) fieldValue);
|
||||
} else if (fieldType.IsEnum) {
|
||||
fieldValue = NodeEditorGUILayout.EnumField(fieldPrettyName, (Enum)fieldValue);
|
||||
} else if (fieldType == typeof(string)) {
|
||||
|
||||
if (fieldName == "name") return; //Ignore 'name'
|
||||
TextAreaAttribute textAreaAttrib;
|
||||
if (NodeEditorUtilities.GetAttrib(fieldAttribs, out textAreaAttrib)) {
|
||||
fieldValue = EditorGUILayout.TextArea(fieldValue != null ? (string) fieldValue : "");
|
||||
} else
|
||||
fieldValue = EditorGUILayout.TextField(fieldPrettyName, fieldValue != null ? (string) fieldValue : "");
|
||||
} else if (fieldType == typeof(Rect)) {
|
||||
if (fieldName == "rect") return; //Ignore 'rect'
|
||||
fieldValue = EditorGUILayout.RectField(fieldPrettyName, (Rect) fieldValue);
|
||||
} else if (fieldType == typeof(float)) {
|
||||
fieldValue = NodeEditorGUILayout.FloatField(fieldPrettyName, (float) fieldValue);
|
||||
} else if (fieldType == typeof(double)) {
|
||||
fieldValue = NodeEditorGUILayout.DoubleField(fieldPrettyName, (double) fieldValue);
|
||||
} else if (fieldType == typeof(long)) {
|
||||
fieldValue = NodeEditorGUILayout.LongField(fieldPrettyName, (long) fieldValue);
|
||||
} else if (fieldType == typeof(Vector2)) {
|
||||
fieldValue = EditorGUILayout.Vector2Field(fieldPrettyName, (Vector2) fieldValue);
|
||||
} else if (fieldType == typeof(Vector3)) {
|
||||
fieldValue = EditorGUILayout.Vector3Field(new GUIContent(fieldPrettyName), (Vector3) fieldValue);
|
||||
} else if (fieldType == typeof(Vector4)) {
|
||||
fieldValue = EditorGUILayout.Vector4Field(fieldPrettyName, (Vector4) fieldValue);
|
||||
} else if (fieldType == typeof(Color)) {
|
||||
Rect rect = EditorGUILayout.GetControlRect();
|
||||
rect.width *= 0.5f;
|
||||
EditorGUI.LabelField(rect, fieldPrettyName);
|
||||
rect.x += rect.width;
|
||||
fieldValue = EditorGUI.ColorField(rect, (Color) fieldValue);
|
||||
} else if (fieldType == typeof(AnimationCurve)) {
|
||||
Rect rect = EditorGUILayout.GetControlRect();
|
||||
rect.width *= 0.5f;
|
||||
EditorGUI.LabelField(rect, fieldPrettyName);
|
||||
rect.x += rect.width;
|
||||
|
||||
AnimationCurve curve = fieldValue != null ? (AnimationCurve) fieldValue : new AnimationCurve();
|
||||
curve = EditorGUI.CurveField(rect, curve);
|
||||
if (fieldValue != curve) fieldInfo.SetValue(target, curve);
|
||||
} else if (fieldType.IsSubclassOf(typeof(UnityEngine.Object)) || fieldType == typeof(UnityEngine.Object)) {
|
||||
if (fieldName == "graph") return; //Ignore 'graph'
|
||||
fieldValue = EditorGUILayout.ObjectField(fieldPrettyName, (UnityEngine.Object) fieldValue, fieldType, true);
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
fieldInfo.SetValue(target, fieldValue);
|
||||
EditorUtility.SetDirty(target);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int GetWidth() {
|
||||
return 200;
|
||||
}
|
||||
|
||||
@ -137,6 +137,7 @@ public partial class NodeEditorWindow {
|
||||
Vector2 mousePos = Event.current.mousePosition;
|
||||
Node newHoverNode = null;
|
||||
foreach (Node node in graph.nodes) {
|
||||
if (node == null) return;
|
||||
//Get node position
|
||||
Vector2 nodePos = GridToWindowPosition(node.rect.position);
|
||||
Rect windowRect = new Rect(nodePos, new Vector2(node.rect.size.x / zoom, node.rect.size.y / zoom));
|
||||
|
||||
35
Scripts/Editor/NodeEditorAssetModProcessor.cs
Normal file
35
Scripts/Editor/NodeEditorAssetModProcessor.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public class NodeEditorAssetModProcessor : UnityEditor.AssetModificationProcessor {
|
||||
public static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOptions options) {
|
||||
UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path);
|
||||
|
||||
if (!(obj is UnityEditor.MonoScript)) return AssetDeleteResult.DidNotDelete;
|
||||
|
||||
UnityEditor.MonoScript script = obj as UnityEditor.MonoScript;
|
||||
System.Type scriptType = script.GetClass();
|
||||
|
||||
if (scriptType != typeof(Node) && !scriptType.IsSubclassOf(typeof(Node))) return AssetDeleteResult.DidNotDelete;
|
||||
|
||||
//Find ScriptableObjects using this script
|
||||
string[] guids = AssetDatabase.FindAssets("t:" + scriptType);
|
||||
for (int i = 0; i < guids.Length; i++) {
|
||||
string assetpath = AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath(assetpath);
|
||||
for (int k = 0; k < objs.Length; k++) {
|
||||
Node node = objs[k] as Node;
|
||||
if (node.GetType() == scriptType) {
|
||||
if (node != null && node.graph != null) {
|
||||
Debug.LogWarning(node.name + " of " + node.graph + " depended on deleted script and has been removed automatically.", node.graph);
|
||||
node.graph.RemoveNode(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return AssetDeleteResult.DidNotDelete;
|
||||
}
|
||||
}
|
||||
12
Scripts/Editor/NodeEditorAssetModProcessor.cs.meta
Normal file
12
Scripts/Editor/NodeEditorAssetModProcessor.cs.meta
Normal file
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e515e86efe8160243a68b7c06d730c9c
|
||||
timeCreated: 1507982232
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -116,6 +116,8 @@ public partial class NodeEditorWindow {
|
||||
/// <summary> Draws all connections </summary>
|
||||
public void DrawConnections() {
|
||||
foreach (Node node in graph.nodes) {
|
||||
//If a null node is found, return. This can happen if the nodes associated script is deleted. It is currently not possible in Unity to delete a null asset.
|
||||
if (node == null) return;
|
||||
for (int i = 0; i < node.OutputCount; i++) {
|
||||
NodePort output = node.outputs[i];
|
||||
|
||||
@ -126,6 +128,7 @@ public partial class NodeEditorWindow {
|
||||
|
||||
NodePort input = output.GetConnection(k);
|
||||
if (input == null) return; //If a script has been updated and the port doesn't exist, it is removed and null is returned. If this happens, return.
|
||||
if (!_portConnectionPoints.ContainsKey(input)) return;
|
||||
Vector2 to = _portConnectionPoints[input].center;
|
||||
DrawConnection(from, to, NodeEditorPreferences.GetTypeColor(output.type));
|
||||
}
|
||||
@ -148,6 +151,7 @@ public partial class NodeEditorWindow {
|
||||
BeginZoomed(position, zoom);
|
||||
|
||||
foreach (Node node in graph.nodes) {
|
||||
if (node == null) return;
|
||||
NodeEditor nodeEditor = GetNodeEditor(node.GetType());
|
||||
nodeEditor.target = node;
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
@ -9,6 +11,115 @@ public class NodeEditorGUILayout {
|
||||
|
||||
private static double tempValue;
|
||||
|
||||
public static object PortField(string label, object value, NodePort port, bool fallback, out Vector2 portPosition) {
|
||||
if (fallback) value = PropertyField(label, value);
|
||||
else EditorGUILayout.LabelField(label);
|
||||
|
||||
Rect rect = GUILayoutUtility.GetLastRect();
|
||||
if (port.direction == NodePort.IO.Input) rect.position = rect.position - new Vector2(16, 0);
|
||||
if (port.direction == NodePort.IO.Output) rect.position = rect.position + new Vector2(rect.width, 0);
|
||||
rect.size = new Vector2(16, 16);
|
||||
|
||||
Color col = GUI.color;
|
||||
GUI.color = new Color32(90, 97, 105, 255);
|
||||
GUI.DrawTexture(rect, NodeEditorResources.dotOuter);
|
||||
GUI.color = NodeEditorPreferences.GetTypeColor(port.type);
|
||||
GUI.DrawTexture(rect, NodeEditorResources.dot);
|
||||
GUI.color = col;
|
||||
portPosition = rect.center;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static object PropertyField(Node target, FieldInfo fieldInfo, Dictionary<NodePort, Vector2> portPositions) {
|
||||
Type fieldType = fieldInfo.FieldType;
|
||||
string fieldName = fieldInfo.Name;
|
||||
string fieldPrettyName = fieldName.PrettifyCamelCase();
|
||||
object fieldValue = fieldInfo.GetValue(target);
|
||||
object[] fieldAttribs = fieldInfo.GetCustomAttributes(false);
|
||||
|
||||
HeaderAttribute headerAttrib;
|
||||
if (NodeEditorUtilities.GetAttrib(fieldAttribs, out headerAttrib)) {
|
||||
EditorGUILayout.LabelField(headerAttrib.header);
|
||||
}
|
||||
|
||||
Node.OutputAttribute outputAttrib;
|
||||
Node.InputAttribute inputAttrib;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
if (NodeEditorUtilities.GetAttrib(fieldAttribs, out inputAttrib)) {
|
||||
NodePort port = target.GetPortByFieldName(fieldName);
|
||||
Vector2 portPos;
|
||||
fieldValue = PortField(fieldPrettyName, fieldValue, port, inputAttrib.fallback, out portPos);
|
||||
portPositions.Add(port, portPos);
|
||||
} else if (NodeEditorUtilities.GetAttrib(fieldAttribs, out outputAttrib)) {
|
||||
NodePort port = target.GetPortByFieldName(fieldName);
|
||||
Vector2 portPos;
|
||||
fieldValue = PortField(fieldPrettyName, fieldValue, port, outputAttrib.fallback, out portPos);
|
||||
portPositions.Add(port, portPos);
|
||||
} else {
|
||||
fieldValue = PropertyField(fieldPrettyName, fieldValue);
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
fieldInfo.SetValue(target, fieldValue);
|
||||
EditorUtility.SetDirty(target);
|
||||
}
|
||||
return fieldValue;
|
||||
}
|
||||
|
||||
public static object PropertyField(string label, object value) {
|
||||
if (value is int) return IntField(label, (int) value);
|
||||
else if (value is float) return FloatField(label, (float) value);
|
||||
else if (value is double) return DoubleField(label, (double) value);
|
||||
else if (value is long) return LongField(label, (long) value);
|
||||
else if (value is bool) return Toggle(label, (bool) value);
|
||||
else if (value is Enum) return EnumField(label, (Enum) value);
|
||||
else if (value is string) return TextField(label, (string) value);
|
||||
else if (value is Rect) return RectField(label, (Rect) value);
|
||||
else if (value is Vector2) return Vector2Field(label, (Vector2) value);
|
||||
else if (value is Vector3) return Vector3Field(label, (Vector3) value);
|
||||
else if (value is Vector4) return Vector4Field(label, (Vector4) value);
|
||||
else if (value is Color) return ColorField(label, (Color) value);
|
||||
else if (value is AnimationCurve) return CurveField(label, (AnimationCurve) value);
|
||||
else if (value == null || value.GetType().IsSubclassOf(typeof(UnityEngine.Object)) || value.GetType() == typeof(UnityEngine.Object)) return ObjectField(label, (UnityEngine.Object) value);
|
||||
else return value;
|
||||
}
|
||||
public static Rect GetRect(string label) {
|
||||
Rect rect = EditorGUILayout.GetControlRect();
|
||||
rect.width *= 0.5f;
|
||||
EditorGUI.LabelField(rect, label);
|
||||
rect.x += rect.width;
|
||||
return rect;
|
||||
}
|
||||
public static UnityEngine.Object ObjectField(string label, UnityEngine.Object value) {
|
||||
return EditorGUI.ObjectField(GetRect(label), value, value.GetType(), true);
|
||||
}
|
||||
public static AnimationCurve CurveField(string label, AnimationCurve value) {
|
||||
if (value == null) value = new AnimationCurve();
|
||||
return EditorGUI.CurveField(GetRect(label), value);
|
||||
}
|
||||
public static Color ColorField(string label, Color value) {
|
||||
return EditorGUI.ColorField(GetRect(label), value);
|
||||
}
|
||||
public static Vector4 Vector4Field(string label, Vector4 value) {
|
||||
return EditorGUILayout.Vector4Field(label, value);
|
||||
}
|
||||
public static Vector3 Vector3Field(string label, Vector3 value) {
|
||||
return EditorGUILayout.Vector3Field(label, value);
|
||||
}
|
||||
public static Vector2 Vector2Field(string label, Vector2 value) {
|
||||
return EditorGUILayout.Vector2Field(label, value);
|
||||
}
|
||||
public static Rect RectField(string label, Rect value) {
|
||||
return EditorGUILayout.RectField(label, value);
|
||||
}
|
||||
public static string TextField(string label, string value) {
|
||||
return EditorGUI.TextField(GetRect(label), value);
|
||||
}
|
||||
public static bool Toggle(string label, bool value) {
|
||||
return EditorGUI.Toggle(GetRect(label), value);
|
||||
}
|
||||
public static int IntField(string label, int value) {
|
||||
GUIUtility.GetControlID(FocusType.Passive);
|
||||
Rect rect = EditorGUILayout.GetControlRect();
|
||||
@ -119,10 +230,6 @@ public class NodeEditorGUILayout {
|
||||
}
|
||||
}
|
||||
public static Enum EnumField(string label, Enum value) {
|
||||
Rect rect = EditorGUILayout.GetControlRect();
|
||||
rect.width *= 0.5f;
|
||||
EditorGUI.LabelField(rect, label);
|
||||
rect.x += rect.width;
|
||||
return EditorGUI.EnumPopup(rect, value);
|
||||
return EditorGUI.EnumPopup(GetRect(label), value);
|
||||
}
|
||||
}
|
||||
@ -48,7 +48,7 @@ public static class NodeEditorResources {
|
||||
nodeBody = new GUIStyle();
|
||||
nodeBody.normal.background = NodeEditorResources.nodeBody;
|
||||
nodeBody.border = new RectOffset(32, 32, 32, 32);
|
||||
nodeBody.padding = new RectOffset(10, 10, 2, 2);
|
||||
nodeBody.padding = new RectOffset(16, 16, 4, 6);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ using UnityEngine;
|
||||
public abstract class Node : ScriptableObject {
|
||||
|
||||
/// <summary> Name of the node </summary>
|
||||
[NonSerialized] public NodeGraph graph;
|
||||
[SerializeField] public NodeGraph graph;
|
||||
[SerializeField] public Rect rect = new Rect(0, 0, 200, 200);
|
||||
/// <summary> Input <see cref="NodePort"/>s. It is recommended not to modify these at hand. Instead, see <see cref="InputAttribute"/> </summary>
|
||||
[SerializeField] public List<NodePort> inputs = new List<NodePort>();
|
||||
@ -99,12 +99,14 @@ public abstract class Node : ScriptableObject {
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
|
||||
public class InputAttribute : Attribute {
|
||||
public InputAttribute() { }
|
||||
public bool fallback;
|
||||
public InputAttribute(bool fallback) { this.fallback = fallback; }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)]
|
||||
public class OutputAttribute : Attribute {
|
||||
public OutputAttribute() { }
|
||||
public bool fallback;
|
||||
public OutputAttribute(bool fallback) { this.fallback = fallback; }
|
||||
}
|
||||
|
||||
private void GetPorts() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user