public override NodeViewData CreateNodeViewData(NodeViewData parent, BehaviorNode rootBehavior) { NodeViewData nvd = base.CreateNodeViewData(parent, rootBehavior); nvd.ChangeShape(NodeShape.Ellipse); return nvd; }
public override NodeViewData CreateNodeViewData(NodeViewData parent, BehaviorNode rootBehavior) { NodeViewData nvd = base.CreateNodeViewData(parent, rootBehavior); nvd.ChangeShape(this.IsEndState ? NodeShape.RoundedRectangle : NodeShape.Rectangle); return nvd; }
public override NodeViewData CreateNodeViewData(NodeViewData parent, Behaviac.Design.Nodes.BehaviorNode rootBehavior) { NodeViewData nvd = base.CreateNodeViewData(parent, rootBehavior); nvd.ChangeShape(NodeShape.Rectangle); return nvd; }
public override NodeViewData CreateNodeViewData(NodeViewData parent, Behaviac.Design.Nodes.BehaviorNode rootBehavior) { NodeViewDataStyled nvd = new NodeViewDataStyled(parent, rootBehavior, this, null, __defaultBackgroundBrush, _label, _description); nvd.ChangeShape(NodeShape.Rectangle); return nvd; }
/// <summary> /// Creates a new NodeLayoutManager. /// </summary> /// <param name="edgePen">The pen which is used to draw the edges connecting the nodes.</param> /// <param name="edgePenSubReferenced">The pen which is used to draw the edges connecting sub-referenced nodes.</param> /// <param name="skipLabels">Defines if labels are drawn or not.</param> /// <param name="rootNode">The root of the nodes shown in the view.</param> internal NodeLayoutManager(NodeViewData rootNode, Pen edgePen, Pen edgePenHighlight, Pen edgePenUpdate, Pen edgePenSubReferenced, bool skipLabels) { _rootNodeLayout = rootNode; _edgePen = edgePen; _edgePenHighLight = edgePenHighlight; _edgePenUpdate = edgePenUpdate; _edgePenReadOnly = edgePenSubReferenced; _skipLabels = skipLabels; }
public override void Draw(Graphics graphics, NodeViewData nvd, RectangleF boundingBox) { Attach evnt = (Attach)_attachment; //// use a different brush depending on if the event is reacted to or blocked. //_labelBrush= evnt.BlockEvent ? Brushes.Orange : Brushes.White; _labelBrush = Brushes.White; base.Draw(graphics, nvd, boundingBox); }
public NodeViewDataStyled(NodeViewData parent, BehaviorNode rootBehavior, Node node, Pen borderPen, Brush backgroundBrush, Brush draggedBackgroundBrush, string label, string description, int minWidth = 120, int minHeight = 35) : base(parent, rootBehavior, node, NodeShape.RoundedRectangle, new Style(backgroundBrush, null, Brushes.White), new Style(null, DefaultCurrentBorderPen, null), new Style(null, __defaultSelectedBorderPen, null), new Style(draggedBackgroundBrush, null, null), new Style(null, __highlightedBorderPen, null), new Style(null, __updatedBorderPen, null), new Style(null, __prefabBorderPen, null), label, __defaultLabelFont, __profileLabelFont, __profileLabelBoldFont, minWidth, minHeight, description) { }
/// <summary> /// Handles when dropping a tree node on the view. /// </summary> private void BehaviorTreeView_DragDrop(object sender, DragEventArgs e) { // make sure the view is focused Focus(); // drag the property or method into the node string dragItem = (string)e.Data.GetData(DataFormats.Text); if (!string.IsNullOrEmpty(dragItem) && _dragTargetNode != null && _dragTargetNode.Node != null) { if (_dragTargetNode.Node.SetDefaultPropertyByDragAndDrop(dragItem)) { if (ClickNode != null) { ClickNode(_dragTargetNode); } UndoManager.Save(this.RootNode); LayoutChanged(); } return; } // get source node TreeNode sourceNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode"); if (sourceNode == null) { return; } NodeTag sourceNodeTag = (NodeTag)sourceNode.Tag; // keep the current node position //KeepNodePosition(_dragTargetNode); bool bDragBTOverNode = !((Node)this.RootNode).IsFSM && sourceNodeTag.Type == NodeTagType.Behavior && _dragTargetNode is Behaviac.Design.NodeViewData; // check if we are dropping an attach // or if we are dropping a bt to a node and the indicator is not left/right/up/bottom/center if (_dragAttachMode == NodeAttachMode.Attachment || (bDragBTOverNode && (_dragAttachMode == NodeAttachMode.None || _dragAttachMode == NodeAttachMode.Attachment))) { Attachments.Attachment attach = null; // when we attach a behaviour we must create a special referenced behaviour node if (bDragBTOverNode) { //drag an event(a bt) to a node if (!File.Exists(sourceNodeTag.Filename)) { MainWindow.Instance.SaveBehavior(sourceNodeTag.Defaults as Nodes.BehaviorNode, false); } if (File.Exists(sourceNodeTag.Filename)) { // get the behavior we want to reference BehaviorNode behavior = _behaviorTreeList.LoadBehavior(sourceNodeTag.Filename); Behavior rootB = _rootNodeView.RootBehavior as Behavior; Behavior b = behavior as Behavior; if (!b.CanBeAttached || !IsCompatibleAgentType(rootB, b)) return; attach = Behaviac.Design.Attachments.Attachment.Create(typeof(Behaviac.Design.Attachments.Event), _dragTargetNode.Node); Behaviac.Design.Attachments.Event evt = (Behaviac.Design.Attachments.Event)attach; evt.ReferencedBehavior = behavior; } } else if (_dragTargetNode != null) { Debug.Check(_dragAttachMode == NodeAttachMode.Attachment); // add the attach to the target node attach = Behaviac.Design.Attachments.Attachment.Create(sourceNodeTag.NodeType, _dragTargetNode.Node); } if (_dragTargetNode != null && attach != null && _dragTargetNode.Node.AcceptsAttachment(attach)) { attach.OnPropertyValueChanged(false); attach.ResetId(); _dragTargetNode.Node.AddAttachment(attach); NodeViewData.SubItemAttachment sub = attach.CreateSubItem(); _dragTargetNode.AddSubItem(sub); SelectedNode = _dragTargetNode; SelectedNode.SelectedSubItem = sub; // call the ClickEvent event handler if (ClickEvent != null) { ClickEvent(SelectedNode); } UndoManager.Save(this.RootNode); LayoutChanged(); } } //else if (_dragAttachMode != NodeAttachMode.None) else { // attach a new node to the target node InsertNewNode(_dragTargetNode, _dragAttachMode, sourceNodeTag, this.PointToClient(new Point(e.X, e.Y))); } // reset drag stuff _dragTargetNode = null; _dragNodeDefaults = null; _dragAttachMode = NodeAttachMode.None; Invalidate(); }
/// <summary> /// Centres the given node in the view. /// </summary> /// <param name="node">The node which will be centred.</param> internal void CenterNode(NodeViewData node) { _maintainNodePosition = node; // we use the existing maintain position stuff for that RectangleF bbox = node.IsFSM ? node.GetTotalBoundingBox() : node.BoundingBox; float width = bbox.Width <= 0.0f ? node.MinWidth : bbox.Width; float height = bbox.Height <= 0.0f ? node.MinHeight : bbox.Height; // Scale the whole graph to the suitable size in the view. float viewWidth = ClientSize.Width - 30; float viewHeight = ClientSize.Height - 30; bool isWidthScale = false; if (viewWidth > 0 && viewHeight > 0) { SizeF totalSize = node.GetTotalSize(_nodeLayoutManager.Padding.Width, int.MaxValue); float scale = 1.0f; if (totalSize.Width / totalSize.Height < viewWidth / viewHeight) { scale = viewHeight / totalSize.Height; isWidthScale = false; } else { scale = viewWidth / totalSize.Width; isWidthScale = true; } const float MinScale = 0.1f; const float MaxScale = 2.0f; if (scale < MinScale) { _nodeLayoutManager.Scale = MinScale; } else if (scale > MaxScale) { _nodeLayoutManager.Scale = MaxScale; } else { _nodeLayoutManager.Scale = scale; } } if (node.IsFSM) { if (isWidthScale) _graphOrigin = new PointF(0.0f, ClientSize.Height * 0.5f - height * 0.5f * _nodeLayoutManager.Scale); else _graphOrigin = new PointF(ClientSize.Width * 0.5f - width * 0.5f * _nodeLayoutManager.Scale, 0.0f); } else { _graphOrigin = new PointF(20.0f, ClientSize.Height * 0.5f - height * 0.5f); } Invalidate(); }
private void saveAsReferencedTree() { if (SelectedNode == null || SelectedNode == _rootNodeView || _rootNodeView.RootBehavior.FileManager == null) { return; } string folder = _rootNodeView.RootBehavior.Folder; if (string.IsNullOrEmpty(folder)) { folder = Path.GetDirectoryName(_rootNodeView.RootBehavior.FileManager.Filename); } string ext = Path.GetExtension(_rootNodeView.RootBehavior.FileManager.Filename); string filename = Path.Combine(folder, "rf_" + SelectedNode.Node.ExportClass); filename = Path.ChangeExtension(filename, ext); using(SaveAsDialog saveAsDialog = new SaveAsDialog(true)) { saveAsDialog.Text = Resources.SaveAsReference; saveAsDialog.FileName = _behaviorTreeList.GetUniqueFileName(filename); if (saveAsDialog.ShowDialog() == DialogResult.OK) { filename = saveAsDialog.FileName; // Remove the selected node. Node parentNode = SelectedNode.Node.Parent as Node; BaseNode.Connector parentConnector = SelectedNode.Node.ParentConnector; int index = parentConnector.GetChildIndex(SelectedNode.Node); parentNode.RemoveChild(parentConnector, SelectedNode.Node); // Create a new behavior node. BehaviorNode behaviorNode = Node.CreateBehaviorNode(SelectedNode.Node.ExportClass); ((Node)behaviorNode).AddChild(behaviorNode.GenericChildren, SelectedNode.Node); ((Behavior)behaviorNode).AgentType = ((Behavior)_rootNodeView.RootBehavior).AgentType; // Copy the used Pars from the current behavior to the new one. foreach(ParInfo par in((Behavior)_rootNodeView.RootBehavior).LocalVars) { List<Node.ErrorCheck> result = new List<Node.ErrorCheck>(); Plugin.CheckPar(SelectedNode.Node, par, ref result); if (result.Count > 0) { ((Behavior)behaviorNode).LocalVars.Add(par); } } // Save the new behavior node. behaviorNode.FileManager = _behaviorTreeList.GetFileManagers()[0].Create(filename, behaviorNode); behaviorNode.FileManager.Save(); _behaviorTreeList.RebuildBehaviorList(); // get the behavior we want to reference behaviorNode = _behaviorTreeList.LoadBehavior(filename); // Create a referenced node to hold the new behavior node. ReferencedBehavior refNode = Node.CreateReferencedBehaviorNode(_rootNodeView.RootBehavior, behaviorNode); // Add the new referenced node. Node newNode = refNode as Node; parentNode.AddChild(parentConnector, newNode, index); // Select the new node automatically. _selectedNodePending = newNode; _selectedNodePendingParent = SelectedNode.Parent; newNode.ResetId(true); UndoManager.Save(this.RootNode); LayoutChanged(); } } }
/// <summary> /// Handles when a tree node is dragged on the view. /// </summary> private void BehaviorTreeView_DragOver(object sender, DragEventArgs e) { // get the node we are dragging over Point pt = PointToClient(new Point(e.X, e.Y)); NodeViewData nodeFound = _rootNodeView.GetInsideNode(new PointF(pt.X, pt.Y)); // update last know mouse position _lastMousePosition = new PointF(pt.X, pt.Y); // update the current node if (nodeFound != _currentNode) { _currentNode = nodeFound; Invalidate(); } // when we are moving on a node we must keep drawing as the ttach ode might change but not the node else if (nodeFound != null) { Invalidate(); } // store the target node _dragTargetNode = _currentNode; // deny drop by default e.Effect = DragDropEffects.None; // process dragging the property and method string value from the Meta Browser string dragItem = (string)e.Data.GetData(DataFormats.Text); if (!string.IsNullOrEmpty(dragItem) && _dragTargetNode != null && _dragTargetNode.Node != null && _dragTargetNode.Node.AcceptDefaultPropertyByDragAndDrop()) { e.Effect = DragDropEffects.Move; _dragAttachMode = NodeAttachMode.None; return; } // make sure the correct drag attach mode is set if (_dragTargetNode != null) { if (_dragNodeDefaults is Nodes.Node && _dragAttachMode == NodeAttachMode.Attachment) { _dragAttachMode = NodeAttachMode.None; } else if (_dragNodeDefaults is Attachments.Attachment && _dragAttachMode != NodeAttachMode.Attachment) { _dragAttachMode = NodeAttachMode.Attachment; } } // check if we are trying to drop a node on another one if (_dragTargetNode != null && (e.KeyState & 1/*left mouse button*/) > 0) { if (_dragNodeDefaults != null && (_dragNodeDefaults is Nodes.Node && (_dragAttachMode != NodeAttachMode.None || !(_dragNodeDefaults is Nodes.BehaviorNode) || !(_dragTargetNode.Node is Nodes.BehaviorNode)) || _dragNodeDefaults is Attachments.Attachment && _dragTargetNode.Node.AcceptsAttachment(_dragNodeDefaults))) { e.Effect = DragDropEffects.Move; } } // If this is an empty node, no effect for it. if (_dragTargetNode == null || _dragTargetNode.Node == null || _dragNodeDefaults == null || _dragAttachMode == NodeAttachMode.None && !_dragTargetNode.Node.AcceptsAttachment(_dragNodeDefaults)) { e.Effect = DragDropEffects.None; } if (_rootNodeView.IsFSM || _rootNodeView.Children.Count == 0) { // fsm or empty behavior if (_dragNodeDefaults != null) { if (_dragNodeDefaults is Node) { Node dragNode = _dragNodeDefaults as Node; if (dragNode.IsFSM || dragNode is Behavior) { if (_dragTargetNode == null) { e.Effect = DragDropEffects.Move; } //else if (_dragNodeDefaults is Nodes.BehaviorNode) { // e.Effect = DragDropEffects.None; //} } } else if (_dragNodeDefaults is Attachments.Attachment) { Attachments.Attachment dragAttachment = _dragNodeDefaults as Attachments.Attachment; if (dragAttachment.IsFSM) { if (_dragTargetNode != null && !(_dragTargetNode.Node is Nodes.BehaviorNode) && _dragTargetNode.Node.AcceptsAttachment(dragAttachment)) { e.Effect = DragDropEffects.Move; } else { e.Effect = DragDropEffects.None; } } } } } }
public override void Draw(Graphics graphics, NodeViewData nvd, RectangleF boundingBox) { // render background DrawBackground(graphics, nvd, this.BackgroundBrush); // render the label PointF center = new PointF(boundingBox.Left + boundingBox.Width * 0.5f, boundingBox.Top + boundingBox.Height * 0.5f); SizeF labelSize = MeasureDisplayStringWidth(graphics, this.DisplayLabel, _labelFont); // draw text switch (_alignment) { case (Alignment.Left): graphics.DrawString(this.DisplayLabel, _labelFont, _labelBrush, boundingBox.Left + 6.0f, center.Y - labelSize.Height * 0.5f); break; case (Alignment.Center): graphics.DrawString(this.DisplayLabel, _labelFont, _labelBrush, center.X - labelSize.Width * 0.5f, center.Y - labelSize.Height * 0.5f); break; case (Alignment.Right): graphics.DrawString(this.DisplayLabel, _labelFont, _labelBrush, boundingBox.Right - labelSize.Width - 6.0f, center.Y - labelSize.Height * 0.5f); break; } }
private bool MoveSubItem(NodeViewData sourceNvd, NodeViewData targetNvd, NodeViewData.SubItemAttachment sourceAttachment, NodeViewData.SubItemAttachment targetAttachment, bool insertPreviously, bool isCopied) { if (sourceNvd != null && targetNvd != null && sourceAttachment != null && sourceNvd.SetSubItem(targetNvd, sourceAttachment, targetAttachment, insertPreviously, isCopied)) { // set the prefab dirty for the node if (!string.IsNullOrEmpty(sourceNvd.Node.PrefabName)) { sourceNvd.Node.HasOwnPrefabData = true; } if (!string.IsNullOrEmpty(targetNvd.Node.PrefabName)) { targetNvd.Node.HasOwnPrefabData = true; } SelectedNode = targetNvd; // call the ClickEvent event handler if (ClickEvent != null) { ClickEvent(SelectedNode); } UndoManager.Save(this.RootNode); LayoutChanged(); return true; } return false; }
private void control_ClickEvent(NodeViewData node) { if (node == null) return; // if there is no subitem selected, use the properties of the node if (node.SelectedSubItem == null || node.SelectedSubItem.SelectableObject == null) { PropertiesDock.InspectObject(node.RootBehavior, node.Node); } // publish the properties of the subitem's selection object else { PropertiesDock.InspectObject(node.RootBehavior, node.SelectedSubItem.SelectableObject); } }
/// <summary> /// Handles the drawing and updating of the graph. /// </summary> protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); // calculate the mouse position in the graph PointF graphMousePos = _nodeLayoutManager.ViewToGraph(_lastMousePosition); // when the layout was changed it needs to be recalculated bool layoutChanged = _nodeLayoutManager.LayoutChanged; if (layoutChanged) { _nodeLayoutManager.UpdateLayout(e.Graphics, _forceChangeLayout); _forceChangeLayout = false; } // center the root behaviour if requested if (_pendingCenterBehavior) { _pendingCenterBehavior = false; CenterNode(_rootNodeView); } // select the pending node if (_selectedNodePending != null) { if (_selectedNodePendingParent != null) { if (_selectedNodePendingParent.CanBeExpanded() && !_selectedNodePendingParent.IsExpanded) { _selectedNodePendingParent.IsExpanded = true; LayoutChanged(); } SelectedNode = _selectedNodePendingParent.GetChild(_selectedNodePending); } else { SelectedNode = RootNodeView.FindNodeViewData(_selectedNodePending); } if (SelectedNode != null) { if (SelectedNode.CanBeExpanded() && !SelectedNode.IsExpanded) { SelectedNode.IsExpanded = true; LayoutChanged(); } SelectedNode.SelectedSubItem = SelectedNode.GetSubItem(_selectedAttachmentPending); ShowNode(SelectedNode); } _selectedNodePending = null; _selectedNodePendingParent = null; _selectedAttachmentPending = null; if (ClickEvent != null) { ClickEvent(SelectedNode); } } // check if we must keep the original position of the mouse if (_maintainMousePosition) { _maintainMousePosition = false; // move the graph so that _graphOrigin is at the same position in the view as it was before float mouseX = (graphMousePos.X - _graphOrigin.X) * _nodeLayoutManager.Scale + _nodeLayoutManager.Offset.X; float mouseY = (graphMousePos.Y - _graphOrigin.Y) * _nodeLayoutManager.Scale + _nodeLayoutManager.Offset.Y; _nodeLayoutManager.Offset = new PointF(mouseX, mouseY); } // check if we must keep the original position of _maintainNodePosition else if (_maintainNodePosition != null) { // move the graph so that _graphOrigin is at the same position in the view as it was before RectangleF bbox = _maintainNodePosition.IsFSM ? _maintainNodePosition.GetTotalBoundingBox() : _maintainNodePosition.BoundingBox; PointF viewpos = new PointF(bbox.X * _nodeLayoutManager.Scale, bbox.Y * _nodeLayoutManager.Scale); _nodeLayoutManager.Offset = new PointF(_graphOrigin.X - viewpos.X, _graphOrigin.Y - viewpos.Y); } // reset the node whose position we want to keep _maintainNodePosition = null; // draw the graph to the view _nodeLayoutManager.DrawGraph(e.Graphics, graphMousePos, _currentNode, SelectedNode, _highlightedNodeIds, _updatedNodeIds, _highlightedTransitionIds, _highlightBreakPoint, _profileInfos); // check if we are currently dragging a node and we must draw additional data if (_dragTargetNode != null && _dragAttachment == null && (KeyCtrlIsDown && _movedNode != null || _dragTargetNode.Node != _movedNode)) { if (_dragAttachMode == NodeAttachMode.Attachment) { // we could draw some stuff for attachements here } else { // draw the arrows for the attach modes // get the bounding box of the node RectangleF bbox = _dragTargetNode.BoundingBox; // get the bounding box of the connector _dragTargetConnector = null; // the depth of the area for the mouse const float offset = 12.0f; // the distance of the arrow from the border and its height const float innerOffset = 2.0f; // the horizintal middle of the node float centerX = bbox.Left + bbox.Width * 0.5f; float centerY = bbox.Top + bbox.Height * 0.5f; float centerBoxX = bbox.X + bbox.Width * 0.4f; float centerBoxWidth = bbox.Width * 0.2f; // the half width of the arrow depending of the node's height float arrowHalfWidth = (bbox.Height - innerOffset - innerOffset) * 0.5f; // calculate the mouse areas for the different attach modes RectangleF top = new RectangleF(centerBoxX, bbox.Top, centerBoxWidth, offset); RectangleF bottom = new RectangleF(centerBoxX, bbox.Bottom - offset, centerBoxWidth, offset); RectangleF center = new RectangleF(centerBoxX, centerY - offset * 0.5f, centerBoxWidth, offset); RectangleF left = new RectangleF(bbox.X, bbox.Y, offset, bbox.Height); // update for dragging in a new node BehaviorNode behavior = _dragNodeDefaults as BehaviorNode; if (behavior != null && behavior.FileManager == null) { behavior = null; } // the node that is currently dragged Node draggedNode = (_movedNode != null) ? _movedNode : (_dragNodeDefaults as Node); if (draggedNode == null) { return; } Node.Connector parentConnector = _dragTargetNode.Node.ParentConnector; bool canBeAdoptedByParent = parentConnector != null && (!parentConnector.IsAsChild || AdoptNodeByAncestor(_dragTargetNode.Node.Parent, draggedNode)); //bool targetCanBeAdoptedByParent = (_movedNode == null) || (_movedNode.ParentConnector != null) && _movedNode.ParentConnector.AcceptsChild(_dragTargetNode.Node); bool hasParentBehavior = _dragTargetNode.HasParentBehavior(behavior); bool parentHasParentBehavior = (_dragTargetNode.Parent == null); bool isFSM = _rootNodeView.IsFSM || (_rootNodeView.Children.Count == 0); bool mayTop = !isFSM && canBeAdoptedByParent /*&& targetCanBeAdoptedByParent*/ && !parentHasParentBehavior && parentConnector != null && parentConnector.AcceptsChild(draggedNode); bool mayBottom = mayTop; bool mayCenter = !parentHasParentBehavior && (_rootNodeView.IsFSM && draggedNode.IsFSM || canBeAdoptedByParent && draggedNode.GetType() != _dragTargetNode.Node.GetType() && parentConnector != null && !parentConnector.IsReadOnly && parentConnector.AcceptsChild(draggedNode, true) && draggedNode.CanAdoptChildren(_dragTargetNode.Node)); bool mayLeft = !isFSM && (_dragTargetNode.Node.Parent != _movedNode) && canBeAdoptedByParent && !parentHasParentBehavior && !hasParentBehavior && parentConnector != null && !parentConnector.IsReadOnly && parentConnector.AcceptsChild(draggedNode, true) && !(draggedNode is BehaviorNode) && draggedNode.CanAdoptNode(_dragTargetNode.Node); // update for moving an existing node bool dragTargetHasParentMovedNode = false; if (_movedNode != null) { mayCenter = false; dragTargetHasParentMovedNode = KeyShiftIsDown && _dragTargetNode.Node.HasParent(_movedNode); // a node may not dragged on itself and may not dragged on one of its own children if (_dragTargetNode.Node == _movedNode || dragTargetHasParentMovedNode) { //mayTop = KeyCtrlIsDown; mayTop &= KeyCtrlIsDown && (_dragTargetNode.Node.ParentConnector != null) && _dragTargetNode.Node.ParentConnector.AcceptsChild(_movedNode); mayBottom = mayTop; mayLeft = false; } else { // a dragged node cannot be placed in the same position again mayTop &= (KeyCtrlIsDown || _dragTargetNode.Node.PreviousNode != _movedNode); mayBottom &= (KeyCtrlIsDown || _dragTargetNode.Node.NextNode != _movedNode); mayLeft &= _movedNode.CanAdoptChildren(_dragTargetNode.Node) && (!KeyShiftIsDown || _movedNode.Children.Count == 0); } } if (_copiedNode != null) { mayCenter = false; mayLeft &= _copiedNode.CanAdoptChildren(_dragTargetNode.Node) && (!KeyShiftIsDown || _copiedNode.Children.Count == 0); mayTop &= (_dragTargetNode.Node.ParentConnector != null) && _dragTargetNode.Node.ParentConnector.AcceptsChild(_copiedNode); mayBottom = mayTop; } else if (_clipboardPasteMode) { mayCenter = false; mayLeft &= !KeyShiftIsDown; } // reset the attach mode _dragAttachMode = NodeAttachMode.None; // the vertices needed to draw the arrows PointF[] vertices = new PointF[3]; // draw the top arrow if this action is allowed if (mayTop) { vertices[0] = new PointF(centerX - arrowHalfWidth, top.Bottom - innerOffset); vertices[1] = new PointF(centerX, top.Top + innerOffset); vertices[2] = new PointF(centerX + arrowHalfWidth, top.Bottom - innerOffset); if (top.Contains(graphMousePos)) { _dragAttachMode = NodeAttachMode.Top; e.Graphics.FillPolygon(Brushes.White, vertices); } else { e.Graphics.FillPolygon(Brushes.Black, vertices); } } // draw the bottom arrow if this action is allowed if (mayBottom) { vertices[0] = new PointF(centerX - arrowHalfWidth, bottom.Top + innerOffset); vertices[1] = new PointF(centerX + arrowHalfWidth, bottom.Top + innerOffset); vertices[2] = new PointF(centerX, bottom.Bottom - innerOffset); if (_dragAttachMode == NodeAttachMode.None && bottom.Contains(graphMousePos)) { _dragAttachMode = NodeAttachMode.Bottom; e.Graphics.FillPolygon(Brushes.White, vertices); } else { e.Graphics.FillPolygon(Brushes.Black, vertices); } } // draw the center rectangle if this action is allowed if (mayCenter) { if (center.Contains(graphMousePos)) { _dragAttachMode = NodeAttachMode.Center; e.Graphics.FillRectangle(Brushes.White, centerX - arrowHalfWidth * 0.5f, centerY - innerOffset * 2.0f, arrowHalfWidth, innerOffset * 4.0f); } else { e.Graphics.FillRectangle(Brushes.Black, centerX - arrowHalfWidth * 0.5f, centerY - innerOffset * 2.0f, arrowHalfWidth, innerOffset * 4.0f); } } // draw the left arrow if this action is allowed if (mayLeft) { vertices[0] = new PointF(left.Right - innerOffset, left.Top + innerOffset); vertices[1] = new PointF(left.Right - innerOffset, left.Bottom - innerOffset); vertices[2] = new PointF(left.Left + innerOffset, left.Top + left.Height * 0.5f); if (_dragAttachMode == NodeAttachMode.None && left.Contains(graphMousePos)) { _dragAttachMode = NodeAttachMode.Left; e.Graphics.FillPolygon(Brushes.White, vertices); } else { e.Graphics.FillPolygon(Brushes.Black, vertices); } } // draw the right arrow if this action is allowed foreach(Node.Connector connector in _dragTargetNode.Connectors) { RectangleF bboxConnector = _dragTargetNode.GetConnectorBoundingBox(bbox, connector); RectangleF right = new RectangleF(bboxConnector.Right - offset, bboxConnector.Y, offset, bboxConnector.Height); bool mayRight = !_rootNodeView.IsFSM && !dragTargetHasParentMovedNode && !hasParentBehavior && !connector.IsReadOnly && connector.AcceptsChild(draggedNode) && (!connector.IsAsChild || AdoptNodeByAncestor(_dragTargetNode.Node, draggedNode)); if (mayRight && draggedNode != null && connector == draggedNode.ParentConnector) { mayRight = false; } if (mayRight) { float inOffset = bboxConnector.Height > innerOffset * 4.0f ? innerOffset : 3.0f; vertices[0] = new PointF(right.Left + inOffset, right.Top + inOffset); vertices[1] = new PointF(right.Right - inOffset, right.Top + right.Height * 0.5f); vertices[2] = new PointF(right.Left + inOffset, right.Bottom - inOffset); if (_dragAttachMode == NodeAttachMode.None && right.Contains(graphMousePos)) { _dragTargetConnector = _dragTargetNode.Node.GetConnector(connector.Identifier); _dragAttachMode = NodeAttachMode.Right; e.Graphics.FillPolygon(Brushes.White, vertices); } else { e.Graphics.FillPolygon(Brushes.Black, vertices); } } } } } // draw last mouse pos //e.Graphics.DrawRectangle(Pens.Red, graphMousePos.X -1.0f, graphMousePos.Y -1.0f, 2.0f, 2.0f); //when we are dragging an existing node we draw a small graph representing it if (_movedNodeGraph != null) { // update the layout for the graph. This happens only once inside the function. _movedNodeGraph.UpdateLayout(e.Graphics); // offset the graph to the mouse position _movedNodeGraph.Offset = new PointF(_nodeLayoutManager.Offset.X + graphMousePos.X * _nodeLayoutManager.Scale, _nodeLayoutManager.Offset.Y + graphMousePos.Y * _nodeLayoutManager.Scale - _movedNodeGraph.RootNodeLayout.LayoutRectangle.Height * 0.5f * _movedNodeGraph.Scale); // draw the graph _movedNodeGraph.DrawGraph(e.Graphics, graphMousePos); } // attachment if (_currentNode != null && _dragTargetNode != null && _dragAttachment != null && _dragTargetAttachment != null && _dragAttachment != _dragTargetAttachment && _dragTargetNode.Node.AcceptsAttachment(_dragAttachment.Attachment)) { _dragAttachMode = NodeAttachMode.None; Attachments.Attachment sourceAttach = _dragAttachment.SelectableObject as Attachments.Attachment; Attachments.Attachment targetAttach = _dragTargetAttachment.SelectableObject as Attachments.Attachment; if (sourceAttach != null && targetAttach != null && sourceAttach.IsPrecondition == targetAttach.IsPrecondition && sourceAttach.IsTransition == targetAttach.IsTransition && sourceAttach.IsEffector == targetAttach.IsEffector) { SubItemRegin regin = _dragTargetNode.GetSubItemRegin(graphMousePos); int itemIndex = _currentNode.GetSubItemIndex(_dragAttachment); int targetItemIndex = _dragTargetNode.GetSubItemIndex(_dragTargetAttachment); if (regin != SubItemRegin.Out && itemIndex >= 0 && targetItemIndex >= 0) { RectangleF bbox = _dragTargetNode.GetSubItemBoundingBox(graphMousePos); const float offset = 8.0f; const float innerOffset = 2.0f; float centerX = bbox.Left + bbox.Width * 0.5f; float centerY = bbox.Top + bbox.Height * 0.5f; float centerBoxX = bbox.X + bbox.Width * 0.4f; float arrowHalfWidth = bbox.Width * 0.12f; RectangleF top = new RectangleF(centerX - arrowHalfWidth, bbox.Top, arrowHalfWidth * 2.0f, offset); RectangleF bottom = new RectangleF(centerX - arrowHalfWidth, bbox.Bottom - offset, arrowHalfWidth * 2.0f, offset); PointF[] vertices = new PointF[3]; switch (regin) { case SubItemRegin.Top: if (KeyCtrlIsDown || _currentNode != _dragTargetNode || itemIndex != targetItemIndex - 1) { vertices[0] = new PointF(centerX - arrowHalfWidth, top.Bottom - innerOffset); vertices[1] = new PointF(centerX, top.Top + innerOffset); vertices[2] = new PointF(centerX + arrowHalfWidth, top.Bottom - innerOffset); if (top.Contains(graphMousePos)) { _dragAttachMode = NodeAttachMode.Top; e.Graphics.FillPolygon(Brushes.White, vertices); } else { e.Graphics.FillPolygon(Brushes.Black, vertices); } } break; case SubItemRegin.Bottom: if (KeyCtrlIsDown || _currentNode != _dragTargetNode || itemIndex != targetItemIndex + 1) { vertices[0] = new PointF(centerX - arrowHalfWidth, bottom.Top + innerOffset); vertices[1] = new PointF(centerX + arrowHalfWidth, bottom.Top + innerOffset); vertices[2] = new PointF(centerX, bottom.Bottom - innerOffset); if (bottom.Contains(graphMousePos)) { _dragAttachMode = NodeAttachMode.Bottom; e.Graphics.FillPolygon(Brushes.White, vertices); } else { e.Graphics.FillPolygon(Brushes.Black, vertices); } } break; } } } } if (_movedSubItem != null) { NodeViewData.SubItemText subitem = _movedSubItem as NodeViewData.SubItemText; if (subitem != null) { RectangleF boundingBox = new RectangleF(graphMousePos, new SizeF(50, 12)); e.Graphics.FillRectangle(subitem.BackgroundBrush, boundingBox); } } // draw FSM related DrawFSMArrow(e, graphMousePos); DrawFSMDragCurve(e, graphMousePos); //the first time of paint, to collapse plan failed branch by default Behavior b = this.RootNode as Behavior; if (b.PlanIsCollapseFailedBranch > 0) { if (b.PlanIsCollapseFailedBranch == Behavior.kPlanIsCollapseFailedBranch) { NodeViewData root = (NodeViewData)this.RootNodeView.Children[0]; CollapseFailedBrach(root); } b.PlanIsCollapseFailedBranch--; this.CenterNode(this._rootNodeView); this.LayoutChanged(); } }
/// <summary> /// Handles when a key is released. /// </summary> protected override void OnKeyUp(KeyEventArgs e) { switch (e.KeyCode) { case (Keys.Enter): if (SelectedNode != null) { if (KeyCtrlIsDown) { SelectedNode.ExpandAll(!SelectedNode.IsExpanded); } else { SelectedNode.IsExpanded = !SelectedNode.IsExpanded; } LayoutChanged(); e.Handled = true; } break; // store when the shift key is released case (Keys.ShiftKey): // update the drawn graph for dragging and duplicating if (_movedNodeGraph != null) { _movedNodeGraph.RenderDepth = 0; Invalidate(); } break; // paste from clipboard case (Keys.V): PasteSelectedNode(); _clipboardPasteMode = false; // reset all the drag data _copiedNode = null; _movedNode = null; _dragTargetNode = null; _dragNodeDefaults = null; _movedNodeGraph = null; // redraw the graph Invalidate(); break; case (Keys.Left): case (Keys.Right): case (Keys.Up): case (Keys.Down): if (e.Control) { break; } if (SelectedNode == null) { SelectedNode = this.RootNodeView; if (ClickNode != null) { ClickNode(SelectedNode); } LayoutChanged(); break; } switch (e.KeyCode) { case (Keys.Left): if (SelectedNode != null && SelectedNode.Parent != null) { SelectedNode = SelectedNode.Parent; if (ClickNode != null) { ClickNode(SelectedNode); } LayoutChanged(); } break; case (Keys.Right): if (SelectedNode != null && SelectedNode.Children.Count > 0) { SelectedNode = SelectedNode.Children[0] as NodeViewData; if (ClickNode != null) { ClickNode(SelectedNode); } LayoutChanged(); } break; case (Keys.Up): if (SelectedNode != null) { if (!KeyShiftIsDown || !SwitchSelection()) { // Node if (SelectedNode.SelectedSubItem == null) { if (SelectedNode.PreviousNode != null) { if (KeyCtrlIsDown) { // Move MoveNode(true); } else { // Select SelectedNode = SelectedNode.PreviousNode as NodeViewData; if (ClickNode != null) { ClickNode(SelectedNode); } } } } // Attachment else { NodeViewData.SubItem previousItem = SelectedNode.PreviousSelectedSubItem; if (previousItem != null) { if (KeyCtrlIsDown) { // Move NodeViewData.SubItemAttachment sourceItem = SelectedNode.SelectedSubItem as NodeViewData.SubItemAttachment; NodeViewData.SubItemAttachment targetItem = previousItem as NodeViewData.SubItemAttachment; MoveSubItem(SelectedNode, SelectedNode, sourceItem, targetItem, true, false); SelectedNode.SelectedSubItem = sourceItem; } else { // Select SelectedNode.SelectedSubItem = previousItem; if (ClickEvent != null) { ClickEvent(SelectedNode); } } } } } LayoutChanged(); } break; case (Keys.Down): if (SelectedNode != null) { if (!KeyShiftIsDown || !SwitchSelection()) { // Node if (SelectedNode.SelectedSubItem == null) { if (SelectedNode.NextNode != null) { if (KeyCtrlIsDown) { // Move MoveNode(false); } else { // Select SelectedNode = SelectedNode.NextNode as NodeViewData; if (ClickNode != null) { ClickNode(SelectedNode); } } } } // Attachment else { NodeViewData.SubItem nextItem = SelectedNode.NextSelectedSubItem; if (nextItem != null) { if (KeyCtrlIsDown) { // Move NodeViewData.SubItemAttachment sourceItem = SelectedNode.SelectedSubItem as NodeViewData.SubItemAttachment; NodeViewData.SubItemAttachment targetItem = nextItem as NodeViewData.SubItemAttachment; MoveSubItem(SelectedNode, SelectedNode, sourceItem, targetItem, false, false); SelectedNode.SelectedSubItem = sourceItem; } else { // Select SelectedNode.SelectedSubItem = nextItem; if (ClickEvent != null) { ClickEvent(SelectedNode); } } } } } LayoutChanged(); } break; } break; default: base.OnKeyUp(e); break; } }
private void KeepNodePosition(NodeViewData nvd) { // keep the position of the current node if (nvd != null && !nvd.IsFSM) { _maintainNodePosition = nvd; _graphOrigin = _maintainNodePosition.DisplayBoundingBox.Location; } }
private void MoveNode(bool insertPreviously) { if (SelectedNode != null) { Node node = SelectedNode.Node as Node; Node parent = node.Parent as Node; BaseNode.Connector connector = node.ParentConnector; if (parent != null && connector != null) { int n = connector.GetChildIndex(node); Debug.Check(n >= 0 && n < connector.ChildCount); if (insertPreviously) { Debug.Check(n > 0); parent.RemoveChild(connector, node); parent.AddChild(connector, node, n - 1); } else { Debug.Check(n < connector.ChildCount - 1); parent.RemoveChild(connector, node); parent.AddChild(connector, node, n + 1); } _selectedNodePending = node; _selectedNodePendingParent = SelectedNode.Parent; // set the prefab dirty for the current node if (!string.IsNullOrEmpty(node.PrefabName)) { node.HasOwnPrefabData = true; } UndoManager.Save(this.RootNode); } } }
/// <summary> /// Handles when a mouse button was pressed. /// </summary> protected override void OnMouseDown(MouseEventArgs e) { // the graph has not yet been dragged _startMousePosition = e.Location; _lastMousePosition = e.Location; _objectDragType = ObjectDragTypes.kNone; _dragAttachment = null; _dragTargetAttachment = null; _movedSubItem = null; _fsmDragMode = FSMDragModes.kNone; if (!_clipboardPasteMode) { _currentNode = _rootNodeView.GetInsideNode(_lastMousePosition); _dragTargetNode = null; _movedNodeGraph = null; _movedNode = null; if (_currentNode != null) { if (KeyCtrlIsDown || _currentNode.IsFSM || _currentNode.CanBeDragged() && (KeyShiftIsDown || _currentNode.Node.ParentCanAdoptChildren)) { _objectDragType = ObjectDragTypes.kNode; } } } else { if (_currentNode == null) { _currentNode = _rootNodeView.GetInsideNode(_lastMousePosition); } if (_dragTargetNode == null) { _dragTargetNode = _currentNode; } } if (e.Button == MouseButtons.Left && _currentNode != null) { Debug.Check(_nodeLayoutManager != null); NodeViewData.SubItem subItem = _currentNode.GetSubItem(_currentNode, _nodeLayoutManager.ViewToGraph(e.Location)); NodeViewData.SubItemAttachment attach = subItem as NodeViewData.SubItemAttachment; if (attach != null && attach.IsSelected) { _objectDragType = ObjectDragTypes.kAttachment; } PointF graphMousePos = _nodeLayoutManager.ViewToGraph(_lastMousePosition); NodeViewData.RangeType rangeType = _currentNode.CheckFSMArrowRange(graphMousePos, out _fsmSubItem, out _fsmItemBoundingBox); if (rangeType != NodeViewData.RangeType.kNode) { _objectDragType = ObjectDragTypes.kNone; if (Plugin.EditMode == EditModes.Design) { if (rangeType == NodeViewData.RangeType.kFSMLeftArrow) { _fsmDragMode = FSMDragModes.kLeft; } else if (rangeType == NodeViewData.RangeType.kFSMRightArrow) { _fsmDragMode = FSMDragModes.kRight; } } } } if (_currentNode == null) { _objectDragType = ObjectDragTypes.kGraph; } // focus the view if not focused if (!Focused) { // we focus twice to avoid an issue with focusing the view Parent.Focus(); //OnMouseDown will cal OnGotFocus as well //Focus(); } base.OnMouseDown(e); }
/// <summary> /// Handles when a mouse button is let go of. /// </summary> protected override void OnMouseUp(MouseEventArgs e) { _movedSubItem = null; // check if we were dragging a transition for the FSM. if (e.Button == MouseButtons.Left && _currentNode != null && ((_objectDragType == ObjectDragTypes.kNode) && _currentNode.IsFSM || _fsmSubItem != null && _fsmDragMode != FSMDragModes.kNone)) { if (Plugin.EditMode == EditModes.Design && _startMousePosition != e.Location) { // drag and move the fsm node if ((_objectDragType == ObjectDragTypes.kNode) && _currentNode.IsFSM) { UndoManager.Save(this.RootNode); LayoutChanged(); } // drag and connector the target node else { NodeViewData targetNvd = _rootNodeView.GetInsideNode(e.Location); if (targetNvd != null && targetNvd.IsFSM && (targetNvd.Parent != null) && _fsmSubItem is NodeViewData.SubItemAttachment) { NodeViewData.SubItemAttachment subItemAttachment = _fsmSubItem as NodeViewData.SubItemAttachment; if (subItemAttachment.Attachment != null && subItemAttachment.Attachment.TargetFSMNodeId != targetNvd.Node.Id) { subItemAttachment.Attachment.TargetFSMNodeId = targetNvd.Node.Id; UndoManager.Save(this.RootNode); LayoutChanged(); } } } } } // check if we were dragging an existing sub item. else if (e.Button == MouseButtons.Left && _currentNode != null && _dragTargetNode != null && _dragAttachment != null) { NodeViewData.SubItem targetSubItem = _dragTargetNode.GetSubItem(_dragTargetNode, _nodeLayoutManager.ViewToGraph(e.Location)); if (KeyCtrlIsDown || targetSubItem != _dragAttachment) { NodeViewData.SubItemAttachment targetAttachment = targetSubItem as NodeViewData.SubItemAttachment; if ((_currentNode != _dragTargetNode || targetAttachment != null) && this.MoveSubItem(_currentNode, _dragTargetNode, _dragAttachment, targetAttachment, _dragAttachMode == NodeAttachMode.Top, KeyCtrlIsDown)) { _currentNode.ClickEvent(_currentNode, _nodeLayoutManager.ViewToGraph(e.Location)); LayoutChanged(); } } _dragAttachment = null; _dragTargetAttachment = null; _dragAttachMode = NodeAttachMode.None; } // check if we were dragging or copying an existing node. else if (e.Button == MouseButtons.Left && (_movedNode != null || _copiedNode != null || _clipboardPasteMode)) { // if we have a valid target node continue if (_dragTargetNode != null) { Node sourceNode = null; if (_copiedNode != null) { bool cloneBranch = !(_copiedNode is ReferencedBehavior); sourceNode = (KeyShiftIsDown && cloneBranch) ? (Nodes.Node)_copiedNode.CloneBranch() : (Nodes.Node)_copiedNode.Clone(); } else if (_clipboardPasteMode) { bool cloneBranch = !(_clipboardNode is ReferencedBehavior); sourceNode = (/*KeyShiftIsDown && */cloneBranch) ? (Nodes.Node)_clipboardNode.CloneBranch() : (Nodes.Node)_clipboardNode.Clone(); } else if (_movedNode != null) { sourceNode = _movedNode; } Debug.Check(sourceNode != null); Node sourceParent = (Node)sourceNode.Parent; BehaviorNode sourceBehavior = sourceNode.Behavior; if (_dragTargetNode.Node == sourceNode) { _dragAttachMode = NodeAttachMode.None; } if (_dragAttachMode == NodeAttachMode.Top || _dragAttachMode == NodeAttachMode.Bottom || _dragAttachMode == NodeAttachMode.Left || _dragAttachMode == NodeAttachMode.Right || _dragAttachMode == NodeAttachMode.Center) { // set the prefab dirty for its previous parent if (sourceParent != null && !string.IsNullOrEmpty(sourceParent.PrefabName)) { sourceParent.HasOwnPrefabData = true; } if (KeyShiftIsDown) { if (sourceParent != null) { sourceParent.RemoveChild(sourceNode.ParentConnector, sourceNode); } } else { sourceNode.ExtractNode(); } } // move the dragged node to the target node, according to the attach mode switch (_dragAttachMode) { // the node will be placed above the target node case (NodeAttachMode.Top): int n = _dragTargetNode.Node.ParentConnector.GetChildIndex(_dragTargetNode.Node); ((Node)_dragTargetNode.Node.Parent).AddChild(_dragTargetNode.Node.ParentConnector, sourceNode, n); _selectedNodePending = sourceNode; _selectedNodePendingParent = _dragTargetNode.Parent; LayoutChanged(); break; // the node will be placed below the target node case (NodeAttachMode.Bottom): int m = _dragTargetNode.Node.ParentConnector.GetChildIndex(_dragTargetNode.Node); ((Node)_dragTargetNode.Node.Parent).AddChild(_dragTargetNode.Node.ParentConnector, sourceNode, m + 1); _selectedNodePending = sourceNode; _selectedNodePendingParent = _dragTargetNode.Parent; LayoutChanged(); break; // the node will be placed in front of the target node case (NodeAttachMode.Left): Node parent = (Node)_dragTargetNode.Node.Parent; Node.Connector conn = _dragTargetNode.Node.ParentConnector; int o = conn.GetChildIndex(_dragTargetNode.Node); parent.RemoveChild(conn, _dragTargetNode.Node); parent.AddChild(conn, sourceNode, o); BaseNode.Connector sourceConn = sourceNode.GetConnector(conn.Identifier); Debug.Check(sourceConn != null); sourceNode.AddChild(sourceConn, _dragTargetNode.Node); _selectedNodePending = sourceNode; _selectedNodePendingParent = _dragTargetNode.Parent; LayoutChanged(); break; // the node will simply attached to the target node case (NodeAttachMode.Right): _dragTargetNode.Node.AddChild(_dragTargetConnector, sourceNode); _selectedNodePending = sourceNode; _selectedNodePendingParent = _dragTargetNode; LayoutChanged(); break; // the node will replace the target node case (NodeAttachMode.Center): if (replaceNode(_dragTargetNode.Node, sourceNode)) { LayoutChanged(); } break; } if (_dragAttachMode != NodeAttachMode.None) { // If cloning a node, its Id should be reset. if (_copiedNode != null || _clipboardPasteMode) { // Cross two different behavior files if (_clipboardPasteMode && _clipboardRootNode != this.RootNodeView) { try { // Copy the used Pars from the current behavior to the new one. if (_clipboardNode != null && _clipboardRootNode != null && _clipboardRootNode.Node is Behavior) { foreach(ParInfo par in((Behavior)(_clipboardRootNode.Node)).LocalVars) { List<Node.ErrorCheck> result = new List<Node.ErrorCheck>(); Plugin.CheckPar(_clipboardNode, par, ref result); if (result.Count > 0) { bool bExist = false; foreach(ParInfo p in((Behavior)this.RootNode).LocalVars) { if (p.Name == par.Name) { bExist = true; break; } } if (!bExist) { ((Behavior)this.RootNode).LocalVars.Add(par); } } } } // reset its properties and methods sourceNode.ResetMembers(false, this.RootNode.AgentType, true); } catch { } } // reset its Id sourceNode.ResetId(true); } // update the node's label sourceNode.OnPropertyValueChanged(false); // set the prefab dirty for its current parent if (sourceNode.Parent != null) { Node parent = (Node)sourceNode.Parent; if (!string.IsNullOrEmpty(parent.PrefabName)) { parent.HasOwnPrefabData = true; sourceNode.SetPrefab(parent.PrefabName, true); } } UndoManager.Save(this.RootNode); } } // reset all the drag data if (!_clipboardPasteMode) { _copiedNode = null; _movedNode = null; _dragTargetNode = null; _dragNodeDefaults = null; _movedNodeGraph = null; } // redraw the graph Invalidate(); } // popup the menu for the current hit node else if (e.Button == MouseButtons.Right && !KeyAltIsDown && !KeyCtrlIsDown && !KeyShiftIsDown) { bool itemEnabled = (SelectedNode != null && SelectedNode.Node.Parent != null); itemEnabled &= (Plugin.EditMode == EditModes.Design); deleteMenuItem.ShortcutKeys = Keys.Delete; deleteTreeMenuItem.ShortcutKeys = Keys.Shift | Keys.Delete; cutMenuItem.Enabled = SelectedNodeCanBeCut(); cutTreeMenuItem.Enabled = (SelectedNode != null) && !SelectedNode.IsFSM && SelectedTreeCanBeCut(); copyMenuItem.Enabled = itemEnabled; copySubtreeMenuItem.Enabled = (SelectedNode != null) && !SelectedNode.IsFSM; pasteMenuItem.Enabled = SelectedNodeCanBePasted(); deleteMenuItem.Enabled = SelectedNodeCanBeDeleted(); deleteTreeMenuItem.Enabled = (SelectedNode != null) && !SelectedNode.IsFSM && SelectedTreeCanBeDeleted(); bool isReferencedBehavior = SelectedNode != null && SelectedNode.Node is ReferencedBehavior; bool isEvent = SelectedNode != null && SelectedNode.SelectedSubItem != null && SelectedNode.SelectedSubItem.SelectableObject is Attachments.Event; referenceMenuItem.Enabled = itemEnabled || isReferencedBehavior || isEvent; referenceMenuItem.Text = (isReferencedBehavior || isEvent) ? Resources.OpenReference : Resources.SaveReference; disableMenuItem.Enabled = false; if (itemEnabled) { if (SelectedNode.SelectedSubItem != null && SelectedNode.SelectedSubItem.SelectableObject is Attachments.Attachment) { Attachments.Attachment attach = SelectedNode.SelectedSubItem.SelectableObject as Attachments.Attachment; disableMenuItem.Enabled = attach.CanBeDisabled(); disableMenuItem.Text = attach.Enable ? Resources.DisableNode : Resources.EnableNode; } else { disableMenuItem.Enabled = SelectedNode.Node.CanBeDisabled(); disableMenuItem.Text = SelectedNode.Node.Enable ? Resources.DisableNode : Resources.EnableNode; } } expandMenuItem.Enabled = (SelectedNode != null && SelectedNode.CanBeExpanded()); collapseMenuItem.Enabled = expandMenuItem.Enabled; expandAllMenuItem.Enabled = expandMenuItem.Enabled; collapseAllMenuItem.Enabled = expandMenuItem.Enabled; bool isPrefabInstance = SelectedNode != null && !string.IsNullOrEmpty(SelectedNode.Node.PrefabName); breakPrefabMenuItem.Enabled = itemEnabled && isPrefabInstance; if (isPrefabInstance) { string fullpath = FileManagers.FileManager.GetFullPath(SelectedNode.Node.PrefabName); isPrefabInstance = File.Exists(fullpath); } savePrefabMenuItem.Enabled = itemEnabled; savePrefabMenuItem.Text = isPrefabInstance ? Resources.OpenPrefab : Resources.SavePrefab; if (SelectedNode != null) { Node prefabRoot = SelectedNode.Node.GetPrefabRoot(); string relativeFilename = FileManagers.FileManager.GetRelativePath(this.RootNode.Filename); applyMenuItem.Enabled = itemEnabled && isPrefabInstance && SelectedNode.Node.PrefabName != relativeFilename && prefabRoot.IsPrefabDataDirty(); } breakpointMenuItem.Enabled = SelectedNode != null && SelectedNode.Parent != null; if (SelectedNode != null) { enterBreakpointMenuItem.Text = SelectedNode.GetBreakpointOperation(HighlightBreakPoint.kEnter); exitBreakpointMenuItem.Text = SelectedNode.GetBreakpointOperation(HighlightBreakPoint.kExit); this.beakpointPlanning.Visible = false; if (SelectedNode.Node is Task) { this.beakpointPlanning.Visible = true; beakpointPlanning.Text = SelectedNode.GetBreakpointOperation(HighlightBreakPoint.kPlanning); } } contextMenu.Show(this, new Point(e.X, e.Y)); } Cursor = Cursors.Default; _fsmDragMode = FSMDragModes.kNone; // redraw the graph Invalidate(); base.OnMouseUp(e); }
/// <summary> /// Shows the given node in the view. /// </summary> /// <param name="node">The node which will be centred.</param> internal void ShowNode(NodeViewData node) { // Expand all of its parents. bool layoutChanged = false; NodeViewData parent = node.Parent; while (parent != null) { if (!parent.IsExpanded) { parent.IsExpanded = true; layoutChanged = true; } parent = parent.Parent; } if (layoutChanged) { LayoutChanged(); } // we use the existing maintain position stuff for that RectangleF bbox = node.BoundingBox; // If the node was not yet shown there is no bounding box, // so we simply use the min width and height for that. float width = bbox.Width <= 0.0f ? node.MinWidth : bbox.Width; float height = bbox.Height <= 0.0f ? node.MinHeight : bbox.Height; RectangleF displayBox = node.DisplayBoundingBox; // If this display bounding box is in the view, the node need not be moved. if (displayBox.X >= 0 && displayBox.X <= ClientSize.Width - width && displayBox.Y >= 0 && displayBox.Y <= ClientSize.Height - height) { return; } _maintainNodePosition = node; _graphOrigin = new PointF(ClientSize.Width * 0.5f - width * 0.5f, ClientSize.Height * 0.5f - height * 0.5f); Invalidate(); }
private void CollapseFailedBrach(NodeViewData nv) { Behavior b = nv.Node.Behavior as Behavior; if (b.PlanningProcess != null) { FrameStatePool.PlanningState nodeState = b.PlanningProcess.GetNode(nv.FullId); if (nodeState != null) { //if (!nodeState._bOk || nodeState._bPreFailed) if (nodeState._bPreFailed) { nv.IsExpanded = false; return; } } else { nv.IsExpanded = false; return; } } if (nv.Children.Count > 0) { nv.IsExpanded = true; foreach(NodeViewData c in nv.Children) { CollapseFailedBrach(c); } } }
/// <summary> /// Attaches a dragged node from the node explorer to an existing node. /// </summary> /// <param name="nvd">The node the new node will be attached to.</param> /// <param name="mode">The way the new node will be attached.</param> /// <param name="nodetag">The tag of the you want to create.</param> /// <param name="label">The label of the new node.</param> private void InsertNewNode(NodeViewData nvd, NodeAttachMode mode, NodeTag nodetag, PointF mousePos) { if (nodetag.Type != NodeTagType.Behavior && nodetag.Type != NodeTagType.Prefab && nodetag.Type != NodeTagType.Node) { throw new Exception("Only behaviours, prefabs and nodes can be attached to a behaviour tree"); } Node newnode = null; bool isPrefabInstance = false; // when we attach a behaviour we must create a special referenced behaviour node if (nodetag.Type == NodeTagType.Behavior || nodetag.Type == NodeTagType.Prefab) { if (!File.Exists(nodetag.Filename)) { if (!SaveBehavior(nodetag.Filename)) { return; } } // get the behavior we want to reference BehaviorNode behavior = _behaviorTreeList.LoadBehavior(nodetag.Filename); // a behaviour reference itself if (nvd != null && nvd.IsBehaviorReferenced(behavior)) { if (DialogResult.Cancel == MessageBox.Show(Resources.CircularReferencedInfo, Resources.Warning, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning)) { return; } } if (nodetag.Type == NodeTagType.Prefab) { behavior = (BehaviorNode)behavior.Clone(); } Behavior rootB = _rootNodeView.RootBehavior as Behavior; Behavior b = behavior as Behavior; if (rootB.AgentType == null) { rootB.AgentType = b.AgentType; } else if (!IsCompatibleAgentType(rootB, b)) { return; } // behavior if (nodetag.Type == NodeTagType.Behavior) { // create the referenced behaviour node for the behaviour ReferencedBehavior refnode = Node.CreateReferencedBehaviorNode(_rootNodeView.RootBehavior, behavior, mode == NodeAttachMode.None || ((Node)this.RootNode).IsFSM); newnode = (Node)refnode; //the comment seems too long to overlap the node //newnode.CommentText = Resources.ThisIsReferenceTree; newnode.CommentBackground = Node.CommentColor.Gray; } // prefab else { // Copy all Pars from the prefab file into the current behavior node. List<ParInfo> pars = new List<ParInfo>(); foreach(ParInfo par in b.LocalVars) { bool found = false; foreach(ParInfo rootPar in rootB.LocalVars) { if (par.Name == rootPar.Name) { if (par.Type != rootPar.Type) { string errorMsg = string.Format(Resources.ParErrorInfo, par.Name, b.Label, rootB.Label); MessageBox.Show(errorMsg, Resources.LoadError, MessageBoxButtons.OK); return; } found = true; break; } } if (!found) { pars.Add(par); } } rootB.LocalVars.AddRange(pars); // The first child should be the root node of the prefab tree. Node behaviorNode = (Node)behavior; if (behaviorNode.Children.Count > 0) { newnode = (Node)behaviorNode.Children[0]; string prefab = Path.GetFileNameWithoutExtension(behavior.Filename); newnode.CommentText = string.Format("Prefab[{0}]", prefab); isPrefabInstance = true; string prefabName = FileManagers.FileManager.GetRelativePath(behavior.Filename); newnode.SetPrefab(prefabName); } } } else { // simply create the node which is supposed to be created. newnode = Node.Create(nodetag.NodeType); if (newnode != null) newnode.PostCreatedByEditor(); } if (newnode == null) { return; } // update label newnode.OnPropertyValueChanged(false); Node node = (nvd != null) ? nvd.Node : null; if (node == null) { mode = NodeAttachMode.None; } Attachments.Attachment startCondition = null; // attach the new node with the correct mode switch (mode) { // the new node is inserted in front of the target node case NodeAttachMode.Left: if (node != null) { Node parent = (Node)node.Parent; int k = node.ParentConnector.GetChildIndex(node); Node.Connector conn = node.ParentConnector; Debug.Check(conn != null); parent.RemoveChild(conn, node); parent.AddChild(conn, newnode, k); Node.Connector newconn = newnode.GetConnector(conn.Identifier); Debug.Check(newconn != null); newnode.AddChild(newconn, node); // automatically select the new node _selectedNodePending = newnode; _selectedNodePendingParent = nvd.Parent; } break; // the new node is simply added to the target node's children case NodeAttachMode.Right: if (newnode != null && newnode.IsFSM) { startCondition = this.addFSMNode(newnode, mousePos); newnode.ScreenLocation = new PointF(_rootNodeView.BoundingBox.Left + _rootNodeView.BoundingBox.Width * 1.5f, _rootNodeView.BoundingBox.Top); } else if (node != null) { node.AddChild(_dragTargetConnector, newnode); _dragTargetConnector.IsExpanded = true; // automatically select the new node _selectedNodePending = newnode; _selectedNodePendingParent = nvd; } break; // the new node is placed above the target node case NodeAttachMode.Top: if (node != null) { int n = _dragTargetNode.Node.ParentConnector.GetChildIndex(node); ((Node)node.Parent).AddChild(_dragTargetNode.Node.ParentConnector, newnode, n); // automatically select the new node _selectedNodePending = newnode; _selectedNodePendingParent = nvd.Parent; } break; // the new node is placed below the target node case NodeAttachMode.Bottom: if (node != null) { int m = _dragTargetNode.Node.ParentConnector.GetChildIndex(node); ((Node)node.Parent).AddChild(_dragTargetNode.Node.ParentConnector, newnode, m + 1); // automatically select the new node _selectedNodePending = newnode; _selectedNodePendingParent = nvd.Parent; } break; // the node will replace the target node case NodeAttachMode.Center: if (node != null && replaceNode(node, newnode)) { // automatically select the new node _selectedNodePending = newnode; _selectedNodePendingParent = nvd.Parent; this.Redraw(); } break; case NodeAttachMode.None: if (newnode != null && newnode.IsFSM) { startCondition = this.addFSMNode(newnode, mousePos); // automatically select the new node _selectedNodePending = newnode; _selectedNodePendingParent = this.RootNodeView; } break; } // After being created, its Id should be reset. if (newnode != null) { newnode.ResetId(true); // set the prefab dirty for the current parent if (newnode.Parent != null) { Node parent = (Node)newnode.Parent; if (!string.IsNullOrEmpty(parent.PrefabName)) { parent.HasOwnPrefabData = true; if (!isPrefabInstance) { newnode.SetPrefab(parent.PrefabName); newnode.HasOwnPrefabData = true; } } } if (startCondition != null) { startCondition.TargetFSMNodeId = newnode.Id; } UndoManager.Save(this.RootNode); } // the layout needs to be recalculated LayoutChanged(); }
public void DeleteSelectedNode(bool deleteSubTree = false) { if (SelectedNode == null || Plugin.EditMode != EditModes.Design) { return; } deleteSubTree &= SelectedNode.CanBeDeleted(true); // when we have a node selected which is not the root node, continue if (SelectedNode != null && (SelectedNode.SelectedSubItem != null || SelectedNode.Node.Parent != null)) { BehaviorNode sourceBehavior = SelectedNode.Node.Behavior; // check whether we have to delete an event or a node if (SelectedNode.SelectedSubItem == null) { if (deleteSubTree || SelectedNode.CanBeDeleted()) { // store the selected node Node node = SelectedNode.Node; if (node.Parent != null) { Node parent = (Node)node.Parent; if (!string.IsNullOrEmpty(parent.PrefabName)) { parent.HasOwnPrefabData = true; } } // select the next node automatically if (node.NextNode != null) { _selectedNodePending = node.NextNode as Node; _selectedNodePendingParent = SelectedNode.Parent; } else if (node.PreviousNode != null) { _selectedNodePending = node.PreviousNode as Node; _selectedNodePendingParent = SelectedNode.Parent; } else if (node.Parent != null) { _selectedNodePending = node.Parent as Node; _selectedNodePendingParent = SelectedNode.Parent != null ? SelectedNode.Parent.Parent : null; } else { _selectedNodePending = null; _selectedNodePendingParent = null; } bool isDeleted = false; if (deleteSubTree) { if (node.Parent != null) { ((Node)node.Parent).RemoveChild(node.ParentConnector, node); // keep the root node in the view KeepNodePosition(RootNodeView); // remove all breakpoints removeBreakpoints(SelectedNode, true); isDeleted = true; } } else if (node.IsFSM) { if (node.Parent != null && node.Parent.RemoveFSMNode(node)) { // remove its breakpoints removeBreakpoints(SelectedNode, false); isDeleted = true; } } else if (node.ExtractNode()) { // remove its breakpoints removeBreakpoints(SelectedNode, false); isDeleted = true; } else { _selectedNodePending = null; _selectedNodePendingParent = null; } if (isDeleted) { Node root = (Node)this.RootNode; if (root.FSMNodes.Count == 0) { // remove the Start condition for the FSM root node for (int i = 0; i < root.Attachments.Count; ++i) { if (root.Attachments[i].IsStartCondition) { root.Attachments.RemoveAt(i); break; } } } UndoManager.Save(this.RootNode); } SelectedNode = null; _currentNode = null; } } else { NodeViewData.SubItem nextItem = SelectedNode.NextSelectedSubItem; if (nextItem == null) { nextItem = SelectedNode.PreviousSelectedSubItem; } // just let the node delete the selected subitem if (SelectedNode.RemoveSelectedSubItem()) { Node node = SelectedNode.Node; if (!string.IsNullOrEmpty(node.PrefabName)) { node.HasOwnPrefabData = true; } UndoManager.Save(this.RootNode); // select the next subitem automatically if (nextItem != null) { SelectedNode.SelectedSubItem = nextItem; // update all labels of its subitems foreach(NodeViewData.SubItem subItem in SelectedNode.SubItems) { NodeViewData.SubItemAttachment attach = subItem as NodeViewData.SubItemAttachment; if (attach != null && attach.Attachment != null) { attach.Attachment.OnPropertyValueChanged(false); } } if (ClickEvent != null) { ClickEvent(SelectedNode); } } else { if (ClickNode != null) { ClickNode(SelectedNode); } } } } // the layout needs to be recalculated LayoutChanged(); } }
private void control_ClickNode(NodeViewData nvd) { OnNodeClicked(nvd); }
public void SetHighlights(List<string> highlightedTransitionIds, List<string> highlightedNodeIds, List<string> updatedNodeIds, HighlightBreakPoint highlightBreakPoint, Dictionary<string, FrameStatePool.NodeProfileInfos.ProfileInfo> profileInfos) { bool shouldRefresh = (_highlightBreakPoint != highlightBreakPoint); if (shouldRefresh && highlightBreakPoint != null) { SelectedNode = RootNodeView.FindNodeViewData(highlightBreakPoint.NodeId); if (ClickNode != null) { ClickNode(SelectedNode); } } if (!shouldRefresh) { shouldRefresh = !compareTwoLists(_highlightedTransitionIds, highlightedTransitionIds); } if (!shouldRefresh) { shouldRefresh = !compareTwoLists(_updatedNodeIds, updatedNodeIds); } if (!shouldRefresh) { shouldRefresh = !compareTwoLists(_highlightedNodeIds, highlightedNodeIds); } if (!shouldRefresh) { shouldRefresh = !compareTwoDicts(_profileInfos, profileInfos); } _highlightedTransitionIds = highlightedTransitionIds; _highlightBreakPoint = highlightBreakPoint; _highlightedNodeIds = highlightedNodeIds; _updatedNodeIds = updatedNodeIds; _profileInfos = profileInfos; if (shouldRefresh) { List<string> allExpandedIds = new List<string>(); if (_highlightedNodeIds != null) { allExpandedIds.AddRange(_highlightedNodeIds); } if (_updatedNodeIds != null) { foreach(string id in _updatedNodeIds) { if (!allExpandedIds.Contains(id)) { allExpandedIds.Add(id); } } } bool layoutChanged = false; foreach(string id in allExpandedIds) { NodeViewData nvd = RootNodeView.FindNodeViewData(id); if (nvd != null && !nvd.CheckAllParentsExpanded()) { nvd.SetAllParentsExpanded(); this._pendingCenterBehavior = true; layoutChanged = true; } } if (layoutChanged) { LayoutChanged(); } Refresh(); } }
public void CopySelectedNode(bool copySubTree = false) { if (SelectedNode == null || Plugin.EditMode != EditModes.Design) { return; } _clipboardRootNode = this.RootNodeView; _clipboardNode = null; _clipboardSubItem = null; if (SelectedNode.SelectedSubItem == null) { if (SelectedNode.Node is ReferencedBehavior) { _clipboardNode = (Node)SelectedNode.Node; } else { _clipboardNode = copySubTree ? (Node)SelectedNode.Node.CloneBranch() : (Node)SelectedNode.Node.Clone(); } } else { _clipboardSubItem = SelectedNode.SelectedSubItem; } }
/// <summary> /// Handles when the mouse is moved. /// </summary> protected override void OnMouseMove(MouseEventArgs e) { if (_lostFocus) { _lostFocus = false; // update the last ouse position _lastMousePosition = e.Location; base.OnMouseMove(e); return; } // returns the mouse under the mouse cursor NodeViewData nodeFound = _rootNodeView.GetInsideNode(e.Location); NodeViewData.SubItem subItemFound = null; if (nodeFound != null) { subItemFound = nodeFound.GetSubItem(nodeFound, _nodeLayoutManager.ViewToGraph(e.Location)); } else { this.toolTip.Hide(this); } // clear previously stored node which can cause problems when dragging to another view //_dragTargetNode = null; if (nodeFound != null || _currentExpandNode != null || subItemFound != null) { if (_dragAttachment == null) { _currentNode = nodeFound; } if (Settings.Default.ShowNodeToolTips) { if (nodeFound != null) { _nodeToolTip = (subItemFound != null) ? subItemFound.ToolTip : nodeFound.ToolTip; } if (!string.IsNullOrEmpty(_nodeToolTip)) { this.toolTipTimer.Start(); } } Invalidate(); } // check if we are currently dragging the graph if ((e.Button == MouseButtons.Middle || (e.Button == MouseButtons.Left && _objectDragType == ObjectDragTypes.kGraph)) && _lastMousePosition != e.Location && !this.contextMenu.Visible) { Cursor = Cursors.SizeAll; // move the graph according to the last mouse position _nodeLayoutManager.Offset = new PointF(_nodeLayoutManager.Offset.X - (_lastMousePosition.X - e.X), _nodeLayoutManager.Offset.Y - (_lastMousePosition.Y - e.Y)); Invalidate(); } // check if we start duplicating an existing node step 1 else if (e.Button == MouseButtons.Left && KeyCtrlIsDown && _lastMousePosition != e.Location && _dragNodeDefaults == null && _copiedNode == null && _currentNode != null && !(_currentNode.Node is BehaviorNode)) { if (_objectDragType == ObjectDragTypes.kNode) { // node _movedNode = null; _copiedNode = _currentNode.Node; // create the layout manager used to draw the graph _movedNodeGraph = new NodeLayoutManager(_copiedNode.CloneBranch().CreateNodeViewData(null, _rootNodeView.RootBehavior), _nodeLayoutManager.EdgePen, _nodeLayoutManager.EdgePenSelected, _nodeLayoutManager.EdgePenHighlighted, _nodeLayoutManager.EdgePenUpdate, _nodeLayoutManager.EdgePenReadOnly, true); _movedNodeGraph.Scale = 0.3f; _movedNodeGraph.RenderDepth = KeyShiftIsDown ? int.MaxValue : 0; // use the existing node as the node defaults _dragNodeDefaults = _copiedNode; } else if (_objectDragType == ObjectDragTypes.kAttachment) { // attachment if (_dragAttachment == null) { NodeViewData.SubItem subItem = _currentNode.GetSubItem(_currentNode, _nodeLayoutManager.ViewToGraph(e.Location)); _dragAttachment = subItem as NodeViewData.SubItemAttachment; } } Invalidate(); } // check if we are duplicating an existing node step 2 else if (e.Button == MouseButtons.Left && KeyCtrlIsDown && (_copiedNode != null || _dragAttachment != null)) { if (_objectDragType == ObjectDragTypes.kNode) { // node _movedNodeGraph.RenderDepth = KeyShiftIsDown ? int.MaxValue : 0; _dragTargetNode = _currentNode; Cursor = _currentNode == null ? Cursors.No : Cursors.Default; //Point movedGraphGraphPos= new Point(e.Location.X + _movedNodeGraph.Offset.X, e.Location.Y + _movedNodeGraph.Offset.Y /-2); //_movedNodeGraph.Location= movedGraphGraphPos; } else if (_objectDragType == ObjectDragTypes.kAttachment) { // attachment _dragTargetNode = nodeFound; if (_dragTargetNode != null) { NodeViewData.SubItem subItem = _dragTargetNode.GetSubItem(_dragTargetNode, _nodeLayoutManager.ViewToGraph(e.Location)); _dragTargetAttachment = subItem as NodeViewData.SubItemAttachment; } } Invalidate(); } // check if we start dragging an existing node step 1 else if (e.Button == MouseButtons.Left && _lastMousePosition != e.Location && !KeyCtrlIsDown && _movedNode == null && _currentNode != null) { if (_objectDragType == ObjectDragTypes.kNode) { // node if (_currentNode.CanBeDragged()) { if (_currentNode.IsFSM) { PointF currentGraphMousePos = _nodeLayoutManager.ViewToGraph(e.Location); PointF lastGraphMousePos = _nodeLayoutManager.ViewToGraph(_lastMousePosition); _currentNode.ScreenLocation = new PointF(_currentNode.ScreenLocation.X + currentGraphMousePos.X - lastGraphMousePos.X, _currentNode.ScreenLocation.Y + currentGraphMousePos.Y - lastGraphMousePos.Y); LayoutChanged(); } else if ((KeyShiftIsDown || _currentNode.Node.ParentCanAdoptChildren)) { _movedNode = _currentNode.Node; // create the layout manager used to draw the graph if (_movedNodeGraph == null) { _movedNodeGraph = new NodeLayoutManager(_movedNode.CloneBranch().CreateNodeViewData(null, _rootNodeView.RootBehavior), _nodeLayoutManager.EdgePen, _nodeLayoutManager.EdgePenSelected, _nodeLayoutManager.EdgePenHighlighted, _nodeLayoutManager.EdgePenUpdate, _nodeLayoutManager.EdgePenReadOnly, true); } _movedNodeGraph.Scale = 0.3f; //_movedNodeGraph.RenderDepth = KeyShiftIsDown ? int.MaxValue : 0; _movedNodeGraph.RenderDepth = int.MaxValue; } } } else if (_objectDragType == ObjectDragTypes.kAttachment) { // attachment if (_fsmDragMode == FSMDragModes.kNone && Plugin.EditMode == EditModes.Design) { _movedNodeGraph = null; _dragTargetNode = nodeFound; if (_dragAttachment == null) { NodeViewData.SubItem subItem = _currentNode.GetSubItem(_currentNode, _nodeLayoutManager.ViewToGraph(e.Location)); _dragAttachment = subItem as NodeViewData.SubItemAttachment; if (_dragAttachment != null) { _movedSubItem = _dragAttachment.Clone(_currentNode.Node); } } else if (_dragTargetNode != null) { NodeViewData.SubItem subItem = _dragTargetNode.GetSubItem(_dragTargetNode, _nodeLayoutManager.ViewToGraph(e.Location)); _dragTargetAttachment = subItem as NodeViewData.SubItemAttachment; } } } Invalidate(); } // check if we start dragging an existing node step 2 else if (e.Button == MouseButtons.Left && _movedNode != null && !_clipboardPasteMode) { // create the layout manager used to draw the graph if (_movedNodeGraph == null) { _movedNodeGraph = new NodeLayoutManager(_movedNode.CloneBranch().CreateNodeViewData(null, _rootNodeView.RootBehavior), _nodeLayoutManager.EdgePen, _nodeLayoutManager.EdgePenSelected, _nodeLayoutManager.EdgePenHighlighted, _nodeLayoutManager.EdgePenUpdate, _nodeLayoutManager.EdgePenReadOnly, true); } _movedNodeGraph.Scale = 0.3f; _movedNodeGraph.RenderDepth = KeyShiftIsDown ? int.MaxValue : 0; _dragNodeDefaults = _movedNode; _dragTargetNode = _currentNode; Cursor = _currentNode == null ? Cursors.No : Cursors.Default; Invalidate(); } else if (_clipboardPasteMode) { if (_movedNodeGraph != null) { //_movedNodeGraph.RenderDepth = KeyShiftIsDown ? int.MaxValue : 0; _movedNodeGraph.RenderDepth = int.MaxValue; } _dragTargetNode = _currentNode; Cursor = _currentNode == null ? Cursors.No : Cursors.Default; Invalidate(); } else if (_currentNode != null && _dragAttachment == null) { // Highlight the expand/collapse flag PointF graphMousePos = _nodeLayoutManager.ViewToGraph(e.Location); bool isInExandRange = _currentNode.IsInExpandRange(graphMousePos); bool isInExandConnectorRange = _currentNode.IsInExpandConnectorRange(graphMousePos); if (isInExandRange || isInExandConnectorRange) { _currentExpandNode = _currentNode; _nodeToolTip = isInExandRange ? Resources.ExpandAllInfo : Resources.ExpandConnectorInfo; Invalidate(); } else if (_currentExpandNode != null) { _currentExpandNode = null; Invalidate(); } } // update the last ouse position _lastMousePosition = e.Location; base.OnMouseMove(e); }
private void control_ClickNode(NodeViewData nvd) { _clickedNVD = nvd; Thread backgroundThread = new Thread(AsyncUpdateProperties); backgroundThread.SetApartmentState(ApartmentState.STA); backgroundThread.Start(); while (backgroundThread.IsAlive) { Application.DoEvents(); } _clickedNVD = null; }
private void removeBreakpoints(NodeViewData nvd, bool removeChildren) { if (nvd == null || RootNode == null || string.IsNullOrEmpty(RootNode.Filename)) { return; } string behaviorFilename = RootNode.MakeRelative(RootNode.Filename); if (string.IsNullOrEmpty(behaviorFilename)) { return; } string[] actionNames = { HighlightBreakPoint.kEnter, HighlightBreakPoint.kExit }; string fullId = nvd.FullId; foreach(string actionName in actionNames) { DebugDataPool.BreakPoint breakPoint = DebugDataPool.FindBreakPoint(behaviorFilename, fullId, actionName); if (breakPoint != null) { DebugDataPool.Action action = breakPoint.FindAction(actionName); Debug.Check(action != null); DebugDataPool.RemoveBreakPoint(behaviorFilename, fullId, action); } } if (removeChildren) { foreach(BaseNode child in nvd.Children) { NodeViewData childNvd = child as NodeViewData; if (childNvd != null) { removeBreakpoints(childNvd, removeChildren); } } } }