From 92125aee3a375bd09409a48497e4310ff78104ff Mon Sep 17 00:00:00 2001 From: YHH <359807859@qq.com> Date: Wed, 18 Jun 2025 15:43:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E8=BF=9E=E7=BA=BF=E6=93=8D?= =?UTF-8?q?=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../composables/useBehaviorTreeEditor.ts | 43 +++++++++++++++++-- .../composables/useConnectionManager.ts | 36 ++++++++++++++++ .../static/style/behavior-tree/index.css | 7 ++- .../behavior-tree/BehaviorTreeEditor.html | 3 ++ 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/source/panels/behavior-tree/composables/useBehaviorTreeEditor.ts b/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/source/panels/behavior-tree/composables/useBehaviorTreeEditor.ts index 60a6acb3..57014cd6 100644 --- a/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/source/panels/behavior-tree/composables/useBehaviorTreeEditor.ts +++ b/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/source/panels/behavior-tree/composables/useBehaviorTreeEditor.ts @@ -303,6 +303,27 @@ export function useBehaviorTreeEditor() { alert(message); }; + // 清除所有连接线 + const clearAllConnections = () => { + if (appState.connections.value.length === 0) { + alert('当前没有连接线需要清除!'); + return; + } + + if (confirm(`确定要清除所有 ${appState.connections.value.length} 条连接线吗?此操作不可撤销。`)) { + // 清除所有节点的父子关系 + appState.treeNodes.value.forEach(node => { + node.parent = undefined; + node.children = []; + }); + + // 清空连接数组 + appState.connections.value = []; + + alert('已清除所有连接线!'); + } + }; + onMounted(() => { const appContainer = document.querySelector('#behavior-tree-app'); if (appContainer) { @@ -321,15 +342,28 @@ export function useBehaviorTreeEditor() { alert('文件加载失败: ' + event.detail.error); }; + // 键盘快捷键处理 + const handleKeydown = (event: KeyboardEvent) => { + // Delete键删除选中的节点 + if (event.key === 'Delete' && appState.selectedNodeId.value) { + event.preventDefault(); + nodeOps.deleteNode(appState.selectedNodeId.value); + } + // Escape键取消连接 + if (event.key === 'Escape' && connectionState.isConnecting) { + event.preventDefault(); + connectionManager.cancelConnection(); + } + }; + document.addEventListener('load-behavior-tree-file', handleLoadBehaviorTreeFile as EventListener); document.addEventListener('file-load-error', handleFileLoadError as EventListener); - - console.log('[BehaviorTreeEditor] 事件系统准备完成(直接方法调用 + DOM事件备用)'); + document.addEventListener('keydown', handleKeydown); onUnmounted(() => { - console.log('[BehaviorTreeEditor] 清理事件监听器'); document.removeEventListener('load-behavior-tree-file', handleLoadBehaviorTreeFile as EventListener); document.removeEventListener('file-load-error', handleFileLoadError as EventListener); + document.removeEventListener('keydown', handleKeydown); // 清理暴露的方法 if (appContainer) { @@ -361,6 +395,7 @@ export function useBehaviorTreeEditor() { startNodeDrag, dragState, autoLayout, - validateTree + validateTree, + clearAllConnections }; } \ No newline at end of file diff --git a/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/source/panels/behavior-tree/composables/useConnectionManager.ts b/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/source/panels/behavior-tree/composables/useConnectionManager.ts index 3c31347e..40323c20 100644 --- a/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/source/panels/behavior-tree/composables/useConnectionManager.ts +++ b/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/source/panels/behavior-tree/composables/useConnectionManager.ts @@ -473,11 +473,47 @@ export function useConnectionManager( }, 50); // 50ms延迟,确保DOM渲染完成 }; + // 删除连接线 + const removeConnection = (connectionId: string) => { + const connection = connections.value.find(conn => conn.id === connectionId); + if (!connection) return; + + const parentNode = treeNodes.value.find(n => n.id === connection.sourceId); + const childNode = treeNodes.value.find(n => n.id === connection.targetId); + + if (parentNode && childNode) { + // 从父节点的children中移除 + const index = parentNode.children.indexOf(connection.targetId); + if (index > -1) { + parentNode.children.splice(index, 1); + } + + // 清除子节点的parent + childNode.parent = undefined; + + // 更新连接线 + updateConnections(); + } + }; + + // 连接线点击事件处理 + const onConnectionClick = (event: MouseEvent, connectionId: string) => { + event.preventDefault(); + event.stopPropagation(); + + // 询问用户是否要删除连接 + if (confirm('确定要删除这条连接线吗?')) { + removeConnection(connectionId); + } + }; + return { getPortPosition, startConnection, cancelConnection, updateConnections, + removeConnection, + onConnectionClick, onPortHover, onPortLeave, isValidConnectionTarget diff --git a/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/static/style/behavior-tree/index.css b/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/static/style/behavior-tree/index.css index 6e0a978a..43f892b5 100644 --- a/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/static/style/behavior-tree/index.css +++ b/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/static/style/behavior-tree/index.css @@ -281,12 +281,15 @@ transition: none; opacity: 0.9; will-change: d; + pointer-events: stroke; + cursor: pointer; } .connection-line:hover { - stroke: #9f7aea; - stroke-width: 4; + stroke: #f56565; + stroke-width: 5; opacity: 1; + filter: drop-shadow(0 0 4px rgba(245, 101, 101, 0.6)); } .connection-active { diff --git a/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/static/template/behavior-tree/BehaviorTreeEditor.html b/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/static/template/behavior-tree/BehaviorTreeEditor.html index 498c7038..0cc65f33 100644 --- a/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/static/template/behavior-tree/BehaviorTreeEditor.html +++ b/extensions/cocos/cocos-ecs/extensions/cocos-ecs-extension/static/template/behavior-tree/BehaviorTreeEditor.html @@ -152,6 +152,7 @@ + @@ -186,6 +187,8 @@ :d="connection.path" class="connection-line" :class="{ 'connection-active': connection.active }" + @click="onConnectionClick($event, connection.id)" + :title="'点击删除连接线 (' + connection.sourceId + ' → ' + connection.targetId + ')'" />