Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/source/overview/core-concepts/visualization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,15 @@ the num of environments can be overwritten and decreased using ``--num_envs``:
The FPS control in the Rerun visualizer UI may not affect the visualization frame rate in all configurations.


**Rerun Visualizer Play/Pause Timeline Controls**

The native Play/Pause timeline controls in the Rerun visualizer UI do not work while visualizing a live
simulation or training run. They are hidden by default, but Rerun's dock panel UI can still be used to reveal
them; when revealed, clicking them has no effect. Use Isaac Lab's own **Pause Rendering** / **Reset Episode**
controls (ImGui sidebar, under **IsaacLab Controls**) to control the live view instead. The timeline controls
are only meaningful when replaying a saved ``.rrd`` recording (see above).


**Newton Contact Visualization**

Newton's native ``Show Contacts`` view can show all contacts from the Newton physics contact buffer. When running
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Fixed
^^^^^

* Fixed the Newton GL visualizer's "Pause Rendering" button not reflecting the paused
state after pressing :kbd:`Space`. Both controls now toggle the same underlying flag, so
the button label and :meth:`~isaaclab_visualizers.newton.newton_visualizer.NewtonViewerGL.is_rendering_paused`
stay in sync regardless of whether rendering was paused via the button or the keyboard shortcut.
Also clarified the on-screen control hint from "Space - Pause/Resume" to "Space - Pause/Resume
Rendering".
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ def _render_left_panel(_g=gui):
imgui.text("Ctrl + Middle Click - Dolly")
imgui.text("Scroll - Dolly")
imgui.text("Ctrl + Scroll - FOV zoom")
imgui.text("Space - Pause/Resume")
imgui.text("Space - Pause/Resume Rendering")
imgui.text(". - Step one frame (when paused)")
imgui.text("H - Toggle UI")
imgui.text("F - Frame camera around model")
Expand All @@ -487,11 +487,13 @@ def _render_training_controls(self, imgui):

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

if imgui.button("Reset Episode"):
self._reset_requested = True
Expand Down Expand Up @@ -733,7 +735,6 @@ def __init__(self, *args, metadata: dict | None = None, update_frequency: int =
"""
super().__init__(*args, **kwargs)
self._paused_training = False
self._paused_rendering = False
self._reset_requested = False
self._metadata = metadata or {}
self._update_frequency = update_frequency
Expand Down Expand Up @@ -763,8 +764,12 @@ def is_training_paused(self) -> bool:
return self._paused_training

def is_rendering_paused(self) -> bool:
"""Return whether rendering is paused by viewer controls."""
return self._paused_rendering
"""Return whether rendering is paused by viewer controls.

Mirrors ``self._paused`` directly since the Newton viewer's Space key handler toggles it
in-place, outside the Isaac Lab "Pause Rendering" button.
"""
return self._paused

def on_key_press(self, symbol, modifiers):
"""Forward key presses unless UI is currently capturing input."""
Expand Down
48 changes: 48 additions & 0 deletions source/isaaclab_visualizers/test/test_newton_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,54 @@ def test_newton_viewer_camera_speed_setter_validates(monkeypatch):
viewer.camera_speed = -1.0


class _FakeTrainingControlsImgui:
"""Minimal imgui double that drives ``_render_training_controls`` by label."""

def __init__(self, clicked_label: str | None = None):
self._clicked_label = clicked_label

def button(self, label):
return label == self._clicked_label

def text(self, _text):
pass

def slider_int(self, _label, value, _min_value, _max_value, _format):
return False, value

def is_item_hovered(self):
return False

def set_tooltip(self, _text):
pass


def test_newton_gl_viewer_rendering_pause_state_stays_in_sync_with_space_key():
"""Space toggles ``_paused`` directly (Newton's own key handler); the "Pause Rendering"
button and ``is_rendering_paused()`` must reflect that instead of a separately tracked flag,
or the UI desyncs from the actual paused state that gates rendering.
"""
viewer = NewtonViewerGL.__new__(NewtonViewerGL)
viewer._paused = False
viewer._paused_training = False
viewer._reset_requested = False
viewer._update_frequency = 1

assert viewer.is_rendering_paused() is False

# Simulate Newton's own Space key handler (newton/_src/viewer/viewer_gui.py), which
# toggles ``_paused`` directly and bypasses the Isaac Lab "Pause Rendering" button.
viewer._paused = not viewer._paused

assert viewer.is_rendering_paused() is True
viewer._render_training_controls(_FakeTrainingControlsImgui()) # must not raise: no click

# The button must read the post-Space state and toggle it back correctly.
resume_click = _FakeTrainingControlsImgui(clicked_label="Resume Rendering")
viewer._render_training_controls(resume_click)
assert viewer.is_rendering_paused() is False


def test_newton_viewer_particle_color_override(monkeypatch):
from newton.viewer import ViewerGL

Expand Down
Loading