fix: ensure renderer is initialized before operations

- Add _ensure_initialized() method to Viewer3DWidget
- Queue pending meshes until widget is shown
- Add remove_mesh() method to PygfxRenderer
- Fix all viewer methods to check initialization
This commit is contained in:
bklronin
2026-03-14 08:59:12 +01:00
parent 5371bf7c38
commit e13769840b
22 changed files with 2997 additions and 0 deletions
+19
View File
@@ -650,43 +650,62 @@ class Viewer3DWidget(QWidget):
self._meshes: Dict[str, Any] = {}
self._selected_normal: Optional[Tuple[float, float, float]] = None
self._centroid: Optional[Tuple[float, float, float]] = None
self._pending_meshes: List[Tuple] = []
def showEvent(self, event):
if not self._initialized:
self._renderer.initialize(self)
self._initialized = True
for args in self._pending_meshes:
self.add_mesh(*args)
self._pending_meshes.clear()
self._renderer.render()
def _ensure_initialized(self):
if not self._initialized:
self._renderer.initialize(self)
self._initialized = True
def get_renderer(self) -> PygfxRenderer:
return self._renderer
def add_mesh(self, vertices, faces, color=None, name=None) -> str:
if not self._initialized:
self._pending_meshes.append((vertices, faces, color, name))
return f"pending_{len(self._pending_meshes)}"
self._ensure_initialized()
mesh_id = self._renderer.add_mesh(vertices, faces, color, name)
self._meshes[mesh_id] = {"vertices": vertices, "faces": faces, "name": name}
self._renderer.render()
return mesh_id
def update_mesh(self, mesh_id: str, vertices, faces):
self._ensure_initialized()
self._renderer.update_mesh(mesh_id, vertices, faces)
self._meshes[mesh_id] = {"vertices": vertices, "faces": faces}
self._renderer.render()
def remove_mesh(self, mesh_id: str):
self._ensure_initialized()
self._renderer.remove_mesh(mesh_id)
if mesh_id in self._meshes:
del self._meshes[mesh_id]
self._renderer.render()
def clear_scene(self):
self._ensure_initialized()
self._renderer.clear_scene()
self._meshes.clear()
self._renderer.render()
def fit_camera(self):
self._ensure_initialized()
self._renderer.fit_camera()
self._renderer.render()
def set_camera_position(self, position, target):
self._ensure_initialized()
self._renderer.set_camera_position(position, target)
self._renderer.render()