#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
选择功能测试 - 验证模型选择功能是否正常工作

测试内容：
1. 验证模型碰撞检测设置
2. 测试射线检测和选择功能
3. 验证选择框和坐标轴显示

控制说明：
- 鼠标左键：点击选择模型
- I键：显示当前选择信息
- C键：显示碰撞检测信息
- S键：切换碰撞体显示（调试用）
- R键：切换射线显示
- Q键：退出
"""

import sys
import os
sys.path.append('..')  # 添加父目录到路径

from direct.showbase.ShowBase import ShowBase
from panda3d.core import (CardMaker, Vec3, Point3, Material, 
                         ModelRoot, PandaNode, CollisionNode, CollisionSphere,
                         BitMask32)
from PyQt5.QtWidgets import QApplication

def create_test_models(world):
    """创建测试模型"""
    print("\n=== 创建测试模型 ===")
    
    # 创建几个简单的测试模型
    test_models = []
    
    positions = [
        (0, 0, 1),      # 中心
        (5, 0, 1),      # 右侧
        (-5, 0, 1),     # 左侧
        (0, 5, 1),      # 后方
    ]
    
    colors = [
        (1, 0, 0, 1),   # 红色
        (0, 1, 0, 1),   # 绿色
        (0, 0, 1, 1),   # 蓝色
        (1, 1, 0, 1),   # 黄色
    ]
    
    for i, (pos, color) in enumerate(zip(positions, colors)):
        # 创建立方体
        cm = CardMaker(f'test_cube_{i}')
        cm.setFrame(-1, 1, -1, 1)
        
        # 创建模型根节点
        model_root = world.render.attachNewNode(ModelRoot(f"TestCube_{i}"))
        
        # 创建6个面（简单立方体）
        faces = [
            # 前面和后面
            (0, 0, 1, 0, 0, 1),   # 前面 Z+
            (0, 0, -1, 0, 0, -1), # 后面 Z-
            # 左面和右面  
            (-1, 0, 0, 1, 0, 0),  # 左面 X-
            (1, 0, 0, -1, 0, 0),  # 右面 X+
            # 顶面和底面
            (0, 1, 0, 0, -1, 0),  # 顶面 Y+
            (0, -1, 0, 0, 1, 0),  # 底面 Y-
        ]
        
        for j, (x, y, z, nx, ny, nz) in enumerate(faces):
            face = model_root.attachNewNode(cm.generate())
            face.setPos(x, y, z)
            if nx != 0:  # X面
                face.setH(90 if nx > 0 else -90)
            elif ny != 0:  # Y面
                face.setP(90 if ny > 0 else -90)
            # Z面保持默认朝向
        
        # 设置位置和颜色
        model_root.setPos(*pos)
        model_root.setColor(*color)
        
        # 创建材质
        material = Material()
        material.setDiffuse(color)
        material.setAmbient((0.2, 0.2, 0.2, 1.0))
        material.setSpecular((0.5, 0.5, 0.5, 1.0))
        material.setShininess(32.0)
        model_root.setMaterial(material)
        
        # 设置标签
        model_root.setTag("file", f"TestCube_{i}")
        model_root.setTag("is_model_root", "1")
        
        # 添加到场景管理器
        world.scene_manager.models.append(model_root)
        test_models.append(model_root)
        
        print(f"✓ 创建测试立方体 {i}: 位置{pos}, 颜色{color[:3]}")
    
    # 为所有模型设置碰撞检测
    print("\n=== 设置碰撞检测 ===")
    for model in test_models:
        world.scene_manager.setupCollision(model)
        print(f"✓ 为 {model.getName()} 设置碰撞检测")
    
    # 更新场景树
    world.scene_manager.updateSceneTree()
    
    print("✓ 测试模型创建完成")
    return test_models

def show_collision_info(world):
    """显示碰撞检测信息"""
    print("\n=== 碰撞检测信息 ===")
    
    for i, model in enumerate(world.scene_manager.models):
        print(f"\n模型 {i+1}: {model.getName()}")
        print(f"位置: {model.getPos()}")
        print(f"边界: {model.getBounds()}")
        
        # 查找碰撞节点
        collision_nodes = []
        for child in model.getChildren():
            if isinstance(child.node(), CollisionNode):
                collision_nodes.append(child)
        
        if collision_nodes:
            print(f"碰撞节点数量: {len(collision_nodes)}")
            for j, cnode in enumerate(collision_nodes):
                cn = cnode.node()
                print(f"  碰撞节点 {j+1}: {cn.getName()}")
                print(f"    碰撞掩码: {cn.getIntoCollideMask()}")
                print(f"    碰撞体数量: {cn.getNumSolids()}")
                for k in range(cn.getNumSolids()):
                    solid = cn.getSolid(k)
                    print(f"      碰撞体 {k+1}: {solid.__class__.__name__}")
        else:
            print("❌ 没有碰撞节点")
    
    print("==================")

def show_selection_info(world):
    """显示当前选择信息"""
    print("\n=== 当前选择信息 ===")
    
    selected = world.selection.getSelectedNode()
    if selected:
        print(f"选中节点: {selected.getName()}")
        print(f"位置: {selected.getPos()}")
        print(f"缩放: {selected.getScale()}")
        print(f"有选择框: {bool(world.selection.selectionBox)}")
        print(f"有坐标轴: {bool(world.selection.gizmo)}")
    else:
        print("当前没有选中任何节点")
    
    print(f"当前工具: {world.currentTool}")
    print("=================")

def toggle_collision_display(world):
    """切换碰撞体显示"""
    print("\n=== 切换碰撞体显示 ===")
    
    count = 0
    for model in world.scene_manager.models:
        for child in model.getChildren():
            if isinstance(child.node(), CollisionNode):
                if child.isHidden():
                    child.show()
                    count += 1
                else:
                    child.hide()
    
    if count > 0:
        print(f"显示了 {count} 个碰撞体")
    else:
        print("隐藏了所有碰撞体")

class SelectionTest(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        
        # 导入我们的模块
        from main import MyWorld
        
        # 创建世界实例
        self.world = MyWorld()
        
        # 设置相机
        self.cam.setPos(0, -20, 10)
        self.cam.lookAt(0, 0, 0)
        
        # 创建测试模型
        self.test_models = create_test_models(self.world)
        
        # 设置键盘事件
        self.setupKeyEvents()
        
        print("\n=== 选择功能测试程序启动 ===")
        print("控制说明：")
        print("鼠标左键：点击选择模型")
        print("I键：显示当前选择信息")
        print("C键：显示碰撞检测信息")
        print("S键：切换碰撞体显示（调试用）")
        print("R键：切换射线显示")
        print("Q键：退出程序")
        print("================================")
        
        # 显示初始信息
        show_collision_info(self.world)
    
    def setupKeyEvents(self):
        """设置键盘事件"""
        self.accept('i', self.showSelectionInfo)
        self.accept('c', self.showCollisionInfo)
        self.accept('s', self.toggleCollisionDisplay)
        self.accept('r', self.toggleRayDisplay)
        self.accept('q', self.quit)
        self.accept('escape', self.quit)
    
    def showSelectionInfo(self):
        """显示选择信息"""
        show_selection_info(self.world)
    
    def showCollisionInfo(self):
        """显示碰撞信息"""
        show_collision_info(self.world)
    
    def toggleCollisionDisplay(self):
        """切换碰撞体显示"""
        toggle_collision_display(self.world)
    
    def toggleRayDisplay(self):
        """切换射线显示"""
        self.world.toggleRayDisplay()
        print(f"射线显示: {'开启' if self.world.getRayDisplay() else '关闭'}")
    
    def quit(self):
        """退出程序"""
        print("\n退出选择功能测试程序")
        sys.exit()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    test = SelectionTest()
    test.run() 