/// <summary> /// Creates a new NodeOutput in NodeBody of specified type /// </summary> public static NodeOutput Create(Node NodeBody, string OutputName, string OutputType) { NodeOutput output = CreateInstance <NodeOutput> (); output.body = NodeBody; output.name = OutputName; output.SetType(OutputType); NodeBody.Outputs.Add(output); return(output); }
/// <summary> /// Creates a new NodeOutput in NodeBody of specified type /// </summary> public static NodeOutput Create(Node NodeBody, string OutputName, string OutputType) { NodeOutput output = CreateInstance <NodeOutput> (); output.body = NodeBody; output.type = OutputType; output.knobTexture = ConnectionTypes.GetTypeData(OutputType).OutputKnob; output.name = OutputName; NodeBody.Outputs.Add(output); return(output); }
/// <summary> /// A recursive function to clear all calculations depending on this node. /// Usually does not need to be called manually /// </summary> public static void ClearCalculation(Node node) { node.calculated = false; for (int outCnt = 0; outCnt < node.Outputs.Count; outCnt++) { NodeOutput output = node.Outputs [outCnt]; for (int conCnt = 0; conCnt < output.connections.Count; conCnt++) { ClearCalculation(output.connections [conCnt].body); } } }
/// <summary> /// Creates a new NodeOutput in NodeBody of specified type at the specified Node Side /// </summary> public static NodeOutput Create(Node nodeBody, string outputName, string outputType, NodeSide nodeSide, float sidePosition) { NodeOutput output = CreateInstance <NodeOutput> (); output.body = nodeBody; output.name = outputName; output.type = outputType; output.side = nodeSide; output.sidePosition = sidePosition; output.ReloadKnobTexture(); nodeBody.Outputs.Add(output); return(output); }
/// <summary> /// Removes the connection from this NodeInput /// </summary> public void RemoveConnection() { if (connection == null) { return; } NodeEditorCallbacks.IssueOnRemoveConnection(this); connection.connections.Remove(this); connection = null; NodeEditor.RecalculateFrom(body); }
/// <summary> /// Removes the connection from this NodeInput /// </summary> public void RemoveConnection() { if (connection == null) { return; } NodeEditorCallbacks.IssueOnRemoveConnection(this); connection.connections.Remove(this); connection = null; NodeEditor.curNodeCanvas.OnNodeChange(body); }
/// <summary> /// Draws the node curves; splitted from knobs because of the render order /// </summary> public void DrawConnections() { for (int outCnt = 0; outCnt < Outputs.Count; outCnt++) { NodeOutput output = Outputs [outCnt]; for (int conCnt = 0; conCnt < output.connections.Count; conCnt++) { NodeEditor.DrawConnection(output.GetGUIKnob().center, output.connections [conCnt].GetGUIKnob().center, ConnectionTypes.GetTypeData(output.type).col); } } }
public bool CanApplyConnection(NodeOutput output) { if ((UnityEngine.Object)output == (UnityEngine.Object)null || (UnityEngine.Object)body == (UnityEngine.Object)output.body || (UnityEngine.Object)connection == (UnityEngine.Object)output || !typeData.Type.IsAssignableFrom(output.typeData.Type)) { return(false); } if (output.body.isChildOf(body) && !output.body.allowsLoopRecursion(body)) { Debug.LogWarning("Cannot apply connection: Recursion detected!"); return(false); } return(true); }
/// <summary> /// Draws the node knobs; splitted from curves because of the render order /// </summary> protected internal virtual void DrawKnobs() { for (int outCnt = 0; outCnt < Outputs.Count; outCnt++) { NodeOutput output = Outputs[outCnt]; Rect knobRect = output.GetGUIKnob(); GUI.DrawTexture(knobRect, output.knobTexture); } for (int inCnt = 0; inCnt < Inputs.Count; inCnt++) { NodeInput input = Inputs[inCnt]; Rect knobRect = input.GetGUIKnob(); GUI.DrawTexture(knobRect, input.knobTexture); } }
public void ClearCalculation() { if (!BeginRecursiveSearchLoop()) { calculated = false; for (int i = 0; i < Outputs.Count; i++) { NodeOutput nodeOutput = Outputs[i]; for (int j = 0; j < nodeOutput.connections.Count; j++) { nodeOutput.connections[j].body.ClearCalculation(); } } EndRecursiveSearchLoop(); } }
/// <summary> /// Applies a connection between output and input. 'CanApplyConnection' has to be checked before /// </summary> public static void ApplyConnection(NodeOutput output, NodeInput input) { if (input != null && output != null) { if (input.connection != null) { input.connection.connections.Remove(input); } input.connection = output; output.connections.Add(input); NodeEditor.RecalculateFrom(input.body); NodeEditorCallbacks.IssueOnAddConnection(input); } }
protected static void ReassignOutputType(ref NodeOutput output, Type newOutputType) { Node body = output.body; string name = output.name; IEnumerable <NodeInput> enumerable = from connection in output.connections where connection.typeData.Type.IsAssignableFrom(newOutputType) select connection; output.Delete(); NodeEditorCallbacks.IssueOnAddNodeKnob(NodeOutput.Create(body, name, newOutputType.AssemblyQualifiedName)); output = body.Outputs[body.Outputs.Count - 1]; foreach (NodeInput item in enumerable) { item.ApplyConnection(output); } }
/// <summary> /// A recursive function to clear all calculations depending on this node. /// Usually does not need to be called manually /// </summary> public void ClearCalculation() { if (BeginRecursiveSearchLoop()) { return; } calculated = false; for (int outCnt = 0; outCnt < Outputs.Count; outCnt++) { NodeOutput output = Outputs [outCnt]; for (int conCnt = 0; conCnt < output.connections.Count; conCnt++) { output.connections [conCnt].body.ClearCalculation(); } } EndRecursiveSearchLoop(); }
/// <summary> /// Reassigns the type of the given output. This actually recreates it /// </summary> protected static void ReassignOutputType(ref NodeOutput output, Type newOutputType) { Node body = output.body; string outputName = output.name; // Store all valid connections that are not affected by the type change IEnumerable <NodeInput> validConnections = output.connections.Where((NodeInput connection) => connection.typeData.Type.IsAssignableFrom(newOutputType)); // Delete the output of the old type output.Delete(); // Create Output with new type NodeEditorCallbacks.IssueOnAddNodeKnob(NodeOutput.Create(body, outputName, newOutputType.AssemblyQualifiedName)); output = body.Outputs[body.Outputs.Count - 1]; // Restore the valid connections foreach (NodeInput input in validConnections) { input.ApplyConnection(output); } }
internal bool isInLoop() { if (BeginRecursiveSearchLoop()) { return((UnityEngine.Object) this == (UnityEngine.Object)startRecursiveSearchNode); } for (int i = 0; i < Inputs.Count; i++) { NodeOutput connection = Inputs[i].connection; if ((UnityEngine.Object)connection != (UnityEngine.Object)null && connection.body.isInLoop()) { StopRecursiveSearchLoop(); return(true); } } EndRecursiveSearchLoop(); return(false); }
protected internal virtual void DrawConnections() { CheckNodeKnobMigration(); if (Event.current.type == EventType.Repaint) { for (int i = 0; i < Outputs.Count; i++) { NodeOutput nodeOutput = Outputs[i]; Vector2 center = nodeOutput.GetGUIKnob().center; Vector2 direction = nodeOutput.GetDirection(); for (int j = 0; j < nodeOutput.connections.Count; j++) { NodeInput nodeInput = nodeOutput.connections[j]; NodeEditorGUI.DrawConnection(center, direction, nodeInput.GetGUIKnob().center, nodeInput.GetDirection(), nodeOutput.typeData.Color); } } } }
/// <summary> /// Recursively checks whether this node is in a loop /// </summary> internal bool isInLoop() { if (BeginRecursiveSearchLoop()) { return(this == startRecursiveSearchNode); } foreach (NodeInput input in Inputs) { NodeOutput connection = input.connection; if (connection != null && connection.body.isInLoop()) { StopRecursiveSearchLoop(); return(true); } } EndRecursiveSearchLoop(); return(false); }
/// <summary> /// Recursively checks whether this node is in a loop /// </summary> internal bool isInLoop() { if (BeginRecursiveSearchLoop()) { return(this == startRecursiveSearchNode); } for (int cnt = 0; cnt < Inputs.Count; cnt++) { NodeOutput connection = Inputs [cnt].connection; if (connection != null && connection.body.isInLoop()) { StopRecursiveSearchLoop(); return(true); } } EndRecursiveSearchLoop(); return(false); }
/// <summary> /// Check if the passed NodeOutput can be connected to this NodeInput /// </summary> public bool CanApplyConnection(NodeOutput output) { if (output == null || body == output.body || connection == output || typeData.Type != output.typeData.Type) { return(false); } if (output.body.isChildOf(body)) { // Recursive if (!output.body.allowsLoopRecursion(body)) { // TODO: Generic Notification Debug.LogWarning("Cannot apply connection: Recursion detected!"); return(false); } } return(true); }
protected static void ReassignInputType(ref NodeInput input, Type newInputType) { Node body = input.body; string name = input.name; NodeOutput nodeOutput = null; if ((UnityEngine.Object)input.connection != (UnityEngine.Object)null && newInputType.IsAssignableFrom(input.connection.typeData.Type)) { nodeOutput = input.connection; } input.Delete(); NodeEditorCallbacks.IssueOnAddNodeKnob(NodeInput.Create(body, name, newInputType.AssemblyQualifiedName)); input = body.Inputs[body.Inputs.Count - 1]; if ((UnityEngine.Object)nodeOutput != (UnityEngine.Object)null) { input.ApplyConnection(nodeOutput); } }
/// <summary> /// Draws the node curves; splitted from knobs because of the render order /// </summary> protected internal virtual void DrawConnections() { for (int outCnt = 0; outCnt < Outputs.Count; outCnt++) { NodeOutput output = Outputs [outCnt]; Vector2 startPos = output.GetGUIKnob().center; Vector2 startDir = output.GetDirection(); for (int conCnt = 0; conCnt < output.connections.Count; conCnt++) { NodeInput input = output.connections [conCnt]; NodeEditorGUI.DrawConnection(startPos, startDir, input.GetGUIKnob().center, input.GetDirection(), ConnectionTypes.GetTypeData(output.type).col); } } }
/// <summary> /// Check if the passed NodeOutput can be connected to this NodeInput /// </summary> public bool CanApplyConnection(NodeOutput output) { if (output == null || body == output.body || connection == output || !typeData.Type.IsAssignableFrom(output.typeData.Type)) { // Debug.LogError ("Cannot assign " + typeData.Type.ToString () + " to " + output.typeData.Type.ToString ()); return(false); } if (output.body.isChildOf(body)) { // Recursive if (!output.body.allowsLoopRecursion(body)) { // TODO: Generic Notification Debug.LogWarning("Cannot apply connection: Recursion detected!"); return(false); } } return(true); }
/// <summary> /// Create the a Node of the type specified by the nodeID at position /// Auto-connects the passed connectingOutput if not null to the first compatible input /// </summary> public static Node Create(string nodeID, Vector2 position, NodeOutput connectingOutput) { if (!NodeCanvasManager.CheckCanvasCompability(nodeID, NodeEditor.curNodeCanvas)) { throw new UnityException("Cannot create Node with ID '" + nodeID + "' as it is not compatible with the current canavs type (" + NodeEditor.curNodeCanvas.GetType().ToString() + ")!"); } if (!NodeEditor.curNodeCanvas.CanAddNode(nodeID)) { throw new UnityException("Cannot create another Node with ID '" + nodeID + "' on the current canvas of type (" + NodeEditor.curNodeCanvas.GetType().ToString() + ")!"); } Node node = NodeTypes.getDefaultNode(nodeID); if (node == null) { throw new UnityException("Cannot create Node as ID '" + nodeID + "' is not registered!"); } node = node.Create(position); if (node == null) { return(null); } node.InitBase(); if (connectingOutput != null) { // Handle auto-connection and link the output to the first compatible input foreach (NodeInput input in node.Inputs) { if (input.TryApplyConnection(connectingOutput)) { break; } } } NodeEditorCallbacks.IssueOnAddNode(node); NodeEditor.curNodeCanvas.Validate(); return(node); }
/// <summary> /// Applies a connection between the passed NodeOutput and this NodeInput. 'CanApplyConnection' has to be checked before to avoid interferences! /// </summary> public void ApplyConnection(NodeOutput output) { if (output == null) { return; } if (connection != null) { NodeEditorCallbacks.IssueOnRemoveConnection(this); connection.connections.Remove(this); } connection = output; output.connections.Add(this); NodeEditor.RecalculateFrom(body); output.body.OnAddOutputConnection(output); body.OnAddInputConnection(this); NodeEditorCallbacks.IssueOnAddConnection(this); }
/// <summary> /// Gets the compatible nodes that have atleast one NodeInput that can connect to the given nodeOutput /// </summary> public static List<Node> getCompatibleNodes(NodeOutput nodeOutput) { if (nodeOutput == null) throw new ArgumentNullException ("nodeOutput"); List<Node> compatibleNodes = new List<Node> (); foreach (Node node in NodeTypes.nodes.Keys) { // Check if any of the NodeInputs is able to connect to the given NodeOutput for (int inputCnt = 0; inputCnt < node.Inputs.Count; inputCnt++) { // Checking for compability, not using CanApplyConnection to leave out unnessecary dependancy checks NodeInput input = node.Inputs[inputCnt]; if (input == null) throw new UnityException ("Input " + inputCnt + " is null!"); if (input.typeData.Type.IsAssignableFrom (nodeOutput.typeData.Type)) { compatibleNodes.Add (node); break; } } } return compatibleNodes; }
/// <summary> /// Recursive function which continues calculation on this node and all the child nodes /// Usually does not need to be called manually /// Returns success/failure of this node only /// </summary> public static bool ContinueCalculation(Node node) { if (node.descendantsCalculated() && node.Calculate()) { // finished Calculating, continue with the children for (int outCnt = 0; outCnt < node.Outputs.Count; outCnt++) { NodeOutput output = node.Outputs [outCnt]; for (int conCnt = 0; conCnt < output.connections.Count; conCnt++) { ContinueCalculation(output.connections [conCnt].body); } } workList.Remove(node); node.calculated = true; return(true); } else if (!workList.Contains(node)) { // failed to calculate, add it to check later workList.Add(node); } return(false); }
/// <summary> /// Applies a connection between the passed NodeOutput and this NodeInput. 'CanApplyConnection' has to be checked before to avoid interferences! /// </summary> public void ApplyConnection(NodeOutput output) { Debug.Log("ApplyConnection"); if (output == null) { return; } if (connection != null) { NodeEditorCallbacks.IssueOnRemoveConnection(this); connection.connections.Remove(this); } connection = output; output.connections.Add(this); output.body.OnAddOutputConnection(output); body.OnAddInputConnection(this); NodeEditorCallbacks.IssueOnAddConnection(this); NodeEditor.curNodeCanvas.OnNodeChange(body); }
/// <summary> /// Reassigns the type of the given output. This actually recreates it /// </summary> protected static void ReassignInputType(ref NodeInput input, Type newInputType) { Node body = input.body; string inputName = input.name; // Store the valid connection if it's not affected by the type change NodeOutput validConnection = null; if (input.connection != null && newInputType.IsAssignableFrom(input.connection.typeData.Type)) { validConnection = input.connection; } // Delete the input of the old type input.Delete(); // Create Output with new type NodeEditorCallbacks.IssueOnAddNodeKnob(NodeInput.Create(body, inputName, newInputType.AssemblyQualifiedName)); input = body.Inputs[body.Inputs.Count - 1]; // Restore the valid connections if (validConnection != null) { input.ApplyConnection(validConnection); } }
public bool isChildOf(Node otherNode) { if ((UnityEngine.Object)otherNode == (UnityEngine.Object)null || (UnityEngine.Object)otherNode == (UnityEngine.Object) this) { return(false); } if (BeginRecursiveSearchLoop()) { return(false); } for (int i = 0; i < Inputs.Count; i++) { NodeOutput connection = Inputs[i].connection; if ((UnityEngine.Object)connection != (UnityEngine.Object)null && (UnityEngine.Object)connection.body != (UnityEngine.Object)startRecursiveSearchNode && ((UnityEngine.Object)connection.body == (UnityEngine.Object)otherNode || connection.body.isChildOf(otherNode))) { StopRecursiveSearchLoop(); return(true); } } EndRecursiveSearchLoop(); return(false); }
/// <summary> /// Deletes this Node from curNodeCanvas and the save file /// </summary> public void Delete() { if (!NodeEditor.curNodeCanvas.nodes.Contains(this)) { throw new UnityException("The Node " + name + " does not exist on the Canvas " + NodeEditor.curNodeCanvas.name + "!"); } NodeEditorCallbacks.IssueOnDeleteNode(this); NodeEditor.curNodeCanvas.nodes.Remove(this); for (int outCnt = 0; outCnt < Outputs.Count; outCnt++) { NodeOutput output = Outputs [outCnt]; while (output.connections.Count != 0) { output.connections[0].RemoveConnection(); } DestroyImmediate(output, true); } for (int inCnt = 0; inCnt < Inputs.Count; inCnt++) { NodeInput input = Inputs [inCnt]; if (input.connection != null) { input.connection.connections.Remove(input); } DestroyImmediate(input, true); } for (int knobCnt = 0; knobCnt < nodeKnobs.Count; knobCnt++) { // Inputs/Outputs need specific treatment, unfortunately if (nodeKnobs[knobCnt] != null) { DestroyImmediate(nodeKnobs[knobCnt], true); } } for (int transCnt = 0; transCnt < transitions.Count; transCnt++) { transitions [transCnt].Delete(); } DestroyImmediate(this, true); }