1
0
forked from Rowland/EG

调整打包后相机

This commit is contained in:
Hector 2025-09-29 11:25:19 +08:00
parent 9633a32c3b
commit 79b2547446
3 changed files with 289 additions and 60 deletions

View File

@ -52,7 +52,11 @@ class MainApp(ShowBase):
# Load the scene
model = loader.loadModel("scene/scene.bam")
# model = loader.loadModel("scene2/Scene.bam")
model_0 = self.loader.loadModel("/home/tiger/下载/Benci/source/s65/s65/s65.fbx")
model_0.reparentTo(self.render)
model_0.setScale(0.01)
model_0.setPos(-8, 42, 0)
model_0.setHpr(0, 90, 0)
model.reparent_to(render)
self.render_pipeline.prepare_scene(model)

View File

@ -403,8 +403,6 @@ class ProjectManager:
self._copyScriptSystemToBuild(build_dir)
self._copyInfoPanelSystemToBuild(build_dir)
source_render_pipeline = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),"RenderPipelineFile")
dest_render_pipeline = os.path.join(build_dir,"RenderPipelineFile")
@ -463,55 +461,25 @@ class ProjectManager:
except Exception as e:
print(f"⚠️ 复制脚本文件时出错: {str(e)}")
def _copyScriptSystemToBuild(self, build_dir):
"""复制core/script_system.py文件到构建目录"""
try:
# 源文件路径
source_script_system = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "core",
"script_system.py")
def _copyScriptSystemToBuild(self,build_dir):
core_files = [
"script_system.py",
"InfoPanelManager.py",
"CustomMouseController.py"
]
# 目标目录
core_dest = os.path.join(build_dir, "core")
source_core_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),"core")
# 如果源文件存在
if os.path.exists(source_script_system):
# 确保目标目录存在
if not os.path.exists(core_dest):
os.makedirs(core_dest)
core_dest = os.path.join(build_dir,"core")
# 复制文件
shutil.copy2(source_script_system, os.path.join(core_dest, "script_system.py"))
print("✓ core/script_system.py文件已复制到build目录")
else:
print("⚠️ core/script_system.py文件未找到")
if not os.path.exists(core_dest):
os.makedirs(core_dest)
except Exception as e:
print(f"⚠️ 复制core/script_system.py文件时出错: {str(e)}")
for file_name in core_files:
source_file = os.path.join(source_core_dir,file_name)
def _copyInfoPanelSystemToBuild(self, build_dir):
"""复制core/script_system.py文件到构建目录"""
try:
# 源文件路径
source_InfoPanel_system = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "core",
"InfoPanelManager.py")
# 目标目录
core_dest = os.path.join(build_dir, "core")
# 如果源文件存在
if os.path.exists(source_InfoPanel_system):
# 确保目标目录存在
if not os.path.exists(core_dest):
os.makedirs(core_dest)
# 复制文件
shutil.copy2(source_InfoPanel_system, os.path.join(core_dest, "InfoPanelManager.py"))
print("✓ core/InfoPanelManager.py文件已复制到build目录")
else:
print("⚠️ core/InfoPanelManager.py文件未找到")
except Exception as e:
print(f"⚠️ 复制core/InfoPanelManager.py文件时出错: {str(e)}")
if os.path.exists(source_file):
shutil.copy2(source_file,os.path.join(core_dest,file_name))
def _saveGUIElementsToJSON(self, build_dir, project_path):
"""保存GUI元素到JSON文件内容与_collectGUIElementInfo保持一致"""

View File

@ -11,7 +11,7 @@ from __future__ import print_function
import json
from direct.actor.Actor import Actor
from panda3d.core import TextNode, CardMaker, TextureStage, NodePath, Texture, TransparencyAttrib
from panda3d.core import TextNode, CardMaker, TextureStage, NodePath, Texture, TransparencyAttrib, CollisionTraverser
from core.InfoPanelManager import InfoPanelManager
# 获取渲染管线路径
# 在文件开头添加sys导入如果还没有的话
@ -52,6 +52,8 @@ from direct.task.TaskManagerGlobal import taskMgr
# os.chdir(os.path.dirname(os.path.realpath(__file__)))
from core.script_system import ScriptManager
from core.CustomMouseController import CustomMouseController
from panda3d.core import CollisionTraverser
class MainApp(ShowBase):
def __init__(self):
@ -109,10 +111,16 @@ class MainApp(ShowBase):
print(f"导入MovementController失败: {e}")
self.controller = None
self._last_click_time = 0
self._last_clicked_node = None
self._double_click_threshold = 0.3
self._loadFont()
self.loadFullScene()
self.loadGUIFromJSON()
self.setupMouseClickHandler()
self.cTrav = CollisionTraverser()
if hasattr(self, 'accept'):
base.accept("l", self.tour)
@ -758,35 +766,284 @@ class MainApp(ShowBase):
print(f"正在为元素 {element.getName()} 挂载脚本")
print(f"可用脚本列表: {self.script_manager.get_available_scripts()}")
if not hasattr(self,'script_manager'):
print("脚本管理器未初始化")
return
for script_info in script_info_list:
script_name = script_info["name"]
script_file = script_info.get("file", "")
# 从文件路径中提取脚本类名
if script_file:
# 获取脚本文件名(不含路径和扩展名)
script_filename = os.path.basename(script_file)
script_class_name = os.path.splitext(script_filename)[0]
print(f"尝试挂载脚本: {script_class_name} (来自文件: {script_file})")
# 使用脚本管理器为元素添加脚本
script_component = self.script_manager.add_script_to_object(element, script_class_name)
if script_name:
script_component = self.script_manager.add_script_to_object(element,script_name)
if script_component:
print(f"✓ 脚本 {script_class_name} 已挂载到元素 {element.getName()}")
print(f"✓ 脚本 {script_name} 已挂载到元素 {element.getName()}")
else:
print(f"⚠️ 脚本 {script_class_name} 挂载失败")
print(f"⚠️ 脚本 {script_name} 挂载失败")
# 列出可用脚本帮助调试
available_scripts = self.script_manager.get_available_scripts()
print(f"当前可用脚本: {available_scripts}")
else:
print(f"⚠️ 脚本信息不完整: {script_name}")
print(f"⚠️ 脚本信息不完整: {script_info}")
# # 从文件路径中提取脚本类名
# if script_file:
# # 获取脚本文件名(不含路径和扩展名)
# script_filename = os.path.basename(script_file)
# script_class_name = os.path.splitext(script_filename)[0]
# print(f"尝试挂载脚本: {script_class_name} (来自文件: {script_file})")
#
# # 使用脚本管理器为元素添加脚本
# script_component = self.script_manager.add_script_to_object(element, script_class_name)
#
# if script_component:
# print(f"✓ 脚本 {script_class_name} 已挂载到元素 {element.getName()}")
# else:
# print(f"⚠️ 脚本 {script_class_name} 挂载失败")
# # 列出可用脚本帮助调试
# available_scripts = self.script_manager.get_available_scripts()
# print(f"当前可用脚本: {available_scripts}")
# else:
# print(f"⚠️ 脚本信息不完整: {script_name}")
except Exception as e:
print(f"挂载脚本到元素 {element.getName()} 失败: {str(e)}")
import traceback
traceback.print_exc()
def checkDoubleClick(self,nodePath):
try:
import time
current_time = time.time()
is_double_click = (self._last_clicked_node == nodePath and
nodePath is not None and
current_time - self._last_click_time<self._double_click_threshold)
if is_double_click:
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 False
except Exception as e:
print(f"双击检测失败:{e}")
return False
def focusCameraOnNode(self,nodePath):
try:
if not nodePath or nodePath.isEmpty():
print("无效的节点")
return
bounds = nodePath.getBounds()
if bounds.isEmpty():
center = nodePath.getPos()
size = 1.0
else:
center = bounds.getCenter()
size = bounds.getRadius()
current_cam_pos = self.cam.getPos()
current_cam_hpr = self.cam.getHpr()
view_direction = current_cam_pos - center
if view_direction.length()<0.001:
view_direction = Vec3(5,-5,2)
view_direction.normalize()
optimal_distance = max(size*2,3.0)
target_cam_pos = center + (view_direction * optimal_distance)
temp_node = self.render.attachNewNode("temp_lookat_target")
temp_node.setPos(center)
dummy_cam = self.render.attachNewNode("dummy_camera")
dummy_cam.setPos(target_cam_pos)
dummy_cam.lookAt(temp_node)
target_cam_hpr = Vec3(dummy_cam.getHpr())
temp_node.removeNode()
dummy_cam.removeNode()
self._startCameraFocusAnimation(current_cam_pos,target_cam_pos,current_cam_hpr,target_cam_hpr)
except Exception as e:
print(f"聚焦到节点失败{e}")
def _startCameraFocusAnimation(self,start_pos,end_pos,start_hpr,end_hpr):
try:
class CameraFocusData:
def __init__(self,start_pos,end_pos,start_hpr,end_hpr):
self.start_pos = start_pos
self.end_pos = end_pos
self.start_hpr = start_hpr
self.end_hpr = end_hpr
self.elapsed_time = 0
self.duration = 0.5
self._camera_focus_data = CameraFocusData(start_pos,end_pos,start_hpr,end_hpr)
from direct.task.TaskManagerGlobal import taskMgr
taskMgr.remove("cameraFocusTask")
taskMgr.add(self._cameraFocusTask, "cameraFocusTask")
except Exception as e:
print(f"启动摄像机聚焦动画失败{e}")
def _normalizeAngle(self,angle):
while angle >180:
angle -= 360
while angle < -180:
angle += 360
return angle
def _cameraFocusTask(self,task):
try:
if not hasattr(self,'_camera_focus_data'):
return task.done
data = self._camera_focus_data
from direct.showbase.ShowBaseGlobal import globalClock
data.elapsed_time += globalClock.getDt()
t = min(1.0,data.elapsed_time/data.duration)
smooth_t = t*t*(3-2*t)
current_pos = data.start_pos + (data.end_pos - data.start_pos) * smooth_t
self.cam.setPos(current_pos)
start_h = self._normalizeAngle(data.start_hpr.x)
end_h = self._normalizeAngle(data.end_hpr.x)
start_p = self._normalizeAngle(data.start_hpr.y)
end_p = self._normalizeAngle(data.end_hpr.y)
start_r = self._normalizeAngle(data.start_hpr.z)
end_r = self._normalizeAngle(data.end_hpr.z)
if abs(end_h - start_h)>180:
if end_h > start_h:
start_h += 360
else:
end_h += 360
if abs(end_p - start_p) > 180:
if end_p > start_p:
start_p += 360
else:
end_p += 360
if abs(end_r - start_r)>180:
if end_r > start_r:
start_r += 360
else:
end_r += 360
current_hpr = Vec3(
start_h + (end_h - start_h)*smooth_t,
start_p + (end_p - start_p)*smooth_t,
start_r + (end_r - start_r)*smooth_t
)
current_hpr.x = self._normalizeAngle(current_hpr.x)
current_hpr.y = self._normalizeAngle(current_hpr.y)
current_hpr.z = self._normalizeAngle(current_hpr.z)
self.cam.setHpr(current_hpr)
if t>=1.0:
return task.done
return task.cont
except Exception as e:
print(f"摄像机聚焦动画失败{e}")
return task.done
def setupMouseClickHandler(self):
try:
self.accept("mouse1", self.onMouseClick)
if not hasattr(self,'mouseWatcherNode'):
from panda3d.core import MouseWatcher
self.mouseWatcherNode = MouseWatcher()
except Exception as e:
print(f"设置鼠标点击处理器失败: {e}")
def onMouseClick(self):
try:
if not hasattr(self, 'mouseWatcherNode') or not self.mouseWatcherNode.hasMouse():
return
mouse_pos = self.mouseWatcherNode.getMouse()
from panda3d.core import CollisionRay, CollisionNode, CollisionHandlerQueue, BitMask32
from panda3d.core import GeomNode
# 创建射线
ray = CollisionRay()
ray.setFromLens(self.camNode, mouse_pos.x, mouse_pos.y)
# 创建碰撞节点
ray_node = CollisionNode('mouseRay')
ray_node.addSolid(ray)
ray_node.setFromCollideMask(BitMask32.bit(0))
# 附加到相机
ray_np = self.camera.attachNewNode(ray_node)
# 创建碰撞队列
handler = CollisionHandlerQueue()
# 修复语法错误:正确初始化碰撞遍历器
if not hasattr(self, 'cTrav') or self.cTrav is None:
self.cTrav = CollisionTraverser()
self.cTrav.addCollider(ray_np, handler)
self.cTrav.traverse(self.render)
# 检查碰撞结果
if handler.getNumEntries() > 0:
# 按距离排序
handler.sortEntries()
# 获取最近的碰撞节点
entry = handler.getEntry(0)
clicked_node = entry.getIntoNodePath()
# 向上遍历找到可选择的父节点
current_node = clicked_node
while current_node and not current_node.isEmpty():
# 检查节点是否应该被选择
if (current_node.hasTag("is_scene_element") or
current_node.hasTag("element_type") or
current_node.getName() not in ["render", "camera", "ambient_light", "directional_light"]):
# 检查是否为双击
if self.checkDoubleClick(current_node):
print(f"双击节点: {current_node.getName()}")
self.focusCameraOnNode(current_node)
break
else:
print(f"单击节点: {current_node.getName()}")
current_node = current_node.getParent()
# 避免无限循环
if current_node.getName() == "render":
break
# 清理碰撞器
ray_np.removeNode()
except Exception as e:
print(f"处理鼠标点击失败: {e}")
import traceback
traceback.print_exc()
# 在 main.py 的最后部分,修改为:
if __name__ == "__main__":