1
0
forked from Rowland/EG

聚焦功能

This commit is contained in:
Hector 2025-09-17 17:48:06 +08:00
parent 1c660c781a
commit 2a76703b89
5 changed files with 152 additions and 47 deletions

View File

@ -452,33 +452,41 @@ class EventHandler:
if selectedModel:
#print(f"✓ 最终选中模型: {selectedModel.getName()}")
self.world.selection.handleMouseClick(selectedModel)
# 更新选择状态并显示选择框和坐标轴
self.world.selection.updateSelection(selectedModel)
# 在树形控件中查找并选中对应的项
if self.world.interface_manager.treeWidget:
#print("查找树形控件中的对应项...")
root = self.world.interface_manager.treeWidget.invisibleRootItem()
foundItem = None
for i in range(root.childCount()):
sceneItem = root.child(i)
if sceneItem.text(0) == "场景":
#print(f"在场景节点下查找...")
foundItem = self.world.interface_manager.findTreeItem(selectedModel, sceneItem)
if foundItem:
print(f"✓ 在树形控件中找到对应项: {foundItem.text(0)}")
self.world.interface_manager.treeWidget.setCurrentItem(foundItem)
self.world.property_panel.updatePropertyPanel(foundItem)
else:
print("× 在树形控件中没有找到对应项")
break
if not foundItem:
print("× 没有找到场景节点或对应的树形项")
else:
print("× 树形控件不存在")
# # 在树形控件中查找并选中对应的项
# if self.world.interface_manager.treeWidget:
# #print("查找树形控件中的对应项...")
# root = self.world.interface_manager.treeWidget.invisibleRootItem()
# foundItem = None
#
# for i in range(root.childCount()):
# sceneItem = root.child(i)
# if sceneItem.text(0) == "场景":
# #print(f"在场景节点下查找...")
# foundItem = self.world.interface_manager.findTreeItem(selectedModel, sceneItem)
# if foundItem:
# print(f"✓ 在树形控件中找到对应项: {foundItem.text(0)}")
# try:
# self.world.interface_manager.treeWidget.itemClicked.disconnect()
# except TypeError:
# pass
#
# self.world.interface_manager.treeWidget.setCurrentItem(foundItem)
#
# self.world.interface_manager.treeWidget.itemClicked.connect(
# self.world.interface_manager.onTreeItemClicked)
# else:
# print("× 在树形控件中没有找到对应项")
# break
#
# if not foundItem:
# print("× 没有找到场景节点或对应的树形项")
# else:
# print("× 树形控件不存在")
else:
print("× 没有找到可选择的模型节点")
self.world.selection.updateSelection(None)

View File

@ -1228,10 +1228,10 @@ class SelectionSystem:
distance = self.distanceToLine(
(mouseX, mouseY), center_screen, axis_screen
)
print(f"{axis_label}距离: {distance:.2f}")
#print(f"{axis_label}距离: {distance:.2f}")
if distance < click_threshold:
print(f"✓ 点击了{axis_label}")
#print(f"✓ 点击了{axis_label}")
return axis_name
return None
@ -1930,8 +1930,10 @@ class SelectionSystem:
is_double_click = self.checkDoubleClick(nodePath)
if is_double_click:
print(f"检测到双击 {node_name},执行聚焦")
# 启动聚焦(在下一帧执行,确保选择状态已更新)
taskMgr.doMethodLater(0.01, self._delayedFocusTask, "delayedFocus")
# 双击时直接执行聚焦,不执行选择逻辑
self.focusCameraOnSelectedNodeAdvanced()
print("=== 选择状态更新完成 ===\n")
return # 直接返回,不执行下面的选择逻辑
self.selectedNode = nodePath
# 添加兼容性属性
@ -2596,19 +2598,22 @@ class SelectionSystem:
import time
current_time = time.time()
is_double_click = (self._last_clicked_node == nodePath and
current_time - self._last_click_time < self._double_click_threshold)
# 检查节点和时间
time_diff = current_time - self._last_click_time
is_same_node = (self._last_clicked_node == nodePath)
if is_double_click:
# 双击 detected重置状态
# 如果是同一节点且在时间阈值内,认为是双击
if is_same_node and time_diff < self._double_click_threshold:
# 只有在双击时才重置状态
self._last_click_time = 0
self._last_clicked_node = None
return True
else:
# 更新状态为单击
self._last_click_time = current_time
self._last_clicked_node = nodePath
return is_double_click
# 只有在非双击情况下才更新状态
if not is_same_node:
self._last_click_time = current_time
self._last_clicked_node = nodePath
return False
except Exception as e:
print(f"双击检测失败: {e}")

View File

@ -143,7 +143,9 @@ class SceneManager:
# 验证并修复模型变换矩阵(在任何操作之前)
#
#self._validateAndFixAllTransforms(model)
self._validateAndFixAllTransforms(model)
self._fixModelStructure(model)
# 设置模型名称
model_name = os.path.basename(filepath)
@ -153,14 +155,14 @@ class SceneManager:
model.setName(model_name)
# 使用安全方法将模型添加到场景
self._safeReparentTo(model, self.world.render)
#self._safeReparentTo(model, self.world.render)
# 设置模型名称
model_name = os.path.basename(filepath)
model.setName(model_name)
# 将模型添加到场景
#model.reparentTo(self.world.render)
model.reparentTo(self.world.render)
# 保存原始路径和转换后的路径
model.setTag("model_path", filepath)
model.setTag("original_path", original_filepath)
@ -236,6 +238,80 @@ class SceneManager:
print(f"导入模型失败: {str(e)}")
return None
def _fixModelStructure(self,model):
try:
from panda3d.core import CharacterNode,AnimBundleNode
character_nodes = model.findAllMatches("**/+CharacterNode")
anim_bundle_nodes = model.findAllMatches("**/+AnimBundleNode")
if character_nodes.getNumPaths() > 0 or anim_bundle_nodes.getNumPaths() > 0:
print(f"检测到模型{model.getName()}包含角色相节点:")
if character_nodes.getNumPaths() > 0:
print(f"CharacterNode数量{character_nodes.getNumPaths()}")
if anim_bundle_nodes.getNumPaths() > 0:
print(f"AnimBundleNode数量: {anim_bundle_nodes.getNumPaths()}")
model.setTag("fixed_structure","true")
return True
except Exception as e:
print(f"修复模型结构时出错{e}")
return False
def _validateAndFixAllTransforms(self, model):
"""验证并修复所有节点的变换矩阵"""
try:
def fix_node_transform(node_path, depth=0):
indent = " " * depth
try:
# 检查节点的变换矩阵是否有效
transform = node_path.getTransform()
if not transform.isInvalid():
# 检查是否有NaN或无穷大值
pos = node_path.getPos()
hpr = node_path.getHpr()
scale = node_path.getScale()
# 检查位置
if pos.x != pos.x or pos.y != pos.y or pos.z != pos.z: # NaN检查
print(f"{indent}修复NaN位置: {node_path.getName()}")
node_path.setPos(0, 0, 0)
# 检查旋转
if hpr.x != hpr.x or hpr.y != hpr.y or hpr.z != hpr.z: # NaN检查
print(f"{indent}修复NaN旋转: {node_path.getName()}")
node_path.setHpr(0, 0, 0)
# 检查缩放
if scale.x != scale.x or scale.y != scale.y or scale.z != scale.z: # NaN检查
print(f"{indent}修复NaN缩放: {node_path.getName()}")
node_path.setScale(1, 1, 1)
# 检查过大值
if abs(pos.x) > 1e10 or abs(pos.y) > 1e10 or abs(pos.z) > 1e10:
print(f"{indent}修复过大位置值: {node_path.getName()}")
node_path.setPos(0, 0, 0)
else:
print(f"{indent}检测到无效变换矩阵: {node_path.getName()}")
node_path.setPos(0, 0, 0)
node_path.setHpr(0, 0, 0)
node_path.setScale(1, 1, 1)
except Exception as e:
print(f"{indent}修复节点变换时出错 {node_path.getName()}: {e}")
# 递归处理子节点
for child in node_path.getChildren():
fix_node_transform(child, depth + 1)
# 从模型根节点开始修复
fix_node_transform(model)
print(f"✓ 完成模型 {model.getName()} 的变换验证和修复")
except Exception as e:
print(f"验证和修复模型变换时出错: {e}")
def _applyModelScale(self, model, scale_factor):
"""应用模型特定缩放
@ -652,6 +728,8 @@ class SceneManager:
def setupCollision(self, model):
"""为模型设置碰撞检测(增强版本)"""
try:
# 创建碰撞节点
cNode = CollisionNode(f'modelCollision_{model.getName()}')
@ -693,7 +771,7 @@ class SceneManager:
# 根据调试设置决定是否显示碰撞体
if hasattr(self.world, 'debug_collision') and self.world.debug_collision:
cNodePath.show()
cNodePath.hide()
else:
cNodePath.hide()
@ -1424,7 +1502,17 @@ class SceneManager:
# 为模型节点设置碰撞检测
if nodePath.hasTag("is_model_root"):
self.setupCollision(nodePath)
print(f"J{indent}处理模型节点{nodePath.getName()}")
self._validateAndFixAllTransforms(nodePath)
self._fixModelStructure(nodePath)
if self.world.property_panel._hasCollision(nodePath):
print(f"{indent}模型{nodePath.getName()}已有碰撞体,跳过碰撞体设置")
else:
print(f"{indent}为模型{nodePath.getName()}设置碰撞检测")
self.setupCollision(nodePath)
self.models.append(nodePath)
# 递归处理子节点
@ -1530,7 +1618,7 @@ class SceneManager:
tags = gui_info.get("tags", {})
text = gui_info.get("text", "")
image_path = gui_info.get("image_path", "")
video_path = gui_info.get("video_path","")
video_path = gui_info.get("video_path", "")
bg_image_path = gui_info.get("bg_image_path", "") # 背景图片路径
panel_id = gui_info.get("panel_id", name) # 信息面板ID
panel_data = gui_info.get("panel_data", None) # 面板数据

View File

@ -1921,7 +1921,7 @@ class MainWindow(QMainWindow):
main_window.addDockWidget(Qt.RightDockWidgetArea, browser_dock)
# 添加到GUI元素列表以便管理
self.gui_elements.append(browser_dock)
self.world.gui_elements.append(browser_dock)
print("✓ 网页浏览器视图已创建并集成到项目中")
return browser_dock

View File

@ -8936,13 +8936,17 @@ except Exception as e:
"""检查模型是否已有碰撞体"""
try:
from panda3d.core import CollisionNode
# if model.hasTag("has_collision") and model.getTag("has_collision") == "true":
# return True
# 检查模型及其子节点是否有碰撞节点
collision_nodes = model.findAllMatches("**/+CollisionNode")
has_collision = collision_nodes.getNumPaths() > 0
print(f"碰撞检查:模型 {model.getName()} - {'' if has_collision else ''}碰撞 (找到{collision_nodes.getNumPaths()}个碰撞节点)")
if has_collision:
print(f"检测到模型{model.getName()}已有{collision_nodes.getNumPaths()}个碰撞节点")
return has_collision
except Exception as e:
print(f"检查碰撞失败: {e}")