public static void DrawExitStatus(BonsaiNode node) { // Draw the exit status in the top right corner. float statusSize = BonsaiPreferences.Instance.statusIconSize; Rect contentRect = node.ContentRect; var rect = new Rect(contentRect.xMax - statusSize, contentRect.yMin, statusSize, statusSize); var prefs = BonsaiPreferences.Instance; var status = node.Behaviour.GetStatusEditor(); if (status == Core.BehaviourNode.StatusEditor.Success) { DrawTexture(rect, prefs.successSymbol, prefs.successColor); } else if (status == Core.BehaviourNode.StatusEditor.Failure) { DrawTexture(rect, prefs.failureSymbol, prefs.failureColor); } else if (status == Core.BehaviourNode.StatusEditor.Aborted) { DrawTexture(rect, prefs.failureSymbol, prefs.abortedColor); } else if (status == Core.BehaviourNode.StatusEditor.Interruption) { DrawTexture(rect, prefs.failureSymbol, prefs.interruptedColor); } }
public static void DrawNode( CanvasTransform t, BonsaiNode node, Color statusColor) { // Convert the node rect from canvas to screen space. Rect screenRect = node.RectPositon; screenRect.position = t.CanvasToScreenSpace(screenRect.position); // Remember the original color that way it is reset when the function exits. Color originalColor = GUI.color; DrawNodeBackground(screenRect, statusColor); // The node contents are grouped together within the node body. GUI.BeginGroup(screenRect); // Make the body of node local to the group coordinate space. Rect localRect = node.RectPositon; localRect.position = Vector2.zero; // Draw the contents inside the node body, automatically laid out. GUILayout.BeginArea(localRect, GUIStyle.none); DrawNodeTypeBackground(node); DrawExitStatus(node); DrawNodeContent(node); GUILayout.EndArea(); GUI.EndGroup(); GUI.color = originalColor; }
private Color NodeStatusColor(BonsaiNode node) { if (IsNodeEvaluating(node)) { return(Preferences.evaluateColor); } else if (IsNodeRunning(node)) { return(Preferences.runningColor); } else if (NodeSelection.IsNodeSelected(node)) { return(Preferences.selectedColor); } else if (NodeSelection.IsReferenced(node)) { return(Preferences.referenceColor); } else if (IsNodeAbortable(node)) { return(Preferences.abortColor); } else if (Canvas.Root == node) { return(Preferences.rootSymbolColor); } return(Preferences.defaultNodeBackgroundColor); }
// Creates and adds an editor node to the canvas. private BonsaiNode AddEditorNode(bool hasOutput, Texture icon = null) { var node = new BonsaiNode(hasOutput, icon); nodes.Add(node); return(node); }
/// <summary> /// Formats the tree to look nicely. /// </summary> public static void PositionNodesNicely(BonsaiNode root, Vector2 anchor) { // Sort parent-child connections so formatter uses latest changes. foreach (BonsaiNode node in TreeTraversal.PreOrder(root)) { node.SortChildren(); } var positioning = new FormatPositioning(); foreach (BonsaiNode node in TreeTraversal.PostOrder(root)) { PositionHorizontal(node, positioning); } foreach (BonsaiNode node in TreeTraversal.PreOrder(root)) { PositionVertical(node); } // Move the entire subtree to the anchor. Vector2 offset = EditorSingleDrag.StartDrag(root, root.Center); EditorSingleDrag.SetSubtreePosition(root, anchor, offset); }
// Highlights nodes that can be aborted by the currently selected node. private void highlightAsAbortable(BonsaiNode node) { // Root must exist. if (!window.tree.Root) { return; } BonsaiNode selected = window.inputHandler.SelectedNode; // A node must be selected. if (selected == null) { return; } var aborter = selected.behaviour as ConditionalAbort; // The selected node must be a conditional abort. if (aborter) { // Highlight this node if it can be aborted by the selected aborter. if (ConditionalAbort.IsAbortable(aborter, node.behaviour)) { backgroundStyle.normal.background = _abortHighlightTex; } } }
public void ToggleSelecion(BonsaiNode node) { if (IsNodeSelected(node)) { selectedNodes.Remove(node); } else { selectedNodes.Add(node); } if (IsSingleSelection) { BonsaiNode selectedNode = SingleSelectedNode; Selection.objects = null; Selection.activeObject = selectedNode.Behaviour; SingleSelected?.Invoke(this, selectedNode); NotifyIfAbortSelected(selectedNode); SelectReferencedNodes(selectedNode); } else if (IsMultiSelection) { Selection.objects = selectedNodes.Select(n => n.Behaviour).ToArray(); } }
// Nodes that are being referenced are highlighted. private void highlightAsReferenced(BonsaiNode node) { if (_referencedNodes.Contains(node.behaviour)) { backgroundStyle.normal.background = _referenceHighlightTex; } }
private void CreateNodeFromType(object sender, Type type) { BonsaiNode node = Canvas.CreateNode(type); NodeSelection.SetSingleSelection(node); lastCreatedNodeToPosition = node; }
private void drawAbortPriorityIcon(Rect localRect, BonsaiNode node) { var abortNode = node.behaviour as ConditionalAbort; // Can only show icon for abort nodes. if (abortNode && abortNode.abortType != AbortType.None) { localRect.position = _abortIconOffset; localRect.size = _abortIconSize; Texture2D tex = null; switch (abortNode.abortType) { case AbortType.LowerPriority: tex = _lowerPrioritySymbol; break; case AbortType.Self: // Offset a bit so it is not too close to left edge. localRect.x += 2f; tex = _selfPrioritySymbol; break; case AbortType.Both: tex = _bothPrioritySymbol; break; } GUILayout.BeginArea(localRect, tex); GUILayout.EndArea(); } }
private void setTreeAsSelected() { EndReferenceLinking(); _window.editor.ClearReferencedNodes(); _selectedNode = null; Selection.activeObject = _window.tree; }
public void PollInput(Event e, CanvasTransform t, Rect inputRect) { if (lastCreatedNodeToPosition != null) { lastCreatedNodeToPosition.Center = BonsaiInput.MousePosition(t); lastCreatedNodeToPosition = null; } if (e.type == EventType.MouseDrag) { if (MotionAction != null) { MotionAction(t); OnCanvasChanged(); } } if (BonsaiInput.IsPanAction(e)) { Pan(e.delta); OnCanvasChanged(); } if (BonsaiInput.IsZoomAction(e)) { Zoom(e.delta.y); OnCanvasChanged(); } Input.HandleMouseEvents(e, t, Canvas.Nodes, inputRect); }
private void StartSingleDrag(BonsaiInputEvent startEvent) { BonsaiNode node = startEvent.node; Vector2 offset = EditorSingleDrag.StartDrag(node, startEvent.canvasMousePostion); MotionAction = (CanvasTransform t) => EditorSingleDrag.Drag(node, BonsaiInput.MousePosition(t), offset); }
private void highlightAsSelected(BonsaiNode node) { // Highlight if node is selected. if (node.behaviour == Selection.activeObject || node.bAreaSelectionFlag) { backgroundStyle.normal.background = _selectedHighlightTex; } }
private void highlightAsRunning(BonsaiNode node) { // Set the color to show that the node is running. if (node.behaviour.GetStatusEditor() == BehaviourNode.StatusEditor.Running) { backgroundStyle.normal.background = _runningBackgroundTex; } }
private BonsaiNode ReconstructEditorNode(BehaviourNode behaviour) { BonsaiNode node = CreateNode(behaviour); node.Behaviour = behaviour; node.Position = behaviour.bonsaiNodePosition; return(node); }
private void handleNewNodeToPositionUnderMouse() { if (_nodeToPositionUnderMouse != null) { _nodeToPositionUnderMouse.bodyRect.position = MousePosition(); _nodeToPositionUnderMouse = null; } }
public void SetSingleSelection(BonsaiNode newSingleSelected) { selectedNodes.Clear(); selectedNodes.Add(newSingleSelected); Selection.objects = null; Selection.activeObject = newSingleSelected.Behaviour; SingleSelected?.Invoke(this, newSingleSelected); SelectReferencedNodes(newSingleSelected); }
private void NotifyIfAbortSelected(BonsaiNode node) { var aborter = node.Behaviour as ConditionalAbort; if (aborter && aborter.abortType != AbortType.None) { AbortSelected?.Invoke(this, aborter); } }
private void resetState() { _bIsAreaSelecting = false; _bIsDragging = false; _bIsMakingConnection = false; _draggingNode = null; _outputKnobToConnect = null; }
public void PushToEnd(BonsaiNode node) { bool bRemoved = nodes.Remove(node); if (bRemoved) { nodes.Add(node); } }
public static BonsaiNode DuplicateSingle(BonsaiCanvas canvas, BonsaiNode original) { BonsaiNode duplicate = canvas.CreateNode(original.Behaviour.GetType()); // Duplicate nodes are placed offset from the original. duplicate.Position = original.Position + Vector2.one * 40f; return(duplicate); }
private void endSingleDrag() { // After doing a drag, the children order might have changed, so to reflect // what we see in the editor to the internal tree structure, we notify the // node of a positional reordering. _draggingNode.NotifyParentOfPostionalReordering(); _bIsDragging = false; _draggingNode = null; }
private void drawRootSymbol(Rect localRect, BonsaiNode node) { if (window.tree.Root == node.behaviour) { // Shift the symbol so it is not in the center. localRect.x -= localRect.width / 2f - 20f; drawTexture(localRect, _rootSymbol, _rootSymbolColor); } }
private static void GetCompositeParent(BonsaiNode aborter, out BonsaiNode compositeParent, out BonsaiNode directChild) { directChild = aborter; compositeParent = aborter.Parent; while (compositeParent != null && !compositeParent.Behaviour.IsComposite()) { directChild = compositeParent; compositeParent = compositeParent.Parent; } }
public static void DrawPorts(CanvasTransform t, BonsaiNode node) { // There is always an input port. DrawPort(t, node.InputRect); if (node.HasOutput) { DrawPort(t, node.OutputRect); } }
public void UpdateNodeGUI(BehaviourNode behaviour) { BonsaiNode node = Canvas.Nodes.FirstOrDefault(n => n.Behaviour == behaviour); if (node != null) { node.UpdateGui(); node.Center = MathExtensions.SnapPosition(node.Center, SnapStep); } }
public void UpdateAbortableSelection(BonsaiNode node) { abortableSelected.Clear(); var aborter = node.Behaviour as Core.ConditionalAbort; if (aborter) { abortableSelected = new HashSet <BonsaiNode>(Abortables(node, aborter.abortType)); } }
public void SetRoot(BonsaiNode newRoot) { if (newRoot.Parent == null) { Root = newRoot; } else { Debug.LogWarning("Root cannot be a child."); } }
private void DrawNodesInEditMode(CanvasTransform t) { var nodes = Canvas.Nodes; for (int i = 0; i < nodes.Count; i++) { BonsaiNode node = nodes[i]; Drawer.DrawNode(t, node, NodeStatusColor(node)); Drawer.DrawPorts(t, node); } }