1
0
forked from Rowland/EG

聚焦功能

This commit is contained in:
Hector 2025-09-18 10:55:06 +08:00
parent bd9fa08cb6
commit 7a621a3a51
5 changed files with 140 additions and 95 deletions

View File

@ -457,36 +457,36 @@ class EventHandler:
# 更新选择状态并显示选择框和坐标轴
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)}")
# 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("× 树形控件不存在")
# 在树形控件中查找并选中对应的项
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

@ -1021,7 +1021,7 @@ class SelectionSystem:
)
mat.setBaseColor(adjusted_color)
mat.setEmission(Vec4(1, 1, 1, 1.0)) # 自发光
#mat.setEmission(Vec4(1, 1, 1, 1.0)) # 自发光
# 应用材质
handle_node.setMaterial(mat, 1)

View File

@ -11,8 +11,8 @@ import os
from PyQt5.QtCore import Qt
from panda3d.core import (
ModelPool, ModelRoot, Filename, NodePath, GeomNode, Material, Vec4, Vec3,
MaterialAttrib, ColorAttrib, Point3, CollisionNode, CollisionSphere,
BitMask32, TransparencyAttrib,LColor
MaterialAttrib, ColorAttrib, Point3, CollisionNode, CollisionSphere,
BitMask32, TransparencyAttrib, LColor, TransformState
)
import json
import aiohttp
@ -141,11 +141,7 @@ class SceneManager:
print("加载模型失败")
return None
# 验证并修复模型变换矩阵(在任何操作之前)
#
self._validateAndFixAllTransforms(model)
self._fixModelStructure(model)
# 设置模型名称
model_name = os.path.basename(filepath)
@ -238,11 +234,11 @@ class SceneManager:
print(f"导入模型失败: {str(e)}")
return None
def _fixModelStructure(self,model):
def _fixModelStructure(self, model):
"""修复模型结构"""
try:
from panda3d.core import CharacterNode,AnimBundleNode
character_nodes = model.findAllMatches("**/+CharacterNode")
# 使用正确的方式查找动画相关节点
character_nodes = model.findAllMatches("**/+Character")
anim_bundle_nodes = model.findAllMatches("**/+AnimBundleNode")
if character_nodes.getNumPaths() > 0 or anim_bundle_nodes.getNumPaths() > 0:
@ -252,65 +248,103 @@ class SceneManager:
if anim_bundle_nodes.getNumPaths() > 0:
print(f"AnimBundleNode数量: {anim_bundle_nodes.getNumPaths()}")
model.setTag("fixed_structure","true")
model.setTag("fixed_structure", "true")
return True
except Exception as e:
print(f"修复模型结构时出错{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()
fixed_count = 0
# 检查位置
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 not self._validateAndFixTransform(model):
fixed_count += 1
# 检查旋转
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)
# 递归处理所有子节点
def process_children(node, depth=0):
nonlocal fixed_count
for i in range(node.getNumChildren()):
try:
child = node.getChild(i)
if not self._validateAndFixTransform(child):
fixed_count += 1
# 递归处理孙节点
process_children(child, depth + 1)
except Exception as e:
print(f"处理子节点时出错 (深度 {depth}): {e}")
continue
# 检查缩放
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)
process_children(model)
# 检查过大值
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)
if fixed_count > 0:
print(f"共修复了 {fixed_count} 个节点的变换")
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)
return True
except Exception as e:
print(f"验证所有变换时出错: {e}")
return False
except Exception as e:
print(f"{indent}修复节点变换时出错 {node_path.getName()}: {e}")
def _validateAndFixTransform(self, node_path):
"""验证并修复单个节点的变换矩阵"""
try:
node_name = node_path.getName()
# 递归处理子节点
for child in node_path.getChildren():
fix_node_transform(child, depth + 1)
# 获取当前变换状态
original_pos = node_path.getPos()
original_hpr = node_path.getHpr()
original_scale = node_path.getScale()
# 从模型根节点开始修复
fix_node_transform(model)
print(f"✓ 完成模型 {model.getName()} 的变换验证和修复")
# 检查位置是否包含无效值
if not original_pos.isFinite():
print(f"警告: 节点 {node_name} 位置包含无效值 {original_pos},重置为 (0,0,0)")
node_path.setPos(0, 0, 0)
return False
# 检查旋转是否包含无效值
if not original_hpr.isFinite():
print(f"警告: 节点 {node_name} 旋转包含无效值 {original_hpr},重置为 (0,0,0)")
node_path.setHpr(0, 0, 0)
return False
# 检查缩放是否包含无效值或为零
if not original_scale.isFinite():
print(f"警告: 节点 {node_name} 缩放包含无效值 {original_scale},重置为 (1,1,1)")
node_path.setScale(1, 1, 1)
return False
# 检查缩放是否为零或接近零
min_scale = 1e-10
if (abs(original_scale.x) < min_scale or
abs(original_scale.y) < min_scale or
abs(original_scale.z) < min_scale):
print(f"警告: 节点 {node_name} 缩放接近零 {original_scale},重置为 (1,1,1)")
node_path.setScale(1, 1, 1)
return False
# 检查缩放是否过大(防止异常大的缩放)
max_scale = 1000000 # 100万倍作为上限
if (abs(original_scale.x) > max_scale or
abs(original_scale.y) > max_scale or
abs(original_scale.z) > max_scale):
print(f"警告: 节点 {node_name} 缩放过异常 {original_scale},重置为 (1,1,1)")
node_path.setScale(1, 1, 1)
return False
return True
except Exception as e:
print(f"验证和修复模型变换时出错: {e}")
print(f"验证/修复节点 {node_path.getName()} 变换时出错: {e}")
# 只在出现严重错误时才重置变换
try:
node_path.setPos(0, 0, 0)
node_path.setHpr(0, 0, 0)
node_path.setScale(1, 1, 1)
except:
pass
return False
def _applyModelScale(self, model, scale_factor):
"""应用模型特定缩放
@ -523,6 +557,18 @@ class SceneManager:
# 应用缩放
model.setScale(scale_factor)
# 应用缩放(添加异常处理)
try:
model.setScale(scale_factor)
except Exception as e:
print(f"直接设置缩放失败: {e},尝试使用变换状态")
try:
model.setTransform(TransformState.makeScale(scale_factor))
except Exception as e2:
print(f"使用变换状态设置缩放也失败: {e2}")
# 应用缩放后验证变换
self._validateAndFixTransform(model)
# 重新调整位置(因为缩放会影响边界)
if original_bounds and not original_bounds.isEmpty():
new_bounds = model.getBounds()
@ -1504,7 +1550,7 @@ class SceneManager:
if nodePath.hasTag("is_model_root"):
print(f"J{indent}处理模型节点{nodePath.getName()}")
self._validateAndFixAllTransforms(nodePath)
#self._validateAndFixAllTransforms(nodePath)
self._fixModelStructure(nodePath)

View File

@ -18,7 +18,6 @@ class InterfaceManager:
"""设置树形控件引用并更新场景树"""
self.treeWidget = treeWidget
# 添加右键菜单
# self.treeWidget.setContextMenuPolicy(Qt.CustomContextMenu)
# self.treeWidget.customContextMenuRequested.connect(self.showTreeContextMenu)

View File

@ -4756,12 +4756,12 @@ class PropertyPanelManager:
if geom_node:
geom_node_name = geom_node.getName()
unique_name = f"{geom_node_name}({model_name})"
print(f"材质 {i}: 使用几何节点名称 '{geom_node_name}'")
#print(f"材质 {i}: 使用几何节点名称 '{geom_node_name}'")
else:
material_name = material.get_name() if hasattr(material,
'get_name') and material.get_name() else f"材质{i + 1}"
unique_name = f"{material_name}({model_name})"
print(f"材质 {i}: 未找到几何节点,使用材质名称 '{material_name}'")
#print(f"材质 {i}: 未找到几何节点,使用材质名称 '{material_name}'")
# 处理重复名称
if unique_name in name_counter:
@ -4800,7 +4800,7 @@ class PropertyPanelManager:
# 基础颜色编辑
base_color = self._getOrCreateMaterialBaseColor(material)
if base_color is not None:
print(f"材质基础颜色: {base_color}")
#print(f"材质基础颜色: {base_color}")
# 基础颜色标题
color_row = 2 if material_status != "标准PBR材质" else 1
@ -5186,7 +5186,7 @@ class PropertyPanelManager:
try:
# 方法1: 尝试获取base_color属性
if hasattr(material, 'base_color') and material.base_color is not None:
print(f"✓ 找到base_color属性: {material.base_color}")
#print(f"✓ 找到base_color属性: {material.base_color}")
return material.base_color
# 方法2: 尝试调用get_base_color方法
@ -5204,7 +5204,7 @@ class PropertyPanelManager:
try:
diffuse_color = material.getDiffuse()
if diffuse_color is not None:
print(f"✓ 从diffuse颜色获取: {diffuse_color}")
#print(f"✓ 从diffuse颜色获取: {diffuse_color}")
# 同时设置为base_color
if hasattr(material, 'set_base_color'):
material.set_base_color(diffuse_color)
@ -6812,7 +6812,7 @@ class PropertyPanelManager:
# print(f"找到匹配的几何节点: {geom_np.get_name()}")
return geom_np
print("未找到匹配的几何节点")
#print("未找到匹配的几何节点")
return None
def _findSpecificGeomNodeForMaterial(self, target_material):
@ -8097,7 +8097,7 @@ class PropertyPanelManager:
format_info = self._getModelFormat(origin_model)
processed = []
print(f"[动画分析] 格式: {format_info}, 原始动画名称: {anim_names}")
#print(f"[动画分析] 格式: {format_info}, 原始动画名称: {anim_names}")
for name in anim_names:
display_name = name
@ -8131,7 +8131,7 @@ class PropertyPanelManager:
display_name = name
processed.append((display_name, original_name))
print(f"[动画分析] {original_name}{display_name}")
#print(f"[动画分析] {original_name} → {display_name}")
return processed
@ -8165,7 +8165,7 @@ class PropertyPanelManager:
if frames > 1:
valid_anims += 1
total_frames += frames
print(f"[动画分析] '{anim_name}': {frames}")
#print(f"[动画分析] '{anim_name}': {frames} 帧")
else:
print(f"[动画分析] '{anim_name}': 无有效帧数 ({frames})")
except Exception as e: