Update ssbo editor

This commit is contained in:
Your Name 2026-02-27 14:24:11 +08:00
parent 53e6a829e4
commit 1fd7e1d7ac

View File

@ -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()