/// <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); }