diff --git a/RenderPipelineFile/toolkit/day_time_editor/curve_widget.py b/RenderPipelineFile/toolkit/day_time_editor/curve_widget.py index 249030af..44bfbd88 100644 --- a/RenderPipelineFile/toolkit/day_time_editor/curve_widget.py +++ b/RenderPipelineFile/toolkit/day_time_editor/curve_widget.py @@ -33,7 +33,9 @@ from six.moves import range # pylint: disable=import-error import math -from RenderPipelineFile.rplibs.pyqt_imports import * # noqa +# 修复导入路径问题 +from rplibs.pyqt_imports import * # noqa + class CurveWidget(QWidget): diff --git a/RenderPipelineFile/toolkit/day_time_editor/main.py b/RenderPipelineFile/toolkit/day_time_editor/main.py index 3031b478..82a68231 100644 --- a/RenderPipelineFile/toolkit/day_time_editor/main.py +++ b/RenderPipelineFile/toolkit/day_time_editor/main.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + """ RenderPipeline @@ -40,8 +42,9 @@ os.chdir(os.path.join(os.path.dirname(os.path.realpath(__file__)))) # Add the render pipeline to the path sys.path.insert(0, "../../") -from RenderPipelineFile.rplibs.six import iteritems # noqa -from RenderPipelineFile.rplibs.pyqt_imports import * # noqa +# 修复导入路径问题 +from rplibs.six import iteritems # noqa +from rplibs.pyqt_imports import * # noqa from curve_widget import CurveWidget # noqa diff --git a/RenderPipelineFile/toolkit/plugin_configurator/main.py b/RenderPipelineFile/toolkit/plugin_configurator/main.py index fd393ae8..ba0ff055 100644 --- a/RenderPipelineFile/toolkit/plugin_configurator/main.py +++ b/RenderPipelineFile/toolkit/plugin_configurator/main.py @@ -1,32 +1,4 @@ -""" - -RenderPipeline - -Copyright (c) 2014-2016 tobspr - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -""" - -# This tool offers an interface to configure the pipeline - -from __future__ import print_function +#!/usr/bin/env python import os import sys @@ -49,7 +21,39 @@ from rplibs.pyqt_imports import * #noqa # Load the generated UI Layout from ui.main_window_generated import Ui_MainWindow # noqa -from ui.widgets import UniversalMessageDialog +# 创建一个简单的UniversalMessageDialog类,避免复杂的导入问题 +class UniversalMessageDialog(QDialog): + @staticmethod + def show_success(parent, title, message, show_cancel=True, confirm_text="确认"): + msg_box = QMessageBox(QMessageBox.Information, title, message, QMessageBox.Ok, parent) + if show_cancel: + msg_box.addButton(QMessageBox.Cancel) + msg_box.button(QMessageBox.Ok).setText(confirm_text) + return msg_box.exec_() + + @staticmethod + def show_warning(parent, title, message, show_cancel=True, confirm_text="确认"): + msg_box = QMessageBox(QMessageBox.Warning, title, message, QMessageBox.Ok, parent) + if show_cancel: + msg_box.addButton(QMessageBox.Cancel) + msg_box.button(QMessageBox.Ok).setText(confirm_text) + return msg_box.exec_() + + @staticmethod + def show_error(parent, title, message, show_cancel=True, confirm_text="确认"): + msg_box = QMessageBox(QMessageBox.Critical, title, message, QMessageBox.Ok, parent) + if show_cancel: + msg_box.addButton(QMessageBox.Cancel) + msg_box.button(QMessageBox.Ok).setText(confirm_text) + return msg_box.exec_() + + @staticmethod + def show_info(parent, title, message, show_cancel=True, confirm_text="确认"): + msg_box = QMessageBox(QMessageBox.Information, title, message, QMessageBox.Ok, parent) + if show_cancel: + msg_box.addButton(QMessageBox.Cancel) + msg_box.button(QMessageBox.Ok).setText(confirm_text) + return msg_box.exec_() from rpcore.pluginbase.manager import PluginManager # noqa from rpcore.util.network_communication import NetworkCommunication # noqa @@ -106,6 +110,15 @@ class PluginConfigurator(QMainWindow, Ui_MainWindow): def closeEvent(self, event): # noqa event.accept() + # 通知主程序配置可能已更改 + try: + # 发送一个信号或者写入一个标记文件来通知主程序 + marker_file = "/tmp/rp_plugin_config_changed.flag" + with open(marker_file, "w") as f: + f.write("Plugin configuration may have changed") + except Exception as e: + print(f"无法创建配置更改标记文件: {e}") + import os os._exit(1) diff --git a/scene/scene_manager.py b/scene/scene_manager.py index 5e7362e4..9811bee8 100644 --- a/scene/scene_manager.py +++ b/scene/scene_manager.py @@ -921,6 +921,13 @@ class SceneManager: if hasattr(gui_node, 'hasTag') and gui_node.hasTag("image_path"): gui_info["image_path"] = gui_node.getTag("image_path") + # 收集GUI元素的可见性信息 + user_visible = gui_node.getPythonTag("user_visible") + if user_visible is not None: + gui_info["user_visible"] = user_visible + else: + # 默认为可见 + gui_info["user_visible"] = True # 收集挂载的脚本信息 if hasattr(self.world, 'script_manager') and self.world.script_manager: @@ -2051,6 +2058,20 @@ class SceneManager: elif len(scale) >= 1: new_element.setScale(scale[0]) + # 恢复GUI元素的可见性状态 + user_visible = gui_info.get("user_visible", True) + new_element.setPythonTag("user_visible", user_visible) + + # 应用可见性状态 + if hasattr(self.world, 'property_panel'): + self.world.property_panel._syncEffectiveVisibility(new_element) + else: + # 如果没有属性面板,直接应用可见性 + if user_visible: + new_element.show() + else: + new_element.hide() + # 设置标签 # 对于NodePath对象 if hasattr(new_element, 'setTag'): diff --git a/ui/main_window.py b/ui/main_window.py index 909196b5..e5f3b4af 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -16,7 +16,8 @@ from PyQt5.QtWidgets import (QApplication, QMainWindow, QMenuBar, QMenu, QAction QLabel, QLineEdit, QFormLayout, QDoubleSpinBox, QScrollArea, QFileSystemModel, QButtonGroup, QToolButton, QPushButton, QHBoxLayout, QComboBox, QGroupBox, QInputDialog, QFileDialog, QMessageBox, QDesktopWidget, QDialog, - QSpinBox, QFrame, QRadioButton, QTextEdit, QCheckBox,QTabWidget, QSizePolicy) + QSpinBox, QFrame, QRadioButton, QTextEdit, QCheckBox, QTabWidget, QSizePolicy, + QListWidgetItem) from PyQt5.QtCore import Qt, QDir, QTimer, QSize, QPoint, QUrl, QRect from direct.showbase.ShowBaseGlobal import aspect2d from panda3d.core import OrthographicLens @@ -26,6 +27,10 @@ from ui.widgets import (CustomMeta3DWidget, CustomFileView, CustomTreeWidget, UniversalMessageDialog) from ui.icon_manager import get_icon_manager, get_icon +import yaml +from PyQt5.QtWidgets import QDialog, QVBoxLayout, QListWidget, QPushButton, QDialogButtonBox, QCheckBox, QLabel, QHBoxLayout +from PyQt5.QtCore import Qt + class StyledTerrainDialog(QDialog): """与新建项目对话框风格一致的参数输入对话框""" @@ -1172,6 +1177,18 @@ class MainWindow(QMainWindow): self.helpMenu = menubar.addMenu('帮助') self.aboutAction = self.helpMenu.addAction('关于') + tool_menu = self.menuBar().addMenu("配置") + plugin_config_action = tool_menu.addAction("渲染管线插件配置") + plugin_config_action.triggered.connect(self.open_plugin_config_dialog) + + def open_plugin_config_dialog(self): + """打开插件配置对话框""" + try: + dialog = PluginConfigDialog(self) + dialog.exec_() + except Exception as e: + print(f"打开插件配置对话框失败: {e}") + def refreshAssetsView(self): """"刷新资源视图""" if hasattr(self,'fileView') and self.fileView: @@ -6000,6 +6017,129 @@ class MainWindow(QMainWindow): UniversalMessageDialog.show_error(self, "错误", f"设置VR测试步骤时发生错误:\n{str(e)}", False, "确定") + +class PluginConfigDialog(QDialog): + def __init__(self,parent=None): + super().__init__(parent) + self.setWindowTitle("渲染管线插件配置") + self.setGeometry(200,200,400,500) + self.plugins_config_path = os.path.join("RenderPipelineFile", "config", "plugins.yaml") + self.init_ui() + self.load_plugins_config() + + def init_ui(self): + layout = QVBoxLayout() + + # 标题 + title_label = QLabel("启用的插件:") + layout.addWidget(title_label) + + # 插件列表 + self.plugins_list = QListWidget() + layout.addWidget(self.plugins_list) + + # 按钮布局 + button_layout = QHBoxLayout() + + # 全选/全不选按钮 + self.select_all_btn = QPushButton("全选") + self.select_all_btn.clicked.connect(self.select_all_plugins) + button_layout.addWidget(self.select_all_btn) + + self.deselect_all_btn = QPushButton("全不选") + self.deselect_all_btn.clicked.connect(self.deselect_all_plugins) + button_layout.addWidget(self.deselect_all_btn) + + button_layout.addStretch() + + # 对话框按钮 + self.button_box = QDialogButtonBox( + QDialogButtonBox.Ok | QDialogButtonBox.Cancel | QDialogButtonBox.Apply + ) + self.button_box.accepted.connect(self.accept) + self.button_box.rejected.connect(self.reject) + self.button_box.button(QDialogButtonBox.Apply).clicked.connect(self.apply_changes) + + button_layout.addWidget(self.button_box) + layout.addLayout(button_layout) + + self.setLayout(layout) + + def load_plugins_config(self): + """加载插件配置""" + try: + # 检查文件是否存在 + if not os.path.exists(self.plugins_config_path): + print(f"插件配置文件不存在: {self.plugins_config_path}") + return + + with open(self.plugins_config_path, 'r', encoding='utf-8') as f: + config = yaml.safe_load(f) + + enabled_plugins = config.get('enabled', []) + + # 清空列表 + self.plugins_list.clear() + + # 添加启用的插件 + for plugin in enabled_plugins: + item = QListWidgetItem(plugin) + item.setFlags(item.flags() | Qt.ItemIsUserCheckable) + item.setCheckState(Qt.Checked) + self.plugins_list.addItem(item) + + except Exception as e: + print(f"加载插件配置失败: {e}") + + def select_all_plugins(self): + """全选所有插件""" + for i in range(self.plugins_list.count()): + item = self.plugins_list.item(i) + item.setCheckState(Qt.Checked) + + def deselect_all_plugins(self): + """取消选择所有插件""" + for i in range(self.plugins_list.count()): + item = self.plugins_list.item(i) + item.setCheckState(Qt.Unchecked) + + def apply_changes(self): + """应用更改到配置文件,保留原有配置结构""" + try: + # 检查文件是否存在 + if not os.path.exists(self.plugins_config_path): + print(f"插件配置文件不存在: {self.plugins_config_path}") + return + + # 读取完整配置 + with open(self.plugins_config_path, 'r', encoding='utf-8') as f: + config = yaml.safe_load(f) or {} + + # 获取选中的插件 + enabled_plugins = [] + for i in range(self.plugins_list.count()): + item = self.plugins_list.item(i) + if item.checkState() == Qt.Checked: + enabled_plugins.append(item.text()) + + # 只更新enabled部分,保留其他配置 + config['enabled'] = enabled_plugins + + # 保存配置时保留原有格式(尽可能) + with open(self.plugins_config_path, 'w', encoding='utf-8') as f: + yaml.dump(config, f, default_flow_style=False, allow_unicode=True, + sort_keys=False, indent=4) + + print("插件配置已保存") + + except Exception as e: + print(f"保存插件配置失败: {e}") + + def accept(self): + """点击确定按钮时保存并关闭""" + self.apply_changes() + super().accept() + def setup_main_window(world,path = None): """设置主窗口的便利函数""" app = QApplication.instance()