Fix SSBO root selection behavior and optimize group sync FPS
This commit is contained in:
parent
756db5b010
commit
2183d3fc3e
@ -78,6 +78,11 @@ class SSBOEditor:
|
||||
self.pick_mask = BitMask32.bit(29)
|
||||
self.pick_buffer = None
|
||||
self._empty_pick_scene = NodePath("ssbo_pick_empty")
|
||||
# Avoid heavy per-frame sync for huge group selections.
|
||||
self._pick_sync_bg_limit = 256
|
||||
self._last_group_sync_mat = None
|
||||
self._last_single_sync_gid = None
|
||||
self._last_single_sync_mat = None
|
||||
|
||||
# Initialize ImGui Backend if not already present
|
||||
if not hasattr(self.base, 'imgui_backend'):
|
||||
@ -389,6 +394,11 @@ class SSBOEditor:
|
||||
self._sync_pick_transforms()
|
||||
return task.cont
|
||||
|
||||
def _reset_pick_sync_cache(self):
|
||||
self._last_group_sync_mat = None
|
||||
self._last_single_sync_gid = None
|
||||
self._last_single_sync_mat = None
|
||||
|
||||
def _matrices_close(self, a, b, eps=1e-5):
|
||||
"""Small helper for robust matrix change detection."""
|
||||
for r in range(4):
|
||||
@ -424,6 +434,45 @@ class SSBOEditor:
|
||||
if not self.controller:
|
||||
return
|
||||
self._sync_pick_root_transform()
|
||||
if not self.selected_ids:
|
||||
return
|
||||
|
||||
# Group selection can contain thousands of objects.
|
||||
# Only resync when proxy transform has changed.
|
||||
proxy = getattr(self, "_group_proxy", None)
|
||||
if proxy and not proxy.is_empty() and len(self.selected_ids) > 1:
|
||||
proxy_world = proxy.get_mat(self.base.render)
|
||||
if self._last_group_sync_mat and self._matrices_close(proxy_world, self._last_group_sync_mat):
|
||||
return
|
||||
self._last_group_sync_mat = LMatrix4f(proxy_world)
|
||||
else:
|
||||
self._last_group_sync_mat = None
|
||||
|
||||
if len(self.selected_ids) == 1:
|
||||
gid = self.selected_ids[0]
|
||||
obj_np = self.controller.id_to_object_np.get(gid)
|
||||
pick_np = self.controller.id_to_pick_np.get(gid)
|
||||
if not (obj_np and pick_np and not obj_np.is_empty() and not pick_np.is_empty()):
|
||||
return
|
||||
obj_world_mat = obj_np.get_mat(self.base.render)
|
||||
if (
|
||||
self._last_single_sync_gid == gid and
|
||||
self._last_single_sync_mat and
|
||||
self._matrices_close(obj_world_mat, self._last_single_sync_mat)
|
||||
):
|
||||
return
|
||||
self._last_single_sync_gid = gid
|
||||
self._last_single_sync_mat = LMatrix4f(obj_world_mat)
|
||||
pick_world_mat = pick_np.get_mat(self.base.render)
|
||||
if not self._matrices_close(obj_world_mat, pick_world_mat):
|
||||
pick_np.set_mat(self.base.render, obj_world_mat)
|
||||
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
|
||||
return
|
||||
|
||||
self._last_single_sync_gid = None
|
||||
self._last_single_sync_mat = None
|
||||
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)
|
||||
@ -440,6 +489,7 @@ class SSBOEditor:
|
||||
|
||||
def clear_selection(self):
|
||||
self._stop_pick_sync_task()
|
||||
self._reset_pick_sync_cache()
|
||||
self._cleanup_group_proxy()
|
||||
self.selected_name = None
|
||||
self.selected_ids = []
|
||||
@ -488,6 +538,7 @@ class SSBOEditor:
|
||||
def select_node(self, key):
|
||||
# Clean up previous group proxy before changing selection
|
||||
self._cleanup_group_proxy()
|
||||
self._reset_pick_sync_cache()
|
||||
|
||||
self.selected_name = key
|
||||
self.selected_ids = self.controller.name_to_ids.get(key, [])
|
||||
@ -532,7 +583,12 @@ class SSBOEditor:
|
||||
obj_np.wrt_reparent_to(proxy)
|
||||
|
||||
self._transform_gizmo.attach(proxy)
|
||||
self._start_pick_sync_task()
|
||||
# For huge groups, avoid per-frame full sync; we still sync on demand
|
||||
# right before picking via pick_object().
|
||||
if len(valid) <= self._pick_sync_bg_limit:
|
||||
self._start_pick_sync_task()
|
||||
else:
|
||||
self._stop_pick_sync_task()
|
||||
|
||||
def _rebuild_filtered_tree_rows(self):
|
||||
"""
|
||||
|
||||
@ -468,8 +468,33 @@ class EditorPanels:
|
||||
|
||||
# 处理节点选择
|
||||
if imgui.is_item_clicked():
|
||||
# In SSBO mode, clicking model root should finally bind gizmo to
|
||||
# SSBO group proxy (not legacy model root). So run legacy
|
||||
# selection first, then force SSBO root selection at the end.
|
||||
force_ssbo_root_key = None
|
||||
ssbo_editor_ref = None
|
||||
try:
|
||||
ssbo_editor = getattr(self.app, "ssbo_editor", None)
|
||||
controller = getattr(ssbo_editor, "controller", None) if ssbo_editor else None
|
||||
ssbo_model = getattr(ssbo_editor, "model", None) if ssbo_editor else None
|
||||
root_key = getattr(controller, "tree_root_key", None) if controller else None
|
||||
if (
|
||||
ssbo_editor and controller and ssbo_model and node == ssbo_model
|
||||
and root_key and root_key in controller.tree_nodes
|
||||
):
|
||||
force_ssbo_root_key = root_key
|
||||
ssbo_editor_ref = ssbo_editor
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if hasattr(self.app, 'selection') and self.app.selection:
|
||||
self.app.selection.updateSelection(node)
|
||||
|
||||
if force_ssbo_root_key and ssbo_editor_ref:
|
||||
try:
|
||||
ssbo_editor_ref.select_node(force_ssbo_root_key)
|
||||
except Exception:
|
||||
pass
|
||||
# Clear LUI selection when a scene node is selected
|
||||
if hasattr(self.app, 'lui_manager'):
|
||||
self.app.lui_manager.selected_index = -1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user