From 1fd7e1d7ac4978ed9df89c533390afcdf3244c79 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 27 Feb 2026 14:24:11 +0800 Subject: [PATCH] Update ssbo editor --- ssbo_component/ssbo_editor.py | 79 ++++++++--------------------------- 1 file changed, 18 insertions(+), 61 deletions(-) diff --git a/ssbo_component/ssbo_editor.py b/ssbo_component/ssbo_editor.py index 225a1a5f..fa7845db 100644 --- a/ssbo_component/ssbo_editor.py +++ b/ssbo_component/ssbo_editor.py @@ -306,22 +306,6 @@ class SSBOEditor: # The per-frame sync task may not have run yet for this frame. self._sync_pick_transforms() - # DEBUG: Compare obj vs pick positions - if self.selected_ids: - gid = self.selected_ids[0] - obj = self.controller.id_to_object_np.get(gid) - pick = self.controller.id_to_pick_np.get(gid) - pm = self.controller.pick_model - if obj and pick: - print(f"[PICK DBG] obj[{gid}] world={obj.get_pos(self.base.render)}") - print(f"[PICK DBG] pick[{gid}] in_pick_model={pick.get_pos(pm)} local={pick.get_pos()}") - pp = getattr(self, '_pick_proxy', None) - gp = getattr(self, '_group_proxy', None) - if pp: - print(f"[PICK DBG] pick_proxy pos={pp.get_pos()} mat row3={pp.get_mat().get_row3(3)}") - if gp: - print(f"[PICK DBG] group_proxy pos_render={gp.get_pos(self.base.render)}") - self.pick_buffer.set_active(True) self.base.graphicsEngine.render_frame() self.pick_buffer.set_active(False) @@ -362,7 +346,7 @@ class SSBOEditor: self._transform_gizmo = gizmo def _start_pick_sync_task(self): - """Start a per-frame task that syncs pick proxy with render proxy.""" + """Start a per-frame task that syncs pick transforms for selected objects.""" self.base.task_mgr.remove("ssbo_pick_sync") self.base.task_mgr.add(self._pick_sync_task, "ssbo_pick_sync") @@ -371,25 +355,20 @@ class SSBOEditor: self.base.task_mgr.remove("ssbo_pick_sync") def _pick_sync_task(self, task): - """Per-frame: keep pick proxy transform in sync with render proxy.""" + """Per-frame: keep pick model transforms in sync with render model.""" self._sync_pick_transforms() return task.cont def _sync_pick_transforms(self): - """Sync pick scene transforms to match render scene.""" - # Group proxy: sync the single pick proxy to the render proxy - proxy = getattr(self, '_group_proxy', None) - pick_proxy = getattr(self, '_pick_proxy', None) - if proxy and pick_proxy and not proxy.is_empty() and not pick_proxy.is_empty(): - pick_proxy.set_mat(proxy.get_mat(self.base.render)) - return - # Single object: sync individual pick_np + """Sync pick model transforms to match render model transforms.""" if not self.controller: return for gid in self.selected_ids: obj_np = self.controller.id_to_object_np.get(gid) pick_np = self.controller.id_to_pick_np.get(gid) if obj_np and pick_np and not obj_np.is_empty() and not pick_np.is_empty(): + # pick_np is direct child of pick_root (identity transform), + # so local mat = world-space mat. pick_np.set_mat(obj_np.get_mat(self.base.render)) def clear_selection(self): @@ -403,38 +382,29 @@ class SSBOEditor: self._transform_gizmo.detach() def _cleanup_group_proxy(self): - """Reparent objects back to their chunks and clean up proxies.""" + """Reparent objects back to their chunk and remove the group proxy.""" proxy = getattr(self, '_group_proxy', None) if not proxy: return originals = getattr(self, '_group_original_parents', {}) - pick_originals = getattr(self, '_pick_original_parents', {}) - - # Reparent render objects back to their original chunk parents + # Sync pick transforms and mark chunks dirty before reparenting + for gid in originals: + obj_np = self.controller.id_to_object_np.get(gid) + pick_np = self.controller.id_to_pick_np.get(gid) + if obj_np and pick_np and not obj_np.is_empty() and not pick_np.is_empty(): + pick_np.set_mat(obj_np.get_mat(self.base.render)) + chunk_id = self.controller.id_to_chunk.get(gid) + if chunk_id is not None and chunk_id in self.controller.chunks: + self.controller.chunks[chunk_id]["dirty"] = True + # Reparent objects back to their original chunk parents for gid, parent_np in originals.items(): obj_np = self.controller.id_to_object_np.get(gid) if obj_np and not obj_np.is_empty() and parent_np and not parent_np.is_empty(): obj_np.wrt_reparent_to(parent_np) - chunk_id = self.controller.id_to_chunk.get(gid) - if chunk_id is not None and chunk_id in self.controller.chunks: - self.controller.chunks[chunk_id]["dirty"] = True - - # Reparent pick objects back to pick_model - for gid, parent_np in pick_originals.items(): - pick_np = self.controller.id_to_pick_np.get(gid) - if pick_np and not pick_np.is_empty() and parent_np and not parent_np.is_empty(): - pick_np.wrt_reparent_to(parent_np) - if not proxy.is_empty(): proxy.remove_node() - pick_proxy = getattr(self, '_pick_proxy', None) - if pick_proxy and not pick_proxy.is_empty(): - pick_proxy.remove_node() - self._group_proxy = None - self._pick_proxy = None self._group_original_parents = {} - self._pick_original_parents = {} def update_selection_mask(self): pass # No selection mask texture needed without custom shader @@ -442,7 +412,6 @@ class SSBOEditor: def select_node(self, key): # Clean up previous group proxy before changing selection self._cleanup_group_proxy() - self._stop_pick_sync_task() self.selected_name = key self.selected_ids = self.controller.name_to_ids.get(key, []) @@ -461,12 +430,10 @@ class SSBOEditor: self._start_pick_sync_task() return - # Multiple objects (parent node): create MIRRORED proxies in both - # render and pick scenes so transforms stay synchronized naturally. + # Multiple objects (parent node): create a group proxy so all children + # follow the gizmo transform together. from panda3d.core import Vec3 proxy = self.base.render.attach_new_node("ssbo_group_proxy") - pick_proxy = self.controller.pick_model.attach_new_node("ssbo_pick_proxy") - center = Vec3(0, 0, 0) valid = [] for gid in self.selected_ids: @@ -476,27 +443,17 @@ class SSBOEditor: valid.append(gid) if not valid: proxy.remove_node() - pick_proxy.remove_node() return center /= len(valid) proxy.set_pos(self.base.render, center) - pick_proxy.set_pos(center) # pick_model has identity transform self._group_proxy = proxy - self._pick_proxy = pick_proxy self._group_original_parents = {} - self._pick_original_parents = {} - for gid in valid: - # Reparent render object under render proxy obj_np = self.controller.id_to_object_np[gid] self._group_original_parents[gid] = obj_np.get_parent() obj_np.wrt_reparent_to(proxy) - # Reparent pick object under pick proxy (mirrored structure) - pick_np = self.controller.id_to_pick_np[gid] - self._pick_original_parents[gid] = pick_np.get_parent() - pick_np.wrt_reparent_to(pick_proxy) self._transform_gizmo.attach(proxy) self._start_pick_sync_task()