public void ShowContextMenu(Vector2 mousePos, Vector2 offset, List <int> nodeList) { if (Application.isPlaying) { return; } var menu = new GenericMenu(); if (nodeList != null && nodeList.Count > 0) { if (nodeList.Count == 1) { BTNode node = BTEditorManager.GetNodeByID(nodeList[0]); // 添加 if (node.CanConnectChild) { foreach (var kvp in mAddContextDic) { menu.AddItem(new GUIContent("Add Child/" + kvp.Key), false, Add, new MenuAction(nodeList, mousePos, kvp.Value)); } } else { menu.AddDisabledItem(new GUIContent("Add")); } // Connect/Disconnect Parent menu.AddSeparator(""); if (!(node is BaseRoot) && !(node is Root)) { if (node.parent != null) { menu.AddItem(new GUIContent("Disconnect from Parent"), false, Unparent, new MenuAction(nodeList)); } else { menu.AddItem(new GUIContent("Connect to Parent"), false, ConnectParent, new MenuAction(nodeList)); } } // Connect Child menu.AddSeparator(""); if (node.CanConnectChild) { menu.AddItem(new GUIContent("Connect to Child"), false, ConnectChild, new MenuAction(nodeList)); } else { menu.AddDisabledItem(new GUIContent("Connect to Child")); } // Copy menu.AddSeparator(""); menu.AddItem(new GUIContent("Copy"), false, Copy, new MenuAction(nodeList, mousePos)); // Delete menu.AddSeparator(""); menu.AddItem(new GUIContent("Delete"), false, Delete, new MenuAction(nodeList)); } else { // Copy menu.AddSeparator(""); menu.AddItem(new GUIContent("Copy"), false, Copy, new MenuAction(nodeList, mousePos)); // Delete menu.AddSeparator(""); menu.AddItem(new GUIContent("Delete"), false, Delete, new MenuAction(nodeList)); } } // 右键点击画布 else { // 添加 foreach (var kvp in mAddContextDic) { menu.AddItem(new GUIContent("Add/" + kvp.Key), false, Add, new MenuAction(nodeList, mousePos, kvp.Value)); } // 粘贴 menu.AddSeparator(""); if (BTEditorManager.CopyFromNodes.Count > 0) { menu.AddItem(new GUIContent("Paste"), false, Paste, new MenuAction(null, mousePos)); } else { menu.AddDisabledItem(new GUIContent("Paste")); } // 保存 menu.AddSeparator(""); menu.AddItem(new GUIContent("Save"), false, Save, null); } menu.DropDown(new Rect(mousePos + offset, Vector2.zero)); }
// Returns true if needs a repaint void HandleMouseEvents(Rect position, Dictionary <int, BTNode> nodeDic) { Event e = Event.current; // MouseDown // // Identify the control being clicked if (Event.current.type == EventType.MouseDown) { // Do nothing for MouseDown on the scrollbar, if present if (e.mousePosition.x >= position.width + mScrollPoint.x || e.mousePosition.y >= position.height + mScrollPoint.y) { mCurMode = Mode.None; } // MouseDown in the canvas, check if in a node or on background else { // Store the mouse position mMouseStartPos = e.mousePosition; // Loop through nodes and check if their rects contain the mouse position BTNode contextNode = null; BTNode tempNode = null; foreach (var kvp in nodeDic) { tempNode = kvp.Value; if (tempNode != null && mNodeRenderer.rectForNode(tempNode).Contains(mMouseStartPos)) { // Connect a parent to a child if (mCurMode == Mode.ConnectChild) { BTEditorManager.Connect(owner.connectOrigin, tempNode.GetInstanceID()); // editorWindow.wantsMouseMove = false; mCurMode = Mode.None; break; } // Connect a child to a parent else if (mCurMode == Mode.ConnectParent) { BTEditorManager.Connect(tempNode.GetInstanceID(), owner.connectOrigin); // editorWindow.wantsMouseMove = false; mCurMode = Mode.None; break; } // Perform a node action at key up else { mCurMode = Mode.NodeAction; contextNode = tempNode; } } } // Cancel the connection if (mCurMode == Mode.ConnectParent || mCurMode == Mode.ConnectChild) { // editorWindow.wantsMouseMove = false; mCurMode = Mode.None; } // MouseDown on the canvas background enables panning the view if (mCurMode == Mode.None && contextNode == null) { mCurMode = Mode.CanvasAction; } SelectNode(contextNode); } return; } // Mouse Up // // MouseUp resets the current interaction mode to None if (e.type == EventType.MouseUp) { mPickingup = false; // Context Menu if (IsRightMouseBtn()) { if (mCurMode == Mode.NodeAction) { owner.ShowContextMenu(e.mousePosition, EditorZoomArea.GetScrollOffset(zoomScale, mScrollPoint), mSelectedNodes); } else if (mCurMode == Mode.CanvasAction) { owner.ShowContextMenu(e.mousePosition, EditorZoomArea.GetScrollOffset(zoomScale, mScrollPoint), null); } } // Resize canvas after a drag else if (mCurMode == Mode.DragNode) { BTEditorManager.Dirty(); } mCurMode = Mode.None; return; } // Mouse Drag // if (e.type == EventType.MouseDrag) { if (IsLeftMouseBtn()) { if (mCurMode == Mode.CanvasAction) { if (e.modifiers == EventModifiers.Alt) { mPickingup = true; mPickupStartPos = mMouseStartPos; } else if (e.modifiers == EventModifiers.None) { mScrollPoint -= (e.delta / zoomScale); } } // Switch to node dragging mode else if (mCurMode == Mode.NodeAction) { if (mSelectedNodes.Count > 0 && e.modifiers != EventModifiers.Control) { Vector2 mousePos = e.mousePosition; float deltaX = Mathf.Abs(mousePos.x - mMouseStartPos.x); float deltaY = Mathf.Abs(mousePos.y - mMouseStartPos.y); // Ignore mouse drags inside nodes lesser than the grid step. These would be rounded, // and make selecting a node slightly more difficult. if (deltaX >= GridRenderer.step.x || deltaY >= GridRenderer.step.y) { mCurMode = Mode.DragNode; } } } // Drag a node if (mCurMode == Mode.DragNode) { // 距离Node中心位置的移动距离 DragNodes(mSelectedNodes); } } return; } // 鼠标移出窗口 if (e.type == EventType.MouseLeaveWindow) { if (mPickingup) { mPickingup = false; } return; } // Zoom if (e.type == EventType.ScrollWheel) { if (e.modifiers == EventModifiers.Alt) { Vector2 delta = e.delta; float zoomDelta = -delta.y / 150.0f; zoomScale += zoomDelta; zoomScale = Mathf.Clamp(zoomScale, ZoomMin, ZoomMax); e.Use(); } return; } // 按键操作 if (e.type == EventType.KeyDown) { if (e.control) { // 复制 if (e.keyCode == KeyCode.C) { BTEditorManager.Copy(mSelectedNodes.ToArray()); return; } // 粘贴 if (e.keyCode == KeyCode.V) { Vector2 to = BTEditorManager.CopyFromPos; to.x += 100f; BTEditorManager.Paste(to); return; } } // 删除 if (e.keyCode == KeyCode.Delete) { BTEditorManager.Delete(mSelectedNodes.ToArray()); return; } } }
public override bool ContainsChild(BTNode child) { return(_children.Contains(child)); }
public BTNode CreateNode(System.Type type) { BTNode node = ScriptableObject.CreateInstance(type) as BTNode; return(node); }
public override bool ContainsChild(BTNode child) { return(m_child == child); }
public override void ConnectChild(BTNode child) { _children.Add(child); child.parent = this; }
public void Draw(BTNode node, bool selected) { float shadowOffset = 4; // Edge if (node.parent != null) { // Shadow Vector2 offset = new Vector2(shadowOffset, shadowOffset); DrawEdge(node.parent.editorPosition + offset, node.editorPosition + offset, Width, Height, shadowColor); // Line DrawEdge(node.parent.editorPosition, node.editorPosition, Width, Height, edgeColor); } // Node Shadow Rect nodeRect = new Rect(node.editorPosition.x, node.editorPosition.y, Width, Height); Rect shadowRect = new Rect(nodeRect.x + shadowOffset, nodeRect.y + shadowOffset, nodeRect.width, nodeRect.height); if (shadowTexture == null) { shadowTexture = new Texture2D(1, 1); shadowTexture.hideFlags = HideFlags.DontSave; shadowTexture.SetPixel(0, 0, shadowColor); shadowTexture.Apply(); } GUI.DrawTexture(shadowRect, shadowTexture); // Node if (nodeTexture == null) { Color colA = new Color(152f / 255, 152f / 255, 152f / 255); Color colB = new Color(183f / 255, 183f / 255, 183f / 255); nodeTexture = new Texture2D(1, (int)Height); nodeTexture.hideFlags = HideFlags.DontSave; for (int y = 0; y < Height; y++) { nodeTexture.SetPixel(0, y, Color.Lerp(colA, colB, y / Height)); } nodeTexture.Apply(); } GUI.DrawTexture(nodeRect, nodeTexture); // Icons DrawNodeIcon(nodeRect, node); // Debug status // DrawStatusIcon(nodeRect, node); DrawLabel(nodeRect, node); // Selection highlight if (selected) { if (selectionTexture == null) { selectionTexture = new Texture2D(1, 1); selectionTexture.hideFlags = HideFlags.DontSave; selectionTexture.SetPixel(0, 0, selColor); selectionTexture.Apply(); } float mbOffset = selMargin + selWidth; // Margin + Border offset GUI.DrawTexture(new Rect(nodeRect.x - mbOffset, nodeRect.y - mbOffset, nodeRect.width + mbOffset * 2, selWidth), selectionTexture); // Top GUI.DrawTexture(new Rect(nodeRect.x - mbOffset, nodeRect.y - selMargin, selWidth, nodeRect.height + selMargin * 2), selectionTexture); // Left GUI.DrawTexture(new Rect(nodeRect.x + nodeRect.width + selMargin, nodeRect.y - selMargin, selWidth, nodeRect.height + selMargin * 2), selectionTexture); // Right GUI.DrawTexture(new Rect(nodeRect.x - mbOffset, nodeRect.y + nodeRect.height + selMargin, nodeRect.width + mbOffset * 2, selWidth), selectionTexture); // Top } }
public Rect rectForNode(BTNode node) { return(new Rect(node.editorPosition.x, node.editorPosition.y, Width, Height)); }
public virtual bool ContainsChild(BTNode child) { return(false); }
public virtual void DisconnectChild(BTNode child) { }
// IComparable for sorting left-to-right in the visual editor public int CompareTo(object other) { BTNode otherNode = other as BTNode; return(editorPosition.x < otherNode.editorPosition.x ? -1 : 1); }