修复引用更改问题

This commit is contained in:
Hector 2025-10-29 10:35:38 +08:00
parent 944ee53d64
commit 85f61bd78a
4 changed files with 2 additions and 552 deletions

View File

@ -10,25 +10,19 @@ project_root = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, project_root)
sys.path.insert(0, render_pipeline_path)
# 现在你可以导入 RenderPipelineFile 中的模块了
# 例如,如果你想导入 RenderPipelineFile 中的 RenderPipeline 模块
from RenderPipelineFile.rpcore import RenderPipeline
_global_render_pipeline = None
# PyQt imports
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
# Panda imports
from panda3d.core import *
from panda3d.core import GraphicsOutput, Texture, ConfigVariableManager, WindowProperties
# Set up Panda environment
from direct.showbase.ShowBase import ShowBase
import platform
# Local imports
from QMeta3D.QMouseWatcherNode import QMouseWatcherNode
from RenderPipelineFile.rpcore.render_target import RenderTarget

View File

@ -1,18 +1,7 @@
# -*- coding: utf-8-*-
"""
Module : QMouseWatcherNode
Author : Niklas Mevenkamp
Description :
This is a MouseWatcherNode implementation that accesses
mouse position and button states through a parent QWidget.
"""
# PyQt imports
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
# Panda imports
from panda3d.core import *
__all__ = ["QMouseWatcherNode"]
@ -25,14 +14,11 @@ class QMouseWatcherNode(MouseWatcher):
self.parent = parent
def getMouse(self, *args, **kwargs):
# map global QCursor pixel position to parent Widget coordinates
pos = self.parent.mapFromGlobal(QCursor.pos())
# map absolute pixel positions to relative ones
rel_x = -1 + 2 * pos.x() / self.parent.width()
rel_y = -1 + 2 * pos.y() / self.parent.height()
# invert y
rel_y = -rel_y
return LPoint2(rel_x, rel_y)

View File

@ -1,171 +0,0 @@
<!-- /home/tiger/音乐/EG/cesium_offline.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>离线 Cesium 地图</title>
<!-- 使用本地 Cesium 文件 -->
<script src="Cesium-1.132/Build/Cesium/Cesium.js"></script>
<link rel="stylesheet" href="Cesium-1.132/Build/Cesium/Widgets/widgets.css">
<style>
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
}
#loadingOverlay {
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
justify-content: center;
align-items: center;
color: white;
font-family: sans-serif;
z-index: 1000;
}
#loadingOverlay.hidden {
display: none;
}
#errorInfo {
position: absolute;
top: 10px;
left: 10px;
color: red;
background: rgba(0,0,0,0.7);
padding: 10px;
border-radius: 5px;
z-index: 1001;
display: none;
}
</style>
</head>
<body>
<div id="cesiumContainer"></div>
<div id="loadingOverlay">
<h2>正在加载 Cesium 地图...</h2>
<div id="loadingStatus"></div>
</div>
<div id="errorInfo"></div>
<script>
// 显示加载状态
document.getElementById('loadingStatus').innerHTML = '正在初始化 Cesium...';
// 错误处理函数
function showError(message) {
console.error('Cesium Error:', message);
document.getElementById('errorInfo').innerHTML = '错误: ' + message;
document.getElementById('errorInfo').style.display = 'block';
document.getElementById('loadingOverlay').innerHTML = '<h2>加载失败</h2><p>' + message + '</p>';
}
// 检查 Cesium.js 是否加载成功
if (typeof Cesium === 'undefined') {
showError('Cesium.js 文件未找到或加载失败,请检查文件路径');
} else {
try {
// 使用最基本的配置确保能显示
var viewer = new Cesium.Viewer('cesiumContainer');
// 设置蓝色地球
viewer.scene.globe.baseColor = new Cesium.Color(0.1, 0.3, 0.8, 1.0);
// 隐藏加载界面
document.getElementById('loadingOverlay').className = 'hidden';
// 设置初始视角
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(0, 0, 25000000.0)
});
// Cesium API 接口供 Python 调用
window.CesiumAPI = {
// 添加模型
addModel: function(modelId, url, position, scale) {
try {
console.log('CesiumAPI.addModel 被调用:', {modelId, url, position, scale});
// 验证参数
if (!modelId || !url) {
console.error('模型ID或URL为空');
return {success: false, message: 'Model ID or URL is empty'};
}
if (!position || typeof position.longitude === 'undefined' || typeof position.latitude === 'undefined') {
console.error('位置参数无效');
return {success: false, message: 'Invalid position parameters'};
}
var cartographicPosition = Cesium.Cartographic.fromDegrees(
position.longitude,
position.latitude,
position.height || 0
);
var cartesianPosition = Cesium.Cartographic.toCartesian(cartographicPosition);
var entity = viewer.entities.add({
id: modelId,
position: cartesianPosition,
model: {
uri: url,
scale: scale || 1.0,
minimumPixelSize: 128,
maximumScale: 20000
}
});
// 尝试飞到模型位置以便查看
viewer.zoomTo(entity).then(function() {
console.log('成功飞到模型位置:', modelId);
}).catch(function(error) {
console.warn('飞到模型位置失败:', error);
});
console.log('模型添加成功:', modelId);
return {success: true, message: '模型添加成功'};
} catch (error) {
console.error('Add model error:', error);
return {success: false, message: error.message};
}
},
// 移除模型
removeModel: function(modelId) {
try {
var entity = viewer.entities.getById(modelId);
if (entity) {
viewer.entities.remove(entity);
return {success: true, message: '模型移除成功'};
} else {
return {success: false, message: '未找到指定模型'};
}
} catch (error) {
console.error('Remove model error:', error);
return {success: false, message: error.message};
}
},
// 飞行到指定位置
flyToPosition: function(longitude, latitude, height) {
try {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, height || 10000),
duration: 2.0
});
return {success: true, message: '视角飞行中'};
} catch (error) {
console.error('Fly to error:', error);
return {success: false, message: error.message};
}
}
};
console.log('✅ Cesium 离线环境已准备就绪');
} catch (initError) {
showError('Cesium 初始化失败: ' + initError.message);
console.error('Cesium initialization error:', initError);
}
}
</script>
</body>
</html>

View File

@ -1,11 +1,3 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
项目管理器 - 负责项目的生命周期管理
处理项目创建打开保存打包等功能
"""
import os
import sys
import json
@ -22,13 +14,9 @@ from PyQt5.QtCore import Qt
from ui.widgets import NewProjectDialog, UniversalMessageDialog
class ProjectManager:
"""项目管理器 - 统一管理项目的生命周期"""
def __init__(self, world):
"""初始化项目管理器
Args:
world: 主程序world对象引用
"""
self.world = world
self.current_project_path = None
self.project_config = None
@ -821,353 +809,6 @@ class ProjectManager:
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):
"""创建优化的标准setup.py文件"""
setup_code = f'''#!/usr/bin/env python3