1
0
forked from Rowland/EG
EG/demo/选择功能修复说明.md
2025-07-10 09:19:51 +08:00

169 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 选择功能修复说明
## 问题描述
用户反馈点击模型后没有反应,应该要能够选中模型并显示选择框和坐标轴。
## 问题分析
通过分析代码发现了几个关键问题:
### 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编辑器的核心交互功能正常工作为后续的编辑操作打下了坚实基础。