/// <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 edgePenSubReferenced, bool skipLabels)
 {
     _rootNodeLayout  = rootNode;
     _edgePen         = edgePen;
     _edgePenReadOnly = edgePenSubReferenced;
     _skipLabels      = skipLabels;
 }
        /// <summary>
        /// Draws the graph.
        /// </summary>
        /// <param name="graphics">The graphics object we want to draw to.</param>
        /// <param name="currentNode">The node the mouse is currently hovering over.</param>
        /// <param name="selectedNode">The node which is currently selected.</param>
        /// <param name="graphMousePos">The mouse's position in the graph.</param>
        internal void DrawGraph(Graphics graphics, NodeViewData currentNode, NodeViewData selectedNode, PointF graphMousePos)
        {
            // setup drawing
            graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
            graphics.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            graphics.Transform         = new System.Drawing.Drawing2D.Matrix(_scale, 0.0f, 0.0f, _scale, _offset.X, _offset.Y);

            // update display bounding boxes
            _rootNodeLayout.UpdateDisplay(_offset.X, _offset.Y, _scale);

            // draw comment backgrounds
            if (!_skipLabels)
            {
                _rootNodeLayout.DrawCommentBackground(graphics, _renderDepth, _padding);
            }

            // draw the edges
            if (_edgePen != null && _renderDepth > 0)
            {
                _rootNodeLayout.DrawEdges(graphics, _edgePen, _edgePenReadOnly, _renderDepth - 1);
            }

            // draw the nodes
            _rootNodeLayout.Draw(graphics, currentNode, selectedNode, _skipLabels, graphMousePos, _renderDepth);

            // draw comment text
            if (!_skipLabels)
            {
                _rootNodeLayout.DrawCommentText(graphics, _renderDepth);
            }

            // draw last mouse pos
            //e.Graphics.DrawRectangle(Pens.Red, graphMousePos.X -1.0f, graphMousePos.Y -1.0f, 2.0f, 2.0f);
        }
예제 #3
0
 /// <summary>
 /// Draws the node's shape as the background.
 /// </summary>
 /// <param name="graphics">The graphics object used for drawing.</param>
 /// <param name="nvd">The node view data of the node the subitem belongs to.</param>
 /// <param name="brush">The brush to draw the node's shape.</param>
 protected void DrawBackground(Graphics graphics, NodeViewData nvd, Brush brush)
 {
     if (brush != null)
     {
         nvd.DrawShapeBackground(graphics, nvd.BoundingBox, brush);
     }
 }
            public override void Draw(Graphics graphics, NodeViewData nvd, RectangleF boundingBox)
            {
                // render background
                DrawBackground(graphics, nvd, _selected ? _backgroundSelected : _backgroundNormal);

                // render the label
                PointF center = new PointF(boundingBox.Left + boundingBox.Width * 0.5f, boundingBox.Top + boundingBox.Height * 0.5f);

                SizeF labelSize = MeasureDisplayStringWidth(graphics, Label, _labelFont);

                // draw text
                switch (_alignment)
                {
                case (Alignment.Left):
                    graphics.DrawString(Label, _labelFont, _labelBrush, boundingBox.Left + 6.0f, center.Y - labelSize.Height * 0.5f);
                    break;

                case (Alignment.Center):
                    graphics.DrawString(Label, _labelFont, _labelBrush, center.X - labelSize.Width * 0.5f, center.Y - labelSize.Height * 0.5f);
                    break;

                case (Alignment.Right):
                    graphics.DrawString(Label, _labelFont, _labelBrush, boundingBox.Right - labelSize.Width - 6.0f, center.Y - labelSize.Height * 0.5f);
                    break;
                }

                //graphics.DrawRectangle(Pens.Red, boundingBox.X, boundingBox.Y, boundingBox.Width, boundingBox.Height);
            }
 /// <summary>
 /// Draws the node's shape as the background.
 /// </summary>
 /// <param name="dc">The graphics object used for drawing.</param>
 /// <param name="nvd">The node view data of the node the subitem belongs to.</param>
 /// <param name="brush">The brush to draw the node's shape.</param>
 protected void DrawBackground(DrawingContext dc, NodeViewData nvd, Brush brush)
 {
     if (brush != null)
     {
         nvd.DrawShape(dc, nvd.BoundingBox, brush, null);
     }
 }
            public override void Update(NodeViewData node, DrawingContext dc)
            {
                // calculate the extent used by the label
                FormattedText formattedText = _labelFont.FormatText(Label, Brushes.White);

                _width = formattedText.Width;
            }
            public override void Draw(DrawingContext dc, NodeViewData nvd, Rect boundingBox)
            {
                // render background
                DrawBackground(dc, nvd, _selected ? _backgroundSelected : _backgroundNormal);

                // render the label
                Point center = new Point(boundingBox.Left + boundingBox.Width * 0.5f, boundingBox.Top + boundingBox.Height * 0.5f);

                FormattedText formattedText = _labelFont.FormatText(Label, _labelBrush);

                // draw text
                switch (_alignment)
                {
                case (Alignment.Left):
                    dc.DrawText(formattedText, new Point(boundingBox.Left + 6.0, center.Y - formattedText.Height * 0.5));
                    break;

                case (Alignment.Center):
                    dc.DrawText(formattedText, new Point(center.X - formattedText.Width * 0.5, center.Y - formattedText.Height * 0.5));
                    break;

                case (Alignment.Right):
                    dc.DrawText(formattedText, new Point(boundingBox.Right - formattedText.Width - 6.0, center.Y - formattedText.Height * 0.5));
                    break;
                }

                //graphics.DrawRectangle(Pens.Red, boundingBox.X, boundingBox.Y, boundingBox.Width, boundingBox.Height);
            }
        /// <summary>
        /// Draws the graph.
        /// </summary>
        /// <param name="dc">The graphics object we want to draw to.</param>
        /// <param name="currentNode">The node the mouse is currently hovering over.</param>
        /// <param name="selectedNode">The node which is currently selected.</param>
        /// <param name="graphMousePos">The mouse's position in the graph.</param>
        internal void DrawGraph(DrawingContext dc, NodeViewData currentNode, NodeViewData selectedNode, Point graphMousePos)
        {
            // setup drawing
            dc.PushTransform(new MatrixTransform(_scale, 0.0, 0.0, _scale, _offset.X, _offset.Y));

            // update display bounding boxes
            _rootNodeLayout.UpdateDisplay(_offset.X, _offset.Y, _scale);

            // draw comment backgrounds
            if (!_skipLabels)
            {
                _rootNodeLayout.DrawCommentBackground(dc, _renderDepth, _padding);
            }

            // draw the edges
            if (_edgePen != null && _renderDepth > 0)
            {
                _rootNodeLayout.DrawEdges(dc, _edgePen, _edgePenReadOnly, _renderDepth - 1);
            }

            // draw the nodes
            _rootNodeLayout.Draw(dc, currentNode, selectedNode, _skipLabels, graphMousePos, _renderDepth);

            // draw comment text
            if (!_skipLabels)
            {
                _rootNodeLayout.DrawCommentText(dc, _renderDepth);
            }

            // draw last mouse pos
            //e.Graphics.DrawRectangle(Pens.Red, graphMousePos.X -1.0f, graphMousePos.Y -1.0f, 2.0f, 2.0f);

            dc.Pop();
        }
예제 #9
0
        /// <summary>
        /// This function adapts the children of the view that they represent the children of the node this view is for.
        /// Children are added and removed.
        /// </summary>
        /// <param name="processedBehaviors">A list of previously processed behaviours to deal with circular references.</param>
        public virtual void SynchronizeWithNode(IList <BehaviorNode> processedBehaviors)
        {
            // allow the node to add some final children or remove some
            _node.PreLayoutUpdate(this);

            // if the counts do not fit we must rebuild
            bool rebuild = _node.Children.Count != _children.Count;

            // check if all children are associated to the correct children of the node
            if (!rebuild)
            {
                for (int i = 0; i < _node.Children.Count; ++i)
                {
                    // this view is associated to another node than the child of the node
                    if (_children[i].Node != _node.Children[i])
                    {
                        rebuild = true;
                        break;
                    }
                }
            }

            // check if we must rebuild the child list
            if (rebuild)
            {
                // store the old children
                List <NodeViewData> oldChildren = _children;

                // create a new list
                _children = new List <NodeViewData>();

                // update the children
                foreach (Node child in _node.Children)
                {
                    // check if our old child list already contains a view for this node. If so copy it.
                    NodeViewData nvd = child.FindNodeViewData(oldChildren);
                    if (nvd != null)
                    {
                        Debug.Check(_rootBehavior == nvd.RootBehavior);

                        _children.Add(nvd);
                    }
                    // otherwise create a new view
                    else
                    {
                        _children.Add(child.CreateNodeViewData(this, _rootBehavior));
                    }
                }
            }

            // synchronise the children as well
            foreach (NodeViewData child in _children)
            {
                Debug.Check(child.RootBehavior == _rootBehavior);

                child.SynchronizeWithNode(processedBehaviors);
            }
        }
예제 #10
0
        /// <summary>
        /// Is called when the node was double-clicked. Used for referenced behaviours.
        /// </summary>
        /// <param name="nvd">The view data of the node in the current view.</param>
        /// <param name="layoutChanged">Does the layout need to be recalculated?</param>
        /// <returns>Returns if the node handled the double click or not.</returns>
        public override bool OnDoubleClick(NodeViewData nvd, out bool layoutChanged)
        {
            NodeViewDataReferencedBehavior nvdrb = (NodeViewDataReferencedBehavior)nvd;

            nvdrb.IsExpanded = !nvdrb.IsExpanded;

            layoutChanged = true;
            return(true);
        }
            public override void Draw(DrawingContext dc, NodeViewData nvd, Rect boundingBox)
            {
                Event evnt = (Event)_attachment;

                // use a different brush depending on if the event is reacted to or blocked.
                _labelBrush = evnt.BlockEvent ? Brushes.Orange : Brushes.White;

                base.Draw(dc, nvd, boundingBox);
            }
예제 #12
0
 public NodeViewDataStyled(NodeViewData parent, BehaviorNode rootBehavior, Node node, Pen borderPen, Brush backgroundBrush, Brush draggedBackgroundBrush, string label, string description) :
     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),
          label, __defaultLabelFont, 120, 35, description)
 {
 }
예제 #13
0
 /// <summary>
 /// Handles when an event of a node is selected.
 /// </summary>
 /// <param name="node">The node whose event is selected.</param>
 private void control_ClickEvent(NodeViewData node)
 {
     // if there is no subitem selected, use the properties of the node
     if (node.SelectedSubItem == null || node.SelectedSubItem.SelectableObject == null)
     {
         PropertiesDock.InspectObject(node.Node);
     }
     // publish the properties of the subitem's selection object
     else
     {
         PropertiesDock.InspectObject(node.SelectedSubItem.SelectableObject);
     }
 }
예제 #14
0
        /// <summary>
        /// Draws the node to the graph.
        /// </summary>
        /// <param name="graphics">The graphics object we render to.</param>
        /// <param name="currentNode">The current node under the mouse cursor.</param>
        /// <param name="selectedNode">The currently selected node.</param>
        /// <param name="isDragged">Determines if the node is currently being dragged.</param>
        /// <param name="graphMousePos">The mouse position in the untransformed graph.</param>
        /// <param name="renderDepth">The depth which is still rendered.</param>
        public virtual void Draw(Graphics graphics, NodeViewData currentNode, NodeViewData selectedNode, bool isDragged, PointF graphMousePos, int renderDepth)
        {
            _node.Draw(graphics, this, currentNode == null ? false : this.Node == currentNode.Node, selectedNode == null ? false : this.Node == selectedNode.Node, isDragged, graphMousePos);

            // draw children
            if (renderDepth > 0)
            {
                foreach (NodeViewData child in _children)
                {
                    child.Draw(graphics, currentNode, selectedNode, isDragged, graphMousePos, renderDepth - 1);
                }
            }
        }
예제 #15
0
        /// <summary>
        /// Creates a new view for a given node.
        /// </summary>
        /// <param name="parent">The parent of the new NodeViewData.</param>
        /// <param name="rootBehavior">The behaviour which is the root of the graph the given node is shown in.</param>
        /// <param name="node">The node the view is created for.</param>
        public NodeViewData(NodeViewData parent, BehaviorNode rootBehavior, Node node)
        {
            Debug.Check(rootBehavior != null);

            _parent       = parent;
            _rootBehavior = rootBehavior;
            _node         = node;

            if (parent != null)
            {
                WasModified = parent.WasModified;
            }

            _node.WasModified += new Node.WasModifiedEventDelegate(node_WasModified);
        }
예제 #16
0
        /// <summary>
        /// Returns the node a given location is in.
        /// </summary>
        /// <param name="location">The location you want to check.</param>
        /// <returns>Returns null if the position is not inside any node.</returns>
        public NodeViewData IsInside(PointF location)
        {
            if (_displayBoundingBox.Contains(location))
            {
                return(this);
            }

            foreach (NodeViewData node in _children)
            {
                NodeViewData insidenode = node.IsInside(location);
                if (insidenode != null)
                {
                    return(insidenode);
                }
            }

            return(null);
        }
예제 #17
0
        /// <summary>
        /// Returns the first NodeViewData which is associated with the given node. Notice that there might be other NodeViewDatas which are ignored.
        /// </summary>
        /// <param name="node">The node you want to get the NodeViewData for.</param>
        /// <returns>Returns the first NodeViewData found.</returns>
        public virtual NodeViewData FindNodeViewData(Node node)
        {
            // check if this is a fitting view
            if (_node == node)
            {
                return(this);
            }

            // search the children
            foreach (NodeViewData child in _children)
            {
                NodeViewData result = child.FindNodeViewData(node);
                if (result != null)
                {
                    return(result);
                }
            }

            return(null);
        }
        private void listView_DoubleClick(object sender, EventArgs e)
        {
            // check if there is an item selected
            if (listView.SelectedItems.Count < 1)
            {
                return;
            }

            // check if this item has a node connected to it. The no-errors message doesn't
            Nodes.BehaviorNode node = (Nodes.BehaviorNode)listView.SelectedItems[0].Tag;
            if (node == null)
            {
                return;
            }

            // show the behaviour and select the node.
            NodeViewData nvd = _behaviorTreeList.ShowNode((Nodes.Node)node);

            _behaviorTreeView.SelectedNode = nvd;
        }
예제 #19
0
 /// <summary>
 /// Handles when a node is clicked.
 /// </summary>
 /// <param name="node">The node that was clicked.</param>
 private void control_ClickNode(NodeViewData node)
 {
     PropertiesDock.InspectObject(node == null ? null : node.Node);
 }
예제 #20
0
		/// <summary>
		/// Handles when a mouse button is let go of.
		/// </summary>
		protected override void OnMouseUp(MouseEventArgs e)
		{
			// check if we were dragging or copying an existing node
			if(e.Button ==MouseButtons.Right && _movedNode !=null || e.Button ==MouseButtons.Left && _copiedNode !=null || e.Button ==MouseButtons.Left && _clipboardPasteMode)
			{
				// if we have a valid target node continue
				if(_dragTargetNode !=null)
				{
					Node sourcenode= null;

					if(_movedNode !=null)
						sourcenode= _movedNode;
					else if(_copiedNode !=null)
						sourcenode= _keyShiftIsDown ? (Nodes.Node)_copiedNode.CloneBranch() : (Nodes.Node)_copiedNode.Clone();
					else if(_clipboardPasteMode)
						sourcenode= _keyShiftIsDown ? (Nodes.Node)_clipboardNode.CloneBranch() : (Nodes.Node)_clipboardNode.Clone();

					// move the dragged node to the target node, according to the attach mode
					switch(_dragAttachMode)
					{
						// the node will be placed above the traget node
						case(NodeAttachMode.Top):
							if(_movedNode !=null)
							{
								if(_keyShiftIsDown)
								{
									_movedNode.Parent.RemoveChild(_movedNode.ParentConnector, _movedNode);
								}
								else
								{
									if(!_movedNode.ExtractNode())
										throw new Exception(Resources.ExceptionNodeCouldNotBeExtracted);
								}
							}

							int n= _dragTargetNode.Node.ParentConnector.GetChildIndex(_dragTargetNode.Node);
							_dragTargetNode.Node.Parent.AddChild(_dragTargetNode.Node.ParentConnector, sourcenode, n);

							LayoutChanged();
						break;

						// the node will be placed below the target node
						case(NodeAttachMode.Bottom):
							if(_movedNode !=null)
							{
								if(_keyShiftIsDown)
								{
									_movedNode.Parent.RemoveChild(_movedNode.ParentConnector, _movedNode);
								}
								else
								{
									if(!_movedNode.ExtractNode())
										throw new Exception(Resources.ExceptionNodeCouldNotBeExtracted);
								}
							}

							int m= _dragTargetNode.Node.ParentConnector.GetChildIndex(_dragTargetNode.Node);
							_dragTargetNode.Node.Parent.AddChild(_dragTargetNode.Node.ParentConnector, sourcenode, m +1);

							LayoutChanged();
						break;

						// the node will be placed in front of the target node
						case(NodeAttachMode.Left):
							if(_movedNode !=null)
							{
								if(_keyShiftIsDown)
								{
									_movedNode.Parent.RemoveChild(_movedNode.ParentConnector, _movedNode);
								}
								else
								{
									if(!_movedNode.ExtractNode())
										throw new Exception(Resources.ExceptionNodeCouldNotBeExtracted);
								}
							}

							Node parent= _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);

							sourcenode.AddChild(sourcenode.DefaultConnector, _dragTargetNode.Node);
						break;

						// the node will simply attached to the target node
						case(NodeAttachMode.Right):
							if(_movedNode !=null)
							{
								if(_keyShiftIsDown)
								{
									_movedNode.Parent.RemoveChild(_movedNode.ParentConnector, _movedNode);
								}
								else
								{
									if(!_movedNode.ExtractNode())
										throw new Exception(Resources.ExceptionNodeCouldNotBeExtracted);
								}
							}

							_dragTargetNode.Node.AddChild(_dragTargetConnector, sourcenode);

							LayoutChanged();
						break;
					}

					// update the node's label
					sourcenode.OnPropertyValueChanged(false);
				}

				// reset all the drag data
				if(!_clipboardPasteMode)
				{
					_copiedNode= null;
					_movedNode= null;
					_dragTargetNode= null;
					_dragNodeDefaults= null;
					_movedNodeGraph= null;
				}

				// redraw the graph
				Invalidate();
			}

			Cursor= Cursors.Hand;

			base.OnMouseUp(e);
		}
 public NodeViewDataReferencedBehavior(NodeViewData parent, Nodes.BehaviorNode rootBehavior, Nodes.ReferencedBehaviorNode node) : base(parent, rootBehavior, (Node)node)
 {
 }
예제 #22
0
 /// <summary>
 /// Handles when a node is clicked.
 /// </summary>
 /// <param name="node">The node that was clicked.</param>
 private void control_ClickNode(NodeViewData node)
 {
     PropertiesDock.InspectObject(node ==null ? null : node.Node);
 }
예제 #23
0
		/// <summary>
		/// Handles when the user doucle-clicks.
		/// </summary>
		protected override void OnMouseDoubleClick(MouseEventArgs e)
		{
			// when the user double-clicked a node and the graph was not dragged and it was the left mouse button, continue
			if(_currentNode !=null && DoubleClickNode !=null && !_wasDragged && e.Button ==MouseButtons.Left)
			{
				// call double-clicked on the node
				bool layoutChanged;
				if(_currentNode.Node.OnDoubleClick(_currentNode, out layoutChanged))
				{
					// check if the node requires the layout to be updated, for example when expanding or collapsing referenced behaviours
					if(layoutChanged)
					{
						// keep the position of the current node
						_maintainNodePosition= _currentNode;

						_graphOrigin= _maintainNodePosition.DisplayBoundingBox.Location;

						LayoutChanged();
					}
				}
				else
				{
					// if the node did not handle the double-click the developer may
					if(DoubleClickNode !=null)
						DoubleClickNode(_currentNode);
				}
			}
			else base.OnMouseDoubleClick(e);
		}
예제 #24
0
		/// <summary>
		/// Handles when a key is pressed.
		/// </summary>
		protected override void OnKeyDown(KeyEventArgs e)
		{
			switch(e.KeyCode)
			{
				// store when the control key is pressed
				case(Keys.ControlKey):
					_keyControlIsDown= true;

					if(_copiedNode ==null && _movedNode ==null)
						Cursor= Cursors.Arrow;
				break;

				// store when the shift key is pressed
				case(Keys.ShiftKey):
					_keyShiftIsDown= true;

					// update the drawn graph for dragging and duplicating
					if(_movedNodeGraph !=null)
					{
						_movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0;
						Invalidate();
					}
				break;

				// copy to clipboard
				case(Keys.C):
					if(_keyControlIsDown && _selectedNode !=null)
					{
						_clipboardNode= _keyShiftIsDown ? (Node)_selectedNode.Node.CloneBranch() : (Node)_selectedNode.Node.Clone();
					}
				break;

				// paste from clipboard
				case(Keys.V):
					if(!_clipboardPasteMode)
					{
						_clipboardPasteMode= _keyControlIsDown && _clipboardNode !=null;

						if(_clipboardPasteMode)
						{
							// create the layout manager used to draw the graph
							_movedNodeGraph= new NodeLayoutManager(_clipboardNode.CreateNodeViewData(null, _rootNode.RootBehavior), _nodeLayoutManager.EdgePen, _nodeLayoutManager.EdgePenReadOnly, true);
							_movedNodeGraph.Scale= 0.3f;
							_movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0;

							// use the existing node as the node defaults
							_dragNodeDefaults= _clipboardNode;

							Invalidate();
						}
					}
				break;

				// cut to clipboard
				case(Keys.X):
					if(_keyControlIsDown && _selectedNode !=null)
					{
						_clipboardNode= _keyShiftIsDown ? (Node)_selectedNode.Node.CloneBranch() : (Node)_selectedNode.Node.Clone();

						// store the selected node
						Node node= _selectedNode.Node;

						// clear the selected and current node
						_selectedNode= null;
						_currentNode= null;

						if(_keyShiftIsDown)
						{
							// remove the node
							node.Parent.RemoveChild(node.ParentConnector, node);

							// call the ClickNode event to delselect the node in the editor
							if(ClickNode !=null)
								ClickNode(null);
						}
						else
						{
							if(node.ExtractNode())
							{
								// call the ClickNode event to delselect the node in the editor
								if(ClickNode !=null)
									ClickNode(null);
							}
						}
					}
				break;

				// handle when the delete key is pressed
				case(Keys.Delete):
					// when we have a node selected which is not the root node, continue
					if(_selectedNode !=null && _selectedNode.Node.Parent !=null)
					{
						// check whether we have to delete an event or a node
						if(_selectedNode.Node.SelectedSubItem ==null)
						{
							// store the selected node
							Node node= _selectedNode.Node;

							// clear the selected and current node
							_selectedNode= null;
							_currentNode= null;

							if(_keyShiftIsDown)
							{
								// remove the node
								node.Parent.RemoveChild(node.ParentConnector, node);

								// call the ClickNode event to delselect the node in the editor
								if(ClickNode !=null)
									ClickNode(null);
							}
							else
							{
								if(node.ExtractNode())
								{
									// call the ClickNode event to delselect the node in the editor
									if(ClickNode !=null)
										ClickNode(null);
								}
							}
						}
						else
						{
							// just let the node delete the selected subitem
							if(_selectedNode.Node.RemoveSelectedSubItem())
							{
								_selectedNode.Node.BehaviorWasModified();

								// call the ClickNode event to select the node instead of the deleted subitem
								if(ClickNode !=null)
									ClickNode(_selectedNode);
							}
						}

						// the layout needs to be recalculated
						LayoutChanged();
					}
				break;

				default: base.OnKeyDown(e); break;
			}
		}
예제 #25
0
		/// <summary>
		/// Handles when the root node changes.
		/// </summary>
		/// <param name="node">The node which was changed, in our case always the root node.</param>
		void nodeViewData_WasModified(NodeViewData node)
		{
			LayoutChanged();
		}
예제 #26
0
		/// <summary>
		/// Centres the given node in the view.
		/// </summary>
		/// <param name="node">The node which will be centred.</param>
		internal void CenterNode(NodeViewData node)
		{
			// we use the existing maintain position stuff for that
			RectangleF bbox= node.BoundingBox;

			_maintainNodePosition= node;

			// if the node was not yet shown there is no bounding box so we simply use the min height for that
			float height= bbox.Height <=0.0f ? node.Node.MinHeight : bbox.Height;

			_graphOrigin= new PointF(20.0f, ClientSize.Height *0.5f - height *0.5f);

			Invalidate();
		}
 public override void Update(NodeViewData node, Graphics graphics)
 {
     // calculate the extent used by the label
     _width = MeasureDisplayStringWidth(graphics, Label, _labelFont).Width;
 }
예제 #28
0
 public NodeViewDataReferencedBehavior(NodeViewData parent, Nodes.BehaviorNode rootBehavior, Nodes.ReferencedBehaviorNode node, Pen borderPen, Brush backgroundBrush, string label, string description) :
     base(parent, rootBehavior, (Node)node, borderPen, backgroundBrush, label, description)
 {
 }
예제 #29
0
		/// <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)
		{
			// check if the attach mode is valid
			if(mode ==NodeAttachMode.Event || mode ==NodeAttachMode.None)
				throw new Exception("A node cannot be created with the given attach mode");

			if(nodetag.Type !=NodeTagType.Behavior && nodetag.Type !=NodeTagType.Node)
				throw new Exception("Only behaviours and nodes can be attached to a behaviour tree");

			Node node= nvd.Node;

			Node newnode;
			// when we attach a behaviour we must create a special referenced behaviour node
			if(nodetag.Type ==NodeTagType.Behavior)
			{
				// reset any previously loaded behaviour
				FileManagers.FileManager.ResetLoadedBehavior();

				// get the behaviour we want to reference
				BehaviorNode behavior= _behaviorTreeList.LoadBehavior(nodetag.Filename);

				// a behaviour may not reference itself
				if(behavior ==_rootNode.RootBehavior)
					return;

				// create the referenced behaviour node for the behaviour
				ReferencedBehavior refnode= new ReferencedBehavior(_rootNode.RootBehavior, behavior);

				// register the view so it gets updated when the referenced behaviour gets updated.
				refnode.ReferencedBehaviorWasModified+= new ReferencedBehavior.ReferencedBehaviorWasModifiedEventDelegate(refnode_ReferencedBehaviorWasModified);

				newnode= refnode;
			}
			else
			{
				// simply create the node which is supposed to be created.
				newnode= Node.Create(nodetag.NodeType);
			}

			// update label
			newnode.OnPropertyValueChanged(false);

			// attach the new node with the correct mode
			switch(mode)
			{
				// the new node is inserted in front of the target node
				case(NodeAttachMode.Left):
					Node parent= node.Parent;

					int k= parent.Children.IndexOf(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):
					node.AddChild(_dragTargetConnector, newnode);

					// automatically select the new node
					_selectedNodePending= newnode;
					_selectedNodePendingParent= nvd;
				break;

				// the new node is placed above the target node
				case(NodeAttachMode.Top):
					int n= _dragTargetNode.Node.ParentConnector.GetChildIndex(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):
					int m= _dragTargetNode.Node.ParentConnector.GetChildIndex(node);
					node.Parent.AddChild(_dragTargetNode.Node.ParentConnector, newnode, m +1);

					// automatically select the new node
					_selectedNodePending= newnode;
					_selectedNodePendingParent= nvd.Parent;
				break;
			}

			// the layout needs to be recalculated
			LayoutChanged();
		}
예제 #30
0
        /// <summary>
        /// Adds nodes to the referenced behaviour which represent sub-referenced behaviours.
        /// </summary>
        /// <param name="processedBehaviors">A list of processed behaviours to handle circular references.</param>
        /// <param name="parent">The node the sub-referenced behaviours will be added to.</param>
        /// <param name="node">The current node we are checking.</param>
        protected void GenerateReferencedBehaviorsTree(ProcessedBehaviors processedBehaviors, NodeViewData parent, Node node)
        {
            if (!processedBehaviors.MayProcess(node))
            {
                return;
            }

            // check if this is a referenced behaviour
            if (node is ReferencedBehaviorNode)
            {
                // create the dummy node and add it without marking the behaviour as being modified as these are no REAL nodes.
                NodeViewData rb = node.CreateNodeViewData(parent, _rootBehavior);

#if DEBUG
                rb.IsSubreferencedGraphNode();
#endif
                rb.DoSynchronizeWithNode(processedBehaviors);

                Connector conn = parent.GetConnector("GenericChildren");
                Debug.Check(conn != null);

                Connector rbconn = parent.GetConnector("GenericChildren");
                Debug.Check(rbconn != null);

                bool parentReadOnly = conn.IsReadOnly;

                conn.IsReadOnly = false;

                parent.AddChildNotModified(conn, rb);

                conn.IsReadOnly = parentReadOnly;

                // we have a circular reference here. Skip the children
                if (((ReferencedBehaviorNode)node).Reference == _rootBehavior)
                {
                    rbconn.IsReadOnly = true;
                    return;
                }

                // do the same for all the children
                foreach (Node child in node.Children)
                {
                    GenerateReferencedBehaviorsTree(processedBehaviors.Branch(child), rb, child);
                }

                rbconn.IsReadOnly = true;
            }
            else if (node is Impulse)
            {
                // create the dummy node and add it without marking the behaviour as being modified as these are no REAL nodes.
                NodeViewData ip = node.CreateNodeViewData(parent, _rootBehavior);

                ip.DoSynchronizeWithNode(processedBehaviors);

                // do the same for all the children
                foreach (Node child in node.Children)
                {
                    GenerateReferencedBehaviorsTree(processedBehaviors.Branch(child), ip, child);
                }

                if (ip.Children.Count > 0)
                {
                    Connector conn = parent.GetConnector("GenericChildren");
                    Debug.Check(conn != null);

                    Connector ipconn = ip.GetConnector("GenericChildren");
                    Debug.Check(ipconn != null);

                    parent.AddChildNotModified(conn, ip);

                    ipconn.IsReadOnly = true;
                }
            }
            else
            {
                // do the same for all the children
                foreach (Node child in node.Children)
                {
                    GenerateReferencedBehaviorsTree(processedBehaviors.Branch(child), parent, child);
                }
            }
        }
예제 #31
0
		/// <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);

			// centre the root behaviour if requested
			if(_pendingCentreBehavior)
			{
				_pendingCentreBehavior= false;

				CenterNode(_rootNode);
			}

			// select the pending node
			if(_selectedNodePending !=null)
			{
				SelectedNode= _selectedNodePendingParent.GetChild(_selectedNodePending);

				_selectedNodePending= null;
				_selectedNodePendingParent= null;

				if(ClickNode !=null)
					ClickNode(_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.BoundingBox;

				PointF viewpos= new PointF(bbox.Location.X * _nodeLayoutManager.Scale, bbox.Location.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, _currentNode, _selectedNode, graphMousePos);

			// check if we are currently dragging a node and we must draw additional data
			if(_dragTargetNode !=null && _dragTargetNode.Node !=_movedNode)
			{
				if(_dragAttachMode == NodeAttachMode.Event)
				{
					// we could draw some stuff for events 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= 20.0f;

					// the distance of the arrow from the border and its height
					const float innerOffset= 6.0f;

					// the horizintal middle of the node
					float centerX= bbox.Left + bbox.Width *0.5f;

					// 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(bbox.X + offset, bbox.Top, bbox.Width - offset - offset, offset);
					RectangleF bottom= new RectangleF(bbox.X + offset, bbox.Bottom - offset, bbox.Width - offset - offset, 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;

					bool hasParentBehavior= _dragTargetNode.HasParentBehavior(behavior);
					bool parentHasParentBehavior= _dragTargetNode.Parent !=null && _dragTargetNode.Parent.HasParentBehavior(behavior);

					bool mayTop= _dragTargetNode.Node.Parent !=null && !parentHasParentBehavior && _dragTargetNode.Node.ParentConnector.AcceptsChildren(1);

					bool mayBottom= _dragTargetNode.Node.Parent !=null && !parentHasParentBehavior && _dragTargetNode.Node.ParentConnector.AcceptsChildren(1);

					bool mayLeft= _dragTargetNode.Parent !=null && !parentHasParentBehavior && !hasParentBehavior &&
									!_dragTargetNode.Node.ParentConnector.IsReadOnly &&
									_dragNodeDefaults is Node &&
									((Node)_dragNodeDefaults).CanAdoptNode(_dragTargetNode.Node) &&
									!(_dragNodeDefaults.GetType() is BehaviorNode);

					// update for moving an existing node
					bool dragTargetHasParentMovedNode= false;
					if(_movedNode !=null)
					{
						dragTargetHasParentMovedNode= _keyShiftIsDown && _dragTargetNode.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= false;
							mayBottom= false;
							mayLeft= false;
						}
						else
						{
							// a dragged node cannot be placed in the same position again
							mayTop= mayTop && _dragTargetNode.Node.PreviousNode !=_movedNode;
							mayBottom= mayBottom && _dragTargetNode.Node.NextNode !=_movedNode;
							mayLeft= mayLeft && _movedNode.CanAdoptChildren(_dragTargetNode.Node) && (!_keyShiftIsDown || _movedNode.Children.Count ==0);
						}
					}
					else if(_copiedNode !=null)
					{
						mayLeft= mayLeft && _copiedNode.CanAdoptChildren(_dragTargetNode.Node) && (!_keyShiftIsDown || _copiedNode.Children.Count ==0);
					}

					// 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 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.Node.Connectors)
					{
						RectangleF bboxConnector= _dragTargetNode.Node.GetConnectorBoundingBox(bbox, connector);

						//e.Graphics.DrawRectangle(Pens.Red, bboxConnector.X, bboxConnector.Y, bboxConnector.Width, bboxConnector.Height);

						RectangleF right= new RectangleF(bboxConnector.Right - offset, bboxConnector.Y, offset, bboxConnector.Height);

						bool mayRight= !dragTargetHasParentMovedNode && !hasParentBehavior && connector.AcceptsChildren(1);

						if(mayRight && _movedNode !=null && connector ==_movedNode.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= connector;
								_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, null, null, graphMousePos);
			}

			//if(_currentNode !=null && _currentNode.SubItems.Count >0)
			//	Invalidate();
		}
 /// <summary>
 /// Called when the node is drawn.
 /// </summary>
 /// <param name="dc">The graphics object used to draw the subitem.</param>
 /// <param name="nvd">The node view data of the node the subitem belongs to.</param>
 /// <param name="boundingBox">The bounding box of the subitem. Drawing is clipped to this.</param>
 public abstract void Draw(DrawingContext dc, NodeViewData nvd, Rect boundingBox);
예제 #33
0
		/// <summary>
		/// Draws the node to the graph.
		/// </summary>
		/// <param name="graphics">The graphics object we render to.</param>
		/// <param name="currentNode">The current node under the mouse cursor.</param>
		/// <param name="selectedNode">The currently selected node.</param>
		/// <param name="isDragged">Determines if the node is currently being dragged.</param>
		/// <param name="graphMousePos">The mouse position in the untransformed graph.</param>
		/// <param name="renderDepth">The depth which is still rendered.</param>
		public virtual void Draw(Graphics graphics, NodeViewData currentNode, NodeViewData selectedNode, bool isDragged, PointF graphMousePos, int renderDepth)
		{
			_node.Draw(graphics, this, currentNode ==null ? false : this.Node ==currentNode.Node, selectedNode ==null ? false : this.Node ==selectedNode.Node, isDragged, graphMousePos);

			// draw children
			if(renderDepth >0)
			{
				foreach(NodeViewData child in _children)
					child.Draw(graphics, currentNode, selectedNode, isDragged, graphMousePos, renderDepth -1);
			}
		}
 /// <summary>
 /// Called when the node gets updated.
 /// </summary>
 /// <param name="node">The node the subitem belongs to.</param>
 /// <param name="dc">The graphics object used for the update, NOT for drawing!</param>
 public abstract void Update(NodeViewData node, DrawingContext dc);
예제 #35
0
 /// <summary>
 /// Called when the node is drawn.
 /// </summary>
 /// <param name="graphics">The graphics object used to draw the subitem.</param>
 /// <param name="nvd">The node view data of the node the subitem belongs to.</param>
 /// <param name="boundingBox">The bounding box of the subitem. Drawing is clipped to this.</param>
 public abstract void Draw(Graphics graphics, NodeViewData nvd, RectangleF boundingBox);
예제 #36
0
		/// <summary>
		/// Handles when a key is released.
		/// </summary>
		protected override void OnKeyUp(KeyEventArgs e)
		{
			switch(e.KeyCode)
			{
				// store when the control key is released
				case(Keys.ControlKey):
					_keyControlIsDown= false;

					if(_copiedNode ==null && _movedNode ==null)
						Cursor= Cursors.Hand;
				break;

				// store when the shift key is released
				case(Keys.ShiftKey):
					_keyShiftIsDown= false;

					// update the drawn graph for dragging and duplicating
					if(_movedNodeGraph !=null)
					{
						_movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0;
						Invalidate();
					}
				break;

				// paste from clipboard
				case(Keys.V):
					_clipboardPasteMode= false;

					// reset all the drag data
					_copiedNode= null;
					_movedNode= null;
					_dragTargetNode= null;
					_dragNodeDefaults= null;
					_movedNodeGraph= null;

					// redraw the graph
					Invalidate();
				break;

				default: base.OnKeyUp(e); break;
			}
		}
예제 #37
0
		/// <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();

			// get source node
			TreeNode sourceNode= (TreeNode) e.Data.GetData("System.Windows.Forms.TreeNode");
			NodeTag sourceNodeTag= (NodeTag)sourceNode.Tag;

			// keep the current node position
			_maintainNodePosition= _dragTargetNode;
			_graphOrigin= _maintainNodePosition.DisplayBoundingBox.Location;

			// check if we are dropping an event
			if(_dragAttachMode ==NodeAttachMode.Event)
			{
				// add the event to the target node
				Events.Event evnt= Brainiac.Design.Events.Event.Create(sourceNodeTag.NodeType, _dragTargetNode.Node);
				evnt.OnPropertyValueChanged(false);
				Nodes.Node.SubItemEvent sub= new Nodes.Node.SubItemEvent(evnt);
				_dragTargetNode.Node.AddSubItem(sub);
				_dragTargetNode.Node.BehaviorWasModified();

				SelectedNode= _dragTargetNode;
				_selectedNode.Node.SelectedSubItem= sub;

				// call the ClickEvent event handler
				if(ClickEvent !=null)
					ClickEvent(_selectedNode);

				LayoutChanged();
			}
			else if(_dragAttachMode !=NodeAttachMode.None)
			{
				// attach a new node to the target node
				InsertNewNode(_dragTargetNode, _dragAttachMode, sourceNodeTag);
			}

			// reset drag stuff
			_dragTargetNode= null;
			_dragNodeDefaults= null;
			_dragAttachMode= NodeAttachMode.None;

			Invalidate();
		}
예제 #38
0
 /// <summary>
 /// Handles when an event of a node is selected.
 /// </summary>
 /// <param name="node">The node whose event is selected.</param>
 private void control_ClickEvent(NodeViewData node)
 {
     // if there is no subitem selected, use the properties of the node
     if(node.Node.SelectedSubItem ==null || node.Node.SelectedSubItem.SelectableObject ==null)
     {
         PropertiesDock.InspectObject(node.Node);
     }
     // publish the properties of the subitem's selection object
     else
     {
         PropertiesDock.InspectObject(node.Node.SelectedSubItem.SelectableObject);
     }
 }
예제 #39
0
 /// <summary>
 /// Called when the node gets updated.
 /// </summary>
 /// <param name="node">The node the subitem belongs to.</param>
 /// <param name="graphics">The graphics object used for the update, NOT for drawing!</param>
 public abstract void Update(NodeViewData node, Graphics graphics);
예제 #40
0
 /// <summary>
 /// Handles when a node is double-clicked.
 /// </summary>
 /// <param name="node">The node that was double-clicked.</param>
 private void control_DoubleClickNode(NodeViewData node)
 {
 }
예제 #41
0
		/// <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= _rootNode.IsInside(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;

			// make sure the correct drag attach mode is set
			if(_dragTargetNode !=null)
			{
				if(_dragNodeDefaults is Nodes.Node && _dragAttachMode ==NodeAttachMode.Event)
					_dragAttachMode= NodeAttachMode.None;
				else if(_dragNodeDefaults is Events.Event && _dragAttachMode !=NodeAttachMode.Event)
					_dragAttachMode= NodeAttachMode.Event;
			}

			// check if we are trying to drop a node on another one
			if(_dragTargetNode !=null && (e.KeyState & 1/*left mouse button*/) >0 && _dragNodeDefaults is Nodes.Node)
			{
				e.Effect= DragDropEffects.Move;
			}
			// check if we are trying attach an event to a node
			else if(_dragTargetNode !=null && (e.KeyState & 1/*left mouse button*/) >0 && _dragNodeDefaults is Events.Event && _dragTargetNode.Node.AcceptsEvents)
			{
				e.Effect= DragDropEffects.Move;
			}

			// update last know mouse position
			_lastMousePosition= new PointF(pt.X, pt.Y);
		}
예제 #42
0
		/// <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 edgePenSubReferenced, bool skipLabels)
		{
			_rootNodeLayout= rootNode;
			_edgePen= edgePen;
			_edgePenReadOnly= edgePenSubReferenced;
			_skipLabels= skipLabels;
		}
예제 #43
0
		/// <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= _rootNode.IsInside(e.Location);

			// clear previously stored node which can cause problems when dragging to another view
			_dragTargetNode= null;

			// if a different node is the current one, update it
			if(nodeFound !=_currentNode)
			{
				_currentNode= nodeFound;

				// if enabled show the tooltip for the node
				if(Settings.Default.ShowNodeToolTips)
				{
					if(_currentNode ==null)
					{
						toolTip.Hide(this);
					}
					else
					{
						if(_currentNode.Node.ToolTip !=string.Empty)
							toolTip.Show(_currentNode.Node.ToolTip, this, new Point( (int)_currentNode.DisplayBoundingBox.X -20, (int)_currentNode.DisplayBoundingBox.Y -30 ));
					}
				}

				Invalidate();
			}

			// check if we are currently dragging the graph
			if(e.Button ==MouseButtons.Left && _lastMousePosition !=e.Location && !_keyControlIsDown && _copiedNode ==null)
			{
				_wasDragged= true;

				// 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 && _keyControlIsDown && _lastMousePosition !=e.Location && _copiedNode ==null && _currentNode !=null && !(_currentNode.Node is BehaviorNode))
			{
				_copiedNode= _currentNode.Node;

				// create the layout manager used to draw the graph
				_movedNodeGraph= new NodeLayoutManager(_copiedNode.CloneBranch().CreateNodeViewData(null, _rootNode.RootBehavior), _nodeLayoutManager.EdgePen, _nodeLayoutManager.EdgePenReadOnly, true);
				_movedNodeGraph.Scale= 0.3f;
				_movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0;

				// use the existing node as the node defaults
				_dragNodeDefaults= _copiedNode;

				Invalidate();
			}
			// check if we are duplicating an existing node step 2
			else if(e.Button ==MouseButtons.Left && _keyControlIsDown && _copiedNode !=null)
			{
				_movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0;

				_dragTargetNode= _currentNode;

				Cursor= _currentNode ==null ? Cursors.No : Cursors.Arrow;

				//Point movedGraphGraphPos= new Point(e.Location.X + _movedNodeGraph.Offset.X, e.Location.Y + _movedNodeGraph.Offset.Y /-2);
				//_movedNodeGraph.Location= movedGraphGraphPos;

				Invalidate();
			}
			// check if we start dragging an existing node step 1
			else if(e.Button ==MouseButtons.Right && _lastMousePosition !=e.Location && _movedNode ==null && _currentNode !=null && !(_currentNode.Node is BehaviorNode) && (_keyShiftIsDown || _currentNode.Node.ParentCanAdoptChildren))
			{
				_movedNode= _currentNode.Node;

				// create the layout manager used to draw the graph
				_movedNodeGraph= new NodeLayoutManager(_movedNode.CloneBranch().CreateNodeViewData(null, _rootNode.RootBehavior), _nodeLayoutManager.EdgePen, _nodeLayoutManager.EdgePenReadOnly, true);
				_movedNodeGraph.Scale= 0.3f;
				_movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0;

				// use the existing node as the node defaults
				_dragNodeDefaults= _movedNode;

				Invalidate();
			}
			// check if we are dragging an existing node step 2
			else if(e.Button ==MouseButtons.Right && _movedNode !=null)
			{
				_movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0;

				_dragTargetNode= _currentNode;

				Cursor= _currentNode ==null ? Cursors.No : Cursors.Arrow;

				Invalidate();
			}
			else if(_clipboardPasteMode)
			{
				_movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0;

				_dragTargetNode= _currentNode;

				Cursor= _currentNode ==null ? Cursors.No : Cursors.Arrow;

				Invalidate();
			}

			// update the last ouse position
			_lastMousePosition= e.Location;

			base.OnMouseMove(e);
		}
예제 #44
0
 /// <summary>
 /// Handles when a node is double-clicked.
 /// </summary>
 /// <param name="node">The node that was double-clicked.</param>
 private void control_DoubleClickNode(NodeViewData node)
 {
 }
예제 #45
0
		/// <summary>
		/// Creates a new view for a given node.
		/// </summary>
		/// <param name="parent">The parent of the new NodeViewData.</param>
		/// <param name="rootBehavior">The behaviour which is the root of the graph the given node is shown in.</param>
		/// <param name="node">The node the view is created for.</param>
		public NodeViewData(NodeViewData parent, BehaviorNode rootBehavior, Node node)
		{
			Debug.Check(rootBehavior !=null);

			_parent= parent;
			_rootBehavior= rootBehavior;
			_node= node;

			if(parent !=null)
				WasModified= parent.WasModified;

			_node.WasModified+= new Node.WasModifiedEventDelegate(node_WasModified);
		}
예제 #46
0
		/// <summary>
		/// Draws the graph.
		/// </summary>
		/// <param name="graphics">The graphics object we want to draw to.</param>
		/// <param name="currentNode">The node the mouse is currently hovering over.</param>
		/// <param name="selectedNode">The node which is currently selected.</param>
		/// <param name="graphMousePos">The mouse's position in the graph.</param>
		internal void DrawGraph(Graphics graphics, NodeViewData currentNode, NodeViewData selectedNode, PointF graphMousePos)
		{
			// setup drawing
			graphics.InterpolationMode= System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
			graphics.SmoothingMode= System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
			graphics.Transform= new System.Drawing.Drawing2D.Matrix(_scale, 0.0f, 0.0f, _scale, _offset.X, _offset.Y);

			// update display bounding boxes
			_rootNodeLayout.UpdateDisplay(_offset.X, _offset.Y, _scale);

			// draw comment backgrounds
			if(!_skipLabels)
				_rootNodeLayout.DrawCommentBackground(graphics, _renderDepth, _padding);

			// draw the edges
			if(_edgePen !=null && _renderDepth >0)
				_rootNodeLayout.DrawEdges(graphics, _edgePen, _edgePenReadOnly, _renderDepth -1);

			// draw the nodes
			_rootNodeLayout.Draw(graphics, currentNode, selectedNode, _skipLabels, graphMousePos, _renderDepth);

			// draw comment text
			if(!_skipLabels)
				_rootNodeLayout.DrawCommentText(graphics, _renderDepth);

			// draw last mouse pos
			//e.Graphics.DrawRectangle(Pens.Red, graphMousePos.X -1.0f, graphMousePos.Y -1.0f, 2.0f, 2.0f);
		}
		public NodeViewDataReferencedBehavior(NodeViewData parent, Nodes.BehaviorNode rootBehavior, Nodes.ReferencedBehaviorNode node) : base(parent, rootBehavior, (Node)node)
		{
		}