# 选择功能修复说明 ## 问题描述 用户反馈点击模型后没有反应,应该要能够选中模型并显示选择框和坐标轴。 ## 问题分析 通过分析代码发现了几个关键问题: ### 1. 缺少碰撞检测设置 **问题**:模型导入时没有设置碰撞检测,导致射线检测无法检测到模型。 - `scene_manager.py` 中的 `importModel` 方法没有调用 `setupCollision` - 所有模型加载方法都缺少碰撞设置 ### 2. 默认工具未设置 **问题**:`tool_manager.py` 中默认工具为 `None`,而选择功能需要当前工具为"选择"。 - 事件处理器中的条件 `if self.world.currentTool == "选择"` 永远不成立 ### 3. 碰撞掩码不匹配 **问题**:射线检测和模型碰撞体使用不同的碰撞掩码。 - 模型碰撞体使用 `BitMask32.bit(2)` - 射线检测使用 `GeomNode.getDefaultCollideMask()` ## 修复方案 ### 1. 为所有模型添加碰撞检测 **修复位置**:`scene/scene_manager.py` 在以下方法中添加碰撞检测设置: - `importModel()` - 主要模型导入方法 - `loadScene()` - 场景加载时为每个模型设置碰撞 - `processLoadedModel()` - 异步加载回调 - `loadAnimatedModel()` - 动画模型加载 ```python # 设置碰撞检测(重要!用于选择功能) print("\n=== 设置碰撞检测 ===") self.setupCollision(model) ``` ### 2. 设置默认工具为选择 **修复位置**:`core/tool_manager.py` ```python def __init__(self, world): """初始化工具管理器""" self.world = world self.currentTool = "选择" # 默认工具为选择工具 ``` ### 3. 统一碰撞掩码设置 **修复位置**:`core/event_handler.py` ```python # 设置射线的碰撞掩码,匹配模型的碰撞掩码(第2位) from panda3d.core import BitMask32 pickerNode.setFromCollideMask(BitMask32.bit(2)) ``` ## 碰撞检测系统工作原理 ### 模型碰撞体设置 每个模型都会创建一个包围球体作为碰撞体: ```python def setupCollision(self, model): # 创建碰撞节点 cNode = CollisionNode(f'modelCollision_{model.getName()}') cNode.setIntoCollideMask(BitMask32.bit(2)) # 使用第2位 # 获取模型边界并创建碰撞球体 bounds = model.getBounds() center = bounds.getCenter() radius = bounds.getRadius() cSphere = CollisionSphere(center, radius) cNode.addSolid(cSphere) # 附加到模型 cNodePath = model.attachNewNode(cNode) ``` ### 射线检测机制 鼠标点击时创建射线进行碰撞检测: ```python # 创建射线检测 picker = CollisionTraverser() queue = CollisionHandlerQueue() pickerNode = CollisionNode('mouseRay') pickerNP = self.world.cam.attachNewNode(pickerNode) pickerNode.setFromCollideMask(BitMask32.bit(2)) # 匹配模型掩码 # 创建射线几何体 direction = farPoint - nearPoint direction.normalize() pickerNode.addSolid(CollisionRay(nearPoint, direction)) # 执行碰撞检测 picker.addCollider(pickerNP, queue) picker.traverse(self.world.render) ``` ## 选择系统工作流程 1. **鼠标点击** → `mousePressEventLeft()` 2. **坐标转换** → 屏幕坐标转世界坐标 3. **创建射线** → 相机位置到点击位置 4. **碰撞检测** → 射线与模型碰撞体检测 5. **选择处理** → `_handleSelectionClick()` 6. **更新UI** → 选择框、坐标轴、属性面板 ## 测试验证 创建了专用测试脚本 `demo/selection_test.py`: ### 测试功能 - 创建多个测试立方体模型 - 验证碰撞检测设置 - 测试点击选择功能 - 显示选择框和坐标轴 ### 测试控制 - **鼠标左键**:点击选择模型 - **I键**:显示当前选择信息 - **C键**:显示碰撞检测信息 - **S键**:切换碰撞体显示(调试) - **R键**:切换射线显示 - **Q键**:退出 ### 运行测试 ```bash cd demo python selection_test.py ``` ## 修复效果 **修复前**: - 点击模型无反应 - 无法选中任何物体 - 选择框和坐标轴不显示 **修复后**: - ✅ 点击模型正确选中 - ✅ 显示橙色选择框 - ✅ 显示彩色坐标轴(红X、绿Y、蓝Z) - ✅ 树形控件同步选择 - ✅ 属性面板更新显示 - ✅ 坐标轴支持拖拽变换 ## 相关功能 选择功能修复后,以下功能也恢复正常: - **坐标轴拖拽**:点击坐标轴可拖拽移动物体 - **属性编辑**:选中后可在属性面板编辑位置、旋转、缩放 - **场景树同步**:点击模型会在场景树中高亮对应项 - **射线调试**:按R键可显示点击射线用于调试 ## 技术要点 1. **碰撞掩码一致性**:射线检测和模型碰撞体必须使用相同的掩码位 2. **碰撞体覆盖**:包围球体确保模型的所有部分都可点击 3. **工具状态管理**:默认工具状态影响事件处理逻辑 4. **模块化设计**:碰撞设置在所有模型加载路径中都要调用 这次修复确保了3D编辑器的核心交互功能正常工作,为后续的编辑操作打下了坚实基础。