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 + ')'"
/>