# 坐标轴系统修复说明

## 问题描述

用户报告主程序中的坐标轴系统无响应：
- 鼠标悬停在坐标轴上无高亮效果
- 点击坐标轴无法开始拖拽
- 独立的demo程序（`standalone_gizmo_test.py`）工作正常

## 根本原因

经过分析发现，问题出在**Qt集成环境下的窗口尺寸获取不准确**：

1. **独立demo**：直接继承自`ShowBase`，使用`self.win.getXSize()`和`self.win.getYSize()`获取窗口尺寸是准确的
2. **主程序**：使用Qt集成的`Panda3DWorld`基类，`self.win.getXSize()`返回的尺寸与实际Qt渲染区域尺寸不匹配
3. **坐标轴点击检测**：依赖屏幕空间投影计算，窗口尺寸错误导致投影坐标计算错误

## 修复方案

### 1. 添加Qt部件引用机制

在`MyWorld`类中添加：
```python
# Qt部件引用（用于获取准确的渲染区域尺寸）
self.qtWidget = None

def setQtWidget(self, widget):
    """设置Qt部件引用"""
    self.qtWidget = widget

def getWindowSize(self):
    """获取准确的窗口尺寸"""
    if self.qtWidget:
        # 优先使用Qt部件的实际尺寸
        width, height = self.qtWidget.getActualSize()
        if width > 0 and height > 0:
            return width, height
    
    # 备用方案：使用Panda3D窗口尺寸
    if hasattr(self, 'win') and self.win:
        width = self.win.getXSize()
        height = self.win.getYSize()
        return width, height
    
    # 最后的默认值
    return 800, 600
```

### 2. 修改CustomPanda3DWidget

添加方法以获取Qt部件实际尺寸：
```python
def getActualSize(self):
    """获取Qt部件的实际渲染尺寸"""
    return (self.width(), self.height())
```

在构造函数中建立引用：
```python
# 让world引用这个widget，以便获取准确的尺寸
if hasattr(world, 'setQtWidget'):
    world.setQtWidget(self)
```

### 3. 修改所有屏幕坐标计算

将所有使用`self.win.getXSize()`和`self.win.getYSize()`的地方改为使用新的`getWindowSize()`方法：

#### 修改前：
```python
win_x = (screen_pos.getX() + 1.0) * 0.5 * self.win.getXSize()
win_y = (1.0 - screen_pos.getY()) * 0.5 * self.win.getYSize()
```

#### 修改后：
```python
# 获取准确的窗口尺寸
win_width, win_height = self.getWindowSize()

win_x = (screen_pos.getX() + 1.0) * 0.5 * win_width
win_y = (1.0 - screen_pos.getY()) * 0.5 * win_height
```

### 4. 修改的关键方法

1. `checkGizmoClick()` - 坐标轴点击检测的主方法
2. `updateGizmoHighlight()` - 坐标轴悬停高亮
3. `updateGizmoDrag()` - 坐标轴拖拽更新
4. `mousePressEventLeft()` - 鼠标点击事件处理
5. `mouseMoveEvent()` - 鼠标移动事件处理
6. `checkGizmoClickFallback()` - 备用点击检测方法

## 技术原理

### 屏幕空间投影算法

坐标轴点击检测使用以下步骤：

1. **世界坐标 → 相机坐标**：
   ```python
   cam_space_pos = self.cam.getRelativePoint(self.render, world_pos)
   ```

2. **相机坐标 → 标准化屏幕坐标**：
   ```python
   screen_pos = Point2()
   self.cam.node().getLens().project(cam_space_pos, screen_pos)
   ```

3. **标准化坐标 → 像素坐标**：
   ```python
   win_x = (screen_pos.getX() + 1.0) * 0.5 * win_width
   win_y = (1.0 - screen_pos.getY()) * 0.5 * win_height
   ```

4. **点到线段距离计算**：
   ```python
   distance = self.distanceToLine((mouse_x, mouse_y), center_screen, axis_screen)
   ```

### 窗口尺寸差异的影响

如果窗口尺寸不准确：
- 步骤3中的像素坐标计算错误
- 坐标轴在屏幕上的投影位置计算错误
- 鼠标点击位置与计算出的轴位置不匹配
- 导致点击检测失败

## 测试验证

创建了测试脚本`demo/test_size_fix.py`来验证修复效果：
- 对比Qt部件尺寸和Panda3D窗口尺寸
- 实时监控尺寸变化
- 验证`getWindowSize()`方法的正确性

## 预期效果

修复后的坐标轴系统应该：
1. ✅ 鼠标悬停时正确高亮对应的轴（红色X轴、绿色Y轴、蓝色Z轴变为黄色）
2. ✅ 点击坐标轴能够正确开始拖拽
3. ✅ 拖拽时只沿选定轴方向移动物体
4. ✅ 松开鼠标时正确结束拖拽

## 兼容性

修复方案完全向后兼容：
- 如果没有Qt环境，自动回退到使用Panda3D窗口尺寸
- 如果Qt部件引用未设置，使用备用方案
- 不影响独立的ShowBase应用程序 