EG/demo/test_selection_follow.py
2025-07-10 09:19:51 +08:00

184 lines
6.9 KiB
Python

#!/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()