forked from Rowland/EG
249 lines
7.8 KiB
Python
249 lines
7.8 KiB
Python
#!/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() |