Refactor viewer loop and shutdown handling to support conditional rendering and clean exits.

This change introduces a get_frame method to the viewer protocol, replacing the previous is_running check. This allows the viewer loop to skip rendering and lifecycle events when no active frame is ready (for example, when no browser is connected to the web viewer).

Additionally, this change:
- Adds a shutdown hook to ViewerHandle to wait for the viewer to cleanly release resources before exiting.
- Implements an ExitEvent handler in the viewer protocol to stop the run loop.
- Adds an http_port configuration option for the web viewer.
- Prevents double-closing in the viewer.

PiperOrigin-RevId: 954603868
Change-Id: Iaba7d131dc94191de51150464514dd10fa7834b0
This commit is contained in:
Matija Kecman
2026-07-27 06:54:26 -07:00
committed by Copybara-Service
parent e23b504201
commit e4d0a88ffd
4 changed files with 68 additions and 24 deletions
@@ -99,11 +99,12 @@ class NativeViewer(viewer_protocol.Viewer):
self._viewer.InitRenderer(model)
self._renderer_model_id = id(model)
def is_running(self) -> bool:
"""Poll for a new frame; returns ``False`` when the window is closed."""
if super().is_running() and not self._viewer.NewFrame():
self.close()
return super().is_running()
def prepare_next_frame(self) -> bool:
"""Advances to the next frame; returns False when the window is closed."""
if not self._viewer.NewFrame():
self._is_running = False
return False
return True
def sync(self) -> None:
"""Render the scene and present it to the window."""