private bool cycleDetected(BonsaiInputKnob input) { var currentNode = this.parentNode; while (currentNode != null) { // Cycle detected. if (input.parentNode == currentNode) { return(true); } // There are no more parents to traverse to. if (currentNode.Input == null || currentNode.Input.outputConnection == null) { break; } // Move up the tree. else { currentNode = currentNode.Input.outputConnection.parentNode; } } // No cycle detected. return(false); }
internal void RemoveInputConnection(BonsaiInputKnob input) { if (_inputs.Remove(input)) { parentNode.OnInputConnectionRemoved(input); input.outputConnection = null; } }
// Reconstruct the editor connections from the tree. private void reconstructEditorConnections(Dictionary <BehaviourNode, BonsaiNode> nodeMap) { // Create the connections foreach (var bonsaiNode in canvas.Nodes) { for (int i = 0; i < bonsaiNode.behaviour.ChildCount(); ++i) { BehaviourNode child = bonsaiNode.behaviour.GetChildAt(i); BonsaiInputKnob input = nodeMap[child].Input; bonsaiNode.Output.Add(input); } } }
/// <summary> /// Called when the output knob made a connection to an input knob. /// </summary> /// <param name="newInput"></param> public void OnNewInputConnection(BonsaiInputKnob newInput) { var newChild = newInput.parentNode.behaviour; // If already connected, this occurs when // building canvas from a loaded tree. if (containsChild(newChild)) { return; } if (!canAddChild(newChild)) { unparent(newChild); } addChild(newChild); }
/// <summary> /// Create a new node for the first time. /// </summary> /// <param name="parentCanvas">The canvas that the node belongs to.</param> /// <param name="bCreateInput">If the node should have an input.</param> /// <param name="bCreateOuput">If the node should have an output.</param> public BonsaiNode(BonsaiCanvas parentCanvas, bool bCreateInput, bool bCreateOuput, bool bCanHaveMultipleChildren) { bodyRect = new Rect(Vector2.zero, kDefaultSize); if (bCreateInput) { _inputKnob = new BonsaiInputKnob(); _inputKnob.parentNode = this; } if (bCreateOuput) { _outputKnob = new BonsaiOutputKnob(); _outputKnob.parentNode = this; } this.bCanHaveMultipleChildren = bCanHaveMultipleChildren; }
public void Add(BonsaiInputKnob input) { // Avoid connecting it to a root. if (input.parentNode.behaviour == input.parentNode.behaviour.Tree.Root) { Debug.LogWarning("A root cannot be a child."); return; } // Avoid re-adding. if (Contains(input)) { Debug.LogWarning("Already added."); return; } // Avoid cycles. if (cycleDetected(input)) { Debug.LogWarning("Cycle detected."); return; } // If it is already parented, then unparent it. if (input.outputConnection != null) { input.outputConnection.RemoveInputConnection(input); } input.outputConnection = this; // Disconnect other inputs since we can only have 1. if (!parentNode.bCanHaveMultipleChildren) { RemoveAllInputs(); } _inputs.Add(input); // Notify the parent that there was a new input. parentNode.OnNewInputConnection(input); }
/// <summary> /// Called when the output knob had an input connection removed. /// </summary> /// <param name="removedInputConnection"></param> public void OnInputConnectionRemoved(BonsaiInputKnob removedInputConnection) { var disconnectedNode = removedInputConnection.parentNode; removeChild(disconnectedNode.behaviour); }
public bool Contains(BonsaiInputKnob input) { return(_inputs.Contains(input)); }