mirror of
https://github.com/Siccity/xNode.git
synced 2025-12-20 17:26:02 +08:00
WIP
This commit is contained in:
parent
f03dbeb159
commit
e89671480c
@ -7,11 +7,11 @@ using UnityEngine;
|
|||||||
namespace XNodeEditor {
|
namespace XNodeEditor {
|
||||||
/// <summary> Base class to derive custom Node editors from. Use this to create your own custom inspectors and editors for your nodes. </summary>
|
/// <summary> Base class to derive custom Node editors from. Use this to create your own custom inspectors and editors for your nodes. </summary>
|
||||||
|
|
||||||
[CustomNodeEditor(typeof(XNode.Node))]
|
[CustomNodeEditor(typeof(XNode.INode))]
|
||||||
public class NodeEditor : XNodeEditor.Internal.NodeEditorBase<NodeEditor, NodeEditor.CustomNodeEditorAttribute, XNode.Node> {
|
public class NodeEditor : XNodeEditor.Internal.NodeEditorBase<NodeEditor, NodeEditor.CustomNodeEditorAttribute, XNode.INode> {
|
||||||
|
|
||||||
/// <summary> Fires every whenever a node was modified through the editor </summary>
|
/// <summary> Fires every whenever a node was modified through the editor </summary>
|
||||||
public static Action<XNode.Node> onUpdateNode;
|
public static Action<XNode.INode> onUpdateNode;
|
||||||
public static Dictionary<XNode.NodePort, Vector2> portPositions;
|
public static Dictionary<XNode.NodePort, Vector2> portPositions;
|
||||||
|
|
||||||
public virtual void OnHeaderGUI() {
|
public virtual void OnHeaderGUI() {
|
||||||
@ -67,9 +67,9 @@ namespace XNodeEditor {
|
|||||||
/// <summary> Add items for the context menu when right-clicking this node. Override to add custom menu items. </summary>
|
/// <summary> Add items for the context menu when right-clicking this node. Override to add custom menu items. </summary>
|
||||||
public virtual void AddContextMenuItems(GenericMenu menu) {
|
public virtual void AddContextMenuItems(GenericMenu menu) {
|
||||||
// Actions if only one node is selected
|
// Actions if only one node is selected
|
||||||
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
|
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.INode) {
|
||||||
XNode.Node node = Selection.activeObject as XNode.Node;
|
XNode.INode node = Selection.activeObject as XNode.INode;
|
||||||
menu.AddItem(new GUIContent("Move To Top"), false, () => NodeEditorWindow.current.MoveNodeToTop(node));
|
menu.AddItem(new GUIContent("Move To Top"), false, () => node.Graph.MoveNodeToTop(node));
|
||||||
menu.AddItem(new GUIContent("Rename"), false, NodeEditorWindow.current.RenameSelectedNode);
|
menu.AddItem(new GUIContent("Rename"), false, NodeEditorWindow.current.RenameSelectedNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,8 +78,8 @@ namespace XNodeEditor {
|
|||||||
menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes);
|
menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes);
|
||||||
|
|
||||||
// Custom sctions if only one node is selected
|
// Custom sctions if only one node is selected
|
||||||
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
|
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.INode) {
|
||||||
XNode.Node node = Selection.activeObject as XNode.Node;
|
XNode.INode node = Selection.activeObject as XNode.INode;
|
||||||
NodeEditorWindow.AddCustomContextMenuItems(menu, node);
|
NodeEditorWindow.AddCustomContextMenuItems(menu, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ namespace XNodeEditor {
|
|||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public class CustomNodeEditorAttribute : Attribute,
|
public class CustomNodeEditorAttribute : Attribute,
|
||||||
XNodeEditor.Internal.NodeEditorBase<NodeEditor, NodeEditor.CustomNodeEditorAttribute, XNode.Node>.INodeEditorAttrib {
|
XNodeEditor.Internal.NodeEditorBase<NodeEditor, NodeEditor.CustomNodeEditorAttribute, XNode.INode>.INodeEditorAttrib {
|
||||||
private Type inspectedType;
|
private Type inspectedType;
|
||||||
/// <summary> Tells a NodeEditor which Node type it is an editor for </summary>
|
/// <summary> Tells a NodeEditor which Node type it is an editor for </summary>
|
||||||
/// <param name="inspectedType">Type that this editor can edit</param>
|
/// <param name="inspectedType">Type that this editor can edit</param>
|
||||||
|
|||||||
@ -83,15 +83,17 @@ namespace XNodeEditor {
|
|||||||
for (int i = 0; i < Selection.objects.Length; i++) {
|
for (int i = 0; i < Selection.objects.Length; i++) {
|
||||||
if (Selection.objects[i] is XNode.INode) {
|
if (Selection.objects[i] is XNode.INode) {
|
||||||
XNode.INode node = Selection.objects[i] as XNode.INode;
|
XNode.INode node = Selection.objects[i] as XNode.INode;
|
||||||
Vector2 initial = node.position;
|
Vector2 initial = node.Position;
|
||||||
node.position = mousePos + dragOffset[i];
|
node.Position = mousePos + dragOffset[i];
|
||||||
if (gridSnap) {
|
if (gridSnap) {
|
||||||
node.position.x = (Mathf.Round((node.position.x + 8) / 16) * 16) - 8;
|
Vector2 position = node.Position;
|
||||||
node.position.y = (Mathf.Round((node.position.y + 8) / 16) * 16) - 8;
|
position.x = (Mathf.Round((node.Position.x + 8) / 16) * 16) - 8;
|
||||||
|
position.y = (Mathf.Round((node.Position.y + 8) / 16) * 16) - 8;
|
||||||
|
node.Position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset portConnectionPoints instantly if a node is dragged so they aren't delayed by a frame.
|
// Offset portConnectionPoints instantly if a node is dragged so they aren't delayed by a frame.
|
||||||
Vector2 offset = node.position - initial;
|
Vector2 offset = node.Position - initial;
|
||||||
if (offset.sqrMagnitude > 0) {
|
if (offset.sqrMagnitude > 0) {
|
||||||
foreach (XNode.NodePort output in node.Outputs) {
|
foreach (XNode.NodePort output in node.Outputs) {
|
||||||
Rect rect;
|
Rect rect;
|
||||||
@ -163,7 +165,7 @@ namespace XNodeEditor {
|
|||||||
}
|
}
|
||||||
} else if (IsHoveringNode && IsHoveringTitle(hoveredNode)) {
|
} else if (IsHoveringNode && IsHoveringTitle(hoveredNode)) {
|
||||||
// If mousedown on node header, select or deselect
|
// If mousedown on node header, select or deselect
|
||||||
if (!Selection.Contains(hoveredNode)) {
|
if (!Selection.Contains((UnityEngine.Object)hoveredNode)) {
|
||||||
SelectNode(hoveredNode, e.control || e.shift);
|
SelectNode(hoveredNode, e.control || e.shift);
|
||||||
if (!e.control && !e.shift) selectedReroutes.Clear();
|
if (!e.control && !e.shift) selectedReroutes.Clear();
|
||||||
} else if (e.control || e.shift) DeselectNode(hoveredNode);
|
} else if (e.control || e.shift) DeselectNode(hoveredNode);
|
||||||
@ -243,7 +245,7 @@ namespace XNodeEditor {
|
|||||||
// Double click to center node
|
// Double click to center node
|
||||||
if (isDoubleClick) {
|
if (isDoubleClick) {
|
||||||
Vector2 nodeDimension = nodeSizes.ContainsKey(hoveredNode) ? nodeSizes[hoveredNode] / 2 : Vector2.zero;
|
Vector2 nodeDimension = nodeSizes.ContainsKey(hoveredNode) ? nodeSizes[hoveredNode] / 2 : Vector2.zero;
|
||||||
panOffset = -hoveredNode.position - nodeDimension;
|
panOffset = -hoverednode.Position - nodeDimension;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +269,7 @@ namespace XNodeEditor {
|
|||||||
} else if (IsHoveringPort) {
|
} else if (IsHoveringPort) {
|
||||||
ShowPortContextMenu(hoveredPort);
|
ShowPortContextMenu(hoveredPort);
|
||||||
} else if (IsHoveringNode && IsHoveringTitle(hoveredNode)) {
|
} else if (IsHoveringNode && IsHoveringTitle(hoveredNode)) {
|
||||||
if (!Selection.Contains(hoveredNode)) SelectNode(hoveredNode, false);
|
if (!Selection.Contains((UnityEngine.Object)hoveredNode)) SelectNode(hoveredNode, false);
|
||||||
GenericMenu menu = new GenericMenu();
|
GenericMenu menu = new GenericMenu();
|
||||||
NodeEditor.GetEditor(hoveredNode, this).AddContextMenuItems(menu);
|
NodeEditor.GetEditor(hoveredNode, this).AddContextMenuItems(menu);
|
||||||
menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
|
menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
|
||||||
@ -330,7 +332,7 @@ namespace XNodeEditor {
|
|||||||
for (int i = 0; i < Selection.objects.Length; i++) {
|
for (int i = 0; i < Selection.objects.Length; i++) {
|
||||||
if (Selection.objects[i] is XNode.INode) {
|
if (Selection.objects[i] is XNode.INode) {
|
||||||
XNode.INode node = Selection.objects[i] as XNode.INode;
|
XNode.INode node = Selection.objects[i] as XNode.INode;
|
||||||
dragOffset[i] = node.position - WindowToGridPosition(current.mousePosition);
|
dragOffset[i] = node.Position - WindowToGridPosition(current.mousePosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,8 +357,8 @@ namespace XNodeEditor {
|
|||||||
}
|
}
|
||||||
selectedReroutes.Clear();
|
selectedReroutes.Clear();
|
||||||
foreach (UnityEngine.Object item in Selection.objects) {
|
foreach (UnityEngine.Object item in Selection.objects) {
|
||||||
if (item is XNode.Node) {
|
if (item is XNode.INode) {
|
||||||
XNode.Node node = item as XNode.Node;
|
XNode.INode node = item as XNode.INode;
|
||||||
graphEditor.RemoveNode(node);
|
graphEditor.RemoveNode(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,8 +366,8 @@ namespace XNodeEditor {
|
|||||||
|
|
||||||
/// <summary> Initiate a rename on the currently selected node </summary>
|
/// <summary> Initiate a rename on the currently selected node </summary>
|
||||||
public void RenameSelectedNode() {
|
public void RenameSelectedNode() {
|
||||||
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.Node) {
|
if (Selection.objects.Length == 1 && Selection.activeObject is XNode.INode) {
|
||||||
XNode.Node node = Selection.activeObject as XNode.Node;
|
XNode.INode node = Selection.activeObject as XNode.INode;
|
||||||
Vector2 size;
|
Vector2 size;
|
||||||
if (nodeSizes.TryGetValue(node, out size)) {
|
if (nodeSizes.TryGetValue(node, out size)) {
|
||||||
RenamePopup.Show(Selection.activeObject, size.x);
|
RenamePopup.Show(Selection.activeObject, size.x);
|
||||||
@ -375,41 +377,32 @@ namespace XNodeEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Draw this node on top of other nodes by placing it last in the graph.nodes list </summary>
|
|
||||||
public void MoveNodeToTop(XNode.Node node) {
|
|
||||||
int index;
|
|
||||||
while ((index = graph.nodes.IndexOf(node)) != graph.nodes.Count - 1) {
|
|
||||||
graph.nodes[index] = graph.nodes[index + 1];
|
|
||||||
graph.nodes[index + 1] = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary> Duplicate selected nodes and select the duplicates </summary>
|
/// <summary> Duplicate selected nodes and select the duplicates </summary>
|
||||||
public void DuplicateSelectedNodes() {
|
public void DuplicateSelectedNodes() {
|
||||||
UnityEngine.Object[] newNodes = new UnityEngine.Object[Selection.objects.Length];
|
UnityEngine.Object[] newNodes = new UnityEngine.Object[Selection.objects.Length];
|
||||||
Dictionary<XNode.Node, XNode.Node> substitutes = new Dictionary<XNode.Node, XNode.Node>();
|
Dictionary<XNode.INode, XNode.INode> substitutes = new Dictionary<XNode.INode, XNode.INode>();
|
||||||
for (int i = 0; i < Selection.objects.Length; i++) {
|
for (int i = 0; i < Selection.objects.Length; i++) {
|
||||||
if (Selection.objects[i] is XNode.Node) {
|
if (Selection.objects[i] is XNode.INode) {
|
||||||
XNode.Node srcNode = Selection.objects[i] as XNode.Node;
|
XNode.INode srcNode = Selection.objects[i] as XNode.INode;
|
||||||
if (srcNode.graph != graph) continue; // ignore nodes selected in another graph
|
if (srcNode.Graph != graph) continue; // ignore nodes selected in another graph
|
||||||
XNode.Node newNode = graphEditor.CopyNode(srcNode);
|
XNode.INode newNode = graphEditor.CopyNode(srcNode);
|
||||||
substitutes.Add(srcNode, newNode);
|
substitutes.Add(srcNode, newNode);
|
||||||
newNode.position = srcNode.position + new Vector2(30, 30);
|
newnode.Position = srcnode.Position + new Vector2(30, 30);
|
||||||
newNodes[i] = newNode;
|
newNodes[i] = newNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk through the selected nodes again, recreate connections, using the new nodes
|
// Walk through the selected nodes again, recreate connections, using the new nodes
|
||||||
for (int i = 0; i < Selection.objects.Length; i++) {
|
for (int i = 0; i < Selection.objects.Length; i++) {
|
||||||
if (Selection.objects[i] is XNode.Node) {
|
if (Selection.objects[i] is XNode.INode) {
|
||||||
XNode.Node srcNode = Selection.objects[i] as XNode.Node;
|
XNode.INode srcNode = Selection.objects[i] as XNode.INode;
|
||||||
if (srcNode.graph != graph) continue; // ignore nodes selected in another graph
|
if (srcNode.graph != graph) continue; // ignore nodes selected in another graph
|
||||||
foreach (XNode.NodePort port in srcNode.Ports) {
|
foreach (XNode.NodePort port in srcNode.Ports) {
|
||||||
for (int c = 0; c < port.ConnectionCount; c++) {
|
for (int c = 0; c < port.ConnectionCount; c++) {
|
||||||
XNode.NodePort inputPort = port.direction == XNode.NodePort.IO.Input ? port : port.GetConnection(c);
|
XNode.NodePort inputPort = port.direction == XNode.NodePort.IO.Input ? port : port.GetConnection(c);
|
||||||
XNode.NodePort outputPort = port.direction == XNode.NodePort.IO.Output ? port : port.GetConnection(c);
|
XNode.NodePort outputPort = port.direction == XNode.NodePort.IO.Output ? port : port.GetConnection(c);
|
||||||
|
|
||||||
XNode.Node newNodeIn, newNodeOut;
|
XNode.INode newNodeIn, newNodeOut;
|
||||||
if (substitutes.TryGetValue(inputPort.node, out newNodeIn) && substitutes.TryGetValue(outputPort.node, out newNodeOut)) {
|
if (substitutes.TryGetValue(inputPort.node, out newNodeIn) && substitutes.TryGetValue(outputPort.node, out newNodeOut)) {
|
||||||
newNodeIn.UpdateStaticPorts();
|
newNodeIn.UpdateStaticPorts();
|
||||||
newNodeOut.UpdateStaticPorts();
|
newNodeOut.UpdateStaticPorts();
|
||||||
@ -459,10 +452,10 @@ namespace XNodeEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsHoveringTitle(XNode.Node node) {
|
bool IsHoveringTitle(XNode.INode node) {
|
||||||
Vector2 mousePos = Event.current.mousePosition;
|
Vector2 mousePos = Event.current.mousePosition;
|
||||||
//Get node position
|
//Get node position
|
||||||
Vector2 nodePos = GridToWindowPosition(node.position);
|
Vector2 nodePos = GridToWindowPosition(node.Position);
|
||||||
float width;
|
float width;
|
||||||
Vector2 size;
|
Vector2 size;
|
||||||
if (nodeSizes.TryGetValue(node, out size)) width = size.x;
|
if (nodeSizes.TryGetValue(node, out size)) width = size.x;
|
||||||
|
|||||||
@ -17,7 +17,7 @@ namespace XNodeEditor {
|
|||||||
// Check script type. Return if deleting a non-node script
|
// Check script type. Return if deleting a non-node script
|
||||||
UnityEditor.MonoScript script = obj as UnityEditor.MonoScript;
|
UnityEditor.MonoScript script = obj as UnityEditor.MonoScript;
|
||||||
System.Type scriptType = script.GetClass ();
|
System.Type scriptType = script.GetClass ();
|
||||||
if (scriptType == null || (scriptType != typeof (XNode.Node) && !scriptType.IsSubclassOf (typeof (XNode.Node)))) return AssetDeleteResult.DidNotDelete;
|
if (scriptType == null || (scriptType != typeof (XNode.INode) && !scriptType.IsSubclassOf (typeof (XNode.INode)))) return AssetDeleteResult.DidNotDelete;
|
||||||
|
|
||||||
// Find all ScriptableObjects using this script
|
// Find all ScriptableObjects using this script
|
||||||
string[] guids = AssetDatabase.FindAssets ("t:" + scriptType);
|
string[] guids = AssetDatabase.FindAssets ("t:" + scriptType);
|
||||||
@ -25,7 +25,7 @@ namespace XNodeEditor {
|
|||||||
string assetpath = AssetDatabase.GUIDToAssetPath (guids[i]);
|
string assetpath = AssetDatabase.GUIDToAssetPath (guids[i]);
|
||||||
Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath (assetpath);
|
Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath (assetpath);
|
||||||
for (int k = 0; k < objs.Length; k++) {
|
for (int k = 0; k < objs.Length; k++) {
|
||||||
XNode.Node node = objs[k] as XNode.Node;
|
XNode.INode node = objs[k] as XNode.INode;
|
||||||
if (node.GetType () == scriptType) {
|
if (node.GetType () == scriptType) {
|
||||||
if (node != null && node.graph != null) {
|
if (node != null && node.graph != null) {
|
||||||
// Delete the node and notify the user
|
// Delete the node and notify the user
|
||||||
@ -51,7 +51,7 @@ namespace XNodeEditor {
|
|||||||
Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath (assetpath);
|
Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath (assetpath);
|
||||||
// Ensure that all sub node assets are present in the graph node list
|
// Ensure that all sub node assets are present in the graph node list
|
||||||
for (int u = 0; u < objs.Length; u++) {
|
for (int u = 0; u < objs.Length; u++) {
|
||||||
if (!graph.nodes.Contains (objs[u] as XNode.Node)) graph.nodes.Add(objs[u] as XNode.Node);
|
if (!graph.nodes.Contains (objs[u] as XNode.INode)) graph.nodes.Add(objs[u] as XNode.INode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,8 +9,8 @@ namespace XNodeEditor.Internal {
|
|||||||
/// <summary> Handles caching of custom editor classes and their target types. Accessible with GetEditor(Type type) </summary>
|
/// <summary> Handles caching of custom editor classes and their target types. Accessible with GetEditor(Type type) </summary>
|
||||||
/// <typeparam name="T">Editor Type. Should be the type of the deriving script itself (eg. NodeEditor) </typeparam>
|
/// <typeparam name="T">Editor Type. Should be the type of the deriving script itself (eg. NodeEditor) </typeparam>
|
||||||
/// <typeparam name="A">Attribute Type. The attribute used to connect with the runtime type (eg. CustomNodeEditorAttribute) </typeparam>
|
/// <typeparam name="A">Attribute Type. The attribute used to connect with the runtime type (eg. CustomNodeEditorAttribute) </typeparam>
|
||||||
/// <typeparam name="K">Runtime Type. The ScriptableObject this can be an editor for (eg. Node) </typeparam>
|
/// <typeparam name="K">Runtime Type. The Object this can be an editor for (eg. Node) </typeparam>
|
||||||
public abstract class NodeEditorBase<T, A, K> : Editor where A : Attribute, NodeEditorBase<T, A, K>.INodeEditorAttrib where T : NodeEditorBase<T, A, K> where K : ScriptableObject {
|
public abstract class NodeEditorBase<T, A, K> : Editor where A : Attribute, NodeEditorBase<T, A, K>.INodeEditorAttrib where T : NodeEditorBase<T, A, K> where K : UnityEngine.Object {
|
||||||
/// <summary> Custom editors defined with [CustomNodeEditor] </summary>
|
/// <summary> Custom editors defined with [CustomNodeEditor] </summary>
|
||||||
private static Dictionary<Type, Type> editorTypes;
|
private static Dictionary<Type, Type> editorTypes;
|
||||||
private static Dictionary<K, T> editors = new Dictionary<K, T>();
|
private static Dictionary<K, T> editors = new Dictionary<K, T>();
|
||||||
|
|||||||
@ -303,8 +303,8 @@ namespace XNodeEditor {
|
|||||||
|
|
||||||
NodeEditor.portPositions = new Dictionary<XNode.NodePort, Vector2>();
|
NodeEditor.portPositions = new Dictionary<XNode.NodePort, Vector2>();
|
||||||
|
|
||||||
//Get node position
|
//Get node.Position
|
||||||
Vector2 nodePos = GridToWindowPositionNoClipped(node.position);
|
Vector2 nodePos = GridToWindowPositionNoClipped(node.Position);
|
||||||
|
|
||||||
GUILayout.BeginArea(new Rect(nodePos, new Vector2(nodeEditor.GetWidth(), 4000)));
|
GUILayout.BeginArea(new Rect(nodePos, new Vector2(nodeEditor.GetWidth(), 4000)));
|
||||||
|
|
||||||
@ -349,7 +349,7 @@ namespace XNodeEditor {
|
|||||||
|
|
||||||
foreach (var kvp in NodeEditor.portPositions) {
|
foreach (var kvp in NodeEditor.portPositions) {
|
||||||
Vector2 portHandlePos = kvp.Value;
|
Vector2 portHandlePos = kvp.Value;
|
||||||
portHandlePos += node.position;
|
portHandlePos += node.Position;
|
||||||
Rect rect = new Rect(portHandlePos.x - 8, portHandlePos.y - 8, 16, 16);
|
Rect rect = new Rect(portHandlePos.x - 8, portHandlePos.y - 8, 16, 16);
|
||||||
if (portConnectionPoints.ContainsKey(kvp.Key)) portConnectionPoints[kvp.Key] = rect;
|
if (portConnectionPoints.ContainsKey(kvp.Key)) portConnectionPoints[kvp.Key] = rect;
|
||||||
else portConnectionPoints.Add(kvp.Key, rect);
|
else portConnectionPoints.Add(kvp.Key, rect);
|
||||||
@ -400,7 +400,7 @@ namespace XNodeEditor {
|
|||||||
|
|
||||||
private bool ShouldBeCulled(XNode.Node node) {
|
private bool ShouldBeCulled(XNode.Node node) {
|
||||||
|
|
||||||
Vector2 nodePos = GridToWindowPositionNoClipped(node.position);
|
Vector2 nodePos = GridToWindowPositionNoClipped(node.Position);
|
||||||
if (nodePos.x / _zoom > position.width) return true; // Right
|
if (nodePos.x / _zoom > position.width) return true; // Right
|
||||||
else if (nodePos.y / _zoom > position.height) return true; // Bottom
|
else if (nodePos.y / _zoom > position.height) return true; // Bottom
|
||||||
else if (nodeSizes.ContainsKey(node)) {
|
else if (nodeSizes.ContainsKey(node)) {
|
||||||
|
|||||||
@ -22,7 +22,7 @@ namespace XNodeEditor {
|
|||||||
/// <summary> Make a field for a serialized property. Automatically displays relevant node port. </summary>
|
/// <summary> Make a field for a serialized property. Automatically displays relevant node port. </summary>
|
||||||
public static void PropertyField(SerializedProperty property, GUIContent label, bool includeChildren = true, params GUILayoutOption[] options) {
|
public static void PropertyField(SerializedProperty property, GUIContent label, bool includeChildren = true, params GUILayoutOption[] options) {
|
||||||
if (property == null) throw new NullReferenceException();
|
if (property == null) throw new NullReferenceException();
|
||||||
XNode.Node node = property.serializedObject.targetObject as XNode.Node;
|
XNode.INode node = property.serializedObject.targetObject as XNode.INode;
|
||||||
XNode.NodePort port = node.GetPort(property.name);
|
XNode.NodePort port = node.GetPort(property.name);
|
||||||
PropertyField(property, label, port, includeChildren);
|
PropertyField(property, label, port, includeChildren);
|
||||||
}
|
}
|
||||||
@ -285,7 +285,7 @@ namespace XNodeEditor {
|
|||||||
/// <param name="connectionType">Connection type of added dynamic ports</param>
|
/// <param name="connectionType">Connection type of added dynamic ports</param>
|
||||||
/// <param name="onCreation">Called on the list on creation. Use this if you want to customize the created ReorderableList</param>
|
/// <param name="onCreation">Called on the list on creation. Use this if you want to customize the created ReorderableList</param>
|
||||||
public static void DynamicPortList(string fieldName, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, XNode.Node.TypeConstraint typeConstraint = XNode.Node.TypeConstraint.None, Action<ReorderableList> onCreation = null) {
|
public static void DynamicPortList(string fieldName, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, XNode.Node.TypeConstraint typeConstraint = XNode.Node.TypeConstraint.None, Action<ReorderableList> onCreation = null) {
|
||||||
XNode.Node node = serializedObject.targetObject as XNode.Node;
|
XNode.INode node = serializedObject.targetObject as XNode.INode;
|
||||||
|
|
||||||
var indexedPorts = node.DynamicPorts.Select(x => {
|
var indexedPorts = node.DynamicPorts.Select(x => {
|
||||||
string[] split = x.fieldName.Split(' ');
|
string[] split = x.fieldName.Split(' ');
|
||||||
@ -315,9 +315,9 @@ namespace XNodeEditor {
|
|||||||
list.DoLayoutList();
|
list.DoLayoutList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReorderableList CreateReorderableList(string fieldName, List<XNode.NodePort> dynamicPorts, SerializedProperty arrayData, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.Node.ConnectionType connectionType, XNode.Node.TypeConstraint typeConstraint, Action<ReorderableList> onCreation) {
|
private static ReorderableList CreateReorderableList(string fieldName, List<XNode.NodePort> dynamicPorts, SerializedProperty arrayData, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.INode.ConnectionType connectionType, XNode.INode.TypeConstraint typeConstraint, Action<ReorderableList> onCreation) {
|
||||||
bool hasArrayData = arrayData != null && arrayData.isArray;
|
bool hasArrayData = arrayData != null && arrayData.isArray;
|
||||||
XNode.Node node = serializedObject.targetObject as XNode.Node;
|
XNode.INode node = serializedObject.targetObject as XNode.INode;
|
||||||
ReorderableList list = new ReorderableList(dynamicPorts, null, true, true, true, true);
|
ReorderableList list = new ReorderableList(dynamicPorts, null, true, true, true, true);
|
||||||
string label = arrayData != null ? arrayData.displayName : ObjectNames.NicifyVariableName(fieldName);
|
string label = arrayData != null ? arrayData.displayName : ObjectNames.NicifyVariableName(fieldName);
|
||||||
|
|
||||||
@ -404,7 +404,7 @@ namespace XNodeEditor {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
while (node.HasPort(newName)) newName = fieldName + " " + (++i);
|
while (node.HasPort(newName)) newName = fieldName + " " + (++i);
|
||||||
|
|
||||||
if (io == XNode.NodePort.IO.Output) node.AddDynamicOutput(type, connectionType, XNode.Node.TypeConstraint.None, newName);
|
if (io == XNode.NodePort.IO.Output) node.AddDynamicOutput(type, connectionType, XNode.INode.TypeConstraint.None, newName);
|
||||||
else node.AddDynamicInput(type, connectionType, typeConstraint, newName);
|
else node.AddDynamicInput(type, connectionType, typeConstraint, newName);
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
EditorUtility.SetDirty(node);
|
EditorUtility.SetDirty(node);
|
||||||
|
|||||||
@ -47,7 +47,7 @@ namespace XNodeEditor {
|
|||||||
UnityEngine.Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath(assetpath);
|
UnityEngine.Object[] objs = AssetDatabase.LoadAllAssetRepresentationsAtPath(assetpath);
|
||||||
// Loop through graph asset and search for nodes (nodes exist inside the graph asset as sub-assets)
|
// Loop through graph asset and search for nodes (nodes exist inside the graph asset as sub-assets)
|
||||||
for (int k = 0; k < objs.Length; k++) {
|
for (int k = 0; k < objs.Length; k++) {
|
||||||
XNode.Node node = objs[k] as XNode.Node;
|
XNode.INode node = objs[k] as XNode.INode;
|
||||||
if (node != null) node.UpdateStaticPorts();
|
if (node != null) node.UpdateStaticPorts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,15 +55,15 @@ namespace XNodeEditor {
|
|||||||
|
|
||||||
public static Type[] GetNodeTypes() {
|
public static Type[] GetNodeTypes() {
|
||||||
//Get all classes deriving from Node via reflection
|
//Get all classes deriving from Node via reflection
|
||||||
return GetDerivedTypes(typeof(XNode.Node));
|
return GetDerivedTypes(typeof(XNode.INode));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<Type, Color> GetNodeTint() {
|
public static Dictionary<Type, Color> GetNodeTint() {
|
||||||
Dictionary<Type, Color> tints = new Dictionary<Type, Color>();
|
Dictionary<Type, Color> tints = new Dictionary<Type, Color>();
|
||||||
for (int i = 0; i < nodeTypes.Length; i++) {
|
for (int i = 0; i < nodeTypes.Length; i++) {
|
||||||
var attribs = nodeTypes[i].GetCustomAttributes(typeof(XNode.Node.NodeTintAttribute), true);
|
var attribs = nodeTypes[i].GetCustomAttributes(typeof(XNode.INode.NodeTintAttribute), true);
|
||||||
if (attribs == null || attribs.Length == 0) continue;
|
if (attribs == null || attribs.Length == 0) continue;
|
||||||
XNode.Node.NodeTintAttribute attrib = attribs[0] as XNode.Node.NodeTintAttribute;
|
XNode.INode.NodeTintAttribute attrib = attribs[0] as XNode.INode.NodeTintAttribute;
|
||||||
tints.Add(nodeTypes[i], attrib.color);
|
tints.Add(nodeTypes[i], attrib.color);
|
||||||
}
|
}
|
||||||
return tints;
|
return tints;
|
||||||
@ -72,9 +72,9 @@ namespace XNodeEditor {
|
|||||||
public static Dictionary<Type, int> GetNodeWidth() {
|
public static Dictionary<Type, int> GetNodeWidth() {
|
||||||
Dictionary<Type, int> widths = new Dictionary<Type, int>();
|
Dictionary<Type, int> widths = new Dictionary<Type, int>();
|
||||||
for (int i = 0; i < nodeTypes.Length; i++) {
|
for (int i = 0; i < nodeTypes.Length; i++) {
|
||||||
var attribs = nodeTypes[i].GetCustomAttributes(typeof(XNode.Node.NodeWidthAttribute), true);
|
var attribs = nodeTypes[i].GetCustomAttributes(typeof(XNode.INode.NodeWidthAttribute), true);
|
||||||
if (attribs == null || attribs.Length == 0) continue;
|
if (attribs == null || attribs.Length == 0) continue;
|
||||||
XNode.Node.NodeWidthAttribute attrib = attribs[0] as XNode.Node.NodeWidthAttribute;
|
XNode.INode.NodeWidthAttribute attrib = attribs[0] as XNode.INode.NodeWidthAttribute;
|
||||||
widths.Add(nodeTypes[i], attrib.width);
|
widths.Add(nodeTypes[i], attrib.width);
|
||||||
}
|
}
|
||||||
return widths;
|
return widths;
|
||||||
@ -85,7 +85,7 @@ namespace XNodeEditor {
|
|||||||
// If we can't find field in the first run, it's probably a private field in a base class.
|
// If we can't find field in the first run, it's probably a private field in a base class.
|
||||||
FieldInfo field = type.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
FieldInfo field = type.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
// Search base classes for private fields only. Public fields are found above
|
// Search base classes for private fields only. Public fields are found above
|
||||||
while (field == null && (type = type.BaseType) != typeof(XNode.Node)) field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
|
while (field == null && (type = type.BaseType) != typeof(XNode.INode)) field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ namespace XNodeEditor {
|
|||||||
private static Texture2D _dot;
|
private static Texture2D _dot;
|
||||||
public static Texture2D dotOuter { get { return _dotOuter != null ? _dotOuter : _dotOuter = Resources.Load<Texture2D>("xnode_dot_outer"); } }
|
public static Texture2D dotOuter { get { return _dotOuter != null ? _dotOuter : _dotOuter = Resources.Load<Texture2D>("xnode_dot_outer"); } }
|
||||||
private static Texture2D _dotOuter;
|
private static Texture2D _dotOuter;
|
||||||
public static Texture2D nodeBody { get { return _nodeBody != null ? _nodeBody : _nodeBody = Resources.Load<Texture2D>("xnode_node"); } }
|
public static Texture2D nodeBody { get { return _nodeBody != null ? _nodeBody : _nodeBody = Resources.Load<Texture2D>("XNode.INode"); } }
|
||||||
private static Texture2D _nodeBody;
|
private static Texture2D _nodeBody;
|
||||||
public static Texture2D nodeHighlight { get { return _nodeHighlight != null ? _nodeHighlight : _nodeHighlight = Resources.Load<Texture2D>("xnode_node_highlight"); } }
|
public static Texture2D nodeHighlight { get { return _nodeHighlight != null ? _nodeHighlight : _nodeHighlight = Resources.Load<Texture2D>("xnode_node_highlight"); } }
|
||||||
private static Texture2D _nodeHighlight;
|
private static Texture2D _nodeHighlight;
|
||||||
|
|||||||
@ -134,7 +134,7 @@ namespace XNodeEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Creates a new C# Class.</summary>
|
/// <summary>Creates a new C# Class.</summary>
|
||||||
[MenuItem("Assets/Create/xNode/Node C# Script", false, 89)]
|
[MenuItem("Assets/Create/XNode.INode C# Script", false, 89)]
|
||||||
private static void CreateNode() {
|
private static void CreateNode() {
|
||||||
string[] guids = AssetDatabase.FindAssets("xNode_NodeTemplate.cs");
|
string[] guids = AssetDatabase.FindAssets("xNode_NodeTemplate.cs");
|
||||||
if (guids.Length == 0) {
|
if (guids.Length == 0) {
|
||||||
|
|||||||
@ -8,7 +8,7 @@ namespace XNodeEditor {
|
|||||||
public partial class NodeEditorWindow : EditorWindow {
|
public partial class NodeEditorWindow : EditorWindow {
|
||||||
public static NodeEditorWindow current;
|
public static NodeEditorWindow current;
|
||||||
|
|
||||||
/// <summary> Stores node positions for all nodePorts. </summary>
|
/// <summary> Stores node.Positions for all nodePorts. </summary>
|
||||||
public Dictionary<XNode.NodePort, Rect> portConnectionPoints { get { return _portConnectionPoints; } }
|
public Dictionary<XNode.NodePort, Rect> portConnectionPoints { get { return _portConnectionPoints; } }
|
||||||
private Dictionary<XNode.NodePort, Rect> _portConnectionPoints = new Dictionary<XNode.NodePort, Rect>();
|
private Dictionary<XNode.NodePort, Rect> _portConnectionPoints = new Dictionary<XNode.NodePort, Rect>();
|
||||||
[SerializeField] private NodePortReference[] _references = new NodePortReference[0];
|
[SerializeField] private NodePortReference[] _references = new NodePortReference[0];
|
||||||
@ -56,9 +56,9 @@ namespace XNodeEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<XNode.Node, Vector2> nodeSizes { get { return _nodeSizes; } }
|
public Dictionary<XNode.INode, Vector2> nodeSizes { get { return _nodeSizes; } }
|
||||||
private Dictionary<XNode.Node, Vector2> _nodeSizes = new Dictionary<XNode.Node, Vector2>();
|
private Dictionary<XNode.INode, Vector2> _nodeSizes = new Dictionary<XNode.INode, Vector2>();
|
||||||
public XNode.NodeGraph graph;
|
public XNode.INodeGraph graph;
|
||||||
public Vector2 panOffset { get { return _panOffset; } set { _panOffset = value; Repaint(); } }
|
public Vector2 panOffset { get { return _panOffset; } set { _panOffset = value; Repaint(); } }
|
||||||
private Vector2 _panOffset;
|
private Vector2 _panOffset;
|
||||||
public float zoom { get { return _zoom; } set { _zoom = Mathf.Clamp(value, 1f, NodeEditorPreferences.GetSettings().zoomOutLimit); Repaint(); } }
|
public float zoom { get { return _zoom; } set { _zoom = Mathf.Clamp(value, 1f, NodeEditorPreferences.GetSettings().zoomOutLimit); Repaint(); } }
|
||||||
@ -78,7 +78,7 @@ namespace XNodeEditor {
|
|||||||
|
|
||||||
/// <summary> Handle Selection Change events</summary>
|
/// <summary> Handle Selection Change events</summary>
|
||||||
private static void OnSelectionChanged() {
|
private static void OnSelectionChanged() {
|
||||||
XNode.NodeGraph nodeGraph = Selection.activeObject as XNode.NodeGraph;
|
XNode.INodeGraph nodeGraph = Selection.activeObject as XNode.INodeGraph;
|
||||||
if (nodeGraph && !AssetDatabase.Contains(nodeGraph)) {
|
if (nodeGraph && !AssetDatabase.Contains(nodeGraph)) {
|
||||||
Open(nodeGraph);
|
Open(nodeGraph);
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ namespace XNodeEditor {
|
|||||||
string path = EditorUtility.SaveFilePanelInProject("Save NodeGraph", "NewNodeGraph", "asset", "");
|
string path = EditorUtility.SaveFilePanelInProject("Save NodeGraph", "NewNodeGraph", "asset", "");
|
||||||
if (string.IsNullOrEmpty(path)) return;
|
if (string.IsNullOrEmpty(path)) return;
|
||||||
else {
|
else {
|
||||||
XNode.NodeGraph existingGraph = AssetDatabase.LoadAssetAtPath<XNode.NodeGraph>(path);
|
XNode.INodeGraph existingGraph = AssetDatabase.LoadAssetAtPath<XNode.INodeGraph>(path);
|
||||||
if (existingGraph != null) AssetDatabase.DeleteAsset(path);
|
if (existingGraph != null) AssetDatabase.DeleteAsset(path);
|
||||||
AssetDatabase.CreateAsset(graph, path);
|
AssetDatabase.CreateAsset(graph, path);
|
||||||
EditorUtility.SetDirty(graph);
|
EditorUtility.SetDirty(graph);
|
||||||
@ -152,7 +152,7 @@ namespace XNodeEditor {
|
|||||||
return new Vector2(xOffset, yOffset);
|
return new Vector2(xOffset, yOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SelectNode(XNode.Node node, bool add) {
|
public void SelectNode(XNode.INode node, bool add) {
|
||||||
if (add) {
|
if (add) {
|
||||||
List<Object> selection = new List<Object>(Selection.objects);
|
List<Object> selection = new List<Object>(Selection.objects);
|
||||||
selection.Add(node);
|
selection.Add(node);
|
||||||
@ -160,7 +160,7 @@ namespace XNodeEditor {
|
|||||||
} else Selection.objects = new Object[] { node };
|
} else Selection.objects = new Object[] { node };
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeselectNode(XNode.Node node) {
|
public void DeselectNode(XNode.INode node) {
|
||||||
List<Object> selection = new List<Object>(Selection.objects);
|
List<Object> selection = new List<Object>(Selection.objects);
|
||||||
selection.Remove(node);
|
selection.Remove(node);
|
||||||
Selection.objects = selection.ToArray();
|
Selection.objects = selection.ToArray();
|
||||||
@ -168,7 +168,7 @@ namespace XNodeEditor {
|
|||||||
|
|
||||||
[OnOpenAsset(0)]
|
[OnOpenAsset(0)]
|
||||||
public static bool OnOpen(int instanceID, int line) {
|
public static bool OnOpen(int instanceID, int line) {
|
||||||
XNode.NodeGraph nodeGraph = EditorUtility.InstanceIDToObject(instanceID) as XNode.NodeGraph;
|
XNode.INodeGraph nodeGraph = EditorUtility.InstanceIDToObject(instanceID) as XNode.INodeGraph;
|
||||||
if (nodeGraph != null) {
|
if (nodeGraph != null) {
|
||||||
Open(nodeGraph);
|
Open(nodeGraph);
|
||||||
return true;
|
return true;
|
||||||
@ -177,7 +177,7 @@ namespace XNodeEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Open the provided graph in the NodeEditor</summary>
|
/// <summary>Open the provided graph in the NodeEditor</summary>
|
||||||
public static void Open(XNode.NodeGraph graph) {
|
public static void Open(XNode.INodeGraph graph) {
|
||||||
if (!graph) return;
|
if (!graph) return;
|
||||||
|
|
||||||
NodeEditorWindow w = GetWindow(typeof(NodeEditorWindow), false, "xNode", true) as NodeEditorWindow;
|
NodeEditorWindow w = GetWindow(typeof(NodeEditorWindow), false, "xNode", true) as NodeEditorWindow;
|
||||||
|
|||||||
@ -34,7 +34,7 @@ namespace XNodeEditor {
|
|||||||
/// <summary> Returns context node menu path. Null or empty strings for hidden nodes. </summary>
|
/// <summary> Returns context node menu path. Null or empty strings for hidden nodes. </summary>
|
||||||
public virtual string GetNodeMenuName(Type type) {
|
public virtual string GetNodeMenuName(Type type) {
|
||||||
//Check if type has the CreateNodeMenuAttribute
|
//Check if type has the CreateNodeMenuAttribute
|
||||||
XNode.Node.CreateNodeMenuAttribute attrib;
|
XNode.INode.CreateNodeMenuAttribute attrib;
|
||||||
if (NodeEditorUtilities.GetAttrib(type, out attrib)) // Return custom path
|
if (NodeEditorUtilities.GetAttrib(type, out attrib)) // Return custom path
|
||||||
return attrib.menuName;
|
return attrib.menuName;
|
||||||
else // Return generated path
|
else // Return generated path
|
||||||
@ -70,8 +70,8 @@ namespace XNodeEditor {
|
|||||||
|
|
||||||
/// <summary> Create a node and save it in the graph asset </summary>
|
/// <summary> Create a node and save it in the graph asset </summary>
|
||||||
public virtual void CreateNode(Type type, Vector2 position) {
|
public virtual void CreateNode(Type type, Vector2 position) {
|
||||||
XNode.Node node = target.AddNode(type);
|
XNode.INode node = target.AddNode(type);
|
||||||
node.position = position;
|
node.Position = position;
|
||||||
if (string.IsNullOrEmpty(node.name)) node.name = UnityEditor.ObjectNames.NicifyVariableName(type.Name);
|
if (string.IsNullOrEmpty(node.name)) node.name = UnityEditor.ObjectNames.NicifyVariableName(type.Name);
|
||||||
AssetDatabase.AddObjectToAsset(node, target);
|
AssetDatabase.AddObjectToAsset(node, target);
|
||||||
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
|
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
|
||||||
@ -79,8 +79,8 @@ namespace XNodeEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Creates a copy of the original node in the graph </summary>
|
/// <summary> Creates a copy of the original node in the graph </summary>
|
||||||
public XNode.Node CopyNode(XNode.Node original) {
|
public XNode.INode CopyNode(XNode.INode original) {
|
||||||
XNode.Node node = target.CopyNode(original);
|
XNode.INode node = target.CopyNode(original);
|
||||||
node.name = original.name;
|
node.name = original.name;
|
||||||
AssetDatabase.AddObjectToAsset(node, target);
|
AssetDatabase.AddObjectToAsset(node, target);
|
||||||
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
|
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
|
||||||
@ -88,7 +88,7 @@ namespace XNodeEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Safely remove a node and all its connections. </summary>
|
/// <summary> Safely remove a node and all its connections. </summary>
|
||||||
public void RemoveNode(XNode.Node node) {
|
public void RemoveNode(XNode.INode node) {
|
||||||
UnityEngine.Object.DestroyImmediate(node, true);
|
UnityEngine.Object.DestroyImmediate(node, true);
|
||||||
target.RemoveNode(node);
|
target.RemoveNode(node);
|
||||||
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
|
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
|
||||||
|
|||||||
@ -5,7 +5,12 @@ using XNode;
|
|||||||
|
|
||||||
public class #SCRIPTNAME# : Node {
|
public class #SCRIPTNAME# : Node {
|
||||||
|
|
||||||
// Use OnEnable for initialization
|
// Reset is called on creation
|
||||||
|
private void Reset() {
|
||||||
|
#NOTRIM#
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnEnable is called on load
|
||||||
private void OnEnable() {
|
private void OnEnable() {
|
||||||
#NOTRIM#
|
#NOTRIM#
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace XNode {
|
namespace XNode {
|
||||||
public interface INode {
|
public interface INode {
|
||||||
string name { get; set; }
|
string Name { get; set; }
|
||||||
INodeGraph Graph { get; }
|
INodeGraph Graph { get; }
|
||||||
Vector2 Position { get; set; }
|
Vector2 Position { get; set; }
|
||||||
object GetValue(NodePort port);
|
object GetValue(NodePort port);
|
||||||
@ -15,8 +15,8 @@ namespace XNode {
|
|||||||
IEnumerable<NodePort> Outputs { get; }
|
IEnumerable<NodePort> Outputs { get; }
|
||||||
IEnumerable<NodePort> Inputs { get; }
|
IEnumerable<NodePort> Inputs { get; }
|
||||||
IEnumerable<NodePort> InstancePorts { get; }
|
IEnumerable<NodePort> InstancePorts { get; }
|
||||||
NodePort AddDynamicOutput(Type type, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = Node.TypeConstraint.None, string fieldName = null);
|
NodePort AddDynamicPort(Type type, NodePort.IO direction, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = Node.TypeConstraint.None, string fieldName = null);
|
||||||
NodePort AddDynamicInput(Type type, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = Node.TypeConstraint.None, string fieldName = null);
|
NodePort RemoveDynamicPort(string fieldName);
|
||||||
NodePort GetInputPort(string fieldName);
|
NodePort GetInputPort(string fieldName);
|
||||||
NodePort GetOutputPort(string fieldName);
|
NodePort GetOutputPort(string fieldName);
|
||||||
void OnCreateConnection(NodePort from, NodePort to);
|
void OnCreateConnection(NodePort from, NodePort to);
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace XNode {
|
namespace XNode {
|
||||||
/// <summary> Used by advanced extensions that need to alter the base classes of NodeGraphs </summary>
|
/// <summary> Used by advanced extensions that need to alter the base classes of NodeGraphs </summary>
|
||||||
public interface INodeGraph {
|
public interface INodeGraph {
|
||||||
int NodesCount { get; }
|
|
||||||
void MoveNodeToTop(INode node);
|
void MoveNodeToTop(INode node);
|
||||||
INode[] GetNodes();
|
IEnumerable<INode> Nodes { get; }
|
||||||
INode AddNode(Type type);
|
INode AddNode(Type type);
|
||||||
INode CopyNode(INode original);
|
INode CopyNode(INode original);
|
||||||
void RemoveNode(INode node);
|
void RemoveNode(INode node);
|
||||||
|
|||||||
@ -92,6 +92,12 @@ namespace XNode {
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Interface implementation
|
||||||
|
string INode.Name { get { return name; } set { name = value; } }
|
||||||
|
INodeGraph INode.Graph { get { return graph; } }
|
||||||
|
Vector2 INode.Position { get { return position; } set { position = value; } }
|
||||||
|
#endregion
|
||||||
|
|
||||||
/// <summary> Iterate over all ports on this node. </summary>
|
/// <summary> Iterate over all ports on this node. </summary>
|
||||||
public IEnumerable<NodePort> Ports { get { foreach (NodePort port in ports.Values) yield return port; } }
|
public IEnumerable<NodePort> Ports { get { foreach (NodePort port in ports.Values) yield return port; } }
|
||||||
/// <summary> Iterate over all outputs on this node. </summary>
|
/// <summary> Iterate over all outputs on this node. </summary>
|
||||||
@ -105,9 +111,7 @@ namespace XNode {
|
|||||||
/// <summary> Iterate over all dynamic inputs on this node. </summary>
|
/// <summary> Iterate over all dynamic inputs on this node. </summary>
|
||||||
public IEnumerable<NodePort> DynamicInputs { get { foreach (NodePort port in Ports) { if (port.IsDynamic && port.IsInput) yield return port; } } }
|
public IEnumerable<NodePort> DynamicInputs { get { foreach (NodePort port in Ports) { if (port.IsDynamic && port.IsInput) yield return port; } } }
|
||||||
/// <summary> Parent <see cref="NodeGraph"/> </summary>
|
/// <summary> Parent <see cref="NodeGraph"/> </summary>
|
||||||
public INodeGraph Graph { get { return graph; } }
|
[SerializeField] public NodeGraph graph;
|
||||||
/// <summary> Parent <see cref="NodeGraph"/> </summary>
|
|
||||||
[SerializeField] private NodeGraph graph;
|
|
||||||
/// <summary> Position on the <see cref="NodeGraph"/> </summary>
|
/// <summary> Position on the <see cref="NodeGraph"/> </summary>
|
||||||
[SerializeField] public Vector2 position;
|
[SerializeField] public Vector2 position;
|
||||||
/// <summary> It is recommended not to modify these at hand. Instead, see <see cref="InputAttribute"/> and <see cref="OutputAttribute"/> </summary>
|
/// <summary> It is recommended not to modify these at hand. Instead, see <see cref="InputAttribute"/> and <see cref="OutputAttribute"/> </summary>
|
||||||
@ -136,20 +140,20 @@ namespace XNode {
|
|||||||
/// <seealso cref="AddInstancePort"/>
|
/// <seealso cref="AddInstancePort"/>
|
||||||
/// <seealso cref="AddInstanceOutput"/>
|
/// <seealso cref="AddInstanceOutput"/>
|
||||||
public NodePort AddDynamicInput(Type type, Node.ConnectionType connectionType = Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null) {
|
public NodePort AddDynamicInput(Type type, Node.ConnectionType connectionType = Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null) {
|
||||||
return AddDynamicPort(type, NodePort.IO.Input, connectionType, typeConstraint, fieldName);
|
return ((INode)this).AddDynamicPort(type, NodePort.IO.Input, connectionType, typeConstraint, fieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Convenience function. </summary>
|
/// <summary> Convenience function. </summary>
|
||||||
/// <seealso cref="AddInstancePort"/>
|
/// <seealso cref="AddInstancePort"/>
|
||||||
/// <seealso cref="AddInstanceInput"/>
|
/// <seealso cref="AddInstanceInput"/>
|
||||||
public NodePort AddDynamicOutput(Type type, Node.ConnectionType connectionType = Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null) {
|
public NodePort AddDynamicOutput(Type type, Node.ConnectionType connectionType = Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null) {
|
||||||
return AddDynamicPort(type, NodePort.IO.Output, connectionType, typeConstraint, fieldName);
|
return ((INode)this).AddDynamicPort(type, NodePort.IO.Output, connectionType, typeConstraint, fieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Add a dynamic, serialized port to this node. </summary>
|
/// <summary> Add a dynamic, serialized port to this node. </summary>
|
||||||
/// <seealso cref="AddDynamicInput"/>
|
/// <seealso cref="AddDynamicInput"/>
|
||||||
/// <seealso cref="AddDynamicOutput"/>
|
/// <seealso cref="AddDynamicOutput"/>
|
||||||
private NodePort AddDynamicPort(Type type, NodePort.IO direction, Node.ConnectionType connectionType = Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null) {
|
NodePort INode.AddDynamicPort(Type type, NodePort.IO direction, Node.ConnectionType connectionType = Node.ConnectionType.Multiple, Node.TypeConstraint typeConstraint = TypeConstraint.None, string fieldName = null) {
|
||||||
if (fieldName == null) {
|
if (fieldName == null) {
|
||||||
fieldName = "dynamicInput_0";
|
fieldName = "dynamicInput_0";
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|||||||
@ -11,11 +11,28 @@ namespace XNode {
|
|||||||
/// See: <see cref="AddNode{T}"/> </summary>
|
/// See: <see cref="AddNode{T}"/> </summary>
|
||||||
[SerializeField] public List<Node> nodes = new List<Node>();
|
[SerializeField] public List<Node> nodes = new List<Node>();
|
||||||
|
|
||||||
|
#region Interface implementation
|
||||||
|
IEnumerable<INode> INodeGraph.Nodes { get { foreach (Node node in nodes) yield return node; } }
|
||||||
|
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
|
||||||
|
|
||||||
/// <summary> Add a node to the graph by type (convenience method - will call the System.Type version) </summary>
|
/// <summary> Add a node to the graph by type (convenience method - will call the System.Type version) </summary>
|
||||||
public T AddNode<T>() where T : Node {
|
public T AddNode<T>() where T : Node {
|
||||||
return AddNode(typeof(T)) as T;
|
return AddNode(typeof(T)) as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary> Draw this node on top of other nodes by placing it last in the graph.nodes list </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary> Add a node to the graph by type </summary>
|
/// <summary> Add a node to the graph by type </summary>
|
||||||
public virtual Node AddNode(Type type) {
|
public virtual Node AddNode(Type type) {
|
||||||
Node.graphHotfix = this;
|
Node.graphHotfix = this;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user