1
0
forked from Rowland/EG

Merge remote-tracking branch 'origin/main_ch_eg' into addRender

# Conflicts:
#	RenderPipelineFile/config/daytime.yaml
#	ui/interface_manager.py
#	ui/main_window.py
#	ui/property_panel.py
This commit is contained in:
Hector 2025-10-20 10:29:23 +08:00
commit e38876f6d8
26 changed files with 5688 additions and 1367 deletions

54
.gitignore vendored
View File

@ -1,3 +1,57 @@
__pycache__/ __pycache__/
*.pyc *.pyc
.idea/ .idea/
【模板】模型及算法与功能对应清单.docx
【模板】GY知识-产品模块架构及功能清单和主要应用场景说明.docx
1.json
2.json
3.json
4.json
6.json
功能清单.md
模型及算法与功能对应清单(完整版).md
维修系统使用说明.md
audio_demo_config.json
create_test_audio.py
demo_universal_dialog.py
Dock按钮样式统一说明.md
Dock面板标题样式线完成说明.md
exam_result_20250926_004454.json
exam_result_20250926_010628.json
exam_result_20250926_011746.json
exam_result_20250926_090330.json
exam_result_20250926_111756.json
exam_test_config.json
Figma布局优化说明.md
Figma设计分析与菜单栏优化文档.md
Figma样式优化完成说明.md
manual_tools_config.json
pm.txt
simple_menubar_test.py
test_audio.py
test_basic_audio.py
test_exam_tool_error.py
test_full_audio_playback.py
test_menu_visibility.py
test_mode_selection.py
test_mp3_audio.py
test_pygame_audio.py
test_score_config.py
test_simple_audio.py
tool_test_config.json
UI设计文档.md
UniversalMessageDialog使用说明.md
.codex/settings/kiroCodex-settings.json
data/projects.json
RenderPipelineFile/config/daytime.yaml
Resources/audio/README.md
Resources/model/a.glb
Resources/model/b.glb
Resources/model/c.glb
Resources/model/JQB_auto_converted.glb
Resources/model/Untitled.glb
Resources/models/Women_1.glb
Subjects/test_maintenance_config.json
Resources/models/Women_1.glb
Resources/models/Women_1.glb
Resources/models/Women_1.glb

View File

@ -49,6 +49,8 @@ from rplibs.pyqt_imports import * #noqa
# Load the generated UI Layout # Load the generated UI Layout
from ui.main_window_generated import Ui_MainWindow # noqa from ui.main_window_generated import Ui_MainWindow # noqa
from ui.widgets import UniversalMessageDialog
from rpcore.pluginbase.manager import PluginManager # noqa from rpcore.pluginbase.manager import PluginManager # noqa
from rpcore.util.network_communication import NetworkCommunication # noqa from rpcore.util.network_communication import NetworkCommunication # noqa
from rpcore.mount_manager import MountManager # noqa from rpcore.mount_manager import MountManager # noqa
@ -119,9 +121,13 @@ class PluginConfigurator(QMainWindow, Ui_MainWindow):
self, "Warning", msg, QMessageBox.Yes, QMessageBox.No) self, "Warning", msg, QMessageBox.Yes, QMessageBox.No)
if reply == QMessageBox.Yes: if reply == QMessageBox.Yes:
QMessageBox.information( UniversalMessageDialog.show_success(
self, "Success", self,
"Settings have been reset! You may have to restart the pipeline.") "Success",
"Settings have been reset! You may have to restart the pipeline.",
show_cancel=False,
confirm_text="OK"
)
self._plugin_mgr.reset_plugin_settings(self._current_plugin) self._plugin_mgr.reset_plugin_settings(self._current_plugin)
# Save config # Save config

0
Resources/a Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
icons/close_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

BIN
icons/delete_fail_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

BIN
icons/down_arrows.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
icons/left_arrows.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
icons/minimize_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

BIN
icons/right_arrows.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
icons/solid_down_arrows.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
icons/success_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

BIN
icons/up_arrows.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
icons/warning_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

BIN
icons/windowing_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

8
new/project.json Normal file
View File

@ -0,0 +1,8 @@
{
"name": "new",
"path": "D:\\PythonProject\\CH_EG\\EG\\new",
"created_at": "2025-09-09 16:47:27",
"last_modified": "2025-09-11 09:28:24",
"version": "1.0.0",
"engine_version": "1.0.0"
}

View File

@ -19,7 +19,7 @@ from PyQt5.QtWidgets import (
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
# 导入自定义对话框 # 导入自定义对话框
from ui.widgets import NewProjectDialog from ui.widgets import NewProjectDialog, UniversalMessageDialog
class ProjectManager: class ProjectManager:
"""项目管理器 - 统一管理项目的生命周期""" """项目管理器 - 统一管理项目的生命周期"""
@ -103,11 +103,23 @@ class ProjectManager:
parent_window.current_project_path = full_project_path parent_window.current_project_path = full_project_path
# 显示成功消息 # 显示成功消息
QMessageBox.information(parent_window, "成功", f"项目 '{project_name}' 创建成功!") UniversalMessageDialog.show_success(
parent_window,
"成功",
f"项目 '{project_name}' 创建成功!",
show_cancel=False,
confirm_text="确认"
)
return True return True
except Exception as e: except Exception as e:
QMessageBox.critical(parent_window, "错误", f"创建项目失败: {str(e)}") UniversalMessageDialog.show_error(
parent_window,
"错误",
f"创建项目失败: {str(e)}",
show_cancel=False,
confirm_text="确认"
)
return False return False
def openProject(self, parent_window): def openProject(self, parent_window):
@ -127,7 +139,13 @@ class ProjectManager:
# 检查是否是有效的项目文件夹 # 检查是否是有效的项目文件夹
config_file = os.path.join(project_path, "project.json") config_file = os.path.join(project_path, "project.json")
if not os.path.exists(config_file): if not os.path.exists(config_file):
QMessageBox.warning(parent_window, "警告", "选择的不是有效的项目文件夹!") UniversalMessageDialog.show_warning(
parent_window,
"警告",
"选择的不是有效的项目文件夹!",
show_cancel=False,
confirm_text="确认"
)
return False return False
# 读取项目配置 # 读取项目配置
@ -161,7 +179,13 @@ class ProjectManager:
if hasattr(parent_window, 'fileView') and hasattr(parent_window, 'fileModel'): if hasattr(parent_window, 'fileView') and hasattr(parent_window, 'fileModel'):
parent_window.fileView.setRootIndex(parent_window.fileModel.index(project_path)) parent_window.fileView.setRootIndex(parent_window.fileModel.index(project_path))
QMessageBox.information(parent_window, "成功", "项目加载成功!") UniversalMessageDialog.show_success(
parent_window,
"成功",
"项目加载成功!",
show_cancel=False,
confirm_text="确认"
)
return True return True
# 检查场景文件 # 检查场景文件
# scene_file = os.path.join(project_path, "scenes", "scene.bam") # scene_file = os.path.join(project_path, "scenes", "scene.bam")
@ -200,7 +224,13 @@ class ProjectManager:
# return False # return False
except Exception as e: except Exception as e:
QMessageBox.critical(parent_window, "错误", f"加载项目时发生错误:{str(e)}") UniversalMessageDialog.show_error(
parent_window,
"错误",
f"加载项目时发生错误:{str(e)}",
show_cancel=False,
confirm_text="确认"
)
return False return False
def openProjectForPath(self, project_path, parent_window=None): def openProjectForPath(self, project_path, parent_window=None):
@ -217,7 +247,13 @@ class ProjectManager:
config_file = os.path.join(project_path, "project.json") config_file = os.path.join(project_path, "project.json")
if not os.path.exists(config_file): if not os.path.exists(config_file):
if parent_window: if parent_window:
QMessageBox.warning(parent_window, "警告", f"选择的不是有效的项目文件夹!{project_path}") UniversalMessageDialog.show_warning(
parent_window,
"警告",
f"选择的不是有效的项目文件夹!{project_path}",
show_cancel=False,
confirm_text="确认"
)
else: else:
print("警告: 选择的不是有效的项目文件夹!") print("警告: 选择的不是有效的项目文件夹!")
return False return False
@ -255,13 +291,25 @@ class ProjectManager:
if hasattr(parent_window, 'fileView') and hasattr(parent_window, 'fileModel'): if hasattr(parent_window, 'fileView') and hasattr(parent_window, 'fileModel'):
parent_window.fileView.setRootIndex(parent_window.fileModel.index(project_path)) parent_window.fileView.setRootIndex(parent_window.fileModel.index(project_path))
QMessageBox.information(parent_window, "成功", "项目加载成功!") UniversalMessageDialog.show_success(
parent_window,
"成功",
"项目加载成功!",
show_cancel=False,
confirm_text="确认"
)
print(f"项目 '{project_path}' 加载成功!") print(f"项目 '{project_path}' 加载成功!")
return True return True
else: else:
if parent_window: if parent_window:
QMessageBox.warning(parent_window, "错误", "加载场景失败!") UniversalMessageDialog.show_warning(
parent_window,
"错误",
"加载场景失败!",
show_cancel=False,
confirm_text="确认"
)
else: else:
print("错误: 加载场景失败!") print("错误: 加载场景失败!")
return False return False
@ -269,7 +317,13 @@ class ProjectManager:
except Exception as e: except Exception as e:
error_msg = f"加载项目时发生错误:{str(e)}" error_msg = f"加载项目时发生错误:{str(e)}"
if parent_window: if parent_window:
QMessageBox.critical(parent_window, "错误", error_msg) UniversalMessageDialog.show_error(
parent_window,
"错误",
error_msg,
show_cancel=False,
confirm_text="确认"
)
else: else:
print(error_msg) print(error_msg)
return False return False
@ -283,7 +337,13 @@ class ProjectManager:
if hasattr(parent_window, 'current_project_path'): if hasattr(parent_window, 'current_project_path'):
self.current_project_path = parent_window.current_project_path self.current_project_path = parent_window.current_project_path
else: else:
QMessageBox.warning(parent_window, "警告", "请先创建或打开一个项目!") UniversalMessageDialog.show_warning(
parent_window,
"警告",
"请先创建或打开一个项目!",
show_cancel=False,
confirm_text="确认"
)
return False return False
project_path = self.current_project_path project_path = self.current_project_path
@ -324,14 +384,32 @@ class ProjectManager:
project_name = os.path.basename(project_path) project_name = os.path.basename(project_path)
self.updateWindowTitle(parent_window, project_name) self.updateWindowTitle(parent_window, project_name)
QMessageBox.information(parent_window, "成功", "项目保存成功!") UniversalMessageDialog.show_success(
parent_window,
"成功",
"项目保存成功!",
show_cancel=False,
confirm_text="确认"
)
return True return True
else: else:
QMessageBox.warning(parent_window, "错误", "保存场景失败!") UniversalMessageDialog.show_warning(
parent_window,
"错误",
"保存场景失败!",
show_cancel=False,
confirm_text="确认"
)
return False return False
except Exception as e: except Exception as e:
QMessageBox.critical(parent_window, "错误", f"保存项目时发生错误:{str(e)}") UniversalMessageDialog.show_error(
parent_window,
"错误",
f"保存项目时发生错误:{str(e)}",
show_cancel=False,
confirm_text="确认"
)
return False return False
# ==================== 项目打包功能 ==================== # ==================== 项目打包功能 ====================
@ -1492,4 +1570,4 @@ def updateWindowTitle(window, project_name=None):
if project_name: if project_name:
window.setWindowTitle(f"{base_title} - {project_name}") window.setWindowTitle(f"{base_title} - {project_name}")
else: else:
window.setWindowTitle(base_title) window.setWindowTitle(base_title)

277
quick_menu_fix.py Normal file
View File

@ -0,0 +1,277 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
快速菜单栏修复脚本
用于诊断和修复菜单栏显示问题
"""
import sys
import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QVBoxLayout, QWidget, QPushButton
from PyQt5.QtCore import Qt, QTimer
# 设置环境变量避免DPI问题
os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"
os.environ["QT_SCALE_FACTOR"] = "1"
class QuickMenuFix(QMainWindow):
def __init__(self):
super().__init__()
self.setupUI()
def setupUI(self):
"""设置UI"""
self.setWindowTitle("菜单栏快速修复工具")
self.setGeometry(300, 300, 900, 700)
# 强制窗口标志
self.setWindowFlags(Qt.Window)
# 设置主窗口样式
self.setStyleSheet("""
QMainWindow {
background-color: #1E1E1E;
color: #FFFFFF;
}
QPushButton {
background-color: #0078D4;
color: white;
border: none;
padding: 10px 20px;
margin: 5px;
border-radius: 5px;
font-size: 12px;
}
QPushButton:hover {
background-color: #106EBE;
}
QPushButton:pressed {
background-color: #005A9E;
}
""")
# 创建中央部件
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
# 标题
title = QLabel("🔧 菜单栏修复工具")
title.setStyleSheet("font-size: 24px; font-weight: bold; color: #0078D4; margin: 20px;")
title.setAlignment(Qt.AlignCenter)
layout.addWidget(title)
# 状态显示
self.status_label = QLabel("准备就绪...")
self.status_label.setStyleSheet("font-size: 14px; color: white; margin: 10px; padding: 10px; background-color: #2D2D30; border-radius: 5px;")
self.status_label.setAlignment(Qt.AlignCenter)
layout.addWidget(self.status_label)
# 按钮区域
button_layout = QVBoxLayout()
# 测试按钮
test_btn = QPushButton("🔍 测试菜单栏显示")
test_btn.clicked.connect(self.testMenuBar)
button_layout.addWidget(test_btn)
# 修复按钮
fix_btn = QPushButton("🛠️ 强制修复菜单栏")
fix_btn.clicked.connect(self.forceFixMenuBar)
button_layout.addWidget(fix_btn)
# 重置按钮
reset_btn = QPushButton("🔄 重置菜单栏样式")
reset_btn.clicked.connect(self.resetMenuBarStyle)
button_layout.addWidget(reset_btn)
# 信息按钮
info_btn = QPushButton("📊 显示系统信息")
info_btn.clicked.connect(self.showSystemInfo)
button_layout.addWidget(info_btn)
layout.addLayout(button_layout)
# 创建初始菜单栏
self.createInitialMenuBar()
def createInitialMenuBar(self):
"""创建初始菜单栏"""
menubar = self.menuBar()
menubar.setNativeMenuBar(False)
# 添加基本菜单
file_menu = menubar.addMenu('文件')
file_menu.addAction('新建')
file_menu.addAction('打开')
edit_menu = menubar.addMenu('编辑')
edit_menu.addAction('复制')
edit_menu.addAction('粘贴')
help_menu = menubar.addMenu('帮助')
help_menu.addAction('关于')
print("✅ 初始菜单栏已创建")
def testMenuBar(self):
"""测试菜单栏显示"""
menubar = self.menuBar()
# 收集信息
info = []
info.append(f"可见性: {menubar.isVisible()}")
info.append(f"启用状态: {menubar.isEnabled()}")
info.append(f"高度: {menubar.height()}px")
info.append(f"宽度: {menubar.width()}px")
info.append(f"位置: {menubar.pos()}")
info.append(f"菜单数量: {len(menubar.actions())}")
info.append(f"原生菜单栏: {menubar.isNativeMenuBar()}")
# 显示结果
status_text = "📊 菜单栏状态:\n" + "\n".join(info)
self.status_label.setText(status_text)
# 控制台输出
print("\n🔍 菜单栏测试结果:")
for item in info:
print(f" - {item}")
# 判断是否正常
if menubar.isVisible() and menubar.height() > 0:
self.status_label.setStyleSheet("font-size: 14px; color: white; margin: 10px; padding: 10px; background-color: #0F7B0F; border-radius: 5px;")
print("✅ 菜单栏显示正常")
else:
self.status_label.setStyleSheet("font-size: 14px; color: white; margin: 10px; padding: 10px; background-color: #A80000; border-radius: 5px;")
print("❌ 菜单栏显示异常")
def forceFixMenuBar(self):
"""强制修复菜单栏"""
menubar = self.menuBar()
print("🛠️ 开始强制修复菜单栏...")
# 重置基本属性
menubar.setNativeMenuBar(False)
menubar.setVisible(True)
menubar.setEnabled(True)
# 设置尺寸
menubar.setMinimumHeight(50)
menubar.setMaximumHeight(50)
# 应用强制样式
menubar.setStyleSheet("""
QMenuBar {
background-color: #FF4444 !important;
color: #FFFFFF !important;
border: 4px solid #00FF00 !important;
min-height: 50px !important;
max-height: 50px !important;
font-size: 18px !important;
font-weight: bold !important;
padding: 8px !important;
}
QMenuBar::item {
background-color: #FFFF00 !important;
color: #000000 !important;
padding: 12px 20px !important;
margin: 4px !important;
font-size: 18px !important;
font-weight: bold !important;
border: 2px solid #FF0000 !important;
border-radius: 3px !important;
}
QMenuBar::item:selected {
background-color: #0066FF !important;
color: #FFFFFF !important;
}
""")
# 强制显示和刷新
menubar.show()
menubar.raise_()
menubar.update()
menubar.repaint()
self.update()
self.repaint()
self.status_label.setText("🛠️ 强制修复已应用!\n如果看到红色菜单栏说明修复成功")
self.status_label.setStyleSheet("font-size: 14px; color: white; margin: 10px; padding: 10px; background-color: #FF6600; border-radius: 5px;")
print("🛠️ 强制修复完成")
# 延迟测试结果
QTimer.singleShot(1000, self.testMenuBar)
def resetMenuBarStyle(self):
"""重置菜单栏样式"""
menubar = self.menuBar()
# 清除样式
menubar.setStyleSheet("")
# 重新设置基本样式
menubar.setStyleSheet("""
QMenuBar {
background-color: #2D2D30;
color: #FFFFFF;
border-bottom: 1px solid #3E3E42;
min-height: 30px;
font-size: 14px;
}
QMenuBar::item {
background-color: transparent;
color: #FFFFFF;
padding: 8px 12px;
margin: 0px 2px;
}
QMenuBar::item:selected {
background-color: #0078D4;
}
""")
menubar.update()
self.status_label.setText("🔄 菜单栏样式已重置为正常样式")
self.status_label.setStyleSheet("font-size: 14px; color: white; margin: 10px; padding: 10px; background-color: #2D2D30; border-radius: 5px;")
print("🔄 菜单栏样式已重置")
def showSystemInfo(self):
"""显示系统信息"""
import platform
from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR
info = []
info.append(f"操作系统: {platform.system()} {platform.release()}")
info.append(f"Python版本: {sys.version.split()[0]}")
info.append(f"PyQt5版本: {PYQT_VERSION_STR}")
info.append(f"Qt版本: {QT_VERSION_STR}")
info.append(f"屏幕分辨率: {QApplication.desktop().screenGeometry().width()}x{QApplication.desktop().screenGeometry().height()}")
status_text = "📊 系统信息:\n" + "\n".join(info)
self.status_label.setText(status_text)
self.status_label.setStyleSheet("font-size: 12px; color: white; margin: 10px; padding: 10px; background-color: #0078D4; border-radius: 5px;")
print("\n📊 系统信息:")
for item in info:
print(f" - {item}")
def main():
"""主函数"""
app = QApplication(sys.argv)
# 设置应用样式
app.setStyle('Fusion')
print("🚀 启动菜单栏修复工具")
print("📋 这个工具可以帮助诊断和修复菜单栏显示问题")
print("🎯 使用明显的颜色来测试菜单栏是否正常显示")
window = QuickMenuFix()
window.show()
return app.exec_()
if __name__ == "__main__":
sys.exit(main())

28
scripts/a.py Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
a - 自定义脚本
"""
from core.script_system import ScriptBase
class A(ScriptBase):
"""自定义脚本类"""
def __init__(self):
super().__init__()
# 在这里初始化您的变量
def start(self):
"""脚本开始时调用"""
self.log("脚本开始运行!")
def update(self, dt):
"""每帧更新"""
# 在这里编写更新逻辑
pass
def on_destroy(self):
"""脚本销毁时调用"""
self.log("脚本被销毁")

View File

@ -52,6 +52,26 @@ class IconManager:
'warning': 'warning.png', 'warning': 'warning.png',
'error': 'error.png', 'error': 'error.png',
'info': 'info.png', 'info': 'info.png',
'up_arrow': 'up_arrows.png',
'down_arrow': 'down_arrows.png',
'left_arrow': 'left_arrows.png',
'right_arrow': 'right_arrows.png',
'solid_down_arrows': 'solid_down_arrows.png',
'solid_right_arrows': 'solid_right_arrows.png',
'minimize_icon': 'minimize_icon.png',
'windowing_icon': 'windowing_icon.png',
'close_icon': 'close_icon.png',
# 弹窗图标
'success_icon': 'success_icon.png',
'warning_icon': 'warning_icon.png',
'fail_icon': 'delete_fail_icon.png',
# 属性面板图标
'property_select_image': 'property_select_image.png',
} }
# 初始化默认图标 # 初始化默认图标

View File

@ -1,4 +1,5 @@
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QMenu, QStyle from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QMenu, QStyle
from PyQt5.QtGui import QFont
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.sip import delete from PyQt5.sip import delete
from panda3d.core import GeomNode, ModelRoot from panda3d.core import GeomNode, ModelRoot
@ -213,6 +214,8 @@ class InterfaceManager:
sceneRoot = QTreeWidgetItem(self.treeWidget, ['场景']) sceneRoot = QTreeWidgetItem(self.treeWidget, ['场景'])
sceneRoot.setData(0, Qt.UserRole, self.world.render) sceneRoot.setData(0, Qt.UserRole, self.world.render)
sceneRoot.setData(0, Qt.UserRole + 1, "SCENE_ROOT") sceneRoot.setData(0, Qt.UserRole + 1, "SCENE_ROOT")
font = QFont("Microsoft YaHei", 10, QFont.Light) # 假设您希望字体大小为10
sceneRoot.setFont(0, font)
# 添加相机节点 # 添加相机节点
cameraItem = QTreeWidgetItem(sceneRoot, ['相机']) cameraItem = QTreeWidgetItem(sceneRoot, ['相机'])
cameraItem.setData(0, Qt.UserRole, self.world.cam) cameraItem.setData(0, Qt.UserRole, self.world.cam)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff