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

"""
FBX模型导入测试 - 演示新的缩放处理选项

修复内容：
1. 默认保持模型原有缩放结构
2. 提供可选的单位转换功能  
3. 智能缩放标准化（处理子节点大缩放值）
4. 避免缩放层级混乱问题

使用说明：
1. 运行脚本启动3D编辑器
2. 通过文件菜单或拖拽导入FBX模型
3. 观察模型的缩放层级结构
4. 按U键切换单位转换模式
5. 按N键切换缩放标准化模式
"""

import sys
import os

# 添加主目录到Python路径
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))

from main import MyWorld
from ui.main_window import setup_main_window
from PyQt5.QtCore import Qt


def setup_fbx_import_demo():
    """设置FBX导入演示"""
    
    # 创建世界对象
    world = MyWorld()
    
    # 使用新的UI模块创建主窗口
    app, main_window = setup_main_window(world)
    
    # 设置窗口标题
    main_window.setWindowTitle("FBX导入测试 - 缩放层级修复")
    
    # 设置焦点策略
    main_window.setFocusPolicy(Qt.StrongFocus)
    main_window.setFocus()
    
    # 导入选项
    unit_conversion_enabled = False
    scale_normalization_enabled = True  # 默认开启缩放标准化
    
    def keyPressEvent(event):
        nonlocal unit_conversion_enabled, scale_normalization_enabled
        key = event.key()
        
        if key == Qt.Key_U:  # U键切换单位转换模式
            unit_conversion_enabled = not unit_conversion_enabled
            status = "开启" if unit_conversion_enabled else "关闭"
            print(f"\n=== 单位转换模式已{status} ===")
            print("下次导入FBX文件时将使用此设置")
            event.accept()
            return
        elif key == Qt.Key_N:  # N键切换缩放标准化模式
            scale_normalization_enabled = not scale_normalization_enabled
            status = "开启" if scale_normalization_enabled else "关闭"
            print(f"\n=== 缩放标准化模式已{status} ===")
            print("下次导入FBX文件时将使用此设置")
            event.accept()
            return
        elif key == Qt.Key_I:  # I键显示导入信息
            print_import_info(world)
            event.accept()
            return
        elif key == Qt.Key_R:  # R键切换射线显示
            state = world.toggleRayDisplay()
            status = "开启" if state else "关闭"
            print(f"\n=== 射线显示已{status} ===")
            event.accept()
            return
        elif key == Qt.Key_S:  # S键显示当前设置
            print_current_settings(unit_conversion_enabled, scale_normalization_enabled)
            event.accept()
            return
        
        # 调用原始键盘事件处理
        if hasattr(main_window, '_original_keyPressEvent'):
            main_window._original_keyPressEvent(event)
        else:
            event.ignore()
    
    # 覆盖importModel方法以使用当前的导入设置
    original_import = world.scene_manager.importModel
    
    def enhanced_import(filepath):
        """增强的导入方法，使用当前导入设置"""
        print(f"\n" + "="*60)
        print(f"导入模型: {os.path.basename(filepath)}")
        print(f"单位转换: {'开启' if unit_conversion_enabled else '关闭'}")
        print(f"缩放标准化: {'开启' if scale_normalization_enabled else '关闭'}")
        print("="*60)
        
        result = original_import(
            filepath, 
            apply_unit_conversion=unit_conversion_enabled,
            normalize_scales=scale_normalization_enabled
        )
        
        if result:
            print("\n导入后的模型结构:")
            print_model_structure(result, max_depth=3, world=world)  # 限制显示深度
        
        return result
    
    world.scene_manager.importModel = enhanced_import
    
    # 保存原始键盘事件处理器
    if hasattr(main_window, 'keyPressEvent'):
        main_window._original_keyPressEvent = main_window.keyPressEvent
    main_window.keyPressEvent = keyPressEvent
    
    # 添加自定义菜单
    add_custom_menus(main_window, world, unit_conversion_enabled, scale_normalization_enabled)
    
    # 输出使用说明
    print_usage_instructions()
    
    return app, main_window, world


def add_custom_menus(main_window, world, unit_conversion_enabled, scale_normalization_enabled):
    """添加自定义菜单选项"""
    # 添加FBX测试菜单
    fbx_menu = main_window.menuBar().addMenu('FBX测试')
    
    # 切换单位转换
    toggle_unit_action = fbx_menu.addAction('切换单位转换 (U)')
    toggle_unit_action.triggered.connect(lambda: toggle_unit_conversion())
    
    # 切换缩放标准化
    toggle_scale_action = fbx_menu.addAction('切换缩放标准化 (N)')
    toggle_scale_action.triggered.connect(lambda: toggle_scale_normalization())
    
    fbx_menu.addSeparator()
    
    # 显示当前设置
    settings_action = fbx_menu.addAction('显示当前设置 (S)')
    settings_action.triggered.connect(lambda: print_current_settings(unit_conversion_enabled, scale_normalization_enabled))
    
    # 显示导入信息
    info_action = fbx_menu.addAction('显示导入信息 (I)')
    info_action.triggered.connect(lambda: print_import_info(world))
    
    # 射线显示切换
    ray_action = fbx_menu.addAction('切换射线显示 (R)')
    ray_action.triggered.connect(lambda: world.toggleRayDisplay())
    
    fbx_menu.addSeparator()
    
    # 手动标准化当前模型
    normalize_action = fbx_menu.addAction('手动标准化当前模型缩放')
    normalize_action.triggered.connect(lambda: manual_normalize_current_models(world))
    
    # 重置所有模型缩放
    reset_action = fbx_menu.addAction('重置所有模型缩放为1.0')
    reset_action.triggered.connect(lambda: reset_all_model_scales(world))
    
    def toggle_unit_conversion():
        nonlocal unit_conversion_enabled
        unit_conversion_enabled = not unit_conversion_enabled
        status = "开启" if unit_conversion_enabled else "关闭"
        print(f"\n=== 单位转换模式已{status} ===")
    
    def toggle_scale_normalization():
        nonlocal scale_normalization_enabled
        scale_normalization_enabled = not scale_normalization_enabled
        status = "开启" if scale_normalization_enabled else "关闭"
        print(f"\n=== 缩放标准化模式已{status} ===")


def print_model_structure(model, depth=0, max_depth=5, world=None):
    """打印模型的层级结构、缩放和位置信息"""
    if depth > max_depth:
        return
        
    indent = "  " * depth
    scale = model.getScale()
    local_pos = model.getPos()
    
    # 如果有world引用，显示世界位置
    if world:
        world_pos = model.getPos(world.render)
        pos_info = f"本地{local_pos} / 世界{world_pos}"
    else:
        pos_info = f"{local_pos}"
    
    # 计算最大缩放分量
    max_scale = max(abs(scale.x), abs(scale.y), abs(scale.z))
    scale_status = "🔴大" if max_scale > 10 else "🟢正常"
    
    print(f"{indent}📦 {model.getName()}")
    print(f"{indent}   缩放: {scale} {scale_status}")
    print(f"{indent}   位置: {pos_info}")
    print(f"{indent}   类型: {model.node().__class__.__name__}")
    
    # 递归打印重要子节点（限制数量避免输出过多）
    child_count = model.getNumChildren()
    max_children_to_show = 3 if depth == 0 else 2
    
    for i in range(min(child_count, max_children_to_show)):
        child = model.getChild(i)
        print_model_structure(child, depth + 1, max_depth, world)
    
    if child_count > max_children_to_show:
        print(f"{indent}  ... 还有 {child_count - max_children_to_show} 个子节点")


def print_import_info(world):
    """打印当前导入的模型信息"""
    print("\n" + "="*60)
    print("🔍 当前场景中的模型信息")
    print("="*60)
    
    if not world.models:
        print("❌ 场景中没有模型")
        return
    
    for i, model in enumerate(world.models):
        print(f"\n📦 模型 {i+1}: {model.getName()}")
        print(f"   文件: {model.getTag('file') if model.hasTag('file') else '未知'}")
        print(f"   单位转换: {'✅是' if model.hasTag('unit_conversion_applied') else '❌否'}")
        print(f"   缩放标准化: {'✅是' if model.hasTag('scale_normalization_applied') else '❌否'}")
        print(f"   根节点位置: {model.getPos()}")
        print(f"   根节点缩放: {model.getScale()}")
        print(f"   子节点数量: {model.getNumChildren()}")
        
        # 检查子节点的缩放情况
        large_scale_children = 0
        if model.getNumChildren() > 0:
            print("   📋 子节点缩放概况:")
            for j in range(min(5, model.getNumChildren())):  # 只检查前5个子节点
                child = model.getChild(j)
                child_scale = child.getScale()
                max_scale = max(abs(child_scale.x), abs(child_scale.y), abs(child_scale.z))
                
                if max_scale > 10:
                    large_scale_children += 1
                    status = "🔴大缩放"
                else:
                    status = "🟢正常"
                
                print(f"     {child.getName()}: {child_scale} {status}")
            
            if model.getNumChildren() > 5:
                print(f"     ... 还有 {model.getNumChildren() - 5} 个子节点")
            
            if large_scale_children > 0:
                print(f"   ⚠️  发现 {large_scale_children} 个子节点有大缩放值")
    
    print("="*60)


def print_current_settings(unit_conversion_enabled, scale_normalization_enabled):
    """显示当前导入设置"""
    print("\n" + "="*40)
    print("⚙️  当前FBX导入设置")
    print("="*40)
    print(f"单位转换 (U键): {'🟢开启' if unit_conversion_enabled else '🔴关闭'}")
    print(f"缩放标准化 (N键): {'🟢开启' if scale_normalization_enabled else '🔴关闭'}")
    print("\n说明:")
    print("• 单位转换: 将FBX的厘米单位转换为米")
    print("• 缩放标准化: 自动处理子节点的大缩放值(如100)")
    print("="*40)


def manual_normalize_current_models(world):
    """手动标准化当前所有模型的缩放"""
    print("\n🔧 手动标准化所有模型缩放...")
    
    if not world.models:
        print("❌ 没有模型需要处理")
        return
    
    for model in world.models:
        print(f"\n处理模型: {model.getName()}")
        world.scene_manager._normalizeModelScales(model)
    
    print("✅ 手动标准化完成")


def reset_all_model_scales(world):
    """重置所有模型的缩放为1.0（调试用）"""
    print("\n🔄 重置所有模型缩放为1.0...")
    
    count = 0
    for model in world.models:
        # 递归重置所有节点
        reset_node_scale_recursive(model)
        count += 1
    
    print(f"✅ 已重置 {count} 个模型的所有节点缩放")


def reset_node_scale_recursive(node, depth=0):
    """递归重置节点缩放"""
    indent = "  " * depth
    node.setScale(1.0, 1.0, 1.0)
    print(f"{indent}重置 {node.getName()}")
    
    for i in range(node.getNumChildren()):
        child = node.getChild(i)
        reset_node_scale_recursive(child, depth + 1)


def print_usage_instructions():
    """打印使用说明"""
    print("\n" + "="*60)
    print("🚀 FBX导入测试启动完成！")
    print("="*60)
    print("🎯 主要改进：")
    print("✅ 智能缩放标准化 - 自动处理子节点大缩放值")
    print("✅ 保持模型原有缩放结构")  
    print("✅ 避免根节点0.01 + 子节点100的复杂层级")
    print("✅ 缩放时保持世界位置不变 - 修复位置偏移问题")
    print("✅ 提供灵活的导入选项")
    print("")
    print("⌨️  键盘快捷键：")
    print("• U键 - 切换单位转换模式")
    print("• N键 - 切换缩放标准化模式")
    print("• S键 - 显示当前设置")
    print("• I键 - 显示模型信息")
    print("• R键 - 切换射线显示")
    print("")
    print("📁 导入方式：")
    print("• 拖拽FBX文件到3D场景")
    print("• 使用菜单 [文件] -> [导入模型]")
    print("• 使用菜单 [FBX测试] 查看更多选项")
    print("")
    print("🎛️  缩放处理模式：")
    print("• 关闭单位转换 + 开启缩放标准化（推荐）")
    print("  → 保持FBX结构，但标准化大缩放值")
    print("• 开启单位转换 + 关闭缩放标准化")  
    print("  → 传统方式，应用0.01根缩放")
    print("• 两者都关闭")
    print("  → 完全保持原始FBX结构")
    print("")
    print("📊 当前设置：")
    print("• 单位转换: 🔴关闭")
    print("• 缩放标准化: 🟢开启 (推荐)")
    print("="*60)


if __name__ == "__main__":
    try:
        app, main_window, world = setup_fbx_import_demo()
        
        # 启动应用程序
        sys.exit(app.exec_())
        
    except Exception as e:
        print(f"❌ 启动失败: {str(e)}")
        import traceback
        traceback.print_exc() 