diff --git a/RenderPipelineFile/rpcore/light_manager.py b/RenderPipelineFile/rpcore/light_manager.py index fe9e4ceb..e336c3d7 100644 --- a/RenderPipelineFile/rpcore/light_manager.py +++ b/RenderPipelineFile/rpcore/light_manager.py @@ -90,7 +90,6 @@ class LightManager(RPObject): def remove_light(self, light): """ Removes a light """ - print(f'333333333333333333333333333333,{light.casts_shadows}') # from RenderPipelineFile.rpcore.pynative.internal_light_manager import InternalLightManager # inter = InternalLightManager() # inter.remove_light(light) diff --git a/RenderPipelineFile/rpcore/render_pipeline.py b/RenderPipelineFile/rpcore/render_pipeline.py index e4c46dbb..1ff75384 100644 --- a/RenderPipelineFile/rpcore/render_pipeline.py +++ b/RenderPipelineFile/rpcore/render_pipeline.py @@ -208,7 +208,6 @@ class RenderPipeline(RPObject): def remove_light(self, light): """ Removes a previously attached light, check out the LightManager remove_light documentation for further information. """ - print(f'222222222222222222222222222,{light.casts_shadows}') self.light_mgr.remove_light(light) def load_ies_profile(self, filename): diff --git a/scene/scene_manager.py b/scene/scene_manager.py index 9811bee8..6d501949 100644 --- a/scene/scene_manager.py +++ b/scene/scene_manager.py @@ -1238,6 +1238,8 @@ class SceneManager: light_obj = node.getPythonTag("rp_light_object") if light_obj: node.setTag("light_energy", str(light_obj.energy)) + if node.hasTag("stored_energy"): + node.setTag("stored_energy", node.getTag("stored_energy")) node.setTag("light_radius", str(getattr(light_obj, 'radius', 0))) if hasattr(light_obj, 'fov'): node.setTag("light_fov", str(light_obj.fov)) @@ -2359,8 +2361,22 @@ class SceneManager: # 确保灯光节点有正确的标签,以便在场景树更新时被识别 if not light_node.hasTag("is_scene_element"): light_node.setTag("is_scene_element", "1") + light_node.setTag("is_scene_element", "1") + light_node.setTag("element_type", "spotlight") + light_node.setTag("tree_item_type", "LIGHT_NODE") - print(f"重新创建聚光灯: {light_node.getName()}") + if light_node.hasTag("stored_energy"): + stored_energy = float(light_node.getTag("stored_energy")) + if stored_energy > 0: + light_node.setTag("stored_energy", str(stored_energy)) + + user_visible = True + if light_node.hasTag("user_visible"): + user_visible = light_node.getTag("user_visible").lower() == "true" + + light_node.setPythonTag("user_visible",user_visible) + if not user_visible: + self.toggleLightVisibility(light_node,False) except Exception as e: print(f"重新创建聚光灯失败: {str(e)}") import traceback @@ -2404,7 +2420,23 @@ class SceneManager: if not light_node.hasTag("is_scene_element"): light_node.setTag("is_scene_element", "1") - print(f"重新创建点光源: {light_node.getName()}") + light_node.setTag("is_scene_element", "1") + light_node.setTag("element_type", "pointlight") + light_node.setTag("tree_item_type", "LIGHT_NODE") + + if light_node.hasTag("stored_energy"): + stored_energy = float(light_node.getTag("stored_energy")) + if stored_energy > 0: + light_node.setTag("stored_energy", str(stored_energy)) + + user_visible = True + if light_node.hasTag("user_visible"): + user_visible = light_node.getTag("user_visible").lower()=="true" + + light_node.setPythonTag("user_visible",user_visible) + + if not user_visible: + self.toggleLightVisibility(light_node,False) except Exception as e: print(f"重新创建点光源失败: {str(e)}") import traceback @@ -2565,6 +2597,7 @@ class SceneManager: light_np.setTag("tree_item_type", "LIGHT_NODE") light_np.setTag("light_energy", str(light.energy)) light_np.setTag("created_by_user", "1") + light_np.setTag("element_type","spotlight") # 保存光源对象引用 light_np.setPythonTag("rp_light_object", light) @@ -2673,6 +2706,7 @@ class SceneManager: light_np.setTag("tree_item_type", "LIGHT_NODE") light_np.setTag("light_energy", str(light.energy)) light_np.setTag("created_by_user", "1") + light_np.setTag("element_type","pointlight") # 保存光源对象引用 light_np.setPythonTag("rp_light_object", light) @@ -2721,6 +2755,103 @@ class SceneManager: traceback.print_exc() return None + def isLightObject(self, nodePath): + """检查是否为灯光对象""" + try: + if not nodePath: + return False + + + # 方法1: 检查PythonTag + if nodePath.hasPythonTag("rp_light_object"): + rp_light = nodePath.getPythonTag("rp_light_object") + if rp_light is not None: + return True + + # 方法2: 检查element_type标签 + if nodePath.hasTag("element_type"): + element_type = nodePath.getTag("element_type") + if element_type in ["spotlight", "pointlight"]: + return True + + # 方法3: 检查tree_item_type标签 + if nodePath.hasTag("tree_item_type"): + tree_item_type = nodePath.getTag("tree_item_type") + if tree_item_type == "LIGHT_NODE": + return True + + # 方法4: 通过名称模式匹配(作为后备方案) + node_name = nodePath.getName().lower() + if "spotlight" in node_name or "pointlight" in node_name: + return True + + return False + except Exception as e: + print(f"检查灯光对象时出错: {e}") + import traceback + traceback.print_exc() + return False + + def toggleLightVisibility(self, light_node, visible): + """切换灯光可见性""" + try: + print(f"切换灯光可见性: {light_node.getName()}, 可见={visible}") + + # 保存用户可见性状态到该特定节点 + light_node.setPythonTag("user_visible", visible) + + # 获取该特定灯光对象 + rp_light_object = light_node.getPythonTag("rp_light_object") + if not rp_light_object: + print(f"错误: {light_node.getName()} 未找到RP灯光对象引用") + return + + # 获取RenderPipeline实例 + from QMeta3D.Meta3DWorld import get_render_pipeline + render_pipeline = get_render_pipeline() + + if not render_pipeline: + print("错误: 无法获取RenderPipeline实例") + return + + try: + if visible: + if light_node.hasTag("stored_energy"): + stored_energy = float(light_node.getTag("stored_energy")) + rp_light_object.energy=stored_energy + print(f"已恢复灯光强度: {light_node.getName()}, 能量={stored_energy}") + # 启用特定灯光 + # render_pipeline.add_light(rp_light_object) + # print(f"已添加灯光到渲染管线: {light_node.getName()}") + else: + # 禁用特定灯光 + current_energy = rp_light_object.energy + if current_energy != 0.0: + light_node.setTag("stored_energy", str(current_energy)) + elif light_node.hasTag("stored_energy"): + stored_energy = float(light_node.getTag("stored_energy")) + current_energy = stored_energy + else: + current_energy = 0.0 + rp_light_object.energy = 0.0 + print(f"已禁用灯光: {light_node.getName()}, 保存的能量={current_energy}") + # render_pipeline.remove_light(rp_light_object) + # print(f"已从渲染管线移除灯光: {light_node.getName()}") + except Exception as e: + print(f"操作RenderPipeline灯光时出错: {e}") + + # 控制节点显示状态(可选,主要是视觉上的) + if visible: + light_node.show() + else: + light_node.hide() + + print(f"灯光可见性设置完成: {visible}") + except Exception as e: + print(f"切换灯光可见性失败: {str(e)}") + import traceback + traceback.print_exc() + def _get_tree_widget(self): """安全获取树形控件""" try: diff --git a/ui/property_panel.py b/ui/property_panel.py index 3411306f..8322f6b4 100644 --- a/ui/property_panel.py +++ b/ui/property_panel.py @@ -678,6 +678,7 @@ class PropertyPanelManager: self.active_check = QCheckBox() # 根据模型的实际可见性状态设置复选框 self.active_check.setChecked(user_visible) + self.active_check.stateChanged.connect(lambda state: self._toggleModelVisibility(model, state)) self.name_input = QLineEdit(itemText) self.name_input.returnPressed.connect( @@ -690,14 +691,14 @@ class PropertyPanelManager: self.name_group.setLayout(name_layout) self._propertyLayout.addWidget(self.name_group) - if model: - try: - self.active_check.stateChanged.disconnect() - except TypeError: - pass - self.active_check.stateChanged.connect( - lambda state, m=model: self._setUserVisible(m, state == Qt.Checked) - ) + # if model: + # try: + # self.active_check.stateChanged.disconnect() + # except TypeError: + # pass + # self.active_check.stateChanged.connect( + # lambda state, m=model: self._setUserVisible(m, state == Qt.Checked) + # ) # nameLabel = QLabel("名称:") # nameEdit = QLineEdit(itemText) # self._propertyLayout.addRow(nameLabel, nameEdit) @@ -1136,6 +1137,15 @@ class PropertyPanelManager: node.setPythonTag("user_visible", visible) self._syncEffectiveVisibility(node) + def _setUserVisible_light(self, node, visible): + """设置用户可见性状态""" + try: + # 保存可见性状态 + node.setPythonTag("user_visible", visible) + + except Exception as e: + print(f"设置用户可见性失败: {e}") + def _syncEffectiveVisibility(self, start_node): """广度优先,确保父隐藏则子一定隐藏""" # 获取起始节点的父节点 @@ -1171,19 +1181,52 @@ class PropertyPanelManager: for child in node.getChildren(): q.append((child, eff)) + # def _toggleModelVisibility(self, model, state): + # """切换模型可见性状态""" + # try: + # visible = (state == Qt.Checked) + # self._setUserVisible(model, visible) + # + # collision_nodes = model.findAllMatches("**/modelCollision_*") + # for collision_node in collision_nodes: + # collision_node.hide() + # + # except Exception as e: + # print(f"切换模型可见性失败: {str(e)}") + # import traceback + # traceback.print_exc() + def _toggleModelVisibility(self, model, state): """切换模型可见性状态""" try: - # 用我们自己维护的可见性接口,而不是直接 show/hide - visible = (state == Qt.Checked) - self._setUserVisible(model, visible) - collision_nodes = model.findAllMatches("**/modelCollision_*") - for collision_node in collision_nodes: - collision_node.hide() + + # 特殊处理灯光对象 + scene_manager = None + if hasattr(self.world, 'scene_manager'): + scene_manager = self.world.scene_manager + + if scene_manager and hasattr(scene_manager, 'isLightObject'): + is_light = scene_manager.isLightObject(model) + + if is_light: + visible = (state == Qt.Checked) + self._setUserVisible_light(model, visible) + if hasattr(scene_manager, 'toggleLightVisibility'): + scene_manager.toggleLightVisibility(model, visible) + return # 关键:这里必须return,避免执行下面的普通模型逻辑 + else: + visible = (state == Qt.Checked) + self._setUserVisible(model, visible) + + collision_nodes = model.findAllMatches("**/modelCollision_*") + for collision_node in collision_nodes: + collision_node.hide() except Exception as e: print(f"切换模型可见性失败: {str(e)}") + import traceback + traceback.print_exc() def refreshModelValues(self, nodePath): """刷新模型值显示""" @@ -5502,11 +5545,22 @@ class PropertyPanelManager: light_group = QGroupBox("光源属性") light_layout = QGridLayout() + current_energy = light_object.energy + stored_energy = None + + if current_energy == 0.0 and model.hasTag("stored_energy"): + try: + stored_energy = float(model.getTag("stored_energy")) + except ValueError: + pass + + display_energy = stored_energy if stored_energy is not None and stored_energy > 0 else current_energy + # 能量 light_layout.addWidget(QLabel("能量:"), 0, 0) energySpinBox = QDoubleSpinBox() energySpinBox.setRange(0, 10000) - energySpinBox.setValue(light_object.energy) + energySpinBox.setValue(display_energy) energySpinBox.valueChanged.connect(lambda v: self._updateLightEnergy(light_object, v)) light_layout.addWidget(energySpinBox, 0, 1, 1, 3)