forked from Rowland/EG
实现打包功能
This commit is contained in:
parent
a66c097048
commit
c9abf0b698
@ -423,7 +423,7 @@ class GUIManager:
|
|||||||
|
|
||||||
entry = DirectEntry(
|
entry = DirectEntry(
|
||||||
text="",
|
text="",
|
||||||
pos=gui_pos,
|
pos=(pos[0],pos[1],pos[2]),
|
||||||
scale=size,
|
scale=size,
|
||||||
command=self.onGUIEntrySubmit,
|
command=self.onGUIEntrySubmit,
|
||||||
extraArgs=[f"entry_{len(self.gui_elements)}"],
|
extraArgs=[f"entry_{len(self.gui_elements)}"],
|
||||||
@ -431,6 +431,12 @@ class GUIManager:
|
|||||||
numLines=1,
|
numLines=1,
|
||||||
width=12,
|
width=12,
|
||||||
focus=0,
|
focus=0,
|
||||||
|
frameColor = (0,0,0,0),
|
||||||
|
text_fg=(1,1,1,1),
|
||||||
|
text_align=TextNode.ACenter,
|
||||||
|
text_wordwrap=None,
|
||||||
|
rolloverSound=None,
|
||||||
|
clickSound=None,
|
||||||
parent=parent_gui_node, # 设置GUI父节点
|
parent=parent_gui_node, # 设置GUI父节点
|
||||||
text_font = font,
|
text_font = font,
|
||||||
frameSize=(-0.1,0.1,-0.05,0.05)
|
frameSize=(-0.1,0.1,-0.05,0.05)
|
||||||
@ -496,7 +502,7 @@ class GUIManager:
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def createGUI2DImage(self, pos=(0, 0, 0), image_path=None, size=0.2):
|
def createGUI2DImage(self, pos=(0, 0, 0), image_path=None, size=1):
|
||||||
"""创建2D GUI图片"""
|
"""创建2D GUI图片"""
|
||||||
try:
|
try:
|
||||||
from direct.gui.DirectGui import DirectButton
|
from direct.gui.DirectGui import DirectButton
|
||||||
@ -536,9 +542,17 @@ class GUIManager:
|
|||||||
parent_gui_node = None # 使用默认的aspect2d
|
parent_gui_node = None # 使用默认的aspect2d
|
||||||
print(f"📎 挂载到3D父节点: {parent_item.text(0)}")
|
print(f"📎 挂载到3D父节点: {parent_item.text(0)}")
|
||||||
|
|
||||||
# 使用CardMaker创建一个更可靠的图片框架
|
if isinstance(size, (list, tuple)) and len(size) >= 2:
|
||||||
cm = CardMaker('gui-2d-image')
|
# 分别处理宽度和高度的缩放
|
||||||
cm.setFrame(-size, size, -size, size)
|
width_scale = size[0] * 0.05
|
||||||
|
height_scale = size[2] * 0.05
|
||||||
|
else:
|
||||||
|
# 如果只提供了一个缩放值,则使用相同值
|
||||||
|
width_scale = size * 0.1 if isinstance(size, (int, float)) else 0.2
|
||||||
|
height_scale = width_scale
|
||||||
|
|
||||||
|
cm = CardMaker("gui-2d-image")
|
||||||
|
cm.setFrame(-width_scale, width_scale, -height_scale, height_scale)
|
||||||
|
|
||||||
# image_node = self.world.aspect2d.attachNewNode(cm.generate())
|
# image_node = self.world.aspect2d.attachNewNode(cm.generate())
|
||||||
if parent_gui_node:
|
if parent_gui_node:
|
||||||
@ -1509,11 +1523,7 @@ class GUIManager:
|
|||||||
video_screen.setTag("tree_item_type", "GUI_2D_VIDEO_SCREEN")
|
video_screen.setTag("tree_item_type", "GUI_2D_VIDEO_SCREEN")
|
||||||
video_screen.setTag("created_by_user", "1")
|
video_screen.setTag("created_by_user", "1")
|
||||||
video_screen.setTag("name",screen_name)
|
video_screen.setTag("name",screen_name)
|
||||||
# 修复后
|
video_screen.setTag("video_path",video_path or "")
|
||||||
if video_path is not None:
|
|
||||||
video_screen.setTag("video_path", video_path)
|
|
||||||
else:
|
|
||||||
video_screen.setTag("video_path", "")
|
|
||||||
|
|
||||||
# 关键修改:预先创建一个占位符纹理,为后续视频播放做准备
|
# 关键修改:预先创建一个占位符纹理,为后续视频播放做准备
|
||||||
placeholder_texture = Texture(f"placeholder_video_texture_{len(self.gui_elements)}")
|
placeholder_texture = Texture(f"placeholder_video_texture_{len(self.gui_elements)}")
|
||||||
@ -1558,7 +1568,7 @@ class GUIManager:
|
|||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
else:
|
else:
|
||||||
if video_path:
|
if not video_path:
|
||||||
print(f"⚠️ 2D视频文件不存在: {video_path}")
|
print(f"⚠️ 2D视频文件不存在: {video_path}")
|
||||||
|
|
||||||
# 添加到GUI元素列表
|
# 添加到GUI元素列表
|
||||||
@ -1614,6 +1624,7 @@ class GUIManager:
|
|||||||
|
|
||||||
video_screen.setTag("video_path",video_path)
|
video_screen.setTag("video_path",video_path)
|
||||||
path = video_screen.getTag("video_path")
|
path = video_screen.getTag("video_path")
|
||||||
|
print({video_screen.getTag("gui_type")})
|
||||||
print(f"🔧 更新2D视频屏幕标签 - video_path: {path}")
|
print(f"🔧 更新2D视频屏幕标签 - video_path: {path}")
|
||||||
|
|
||||||
if not video_path or not os.path.exists(video_path):
|
if not video_path or not os.path.exists(video_path):
|
||||||
|
|||||||
4
main.py
4
main.py
@ -248,9 +248,9 @@ class MyWorld(CoreWorld):
|
|||||||
"""创建3D图片"""
|
"""创建3D图片"""
|
||||||
return self.gui_manager.createGUI3DImage(pos,text,size)
|
return self.gui_manager.createGUI3DImage(pos,text,size)
|
||||||
|
|
||||||
def createGUI2DImage(self, pos=(0, 0, 0), image_path=None, size=1):
|
def createGUI2DImage(self, pos=(0, 0, 0), image_path=None, size=2):
|
||||||
"""创建2D GUI图片"""
|
"""创建2D GUI图片"""
|
||||||
return self.gui_manager.createGUI2DImage(pos, image_path, size*0.2)
|
return self.gui_manager.createGUI2DImage(pos, image_path, size)
|
||||||
|
|
||||||
def createVideoScreen(self,pos=(0,0,0),size=1,video_path=None):
|
def createVideoScreen(self,pos=(0,0,0),size=1,video_path=None):
|
||||||
"""创建视频屏幕"""
|
"""创建视频屏幕"""
|
||||||
|
|||||||
@ -613,207 +613,366 @@ class ProjectManager:
|
|||||||
return ext in media_extensions
|
return ext in media_extensions
|
||||||
|
|
||||||
def _createAppFile(self, build_dir, project_name):
|
def _createAppFile(self, build_dir, project_name):
|
||||||
"""创建应用程序主文件"""
|
"""创建应用程序主文件 - 通过复制模板文件"""
|
||||||
app_code = f'''#!/usr/bin/env python3
|
# 获取模板文件路径(假设模板文件在项目根目录下的templates文件夹中)
|
||||||
# -*- coding: utf-8 -*-
|
template_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
||||||
|
"templates", "main_template.py")
|
||||||
"""
|
|
||||||
{project_name} - Panda3D应用程序
|
|
||||||
使用Panda3D引擎编辑器创建
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
#获取渲染管线路径
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
render_pipeline_path = 'RenderPipelineFile'
|
|
||||||
project_root = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
sys.path.insert(0,project_root)
|
|
||||||
sys.path.insert(0,render_pipeline_path)
|
|
||||||
|
|
||||||
import math
|
|
||||||
from random import random,randint,seed
|
|
||||||
from panda3d.core import Vec3,load_prc_file_data,Filename
|
|
||||||
from direct.showbase.ShowBase import ShowBase
|
|
||||||
|
|
||||||
os.chdir(os.path.dirname(os.path.realpath(__file__)))
|
|
||||||
|
|
||||||
class MainApp(ShowBase):
|
|
||||||
def __init__(self):
|
|
||||||
load_prc_file_data("","""
|
|
||||||
win-size 1200 720
|
|
||||||
window-title Render
|
|
||||||
""")
|
|
||||||
|
|
||||||
pipeline_path = "../../"
|
|
||||||
|
|
||||||
if not os.path.isfile(os.path.join(pipeline_path,"setup.py")):
|
|
||||||
pipeline_path = "../../RenderPipeline"
|
|
||||||
|
|
||||||
sys.path.insert(0,pipeline_path)
|
|
||||||
|
|
||||||
from rpcore import RenderPipeline,SpotLight
|
|
||||||
self.render_pipeline = RenderPipeline()
|
|
||||||
self.render_pipeline.create(self)
|
|
||||||
|
|
||||||
from rpcore.util.movement_controller import MovementController
|
|
||||||
|
|
||||||
self.render_pipeline.daytime_mgr.time = "12:00"
|
|
||||||
|
|
||||||
self.loadFullScene()
|
|
||||||
|
|
||||||
self.controller = MovementController(self)
|
|
||||||
self.controller.set_initial_position(
|
|
||||||
Vec3(-7.5,-5.3,1.8),Vec3(-5.9,-4.0,1.6))
|
|
||||||
self.controller.setup()
|
|
||||||
|
|
||||||
base.accept("l",self.tour)
|
|
||||||
|
|
||||||
def loadFullScene(self):
|
|
||||||
"""加载完整场景,包括所有元素"""
|
|
||||||
try:
|
|
||||||
scene_file = "scene.bam"
|
|
||||||
if os.path.exists(scene_file):
|
|
||||||
# 使用readBamFile加载完整场景
|
|
||||||
from panda3d.core import BamCache
|
|
||||||
BamCache.getGlobalPtr().setActive(False) # 禁用缓存以避免问题
|
|
||||||
|
|
||||||
scene = self.loader.loadModel(Filename.fromOsSpecific(scene_file))
|
|
||||||
if scene:
|
|
||||||
scene.reparentTo(self.render)
|
|
||||||
self.render_pipeline.prepare_scene(scene)
|
|
||||||
print("✓ 完整场景加载成功")
|
|
||||||
|
|
||||||
# 处理场景中的各种元素
|
|
||||||
self.processSceneElements(scene)
|
|
||||||
else:
|
|
||||||
print("⚠️ 场景文件加载失败")
|
|
||||||
else:
|
|
||||||
print("⚠️ 未找到场景文件")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"加载完整场景时出错: {{str(e)}}")
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
def processSceneElements(self, scene):
|
|
||||||
"""处理场景中的各种元素"""
|
|
||||||
try:
|
|
||||||
# 处理光源
|
|
||||||
self.processLights(scene)
|
|
||||||
|
|
||||||
# 处理GUI元素
|
|
||||||
self.processGUIElements(scene)
|
|
||||||
|
|
||||||
# 处理其他特殊元素
|
|
||||||
self.processSpecialElements(scene)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"处理场景元素时出错: {{str(e)}}")
|
|
||||||
|
|
||||||
def processLights(self, scene):
|
|
||||||
"""处理场景中的光源"""
|
|
||||||
try:
|
|
||||||
# 查找并处理点光源
|
|
||||||
point_lights = scene.findAllMatches("**/=element_type=point_light")
|
|
||||||
for light_node in point_lights:
|
|
||||||
try:
|
|
||||||
from RenderPipelineFile.rpcore import PointLight
|
|
||||||
light = PointLight()
|
|
||||||
|
|
||||||
# 恢复光源属性
|
|
||||||
if light_node.hasTag("light_energy"):
|
|
||||||
light.energy = float(light_node.getTag("light_energy"))
|
|
||||||
else:
|
|
||||||
light.energy = 5000
|
|
||||||
|
|
||||||
light.radius = 1000
|
|
||||||
light.inner_radius = 0.4
|
|
||||||
light.set_color_from_temperature(5 * 1000.0)
|
|
||||||
light.casts_shadows = True
|
|
||||||
light.shadow_map_resolution = 256
|
|
||||||
|
|
||||||
light.setPos(light_node.getPos())
|
|
||||||
self.render_pipeline.add_light(light)
|
|
||||||
print(f"✓ 点光源 {{light_node.getName()}} 恢复成功")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"恢复点光源 {{light_node.getName()}} 失败: {{str(e)}}")
|
|
||||||
|
|
||||||
# 查找并处理聚光灯
|
|
||||||
spot_lights = scene.findAllMatches("**/=element_type=spot_light")
|
|
||||||
for light_node in spot_lights:
|
|
||||||
try:
|
|
||||||
from RenderPipelineFile.rpcore import SpotLight
|
|
||||||
light = SpotLight()
|
|
||||||
|
|
||||||
# 恢复光源属性
|
|
||||||
if light_node.hasTag("light_energy"):
|
|
||||||
light.energy = float(light_node.getTag("light_energy"))
|
|
||||||
else:
|
|
||||||
light.energy = 5000
|
|
||||||
|
|
||||||
light.radius = 1000
|
|
||||||
light.inner_radius = 0.4
|
|
||||||
light.set_color_from_temperature(5 * 1000.0)
|
|
||||||
light.casts_shadows = True
|
|
||||||
light.shadow_map_resolution = 256
|
|
||||||
|
|
||||||
light.setPos(light_node.getPos())
|
|
||||||
self.render_pipeline.add_light(light)
|
|
||||||
print(f"✓ 聚光灯 {{light_node.getName()}} 恢复成功")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"恢复聚光灯 {{light_node.getName()}} 失败: {{str(e)}}")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"处理光源时出错: {{str(e)}}")
|
|
||||||
|
|
||||||
def processGUIElements(self, scene):
|
|
||||||
"""处理场景中的GUI元素"""
|
|
||||||
try:
|
|
||||||
# 查找并处理2D图像
|
|
||||||
images_2d = scene.findAllMatches("**/=gui_type=image_2d")
|
|
||||||
for img_node in images_2d:
|
|
||||||
try:
|
|
||||||
# GUI元素通常在场景加载时自动处理
|
|
||||||
print(f"✓ 2D图像 {{img_node.getName()}} 已加载")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"处理2D图像 {{img_node.getName()}} 失败: {{str(e)}}")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"处理GUI元素时出错: {{str(e)}}")
|
|
||||||
|
|
||||||
def processSpecialElements(self, scene):
|
|
||||||
"""处理特殊元素"""
|
|
||||||
try:
|
|
||||||
# 处理Cesium Tilesets
|
|
||||||
tilesets = scene.findAllMatches("**/=element_type=cesium_tileset")
|
|
||||||
for tileset_node in tilesets:
|
|
||||||
try:
|
|
||||||
# Tilesets需要特殊处理,这里只是标记
|
|
||||||
print(f"✓ Cesium Tileset {{tileset_node.getName()}} 已识别")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"处理Cesium Tileset {{tileset_node.getName()}} 失败: {{str(e)}}")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"处理特殊元素时出错: {{str(e)}}")
|
|
||||||
|
|
||||||
def tour(self):
|
|
||||||
mopath = (
|
|
||||||
(Vec3(-10.8645000458, 9.76458263397, 2.13306283951), Vec3(-133.556228638, -4.23447799683, 0.0)),
|
|
||||||
(Vec3(-10.6538448334, -5.98406457901, 1.68028640747), Vec3(-59.3999938965, -3.32706642151, 0.0)),
|
|
||||||
(Vec3(9.58458328247, -5.63625621796, 2.63269257545), Vec3(58.7906494141, -9.40668964386, 0.0)),
|
|
||||||
(Vec3(6.8135137558, 11.0153560638, 2.25509500504), Vec3(148.762527466, -6.41223621368, 0.0)),
|
|
||||||
(Vec3(-9.07093334198, 3.65908527374, 1.42396306992), Vec3(245.362503052, -3.59927511215, 0.0)),
|
|
||||||
(Vec3(-8.75390911102, -3.82727789879, 0.990055501461), Vec3(296.090484619, -0.604830980301, 0.0)),
|
|
||||||
)
|
|
||||||
self.controller.play_motion_path(mopath,3.0)
|
|
||||||
|
|
||||||
MainApp().run()
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
# 目标文件路径
|
||||||
app_path = os.path.join(build_dir, "main.py")
|
app_path = os.path.join(build_dir, "main.py")
|
||||||
with open(app_path, "w", encoding="utf-8") as f:
|
|
||||||
f.write(app_code)
|
# 检查模板文件是否存在
|
||||||
|
if os.path.exists(template_path):
|
||||||
|
# 直接复制模板文件
|
||||||
|
shutil.copy2(template_path, app_path)
|
||||||
|
print(f"✓ 应用程序主文件已从模板创建: {app_path}")
|
||||||
|
|
||||||
|
# def _createAppFile(self, build_dir, project_name):
|
||||||
|
# """创建应用程序主文件"""
|
||||||
|
# app_code = f'''#!/usr/bin/env python3
|
||||||
|
# # -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# """
|
||||||
|
# {project_name} - Panda3D应用程序
|
||||||
|
# 使用Panda3D引擎编辑器创建
|
||||||
|
# """
|
||||||
|
#
|
||||||
|
# from __future__ import print_function
|
||||||
|
#
|
||||||
|
# import json
|
||||||
|
#
|
||||||
|
# from direct.actor.Actor import Actor
|
||||||
|
# from panda3d.core import TextNode, CardMaker, TextureStage, NodePath
|
||||||
|
# #获取渲染管线路径
|
||||||
|
# import sys
|
||||||
|
# import os
|
||||||
|
#
|
||||||
|
# render_pipeline_path = 'RenderPipelineFile'
|
||||||
|
# project_root = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
# sys.path.insert(0,project_root)
|
||||||
|
# sys.path.insert(0,render_pipeline_path)
|
||||||
|
#
|
||||||
|
# import math
|
||||||
|
# from random import random,randint,seed
|
||||||
|
# from panda3d.core import Vec3,load_prc_file_data,Filename
|
||||||
|
# from direct.showbase.ShowBase import ShowBase
|
||||||
|
#
|
||||||
|
# os.chdir(os.path.dirname(os.path.realpath(__file__)))
|
||||||
|
#
|
||||||
|
# class MainApp(ShowBase):
|
||||||
|
# def __init__(self):
|
||||||
|
# load_prc_file_data("","""
|
||||||
|
# win-size 1200 720
|
||||||
|
# window-title Render
|
||||||
|
# """)
|
||||||
|
#
|
||||||
|
# pipeline_path = "../../"
|
||||||
|
#
|
||||||
|
# if not os.path.isfile(os.path.join(pipeline_path,"setup.py")):
|
||||||
|
# pipeline_path = "../../RenderPipeline"
|
||||||
|
#
|
||||||
|
# sys.path.insert(0,pipeline_path)
|
||||||
|
#
|
||||||
|
# from rpcore import RenderPipeline,SpotLight
|
||||||
|
# self.render_pipeline = RenderPipeline()
|
||||||
|
# self.render_pipeline.create(self)
|
||||||
|
#
|
||||||
|
# from rpcore.util.movement_controller import MovementController
|
||||||
|
#
|
||||||
|
# self.render_pipeline.daytime_mgr.time = "12:00"
|
||||||
|
# self._loadFont()
|
||||||
|
#
|
||||||
|
# self.loadFullScene()
|
||||||
|
# self.loadGUIFromJSON()
|
||||||
|
#
|
||||||
|
# self.controller = MovementController(self)
|
||||||
|
# self.controller.set_initial_position(
|
||||||
|
# Vec3(-7.5,-5.3,1.8),Vec3(-5.9,-4.0,1.6))
|
||||||
|
# self.controller.setup()
|
||||||
|
#
|
||||||
|
# base.accept("l",self.tour)
|
||||||
|
#
|
||||||
|
# def _loadFont(self):
|
||||||
|
# """加载中文字体"""
|
||||||
|
# self.chinese_font = None
|
||||||
|
# try:
|
||||||
|
# self.chinese_font = self.loader.loadFont('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc')
|
||||||
|
# if not self.chinese_font:
|
||||||
|
# print("警告: 无法加载中文字体,将使用默认字体")
|
||||||
|
# else:
|
||||||
|
# print("✓ 中文字体加载成功")
|
||||||
|
# except:
|
||||||
|
# print("警告: 无法加载中文字体,将使用默认字体")
|
||||||
|
# self.chinese_font = None
|
||||||
|
#
|
||||||
|
# def getChineseFont(self):
|
||||||
|
# """获取中文字体"""
|
||||||
|
# return self.chinese_font
|
||||||
|
#
|
||||||
|
# def loadFullScene(self):
|
||||||
|
# """加载完整场景,包括所有元素"""
|
||||||
|
# try:
|
||||||
|
# scene_file = "scene.bam"
|
||||||
|
# if os.path.exists(scene_file):
|
||||||
|
# # 使用readBamFile加载完整场景
|
||||||
|
# from panda3d.core import BamCache
|
||||||
|
# BamCache.getGlobalPtr().setActive(False) # 禁用缓存以避免问题
|
||||||
|
#
|
||||||
|
# scene = self.loader.loadModel(Filename.fromOsSpecific(scene_file))
|
||||||
|
# if scene:
|
||||||
|
# scene.reparentTo(self.render)
|
||||||
|
# self.render_pipeline.prepare_scene(scene)
|
||||||
|
# print("✓ 完整场景加载成功")
|
||||||
|
#
|
||||||
|
# # 处理场景中的各种元素
|
||||||
|
# self.processSceneElements(scene)
|
||||||
|
# else:
|
||||||
|
# print("⚠️ 场景文件加载失败")
|
||||||
|
# else:
|
||||||
|
# print("⚠️ 未找到场景文件")
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"加载完整场景时出错: {{str(e)}}")
|
||||||
|
# import traceback
|
||||||
|
# traceback.print_exc()
|
||||||
|
#
|
||||||
|
# def processSceneElements(self, scene):
|
||||||
|
# """处理场景中的各种元素"""
|
||||||
|
# try:
|
||||||
|
# # 处理光源
|
||||||
|
# self.processLights(scene)
|
||||||
|
#
|
||||||
|
# # 处理GUI元素
|
||||||
|
# self.processGUIElements(scene)
|
||||||
|
#
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"处理场景元素时出错: {{str(e)}}")
|
||||||
|
#
|
||||||
|
# def processLights(self, scene):
|
||||||
|
# """处理场景中的光源"""
|
||||||
|
# try:
|
||||||
|
# # 查找并处理点光源
|
||||||
|
# point_lights = scene.findAllMatches("**/=element_type=point_light")
|
||||||
|
# for light_node in point_lights:
|
||||||
|
# try:
|
||||||
|
# from RenderPipelineFile.rpcore import PointLight
|
||||||
|
# light = PointLight()
|
||||||
|
#
|
||||||
|
# # 恢复光源属性
|
||||||
|
# if light_node.hasTag("light_energy"):
|
||||||
|
# light.energy = float(light_node.getTag("light_energy"))
|
||||||
|
# else:
|
||||||
|
# light.energy = 5000
|
||||||
|
#
|
||||||
|
# light.radius = 1000
|
||||||
|
# light.inner_radius = 0.4
|
||||||
|
# light.set_color_from_temperature(5 * 1000.0)
|
||||||
|
# light.casts_shadows = True
|
||||||
|
# light.shadow_map_resolution = 256
|
||||||
|
#
|
||||||
|
# light.setPos(light_node.getPos())
|
||||||
|
# self.render_pipeline.add_light(light)
|
||||||
|
# print(f"✓ 点光源 {{light_node.getName()}} 恢复成功")
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"恢复点光源 {{light_node.getName()}} 失败: {{str(e)}}")
|
||||||
|
#
|
||||||
|
# # 查找并处理聚光灯
|
||||||
|
# spot_lights = scene.findAllMatches("**/=element_type=spot_light")
|
||||||
|
# for light_node in spot_lights:
|
||||||
|
# try:
|
||||||
|
# from RenderPipelineFile.rpcore import SpotLight
|
||||||
|
# light = SpotLight()
|
||||||
|
#
|
||||||
|
# # 恢复光源属性
|
||||||
|
# if light_node.hasTag("light_energy"):
|
||||||
|
# light.energy = float(light_node.getTag("light_energy"))
|
||||||
|
# else:
|
||||||
|
# light.energy = 5000
|
||||||
|
#
|
||||||
|
# light.radius = 1000
|
||||||
|
# light.inner_radius = 0.4
|
||||||
|
# light.set_color_from_temperature(5 * 1000.0)
|
||||||
|
# light.casts_shadows = True
|
||||||
|
# light.shadow_map_resolution = 256
|
||||||
|
#
|
||||||
|
# light.setPos(light_node.getPos())
|
||||||
|
# self.render_pipeline.add_light(light)
|
||||||
|
# print(f"✓ 聚光灯 {{light_node.getName()}} 恢复成功")
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"恢复聚光灯 {{light_node.getName()}} 失败: {{str(e)}}")
|
||||||
|
#
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"处理光源时出错: {{str(e)}}")
|
||||||
|
#
|
||||||
|
# def processGUIElements(self, scene):
|
||||||
|
# """处理场景中的GUI元素"""
|
||||||
|
# try:
|
||||||
|
# # 查找并处理2D图像
|
||||||
|
# images_2d = scene.findAllMatches("**/=gui_type=image_2d")
|
||||||
|
# for img_node in images_2d:
|
||||||
|
# try:
|
||||||
|
# # GUI元素通常在场景加载时自动处理
|
||||||
|
# print(f"✓ 2D图像 {{img_node.getName()}} 已加载")
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"处理2D图像 {{img_node.getName()}} 失败: {{str(e)}}")
|
||||||
|
#
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"处理GUI元素时出错: {{str(e)}}")
|
||||||
|
#
|
||||||
|
# def tour(self):
|
||||||
|
# mopath = (
|
||||||
|
# (Vec3(-10.8645000458, 9.76458263397, 2.13306283951), Vec3(-133.556228638, -4.23447799683, 0.0)),
|
||||||
|
# (Vec3(-10.6538448334, -5.98406457901, 1.68028640747), Vec3(-59.3999938965, -3.32706642151, 0.0)),
|
||||||
|
# (Vec3(9.58458328247, -5.63625621796, 2.63269257545), Vec3(58.7906494141, -9.40668964386, 0.0)),
|
||||||
|
# (Vec3(6.8135137558, 11.0153560638, 2.25509500504), Vec3(148.762527466, -6.41223621368, 0.0)),
|
||||||
|
# (Vec3(-9.07093334198, 3.65908527374, 1.42396306992), Vec3(245.362503052, -3.59927511215, 0.0)),
|
||||||
|
# (Vec3(-8.75390911102, -3.82727789879, 0.990055501461), Vec3(296.090484619, -0.604830980301, 0.0)),
|
||||||
|
# )
|
||||||
|
# self.controller.play_motion_path(mopath,3.0)
|
||||||
|
#
|
||||||
|
# def loadGUIFromJSON(self):
|
||||||
|
# gui_json_path = "gui/gui_elements.json"
|
||||||
|
#
|
||||||
|
# try:
|
||||||
|
# if os.path.exists(gui_json_path):
|
||||||
|
# with open(gui_json_path, "r", encoding="utf-8") as f:
|
||||||
|
# content = f.read().strip()
|
||||||
|
# if content:
|
||||||
|
# gui_data = json.loads(content)
|
||||||
|
# self.createGUIElement(gui_data)
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"加载GUI元素失败: {{str(e)}}")
|
||||||
|
# import traceback
|
||||||
|
# traceback.print_exc()
|
||||||
|
#
|
||||||
|
# def createGUIElement(self,element_data):
|
||||||
|
# try:
|
||||||
|
# processed_names = set()
|
||||||
|
# element_original_data={{}}
|
||||||
|
# for i, gui_info in enumerate(element_data):
|
||||||
|
# name = gui_info.get("name", f"gui_element_{{i}}")
|
||||||
|
# element_original_data[name] = {
|
||||||
|
# "scale": gui_info.get("scale", [1, 1, 1]),
|
||||||
|
# "position": gui_info.get("position", [0, 0, 0]),
|
||||||
|
# "parent_name": gui_info.get("parent_name")
|
||||||
|
# }
|
||||||
|
# valid_parents = set()
|
||||||
|
# for gui_info in element_data:
|
||||||
|
# name = gui_info.get("name", f"gui_element_{{gui_info.get('index', 0)}}")
|
||||||
|
# valid_parents.add(name)
|
||||||
|
#
|
||||||
|
# for i ,gui_info in enumerate(element_data):
|
||||||
|
# try:
|
||||||
|
# gui_type = gui_info.get("type","unknown")
|
||||||
|
# name = gui_info.get("name",f"gui_element_{{i}}")
|
||||||
|
# position = gui_info.get("position",[0,0,0])
|
||||||
|
# scale = gui_info.get("scale",[1,1,1])
|
||||||
|
# tags = gui_info.get("tags",{{}})
|
||||||
|
# text = gui_info.get("text","")
|
||||||
|
# image_path = gui_info.get("image_path","")
|
||||||
|
# video_path = gui_info.get("video_path","")
|
||||||
|
# bg_image_path = gui_info.get("bg_image_path","")
|
||||||
|
# parent_name = gui_info.get("parent_name")
|
||||||
|
#
|
||||||
|
# if name in processed_names:
|
||||||
|
# continue
|
||||||
|
#
|
||||||
|
# processed_names.add(name)
|
||||||
|
#
|
||||||
|
# absolute_position = list(position)
|
||||||
|
# absolute_scale = list(scale)
|
||||||
|
#
|
||||||
|
# if parent_name and parent_name in element_original_data:
|
||||||
|
# parent_data = element_original_data[parent_name]
|
||||||
|
# parent_scale = parent_data["scale"]
|
||||||
|
#
|
||||||
|
# if gui_type in ["3d_text", "3d_image", "button", "label", "entry", "2d_image",
|
||||||
|
# "2d_video_screen"]:
|
||||||
|
# # 位置需要乘以父级缩放来得到绝对位置
|
||||||
|
# for j in range(min(len(absolute_position), len(parent_scale))):
|
||||||
|
# absolute_position[j] *= parent_scale[j] if len(parent_scale) > j else parent_scale[0]
|
||||||
|
#
|
||||||
|
# # 缩放需要乘以父级缩放来得到绝对缩放
|
||||||
|
# for j in range(min(len(absolute_scale), len(parent_scale))):
|
||||||
|
# absolute_scale[j] *= parent_scale[j] if len(parent_scale) > j else parent_scale[0]
|
||||||
|
#
|
||||||
|
# new_element = None
|
||||||
|
#
|
||||||
|
# if gui_type =="3d_text":
|
||||||
|
# size = absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 0.5
|
||||||
|
# new_element = self.createGUI3DText(
|
||||||
|
# pos = tuple(absolute_position),
|
||||||
|
# text = text,
|
||||||
|
# size = size
|
||||||
|
# )
|
||||||
|
# elif gui_type == "button":
|
||||||
|
# # 确保传入正确的参数类型
|
||||||
|
# new_element = self.createGUIButton(
|
||||||
|
# pos=tuple(absolute_position),
|
||||||
|
# text=text,
|
||||||
|
# size=absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 1.0,
|
||||||
|
# )
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"重建GUI元素失败 {{name}}: {{e}}")
|
||||||
|
# import traceback
|
||||||
|
# traceback.print_exc()
|
||||||
|
# continue
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"重建GUI元素失败: {{str(e)}}")
|
||||||
|
#
|
||||||
|
# def createGUIButton(self, pos=(0, 0, 0), text="按钮", size=0.1,command=None):
|
||||||
|
# from direct.gui.DirectGui import DirectButton
|
||||||
|
#
|
||||||
|
# button = DirectButton(
|
||||||
|
# text=text,
|
||||||
|
# pos=(pos[0], pos[1], pos[2]), # 保持正确的坐标格式
|
||||||
|
# scale=size, # size 应该是数值而不是元组
|
||||||
|
# frameColor=(0.2, 0.6, 0.8, 1),
|
||||||
|
# text_font=self.getChineseFont() if self.getChineseFont() else None,
|
||||||
|
# rolloverSound=None,
|
||||||
|
# clickSound=None,
|
||||||
|
# parent=None,
|
||||||
|
# command=command
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# def createGUI3DText(self, pos=(0, 0, 0), text="3D文本", size=0.5):
|
||||||
|
# """创建3D文本GUI元素"""
|
||||||
|
# try:
|
||||||
|
# # 创建文本节点
|
||||||
|
# text_node = TextNode("gui_3d_text")
|
||||||
|
# text_node.setText(text)
|
||||||
|
# text_node.setAlign(TextNode.ACenter)
|
||||||
|
#
|
||||||
|
# # 设置字体(如果可用)
|
||||||
|
# if self.getChineseFont():
|
||||||
|
# text_node.setFont(self.getChineseFont())
|
||||||
|
#
|
||||||
|
# # 创建节点路径并添加到场景
|
||||||
|
# text_np = self.render.attachNewNode(text_node)
|
||||||
|
#
|
||||||
|
# # 设置位置和大小
|
||||||
|
# text_np.setPos(Vec3(pos[0], pos[1], pos[2]))
|
||||||
|
# text_np.setScale(size)
|
||||||
|
#
|
||||||
|
# # 设置面向摄像机
|
||||||
|
# #text_np.setBillboardPointEye()
|
||||||
|
#
|
||||||
|
# # 设置渲染属性
|
||||||
|
# text_np.setBin("fixed", 40)
|
||||||
|
# text_np.setDepthWrite(False)
|
||||||
|
#
|
||||||
|
# return text_np
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"❌ 创建3D文本失败: {{str(e)}}")
|
||||||
|
# import traceback
|
||||||
|
# traceback.print_exc()
|
||||||
|
# return None
|
||||||
|
#
|
||||||
|
# MainApp().run()
|
||||||
|
# '''
|
||||||
|
#
|
||||||
|
# app_path = os.path.join(build_dir, "main.py")
|
||||||
|
# with open(app_path, "w", encoding="utf-8") as f:
|
||||||
|
# f.write(app_code)
|
||||||
|
|
||||||
def _createStandardSetupFile(self, build_dir, project_name):
|
def _createStandardSetupFile(self, build_dir, project_name):
|
||||||
"""创建标准的setup.py文件 - 按照Panda3D官方文档"""
|
"""创建标准的setup.py文件 - 按照Panda3D官方文档"""
|
||||||
@ -878,6 +1037,8 @@ setup(
|
|||||||
'direct.interval',
|
'direct.interval',
|
||||||
'panda3d.core',
|
'panda3d.core',
|
||||||
'panda3d.direct',
|
'panda3d.direct',
|
||||||
|
'rpcore',
|
||||||
|
'rpcore.util.movement_controller',
|
||||||
],
|
],
|
||||||
}},
|
}},
|
||||||
|
|
||||||
|
|||||||
@ -900,7 +900,8 @@ class SceneManager:
|
|||||||
"rotation": list(gui_node.getHpr()),
|
"rotation": list(gui_node.getHpr()),
|
||||||
"scale": list(gui_node.getScale()),
|
"scale": list(gui_node.getScale()),
|
||||||
"tags": {},
|
"tags": {},
|
||||||
"parent_name":None
|
"parent_name":None,
|
||||||
|
"video_path":gui_node.getTag("video_path") if gui_node.hasTag("video_path") else None,
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = gui_node.getParent()
|
parent = gui_node.getParent()
|
||||||
@ -910,13 +911,13 @@ class SceneManager:
|
|||||||
gui_info["parent_name"] = parent_name
|
gui_info["parent_name"] = parent_name
|
||||||
|
|
||||||
# 收集所有标签(仅对NodePath类型的对象)
|
# 收集所有标签(仅对NodePath类型的对象)
|
||||||
if hasattr(gui_node, 'getTagNames'):
|
# if hasattr(gui_node, 'getTagNames'):
|
||||||
for tag in gui_node.getTagNames():
|
# for tag in gui_node.getTagNames():
|
||||||
gui_info["tags"][tag] = gui_node.getTag(tag)
|
# gui_info["tags"][tag] = gui_node.getTag(tag)
|
||||||
elif hasattr(gui_node, 'getTags'): # 对于DirectGUI对象
|
# elif hasattr(gui_node, 'getTags'): # 对于DirectGUI对象
|
||||||
# DirectGUI对象使用不同的方法存储标签
|
# # DirectGUI对象使用不同的方法存储标签
|
||||||
if hasattr(gui_node, '_tags'):
|
# if hasattr(gui_node, '_tags'):
|
||||||
gui_info["tags"] = gui_node._tags.copy()
|
# gui_info["tags"] = gui_node._tags.copy()
|
||||||
|
|
||||||
# 根据类型收集特定信息
|
# 根据类型收集特定信息
|
||||||
if gui_type == "button":
|
if gui_type == "button":
|
||||||
@ -949,9 +950,11 @@ class SceneManager:
|
|||||||
elif gui_type == "3d_image":
|
elif gui_type == "3d_image":
|
||||||
if hasattr(gui_node,'hasTag') and gui_node.hasTag("gui_image_path"):
|
if hasattr(gui_node,'hasTag') and gui_node.hasTag("gui_image_path"):
|
||||||
gui_info["image_path"] = gui_node.getTag("gui_image_path")
|
gui_info["image_path"] = gui_node.getTag("gui_image_path")
|
||||||
elif gui_type in ["video_screen", "2d_video_screen"]:
|
elif gui_type == "video_screen":
|
||||||
if hasattr(gui_node, 'hasTag') and gui_node.hasTag("video_path"):
|
if hasattr(gui_node, 'hasTag') and gui_node.hasTag("video_path"):
|
||||||
gui_info["video_path"] = gui_node.getTag("video_path")
|
gui_info["video_path"] = gui_node.getTag("video_path")
|
||||||
|
elif gui_type == "2d_video_screen":
|
||||||
|
if hasattr(gui_node, 'hasTag') and gui_node.hasTag("video_path"):
|
||||||
gui_info["video_path"] = gui_node.getTag("video_path")
|
gui_info["video_path"] = gui_node.getTag("video_path")
|
||||||
elif gui_type == "virtual_screen":
|
elif gui_type == "virtual_screen":
|
||||||
if hasattr(gui_node, 'hasTag') and gui_node.hasTag("gui_text"):
|
if hasattr(gui_node, 'hasTag') and gui_node.hasTag("gui_text"):
|
||||||
@ -1991,11 +1994,12 @@ class SceneManager:
|
|||||||
size=absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 1.0
|
size=absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 1.0
|
||||||
)
|
)
|
||||||
elif gui_type == "2d_image" and hasattr(gui_manager, 'createGUI2DImage'):
|
elif gui_type == "2d_image" and hasattr(gui_manager, 'createGUI2DImage'):
|
||||||
scale_value = absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 0.2
|
scale_value = absolute_scale[0]
|
||||||
|
print(f"2d_image{scale_value}")
|
||||||
new_element = gui_manager.createGUI2DImage(
|
new_element = gui_manager.createGUI2DImage(
|
||||||
pos=tuple(absolute_position),
|
pos=tuple(absolute_position),
|
||||||
image_path=image_path,
|
image_path=image_path,
|
||||||
size=scale_value * 0.2
|
size=absolute_scale
|
||||||
)
|
)
|
||||||
elif gui_type == "3d_text" and hasattr(gui_manager, 'createGUI3DText'):
|
elif gui_type == "3d_text" and hasattr(gui_manager, 'createGUI3DText'):
|
||||||
size = absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 0.5
|
size = absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 0.5
|
||||||
@ -2342,7 +2346,6 @@ class SceneManager:
|
|||||||
"""重新创建聚光灯"""
|
"""重新创建聚光灯"""
|
||||||
try:
|
try:
|
||||||
from RenderPipelineFile.rpcore import SpotLight
|
from RenderPipelineFile.rpcore import SpotLight
|
||||||
from QPanda3D.Panda3DWorld import get_render_pipeline
|
|
||||||
from panda3d.core import Vec3
|
from panda3d.core import Vec3
|
||||||
|
|
||||||
# 创建聚光灯对象
|
# 创建聚光灯对象
|
||||||
|
|||||||
641
templates/main_template.py
Normal file
641
templates/main_template.py
Normal file
@ -0,0 +1,641 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
测试动画模型 - Panda3D应用程序
|
||||||
|
使用Panda3D引擎编辑器创建
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
from direct.actor.Actor import Actor
|
||||||
|
from panda3d.core import TextNode, CardMaker, TextureStage, NodePath, Texture, TransparencyAttrib
|
||||||
|
# 获取渲染管线路径
|
||||||
|
# 在文件开头添加sys导入(如果还没有的话)
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# 修改工作目录设置部分
|
||||||
|
if getattr(sys, 'frozen', False):
|
||||||
|
# 打包后的环境
|
||||||
|
project_root = os.path.dirname(sys.executable)
|
||||||
|
else:
|
||||||
|
# 开发环境
|
||||||
|
try:
|
||||||
|
project_root = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
except NameError:
|
||||||
|
project_root = os.getcwd()
|
||||||
|
|
||||||
|
os.chdir(project_root)
|
||||||
|
|
||||||
|
render_pipeline_path = 'RenderPipelineFile'
|
||||||
|
sys.path.insert(0, render_pipeline_path)
|
||||||
|
|
||||||
|
# 修改管线路径查找
|
||||||
|
pipeline_path = os.path.join(project_root, "RenderPipelineFile")
|
||||||
|
if not os.path.isfile(os.path.join(pipeline_path, "setup.py")):
|
||||||
|
pipeline_path = os.path.join(project_root, "RenderPipelineFile")
|
||||||
|
|
||||||
|
import math
|
||||||
|
from random import random, randint, seed
|
||||||
|
from panda3d.core import Vec3, load_prc_file_data, Filename
|
||||||
|
from direct.showbase.ShowBase import ShowBase
|
||||||
|
|
||||||
|
|
||||||
|
# os.chdir(os.path.dirname(os.path.realpath(__file__)))
|
||||||
|
|
||||||
|
|
||||||
|
class MainApp(ShowBase):
|
||||||
|
def __init__(self):
|
||||||
|
load_prc_file_data("", """
|
||||||
|
win-size 1380 750
|
||||||
|
window-title Render
|
||||||
|
""")
|
||||||
|
|
||||||
|
pipeline_path = "../../"
|
||||||
|
|
||||||
|
if not os.path.isfile(os.path.join(pipeline_path, "setup.py")):
|
||||||
|
pipeline_path = "../../RenderPipeline"
|
||||||
|
|
||||||
|
sys.path.insert(0, pipeline_path)
|
||||||
|
|
||||||
|
from rpcore import RenderPipeline, SpotLight
|
||||||
|
self.render_pipeline = RenderPipeline()
|
||||||
|
self.render_pipeline.create(self)
|
||||||
|
|
||||||
|
from rpcore.util.movement_controller import MovementController
|
||||||
|
|
||||||
|
self.render_pipeline.daytime_mgr.time = "12:00"
|
||||||
|
self._loadFont()
|
||||||
|
|
||||||
|
self.loadFullScene()
|
||||||
|
self.loadGUIFromJSON()
|
||||||
|
|
||||||
|
self.controller = MovementController(self)
|
||||||
|
self.controller.set_initial_position(
|
||||||
|
Vec3(0, -50, 20), Vec3(0, 0, 0))
|
||||||
|
self.controller.setup()
|
||||||
|
|
||||||
|
base.accept("l", self.tour)
|
||||||
|
|
||||||
|
def _loadFont(self):
|
||||||
|
"""加载中文字体"""
|
||||||
|
self.chinese_font = None
|
||||||
|
try:
|
||||||
|
self.chinese_font = self.loader.loadFont('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc')
|
||||||
|
if not self.chinese_font:
|
||||||
|
print("警告: 无法加载中文字体,将使用默认字体")
|
||||||
|
else:
|
||||||
|
print("✓ 中文字体加载成功")
|
||||||
|
except:
|
||||||
|
print("警告: 无法加载中文字体,将使用默认字体")
|
||||||
|
self.chinese_font = None
|
||||||
|
|
||||||
|
def getChineseFont(self):
|
||||||
|
"""获取中文字体"""
|
||||||
|
return self.chinese_font
|
||||||
|
|
||||||
|
def loadFullScene(self):
|
||||||
|
"""加载完整场景,包括所有元素"""
|
||||||
|
try:
|
||||||
|
import sys
|
||||||
|
# 获取场景文件路径
|
||||||
|
if getattr(sys, 'frozen', False):
|
||||||
|
scene_file = os.path.join(os.path.dirname(sys.executable), "scene.bam")
|
||||||
|
else:
|
||||||
|
scene_file = "scene.bam"
|
||||||
|
|
||||||
|
if os.path.exists(scene_file):
|
||||||
|
# 使用readBamFile加载完整场景
|
||||||
|
from panda3d.core import BamCache
|
||||||
|
BamCache.getGlobalPtr().setActive(False) # 禁用缓存以避免问题
|
||||||
|
|
||||||
|
scene = self.loader.loadModel(Filename.fromOsSpecific(scene_file))
|
||||||
|
if scene:
|
||||||
|
scene.reparentTo(self.render)
|
||||||
|
self.render_pipeline.prepare_scene(scene)
|
||||||
|
print("✓ 完整场景加载成功")
|
||||||
|
|
||||||
|
# 处理场景中的各种元素
|
||||||
|
self.processSceneElements(scene)
|
||||||
|
else:
|
||||||
|
print("⚠️ 场景文件加载失败")
|
||||||
|
else:
|
||||||
|
print("⚠️ 未找到场景文件")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"加载完整场景时出错: {str(e)}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def processSceneElements(self, scene):
|
||||||
|
"""处理场景中的各种元素"""
|
||||||
|
try:
|
||||||
|
processed_lights = []
|
||||||
|
loaded_nodes = {}
|
||||||
|
def processNode(nodePath,depth=0):
|
||||||
|
loaded_nodes[nodePath.getName()] = nodePath
|
||||||
|
|
||||||
|
if nodePath.hasTag("light_type"):
|
||||||
|
light_type = nodePath.getTag("light_type")
|
||||||
|
|
||||||
|
if nodePath not in processed_lights:
|
||||||
|
if light_type == "spot_light":
|
||||||
|
self._recreateSpotLight(nodePath)
|
||||||
|
elif light_type == "point_light":
|
||||||
|
self._recreatePointLight(nodePath)
|
||||||
|
processed_lights.append(nodePath)
|
||||||
|
|
||||||
|
for child in nodePath.getChildren():
|
||||||
|
processNode(child,depth+1)
|
||||||
|
|
||||||
|
processNode(scene)
|
||||||
|
|
||||||
|
# 处理GUI元素
|
||||||
|
#self.processGUIElements(scene)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"处理场景元素时出错: {str(e)}")
|
||||||
|
|
||||||
|
def _recreateSpotLight(self,light_node):
|
||||||
|
try:
|
||||||
|
from RenderPipelineFile.rpcore import SpotLight
|
||||||
|
from panda3d.core import Vec3
|
||||||
|
|
||||||
|
light = SpotLight()
|
||||||
|
light.direction = Vec3(0,0,-1)
|
||||||
|
light.fov = 70
|
||||||
|
light.set_color_from_temperature(5*1000.0)
|
||||||
|
|
||||||
|
if light_node.hasTag("light_energy"):
|
||||||
|
light.energy = float(light_node.getTag("light_energy"))
|
||||||
|
else:
|
||||||
|
light.energy = 5000
|
||||||
|
|
||||||
|
light.radius = 1000
|
||||||
|
light.casts_shadows = True
|
||||||
|
light.shadow_map_resolution = 256
|
||||||
|
|
||||||
|
light_pos = light_node.getPos()
|
||||||
|
light.setPos(light_pos)
|
||||||
|
|
||||||
|
self.render_pipeline.add_light(light)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"创建点光源 {light_node.getName()} 失败: {str(e)}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def _recreatePointLight(self,light_node):
|
||||||
|
try:
|
||||||
|
from RenderPipelineFile.rpcore import PointLight
|
||||||
|
|
||||||
|
light = PointLight()
|
||||||
|
|
||||||
|
if light_node.hasTag("light_energy"):
|
||||||
|
light.energy = float(light_node.getTag("light_energy"))
|
||||||
|
else:
|
||||||
|
light.energy = 5000
|
||||||
|
|
||||||
|
light.radius = 1000
|
||||||
|
light.inner_radius = 0.4
|
||||||
|
light.set_color_from_temperature(5*1000.0)
|
||||||
|
light.casts_shadows = True
|
||||||
|
light.shadow_map_resolution = 256
|
||||||
|
|
||||||
|
light.setPos(light_node.getPos())
|
||||||
|
|
||||||
|
self.render_pipeline.add_light(light)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"创建点光源 {light_node.getName()} 失败: {str(e)}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def processGUIElements(self, scene):
|
||||||
|
"""处理场景中的GUI元素"""
|
||||||
|
try:
|
||||||
|
# 查找并处理2D图像
|
||||||
|
images_2d = scene.findAllMatches("**/=gui_type=image_2d")
|
||||||
|
for img_node in images_2d:
|
||||||
|
try:
|
||||||
|
# GUI元素通常在场景加载时自动处理
|
||||||
|
print(f"✓ 2D图像 {img_node.getName()} 已加载")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"处理2D图像 {img_node.getName()} 失败: {str(e)}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"处理GUI元素时出错: {str(e)}")
|
||||||
|
|
||||||
|
def tour(self):
|
||||||
|
mopath = (
|
||||||
|
(Vec3(-10.8645000458, 9.76458263397, 2.13306283951), Vec3(-133.556228638, -4.23447799683, 0.0)),
|
||||||
|
(Vec3(-10.6538448334, -5.98406457901, 1.68028640747), Vec3(-59.3999938965, -3.32706642151, 0.0)),
|
||||||
|
(Vec3(9.58458328247, -5.63625621796, 2.63269257545), Vec3(58.7906494141, -9.40668964386, 0.0)),
|
||||||
|
(Vec3(6.8135137558, 11.0153560638, 2.25509500504), Vec3(148.762527466, -6.41223621368, 0.0)),
|
||||||
|
(Vec3(-9.07093334198, 3.65908527374, 1.42396306992), Vec3(245.362503052, -3.59927511215, 0.0)),
|
||||||
|
(Vec3(-8.75390911102, -3.82727789879, 0.990055501461), Vec3(296.090484619, -0.604830980301, 0.0)),
|
||||||
|
)
|
||||||
|
self.controller.play_motion_path(mopath, 3.0)
|
||||||
|
|
||||||
|
def loadGUIFromJSON(self):
|
||||||
|
import sys
|
||||||
|
# 获取GUI元素JSON文件路径
|
||||||
|
if getattr(sys, 'frozen', False):
|
||||||
|
gui_json_path = os.path.join(os.path.dirname(sys.executable), "gui", "gui_elements.json")
|
||||||
|
else:
|
||||||
|
gui_json_path = "gui/gui_elements.json"
|
||||||
|
|
||||||
|
try:
|
||||||
|
if os.path.exists(gui_json_path):
|
||||||
|
with open(gui_json_path, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read().strip()
|
||||||
|
if content:
|
||||||
|
gui_data = json.loads(content)
|
||||||
|
self.createGUIElement(gui_data)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"加载GUI元素时出错: {str(e)}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def createGUIElement(self, element_data):
|
||||||
|
try:
|
||||||
|
processed_names = set()
|
||||||
|
element_original_data = {}
|
||||||
|
|
||||||
|
for i, gui_info in enumerate(element_data):
|
||||||
|
name = gui_info.get("name", f"gui_element_{i}")
|
||||||
|
element_original_data[name] = {
|
||||||
|
"scale": gui_info.get("scale", [1, 1, 1]),
|
||||||
|
"position": gui_info.get("position", [0, 0, 0]),
|
||||||
|
"parent_name": gui_info.get("parent_name")
|
||||||
|
}
|
||||||
|
valid_parents = set()
|
||||||
|
for gui_info in element_data:
|
||||||
|
name = gui_info.get("name", f"gui_element_{gui_info.get('index', 0)}")
|
||||||
|
valid_parents.add(name)
|
||||||
|
|
||||||
|
for i, gui_info in enumerate(element_data):
|
||||||
|
try:
|
||||||
|
gui_type = gui_info.get("type", "unknown")
|
||||||
|
name = gui_info.get("name", f"gui_element_{i}")
|
||||||
|
position = gui_info.get("position", [0, 0, 0])
|
||||||
|
scale = gui_info.get("scale", [1, 1, 1])
|
||||||
|
tags = gui_info.get("tags", {})
|
||||||
|
text = gui_info.get("text", "")
|
||||||
|
image_path = gui_info.get("image_path", "")
|
||||||
|
video_path = gui_info.get("video_path", "")
|
||||||
|
bg_image_path = gui_info.get("bg_image_path", "")
|
||||||
|
parent_name = gui_info.get("parent_name")
|
||||||
|
|
||||||
|
if name in processed_names:
|
||||||
|
continue
|
||||||
|
|
||||||
|
processed_names.add(name)
|
||||||
|
|
||||||
|
absolute_position = list(position)
|
||||||
|
absolute_scale = list(scale)
|
||||||
|
|
||||||
|
if parent_name and parent_name in element_original_data:
|
||||||
|
parent_data = element_original_data[parent_name]
|
||||||
|
parent_scale = parent_data["scale"]
|
||||||
|
|
||||||
|
if gui_type in ["3d_text", "3d_image", "button", "label", "entry", "2d_image",
|
||||||
|
"2d_video_screen"]:
|
||||||
|
# 位置需要乘以父级缩放来得到绝对位置
|
||||||
|
for j in range(min(len(absolute_position), len(parent_scale))):
|
||||||
|
absolute_position[j] *= parent_scale[j] if len(parent_scale) > j else parent_scale[0]
|
||||||
|
|
||||||
|
# 缩放需要乘以父级缩放来得到绝对缩放
|
||||||
|
for j in range(min(len(absolute_scale), len(parent_scale))):
|
||||||
|
absolute_scale[j] *= parent_scale[j] if len(parent_scale) > j else parent_scale[0]
|
||||||
|
|
||||||
|
new_element = None
|
||||||
|
|
||||||
|
if gui_type == "3d_text":
|
||||||
|
size = absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 0.5
|
||||||
|
new_element = self.createGUI3DText(
|
||||||
|
pos=tuple(absolute_position),
|
||||||
|
text=text,
|
||||||
|
size=size
|
||||||
|
)
|
||||||
|
elif gui_type == "button":
|
||||||
|
new_element = self.createGUIButton(
|
||||||
|
pos=tuple(absolute_position),
|
||||||
|
text=text,
|
||||||
|
size=absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 1.0,
|
||||||
|
command=self.resetWomenModel
|
||||||
|
)
|
||||||
|
elif gui_type == "label":
|
||||||
|
new_element = self.createGUILabel(
|
||||||
|
pos=tuple(absolute_position),
|
||||||
|
text=text,
|
||||||
|
size=absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 1.0
|
||||||
|
)
|
||||||
|
elif gui_type == "entry":
|
||||||
|
new_element = self.createGUIEntry(
|
||||||
|
pos=tuple(absolute_position),
|
||||||
|
placeholder=text,
|
||||||
|
size=absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 1.0,
|
||||||
|
command=self.onGUIEntrySubmit
|
||||||
|
)
|
||||||
|
elif gui_type == "2d_image":
|
||||||
|
|
||||||
|
scale_value = absolute_scale[0]
|
||||||
|
print(f"2d_image{scale_value}")
|
||||||
|
new_element = self.createGUI2DImage(
|
||||||
|
pos=tuple(absolute_position),
|
||||||
|
image_path=image_path,
|
||||||
|
size=absolute_scale
|
||||||
|
)
|
||||||
|
elif gui_type == "2d_video_screen":
|
||||||
|
scale_value = absolute_scale[0] if absolute_scale and len(absolute_scale) > 0 else 0.2
|
||||||
|
new_element = self.createGUI2DVideoScreen(
|
||||||
|
pos=tuple(absolute_position),
|
||||||
|
video_path=video_path,
|
||||||
|
size=scale_value * 0.2
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"重建GUI元素失败 {name}: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
continue
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"创建GUI元素时出错: {str(e)}")
|
||||||
|
|
||||||
|
def createGUIButton(self, pos=(0, 0, 0), text="按钮", size=0.1, command=None):
|
||||||
|
from direct.gui.DirectGui import DirectButton
|
||||||
|
|
||||||
|
button = DirectButton(
|
||||||
|
text=text,
|
||||||
|
pos=(pos[0], pos[1], pos[2]), # 保持正确的坐标格式
|
||||||
|
scale=size, # size 应该是数值而不是元组
|
||||||
|
frameColor=(0.2, 0.6, 0.8, 1),
|
||||||
|
text_font=self.getChineseFont() if self.getChineseFont() else None,
|
||||||
|
rolloverSound=None,
|
||||||
|
clickSound=None,
|
||||||
|
parent=None,
|
||||||
|
command=command
|
||||||
|
)
|
||||||
|
|
||||||
|
def createGUI3DText(self, pos=(0, 0, 0), text="3D文本", size=0.5):
|
||||||
|
"""创建3D文本GUI元素"""
|
||||||
|
try:
|
||||||
|
# 创建文本节点
|
||||||
|
text_node = TextNode("gui_3d_text")
|
||||||
|
text_node.setText(text)
|
||||||
|
text_node.setAlign(TextNode.ACenter)
|
||||||
|
|
||||||
|
# 设置字体(如果可用)
|
||||||
|
if self.getChineseFont():
|
||||||
|
text_node.setFont(self.getChineseFont())
|
||||||
|
|
||||||
|
# 创建节点路径并添加到场景
|
||||||
|
text_np = self.render.attachNewNode(text_node)
|
||||||
|
|
||||||
|
# 设置位置和大小
|
||||||
|
text_np.setPos(Vec3(pos[0], pos[1], pos[2]))
|
||||||
|
text_np.setScale(size)
|
||||||
|
|
||||||
|
# 设置面向摄像机
|
||||||
|
# text_np.setBillboardPointEye()
|
||||||
|
|
||||||
|
# 设置渲染属性
|
||||||
|
text_np.setBin("fixed", 40)
|
||||||
|
text_np.setDepthWrite(False)
|
||||||
|
|
||||||
|
return text_np
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 创建3D文本失败: {str(e)}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def createGUILabel(self, pos=(0, 0, 0), text="标签", size=0.08):
|
||||||
|
from direct.gui.DirectGui import DirectLabel
|
||||||
|
label = DirectLabel(
|
||||||
|
text=text,
|
||||||
|
pos=(pos[0], pos[1], pos[2]),
|
||||||
|
scale=size,
|
||||||
|
frameColor=(0, 0, 0, 0),
|
||||||
|
text_fg=(1, 1, 1, 1),
|
||||||
|
text_font=self.getChineseFont() if self.getChineseFont() else None,
|
||||||
|
text_align=TextNode.ACenter,
|
||||||
|
text_wordwrap=None,
|
||||||
|
text_mayChange=True,
|
||||||
|
parent=None
|
||||||
|
)
|
||||||
|
|
||||||
|
def createGUIEntry(self, pos=(0, 0, 0), placeholder="输入文本...", size=0.08, command=None):
|
||||||
|
from direct.gui.DirectGui import DirectEntry
|
||||||
|
|
||||||
|
entry = DirectEntry(
|
||||||
|
text="",
|
||||||
|
pos=(pos[0], pos[1], pos[2]),
|
||||||
|
scale=size,
|
||||||
|
command=command,
|
||||||
|
initialText=placeholder,
|
||||||
|
numLines=1,
|
||||||
|
width=12,
|
||||||
|
focus=0,
|
||||||
|
frameColor=(0, 0, 0, 0),
|
||||||
|
text_fg=(1, 1, 1, 1),
|
||||||
|
text_font=self.getChineseFont() if self.getChineseFont() else None,
|
||||||
|
text_align=TextNode.ACenter,
|
||||||
|
text_wordwrap=None,
|
||||||
|
text_mayChange=True,
|
||||||
|
parent=None,
|
||||||
|
rolloverSound=None,
|
||||||
|
clickSound=None,
|
||||||
|
# 添加焦点管理命令
|
||||||
|
focusInCommand=self.disableCameraControl,
|
||||||
|
focusOutCommand=self.enableCameraControl,
|
||||||
|
# 确保输入框能正确捕获所有键盘事件
|
||||||
|
suppressKeys=True, # 这个参数很重要,它会阻止按键事件传播到其他处理器
|
||||||
|
suppressMouse=True
|
||||||
|
)
|
||||||
|
return entry
|
||||||
|
|
||||||
|
def disableCameraControl(self):
|
||||||
|
"""禁用相机控制"""
|
||||||
|
try:
|
||||||
|
if hasattr(self, 'controller'):
|
||||||
|
# 如果控制器有内置的禁用方法
|
||||||
|
if hasattr(self.controller, 'disable'):
|
||||||
|
self.controller.disable()
|
||||||
|
else:
|
||||||
|
# 否则手动禁用事件监听
|
||||||
|
self.controller.ignoreAll() # 忽略所有已注册的事件
|
||||||
|
print("相机控制已禁用")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"禁用相机控制时出错: {e}")
|
||||||
|
|
||||||
|
def enableCameraControl(self):
|
||||||
|
"""启用相机控制"""
|
||||||
|
try:
|
||||||
|
if hasattr(self, 'controller'):
|
||||||
|
# 如果控制器有内置的启用方法
|
||||||
|
if hasattr(self.controller, 'enable'):
|
||||||
|
self.controller.enable()
|
||||||
|
else:
|
||||||
|
# 重新设置控制器
|
||||||
|
self.controller.setup()
|
||||||
|
print("相机控制已启用")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"启用相机控制时出错: {e}")
|
||||||
|
|
||||||
|
def onGUIEntrySubmit(self, text, entry_id=None):
|
||||||
|
"""GUI输入框提交事件处理"""
|
||||||
|
try:
|
||||||
|
print(f"GUI输入框提交: {entry_id} = {text}")
|
||||||
|
|
||||||
|
# 重新启用相机控制
|
||||||
|
self.enableCameraControl()
|
||||||
|
|
||||||
|
# 清除输入框焦点(如果需要)
|
||||||
|
# base.win.focus()
|
||||||
|
|
||||||
|
# 在这里添加您需要的文本处理逻辑
|
||||||
|
# 例如保存文本、更新UI等
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"处理输入框提交时出错: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def createGUI2DImage(self, pos=(0, 0, 0), image_path=None, size=0.2):
|
||||||
|
# 处理非均匀缩放
|
||||||
|
if isinstance(size, (list, tuple)) and len(size) >= 2:
|
||||||
|
# 分别处理宽度和高度的缩放
|
||||||
|
width_scale = size[0] * 0.2
|
||||||
|
height_scale = size[2] * 0.2
|
||||||
|
else:
|
||||||
|
# 如果只提供了一个缩放值,则使用相同值
|
||||||
|
width_scale = size * 0.1 if isinstance(size, (int, float)) else 0.2
|
||||||
|
height_scale = width_scale
|
||||||
|
|
||||||
|
cm = CardMaker("gui-2d-image")
|
||||||
|
cm.setFrame(-width_scale, width_scale, -height_scale, height_scale)
|
||||||
|
#cm.setFrame(-size, size, -size, size)
|
||||||
|
|
||||||
|
image_node = self.aspect2d.attachNewNode(cm.generate())
|
||||||
|
image_node.setPos(pos)
|
||||||
|
image_node.setBin("fixed", 0)
|
||||||
|
image_node.setDepthWrite(False)
|
||||||
|
image_node.setDepthTest(False)
|
||||||
|
image_node.setColor(1, 1, 1, 1)
|
||||||
|
|
||||||
|
# 设置透明度支持
|
||||||
|
image_node.setTransparency(TransparencyAttrib.MAlpha)
|
||||||
|
|
||||||
|
if image_path:
|
||||||
|
try:
|
||||||
|
texture = self.loader.loadTexture(image_path)
|
||||||
|
if texture:
|
||||||
|
image_node.setTexture(texture, 1)
|
||||||
|
texture.setWrapU(Texture.WM_clamp)
|
||||||
|
texture.setWrapV(Texture.WM_clamp)
|
||||||
|
texture.setMinfilter(Texture.FT_linear)
|
||||||
|
texture.setMagfilter(Texture.FT_linear)
|
||||||
|
image_node.setColor(1, 1, 1, 1)
|
||||||
|
else:
|
||||||
|
print(f"无法加载图片: {image_path}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"加载图片时出错: {e}")
|
||||||
|
|
||||||
|
def createGUI2DVideoScreen(self, pos=(0, 0, 0), size=0.2, video_path=None):
|
||||||
|
from direct.gui.DirectGui import DirectFrame
|
||||||
|
from panda3d.core import TransparencyAttrib, Texture, TextureStage
|
||||||
|
import os
|
||||||
|
|
||||||
|
video_screen = DirectFrame(
|
||||||
|
frameSize=(-size, size, -size, size),
|
||||||
|
frameColor=(1, 1, 1, 1),
|
||||||
|
pos=pos,
|
||||||
|
parent=None,
|
||||||
|
suppressMouse=True
|
||||||
|
)
|
||||||
|
video_screen.setTransparency(TransparencyAttrib.MAlpha)
|
||||||
|
|
||||||
|
placeholder_texture = Texture()
|
||||||
|
placeholder_texture.setup2dTexture(1, 1, Texture.TUnsignedByte, Texture.FRgb)
|
||||||
|
placeholder_data = b'\x19\x19\x4c'
|
||||||
|
placeholder_texture.setRamImage(placeholder_data)
|
||||||
|
|
||||||
|
if video_path and os.path.exists(video_path):
|
||||||
|
movie_texture = self._loadMovieTexture(video_path)
|
||||||
|
if movie_texture:
|
||||||
|
video_screen["frameTexture"] = movie_texture
|
||||||
|
|
||||||
|
def _loadMovieTexture(self, video_path):
|
||||||
|
from panda3d.core import Texture, MovieTexture
|
||||||
|
import os
|
||||||
|
movie_texture = MovieTexture(video_path)
|
||||||
|
if movie_texture.read(video_path):
|
||||||
|
self._configureVideoTexture(movie_texture)
|
||||||
|
return movie_texture
|
||||||
|
|
||||||
|
def _configureVideoTexture(self, texture):
|
||||||
|
from panda3d.core import Texture
|
||||||
|
|
||||||
|
texture.setWrapU(Texture.WM_clamp)
|
||||||
|
texture.setWrapV(Texture.WM_clamp)
|
||||||
|
texture.setMinfilter(Texture.FT_linear)
|
||||||
|
texture.setMagfilter(Texture.FT_linear)
|
||||||
|
|
||||||
|
if hasattr(texture, 'set_loop') and hasattr(texture, 'set_play_rate'):
|
||||||
|
texture.set_loop(True)
|
||||||
|
texture.set_play_rate(1.0)
|
||||||
|
|
||||||
|
def resetWomenModel(self):
|
||||||
|
"""调整 Women_1.glb 模型大小,实现从小到大再到小的完整循环效果"""
|
||||||
|
try:
|
||||||
|
# 查找 Women_1.glb 模型
|
||||||
|
women_models = self.render.findAllMatches("**/Women_1.glb*")
|
||||||
|
|
||||||
|
if women_models:
|
||||||
|
for model in women_models:
|
||||||
|
# 定义完整的缩放级别序列(从0.5到3.0再回到0.5)
|
||||||
|
scale_levels = [0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 2.5, 2.0, 1.5, 1.0, 0.5]
|
||||||
|
|
||||||
|
# 获取当前缩放值
|
||||||
|
current_scale = model.getScale()
|
||||||
|
|
||||||
|
# 查找当前最接近的缩放级别索引
|
||||||
|
current_index = 0
|
||||||
|
min_diff = float('inf')
|
||||||
|
for i, scale in enumerate(scale_levels):
|
||||||
|
diff = abs(current_scale.x - scale)
|
||||||
|
if diff < min_diff:
|
||||||
|
min_diff = diff
|
||||||
|
current_index = i
|
||||||
|
|
||||||
|
# 计算下一个缩放级别(循环)
|
||||||
|
next_index = (current_index + 1) % len(scale_levels)
|
||||||
|
next_scale = scale_levels[next_index]
|
||||||
|
|
||||||
|
# 应用新的缩放
|
||||||
|
model.setScale(next_scale)
|
||||||
|
print(f"✓ 调整模型 {model.getName()} 大小: {current_scale.x:.1f} -> {next_scale:.1f}")
|
||||||
|
print(f" 当前索引: {current_index}, 下一个索引: {next_index}")
|
||||||
|
else:
|
||||||
|
print("⚠️ 未找到 Women_1.glb 模型")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"调整模型大小时出错: {str(e)}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
app = MainApp()
|
||||||
|
app.run()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"应用程序启动失败: {str(e)}")
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
traceback.print_exc()
|
||||||
|
# 在Windows上可以使用下面的代码显示错误对话框
|
||||||
|
# input("按回车键退出...")
|
||||||
|
|
||||||
@ -3493,6 +3493,16 @@ class PropertyPanelManager:
|
|||||||
path_label.setWordWrap(True)
|
path_label.setWordWrap(True)
|
||||||
path_label.setStyleSheet("color: #00AAFF;")
|
path_label.setStyleSheet("color: #00AAFF;")
|
||||||
video_info_layout.addWidget(path_label, 0, 1)
|
video_info_layout.addWidget(path_label, 0, 1)
|
||||||
|
|
||||||
|
# 添加文件大小信息
|
||||||
|
try:
|
||||||
|
file_size = os.path.getsize(video_path)
|
||||||
|
file_size_mb = file_size / (1024 * 1024)
|
||||||
|
size_label = QLabel(f"大小: {file_size_mb:.2f} MB")
|
||||||
|
size_label.setStyleSheet("font-size: 10px; color: gray;")
|
||||||
|
video_info_layout.addWidget(size_label, 1, 1)
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
# 文件不存在
|
# 文件不存在
|
||||||
video_info_layout.addWidget(QLabel("状态:"), 0, 0)
|
video_info_layout.addWidget(QLabel("状态:"), 0, 0)
|
||||||
@ -3849,8 +3859,9 @@ class PropertyPanelManager:
|
|||||||
if success:
|
if success:
|
||||||
print(f"成功加载新视频: {file_path}")
|
print(f"成功加载新视频: {file_path}")
|
||||||
# 刷新属性面板以显示新视频信息
|
# 刷新属性面板以显示新视频信息
|
||||||
self._stop2DVideo(video_screen)
|
|
||||||
self.updateGUIPropertyPanel(video_screen, item)
|
self.updateGUIPropertyPanel(video_screen, item)
|
||||||
|
#self._stop2DVideo(video_screen)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"加载新视频失败: {e}")
|
print(f"加载新视频失败: {e}")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user