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

"""
测试脚本：验证子节点的选择框和坐标轴跟随父模型移动
"""

import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))

from main import MyWorld
from panda3d.core import Vec3, Point3, CardMaker, GeomNode
from direct.task.TaskManagerGlobal import taskMgr
import time

def getWorldCenter(nodePath, render):
    """获取节点在世界坐标系中的边界框中心"""
    minPoint = Point3()
    maxPoint = Point3()
    if nodePath.calcTightBounds(minPoint, maxPoint, render):
        return Point3((minPoint.x + maxPoint.x) * 0.5,
                     (minPoint.y + maxPoint.y) * 0.5,
                     (minPoint.z + maxPoint.z) * 0.5)
    return Point3(0, 0, 0)

def test_selection_follow():
    """测试子节点选择框和坐标轴跟随父模型移动"""
    print("=== 测试子节点选择框和坐标轴跟随 ===")
    
    # 创建世界
    world = MyWorld()
    
    # 创建主父节点
    parent = world.render.attachNewNode("parent_model")
    
    # 创建子节点1 - 一个简单的几何体
    cm1 = CardMaker("child1_card")
    cm1.setFrame(-1, 1, -1, 1)
    child1 = parent.attachNewNode(cm1.generate())
    child1.setName("child1")
    child1.setPos(2, 0, 0)  # 相对于父节点的位置
    child1.setColor(1, 0, 0, 1)  # 红色
    
    # 创建子节点2 - 另一个几何体
    cm2 = CardMaker("child2_card")
    cm2.setFrame(-0.5, 0.5, -0.5, 0.5)
    child2 = parent.attachNewNode(cm2.generate())
    child2.setName("child2")
    child2.setPos(-2, 0, 1)  # 相对于父节点的位置
    child2.setColor(0, 1, 0, 1)  # 绿色
    
    # 设置父节点的初始位置
    parent.setPos(0, 0, 0)
    
    # 将父节点添加到模型列表（这样它可以被选择）
    world.models.append(parent)
    world.models.append(child1)
    world.models.append(child2)
    
    print(f"创建了父节点: {parent.getName()}")
    print(f"创建了子节点1: {child1.getName()}, 位置: {child1.getPos()}")
    print(f"创建了子节点2: {child2.getName()}, 位置: {child2.getPos()}")
    
    # 选择子节点1
    print("\n--- 选择子节点1 ---")
    world.selection.updateSelection(child1)
    
    print(f"子节点1的相对边界框: {child1.getBounds()}")
    
    # 获取移动后的世界边界框
    minPoint = Point3()
    maxPoint = Point3()
    if child1.calcTightBounds(minPoint, maxPoint, world.render):
        print(f"子节点1的世界边界框: min={minPoint}, max={maxPoint}")
    else:
        print("子节点1无法计算世界边界框")
    
    # 移动父节点
    print("\n--- 移动父节点到新位置 ---")
    new_parent_pos = Vec3(5, 3, 2)
    parent.setPos(new_parent_pos)
    
    print(f"父节点新位置: {parent.getPos()}")
    print(f"子节点1的相对边界框: {child1.getBounds()}")
    
    # 获取移动后的世界边界框
    minPoint = Point3()
    maxPoint = Point3()
    if child1.calcTightBounds(minPoint, maxPoint, world.render):
        print(f"子节点1的世界边界框: min={minPoint}, max={maxPoint}")
    else:
        print("子节点1无法计算世界边界框")
    
    # 等待一帧，让更新任务运行
    def check_after_move(task):
        print("\n--- 检查移动后的状态 ---")
        
        # 检查选择框是否跟随
        if world.selection.selectionBox:
            # 获取选择框目标的世界边界框
            minPoint = Point3()
            maxPoint = Point3()
            if world.selection.selectionBoxTarget.calcTightBounds(minPoint, maxPoint, world.render):
                print(f"选择框目标的世界边界框: min={minPoint}, max={maxPoint}")
            print(f"选择框是否存在: {world.selection.selectionBox is not None}")
        
        # 检查坐标轴是否跟随
        if world.selection.gizmo:
            gizmo_pos = world.selection.gizmo.getPos()
            print(f"坐标轴位置: {gizmo_pos}")
            
            # 验证坐标轴是否在正确的位置
            expected_center = getWorldCenter(child1, world.render)
            print(f"期望的坐标轴位置: {expected_center}")
            
            # 计算位置差异
            diff = (gizmo_pos - expected_center).length()
            print(f"坐标轴位置差异: {diff}")
            
            if diff < 0.1:  # 允许小的浮点误差
                print("✓ 坐标轴正确跟随了父模型移动")
            else:
                print("✗ 坐标轴没有正确跟随父模型移动")
        
        # 再次移动父节点测试
        print("\n--- 再次移动父节点 ---")
        another_pos = Vec3(-3, -2, 1)
        parent.setPos(another_pos)
        print(f"父节点再次移动到: {another_pos}")
        
        # 等待另一帧
        def final_check(task):
            print("\n--- 最终检查 ---")
            if world.selection.gizmo:
                final_gizmo_pos = world.selection.gizmo.getPos()
                final_expected_center = getWorldCenter(child1, world.render)
                final_diff = (final_gizmo_pos - final_expected_center).length()
                
                print(f"最终坐标轴位置: {final_gizmo_pos}")
                print(f"最终期望位置: {final_expected_center}")
                print(f"最终位置差异: {final_diff}")
                
                if final_diff < 0.1:
                    print("✓ 测试通过：坐标轴正确跟随父模型移动")
                else:
                    print("✗ 测试失败：坐标轴没有正确跟随")
            
            # 测试选择其他子节点
            print("\n--- 测试选择子节点2 ---")
            world.selection.updateSelection(child2)
            
            def check_child2(task):
                if world.selection.gizmo:
                    child2_gizmo_pos = world.selection.gizmo.getPos()
                    child2_expected_center = getWorldCenter(child2, world.render)
                    child2_diff = (child2_gizmo_pos - child2_expected_center).length()
                    
                    print(f"子节点2坐标轴位置: {child2_gizmo_pos}")
                    print(f"子节点2期望位置: {child2_expected_center}")
                    print(f"子节点2位置差异: {child2_diff}")
                    
                    if child2_diff < 0.1:
                        print("✓ 子节点2坐标轴位置正确")
                    else:
                        print("✗ 子节点2坐标轴位置错误")
                
                print("\n=== 测试完成 ===")
                return task.done
            
            taskMgr.doMethodLater(0.1, check_child2, "check_child2")
            return task.done
        
        taskMgr.doMethodLater(0.1, final_check, "final_check")
        return task.done
    
    taskMgr.doMethodLater(0.1, check_after_move, "check_after_move")
    
    # 运行测试
    print("\n开始运行测试...")
    world.run()

if __name__ == "__main__":
    test_selection_follow() 