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

"""
Qt环境GUI事件修复测试
解决Qt集成环境中DirectGUI事件处理问题
"""

import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QLabel
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QMouseEvent
from QMeta3D.QMeta3DWidget import QMeta3DWidget
from QMeta3D.Meta3DWorld import Meta3DWorld
from direct.gui.DirectGui import *
from direct.gui.OnscreenText import OnscreenText
from panda3d.core import *

class QtGUIFixWorld(Meta3DWorld):
    def __init__(self):
        super().__init__()
        
        print("=== Qt GUI事件修复测试 ===")
        self.setBackgroundColor(0.2, 0.2, 0.3)
        
        # 检查环境
        print(f"窗口类型: {type(self.win)}")
        print(f"图形引擎: {self.graphicsEngine}")
        
        # 延迟创建GUI
        self.taskMgr.doMethodLater(0.5, self.createTestGUI, "create-gui")
        
        # 保存GUI元素引用用于事件处理
        self.gui_elements = []
    
    def createTestGUI(self, task=None):
        """创建测试GUI"""
        print("\n--- 创建Qt环境GUI ---")
        
        # 方法1: 标准DirectGUI创建
        try:
            self.title = OnscreenText(
                text="Qt环境GUI测试",
                pos=(0, 0.8),
                scale=0.08,
                fg=(1, 1, 1, 1),
                align=TextNode.ACenter
            )
            print(f"✓ 标题创建成功: {self.title}")
        except Exception as e:
            print(f"❌ 标题创建失败: {str(e)}")
        
        # 测试按钮1 - 标准创建
        try:
            self.button1 = DirectButton(
                text="标准按钮",
                pos=(0, 0, 0.4),
                scale=0.1,
                frameColor=(0, 1, 0, 1),
                command=self.onButton1Click
            )
            self.gui_elements.append(('button1', self.button1))
            print(f"✓ 标准按钮创建成功: {self.button1}")
        except Exception as e:
            print(f"❌ 标准按钮创建失败: {str(e)}")
        
        # 测试按钮2 - 手动事件处理
        try:
            self.button2 = DirectButton(
                text="修复按钮",
                pos=(0, 0, 0.1),
                scale=0.1,
                frameColor=(1, 0, 0, 1),
                command=self.onButton2Click
            )
            
            # 手动设置事件处理
            self.setupManualEvents(self.button2)
            self.gui_elements.append(('button2', self.button2))
            print(f"✓ 修复按钮创建成功: {self.button2}")
        except Exception as e:
            print(f"❌ 修复按钮创建失败: {str(e)}")
        
        # 测试按钮3 - 自定义点击检测
        try:
            self.button3 = DirectButton(
                text="自检按钮",
                pos=(0, 0, -0.2),
                scale=0.1,
                frameColor=(0, 0, 1, 1),
                # 不设置command，使用自定义检测
            )
            self.gui_elements.append(('button3', self.button3))
            print(f"✓ 自检按钮创建成功: {self.button3}")
            
            # 启动自定义点击检测
            self.taskMgr.add(self.checkButtonClicks, "check-clicks")
            
        except Exception as e:
            print(f"❌ 自检按钮创建失败: {str(e)}")
        
        return task.done if task else None
    
    def setupManualEvents(self, button):
        """为按钮设置手动事件处理"""
        try:
            # 获取按钮的PGItem
            if hasattr(button, 'guiItem'):
                pgItem = button.guiItem
                # 强制启用事件
                pgItem.setActive(True)
                print(f"  手动启用按钮事件: {pgItem}")
        except Exception as e:
            print(f"  手动事件设置失败: {str(e)}")
    
    def checkButtonClicks(self, task):
        """自定义按钮点击检测"""
        # 检查鼠标状态
        if hasattr(self, 'mouseWatcherNode') and self.mouseWatcherNode.hasMouse():
            # 获取鼠标位置
            mouseX = self.mouseWatcherNode.getMouseX()
            mouseY = self.mouseWatcherNode.getMouseY()
            
            # 检查是否在button3范围内
            if hasattr(self, 'button3'):
                buttonPos = self.button3.getPos()
                buttonScale = self.button3.getScale()
                
                # 简单的边界检测
                if (abs(mouseX - buttonPos.getX()) < buttonScale.getX() * 0.5 and
                    abs(mouseY - buttonPos.getZ()) < buttonScale.getZ() * 0.5):
                    
                    # 检查是否有鼠标点击
                    if self.mouseWatcherNode.isButtonDown('button1'):
                        self.onButton3Click()
                        # 防止重复触发
                        return task.pause(0.5)
        
        return task.cont
    
    def onButton1Click(self):
        """标准按钮点击"""
        print("🟢 标准按钮被点击！")
    
    def onButton2Click(self):
        """修复按钮点击"""
        print("🔴 修复按钮被点击！")
    
    def onButton3Click(self):
        """自检按钮点击"""
        print("🔵 自检按钮被点击！")
    
    def handleQtMouseEvent(self, event):
        """处理Qt鼠标事件"""
        try:
            # 将Qt事件转换为Panda3D坐标
            if hasattr(self, 'win'):
                winX = event.x()
                winY = event.y()
                winWidth = self.win.getXSize()
                winHeight = self.win.getYSize()
                
                # 转换为归一化坐标 (-1 到 1)
                normalizedX = (winX / winWidth) * 2.0 - 1.0
                normalizedY = 1.0 - (winY / winHeight) * 2.0
                
                print(f"Qt鼠标事件: ({winX}, {winY}) -> 归一化: ({normalizedX:.3f}, {normalizedY:.3f})")
                
                # 手动检查GUI元素
                for name, element in self.gui_elements:
                    if hasattr(element, 'getPos'):
                        elemPos = element.getPos()
                        elemScale = element.getScale()
                        
                        # 简单边界检测
                        if (abs(normalizedX - elemPos.getX()) < elemScale.getX() * 0.5 and
                            abs(normalizedY - elemPos.getZ()) < elemScale.getZ() * 0.5):
                            print(f"  点击在 {name} 范围内！")
                            
                            # 手动触发回调
                            if name == 'button1':
                                self.onButton1Click()
                            elif name == 'button2':
                                self.onButton2Click()
                            elif name == 'button3':
                                self.onButton3Click()
                            
                            return True
                            
        except Exception as e:
            print(f"Qt事件处理失败: {str(e)}")
        return False

class CustomQMeta3DWidget(QMeta3DWidget):
    """自定义QPanda3DWidget，支持事件转发"""
    def __init__(self, world, parent=None):
        super().__init__(world, parent)
        self.world = world
        print("自定义QPanda3D部件初始化")
    
    def mousePressEvent(self, event):
        """重写鼠标按下事件"""
        print(f"\n=== Qt鼠标按下事件 ===")
        print(f"位置: ({event.x()}, {event.y()})")
        print(f"按钮: {event.button()}")
        
        # 尝试让世界处理事件
        if hasattr(self.world, 'handleQtMouseEvent'):
            handled = self.world.handleQtMouseEvent(event)
            if handled:
                print("事件已被世界处理")
                return
        
        # 调用父类方法
        super().mousePressEvent(event)

def main():
    print("启动Qt环境GUI事件修复测试...")
    
    app = QApplication(sys.argv)
    
    # 创建主窗口
    mainWindow = QMainWindow()
    mainWindow.setWindowTitle("Qt GUI事件修复测试")
    mainWindow.setGeometry(100, 100, 800, 600)
    
    # 创建布局
    centralWidget = QWidget()
    layout = QVBoxLayout(centralWidget)
    
    # 添加说明
    label = QLabel("Qt环境DirectGUI事件修复测试")
    label.setAlignment(Qt.AlignCenter)
    label.setStyleSheet("background-color: lightgreen; padding: 10px;")
    layout.addWidget(label)
    
    # 创建世界
    world = QtGUIFixWorld()
    
    # 创建自定义Panda3D部件
    pandaWidget = CustomQMeta3DWidget(world)
    layout.addWidget(pandaWidget)
    
    mainWindow.setCentralWidget(centralWidget)
    mainWindow.show()
    
    print("\n测试说明:")
    print("绿色按钮: 标准DirectGUI事件处理")
    print("红色按钮: 手动事件修复")
    print("蓝色按钮: 自定义点击检测")
    print("查看控制台输出了解事件处理情况")
    
    return app.exec_()

if __name__ == "__main__":
    main() 