Skip to content

Commit 71defbc

Browse files
committed
Fix Newton GL visualizer Pause Rendering button desync with Space key
Space toggled the viewer's own _paused flag directly, bypassing the Isaac Lab Pause Rendering button's separately tracked _paused_rendering flag, so the button label and is_rendering_paused() went stale after pressing Space. Both controls now read/write the same _paused flag.
1 parent 4f15463 commit 71defbc

3 files changed

Lines changed: 69 additions & 7 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Fixed
2+
^^^^^
3+
4+
* Fixed the Newton GL visualizer's "Pause Rendering" button not reflecting the paused
5+
state after pressing :kbd:`Space`. Both controls now toggle the same underlying flag, so
6+
the button label and :meth:`~isaaclab_visualizers.newton.newton_visualizer.NewtonViewerGL.is_rendering_paused`
7+
stay in sync regardless of whether rendering was paused via the button or the keyboard shortcut.
8+
Also clarified the on-screen control hint from "Space - Pause/Resume" to "Space - Pause/Resume
9+
Rendering".

source/isaaclab_visualizers/isaaclab_visualizers/newton/newton_visualizer.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ def _render_left_panel(_g=gui):
467467
imgui.text("Ctrl + Middle Click - Dolly")
468468
imgui.text("Scroll - Dolly")
469469
imgui.text("Ctrl + Scroll - FOV zoom")
470-
imgui.text("Space - Pause/Resume")
470+
imgui.text("Space - Pause/Resume Rendering")
471471
imgui.text(". - Step one frame (when paused)")
472472
imgui.text("H - Toggle UI")
473473
imgui.text("F - Frame camera around model")
@@ -487,11 +487,13 @@ def _render_training_controls(self, imgui):
487487

488488
# Pause/Resume Rendering is not exposed on RTX: stopping end_frame() would
489489
# freeze the imgui, and OVRTX naturally converges when the scene is paused.
490+
# ``self._paused`` (not a separately tracked flag) is the single source of truth here
491+
# because the Newton viewer's own Space key handler toggles it directly, bypassing this
492+
# button; mirroring a separate flag would let the button state drift out of sync with Space.
490493
if not isinstance(self, NewtonViewerRTX):
491-
rendering_label = "Resume Rendering" if self._paused_rendering else "Pause Rendering"
494+
rendering_label = "Resume Rendering" if self._paused else "Pause Rendering"
492495
if imgui.button(rendering_label):
493-
self._paused_rendering = not self._paused_rendering
494-
self._paused = self._paused_rendering
496+
self._paused = not self._paused
495497

496498
if imgui.button("Reset Episode"):
497499
self._reset_requested = True
@@ -733,7 +735,6 @@ def __init__(self, *args, metadata: dict | None = None, update_frequency: int =
733735
"""
734736
super().__init__(*args, **kwargs)
735737
self._paused_training = False
736-
self._paused_rendering = False
737738
self._reset_requested = False
738739
self._metadata = metadata or {}
739740
self._update_frequency = update_frequency
@@ -763,8 +764,12 @@ def is_training_paused(self) -> bool:
763764
return self._paused_training
764765

765766
def is_rendering_paused(self) -> bool:
766-
"""Return whether rendering is paused by viewer controls."""
767-
return self._paused_rendering
767+
"""Return whether rendering is paused by viewer controls.
768+
769+
Mirrors ``self._paused`` directly since the Newton viewer's Space key handler toggles it
770+
in-place, outside the Isaac Lab "Pause Rendering" button.
771+
"""
772+
return self._paused
768773

769774
def on_key_press(self, symbol, modifiers):
770775
"""Forward key presses unless UI is currently capturing input."""

source/isaaclab_visualizers/test/test_newton_adapter.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,54 @@ def test_newton_viewer_camera_speed_setter_validates(monkeypatch):
292292
viewer.camera_speed = -1.0
293293

294294

295+
class _FakeTrainingControlsImgui:
296+
"""Minimal imgui double that drives ``_render_training_controls`` by label."""
297+
298+
def __init__(self, clicked_label: str | None = None):
299+
self._clicked_label = clicked_label
300+
301+
def button(self, label):
302+
return label == self._clicked_label
303+
304+
def text(self, _text):
305+
pass
306+
307+
def slider_int(self, _label, value, _min_value, _max_value, _format):
308+
return False, value
309+
310+
def is_item_hovered(self):
311+
return False
312+
313+
def set_tooltip(self, _text):
314+
pass
315+
316+
317+
def test_newton_gl_viewer_rendering_pause_state_stays_in_sync_with_space_key():
318+
"""Space toggles ``_paused`` directly (Newton's own key handler); the "Pause Rendering"
319+
button and ``is_rendering_paused()`` must reflect that instead of a separately tracked flag,
320+
or the UI desyncs from the actual paused state that gates rendering.
321+
"""
322+
viewer = NewtonViewerGL.__new__(NewtonViewerGL)
323+
viewer._paused = False
324+
viewer._paused_training = False
325+
viewer._reset_requested = False
326+
viewer._update_frequency = 1
327+
328+
assert viewer.is_rendering_paused() is False
329+
330+
# Simulate Newton's own Space key handler (newton/_src/viewer/viewer_gui.py), which
331+
# toggles ``_paused`` directly and bypasses the Isaac Lab "Pause Rendering" button.
332+
viewer._paused = not viewer._paused
333+
334+
assert viewer.is_rendering_paused() is True
335+
viewer._render_training_controls(_FakeTrainingControlsImgui()) # must not raise: no click
336+
337+
# The button must read the post-Space state and toggle it back correctly.
338+
resume_click = _FakeTrainingControlsImgui(clicked_label="Resume Rendering")
339+
viewer._render_training_controls(resume_click)
340+
assert viewer.is_rendering_paused() is False
341+
342+
295343
def test_newton_viewer_particle_color_override(monkeypatch):
296344
from newton.viewer import ViewerGL
297345

0 commit comments

Comments
 (0)