Skip to content

Commit cc2b954

Browse files
authored
[FEATURE] Add an option to disable keyboard shortcuts. (#2026)
1 parent c533bb5 commit cc2b954

File tree

4 files changed

+72
-37
lines changed

4 files changed

+72
-37
lines changed

genesis/ext/pyrender/viewer.py

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ def __init__(
205205
plane_reflection=False,
206206
env_separate_rigid=False,
207207
enable_interaction=False,
208+
disable_keyboard_shortcuts=False,
208209
**kwargs,
209210
):
210211
#######################################################################
@@ -284,6 +285,8 @@ def __init__(
284285
if registered_keys is not None:
285286
self._registered_keys = {ord(k.lower()): registered_keys[k] for k in registered_keys}
286287

288+
self._disable_keyboard_shortcuts = disable_keyboard_shortcuts
289+
287290
#######################################################################
288291
# Save internal settings
289292
#######################################################################
@@ -294,6 +297,7 @@ def __init__(
294297
self._message_opac = 1.0 + self._ticks_till_fade
295298

296299
self._display_instr = False
300+
297301
self._instr_texts = [
298302
["> [i]: show keyboard instructions"],
299303
[
@@ -735,47 +739,48 @@ def on_draw(self):
735739

736740
self.viewer_interaction.on_draw()
737741

738-
if self._display_instr:
739-
self._renderer.render_texts(
740-
self._instr_texts[1],
741-
TEXT_PADDING,
742-
self.viewport_size[1] - TEXT_PADDING,
743-
font_pt=26,
744-
color=np.array([1.0, 1.0, 1.0, 0.85]),
745-
)
746-
else:
747-
self._renderer.render_texts(
748-
self._instr_texts[0],
749-
TEXT_PADDING,
750-
self.viewport_size[1] - TEXT_PADDING,
751-
font_pt=26,
752-
color=np.array([1.0, 1.0, 1.0, 0.85]),
753-
)
754-
755-
if self._message_text is not None:
756-
self._renderer.render_text(
757-
self._message_text,
758-
self.viewport_size[0] - TEXT_PADDING,
759-
TEXT_PADDING,
760-
font_pt=20,
761-
color=np.array([0.1, 0.7, 0.2, np.clip(self._message_opac, 0.0, 1.0)]),
762-
align=TextAlign.BOTTOM_RIGHT,
763-
)
742+
if not self._disable_keyboard_shortcuts:
743+
if self._display_instr:
744+
self._renderer.render_texts(
745+
self._instr_texts[1],
746+
TEXT_PADDING,
747+
self.viewport_size[1] - TEXT_PADDING,
748+
font_pt=26,
749+
color=np.array([1.0, 1.0, 1.0, 0.85]),
750+
)
751+
else:
752+
self._renderer.render_texts(
753+
self._instr_texts[0],
754+
TEXT_PADDING,
755+
self.viewport_size[1] - TEXT_PADDING,
756+
font_pt=26,
757+
color=np.array([1.0, 1.0, 1.0, 0.85]),
758+
)
764759

765-
if self.viewer_flags["caption"] is not None:
766-
for caption in self.viewer_flags["caption"]:
767-
xpos, ypos = self._location_to_x_y(caption["location"])
760+
if self._message_text is not None:
768761
self._renderer.render_text(
769-
caption["text"],
770-
xpos,
771-
ypos,
772-
font_name=caption["font_name"],
773-
font_pt=caption["font_pt"],
774-
color=caption["color"],
775-
scale=caption["scale"],
776-
align=caption["location"],
762+
self._message_text,
763+
self.viewport_size[0] - TEXT_PADDING,
764+
TEXT_PADDING,
765+
font_pt=20,
766+
color=np.array([0.1, 0.7, 0.2, np.clip(self._message_opac, 0.0, 1.0)]),
767+
align=TextAlign.BOTTOM_RIGHT,
777768
)
778769

770+
if self.viewer_flags["caption"] is not None:
771+
for caption in self.viewer_flags["caption"]:
772+
xpos, ypos = self._location_to_x_y(caption["location"])
773+
self._renderer.render_text(
774+
caption["text"],
775+
xpos,
776+
ypos,
777+
font_name=caption["font_name"],
778+
font_pt=caption["font_pt"],
779+
color=caption["color"],
780+
scale=caption["scale"],
781+
align=caption["location"],
782+
)
783+
779784
if self._run_in_thread or not self.auto_start:
780785
self.render_lock.release()
781786

@@ -870,6 +875,10 @@ def on_key_press(self, symbol: int, modifiers: int) -> EVENT_HANDLE_STATE:
870875
callback(self, *args, **kwargs)
871876
return self.viewer_interaction.on_key_press(symbol, modifiers)
872877

878+
# If keyboard shortcuts are disabled, skip default key functions
879+
if self._disable_keyboard_shortcuts:
880+
return self.viewer_interaction.on_key_press(symbol, modifiers)
881+
873882
# Otherwise, use default key functions
874883

875884
# A causes the frame to rotate

genesis/options/vis.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class ViewerOptions(Options):
3333
The up vector of the camera's extrinsic pose.
3434
camera_fov : float
3535
The field of view (in degrees) of the camera.
36+
disable_keyboard_shortcuts : bool
37+
Whether to disable all keyboard shortcuts in the viewer. Defaults to False.
3638
"""
3739

3840
res: Optional[tuple] = None
@@ -44,6 +46,7 @@ class ViewerOptions(Options):
4446
camera_up: tuple = (0.0, 0.0, 1.0)
4547
camera_fov: float = 40
4648
enable_interaction: bool = False
49+
disable_keyboard_shortcuts: bool = False
4750

4851

4952
class VisOptions(Options):

genesis/vis/viewer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def __init__(self, options: "ViewerOptions", context):
4141
self._camera_up = np.asarray(options.camera_up, dtype=gs.np_float)
4242
self._camera_fov = options.camera_fov
4343
self._enable_interaction = options.enable_interaction
44+
self._disable_keyboard_shortcuts = options.disable_keyboard_shortcuts
4445

4546
# Validate viewer options
4647
if any(e.shape != (3,) for e in (self._camera_init_pos, self._camera_init_lookat, self._camera_up)):
@@ -100,6 +101,7 @@ def build(self, scene):
100101
plane_reflection=self.context.plane_reflection,
101102
env_separate_rigid=self.context.env_separate_rigid,
102103
enable_interaction=self._enable_interaction,
104+
disable_keyboard_shortcuts=self._disable_keyboard_shortcuts,
103105
viewer_flags={
104106
"window_title": f"Genesis {gs.__version__}",
105107
"refresh_rate": self._refresh_rate,

tests/test_render.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,27 @@ def on_key_press(self, symbol: int, modifiers: int):
10681068
assert f.read() == png_snapshot
10691069

10701070

1071+
@pytest.mark.required
1072+
@pytest.mark.parametrize("renderer_type", [RENDERER_TYPE.RASTERIZER])
1073+
@pytest.mark.skipif(not IS_INTERACTIVE_VIEWER_AVAILABLE, reason="Interactive viewer not supported on this platform.")
1074+
def test_interactive_viewer_disable_keyboard_shortcuts():
1075+
"""Test that keyboard shortcuts can be disabled in the interactive viewer."""
1076+
1077+
# Test with keyboard shortcuts DISABLED
1078+
scene = gs.Scene(
1079+
viewer_options=gs.options.ViewerOptions(
1080+
disable_keyboard_shortcuts=True,
1081+
),
1082+
show_viewer=True,
1083+
)
1084+
scene.build()
1085+
pyrender_viewer = scene.visualizer.viewer._pyrender_viewer
1086+
assert pyrender_viewer.is_active
1087+
1088+
# Verify the flag is set correctly
1089+
assert pyrender_viewer._disable_keyboard_shortcuts is True
1090+
1091+
10711092
@pytest.mark.parametrize(
10721093
"renderer_type",
10731094
[RENDERER_TYPE.RASTERIZER, RENDERER_TYPE.BATCHRENDER_RASTERIZER, RENDERER_TYPE.BATCHRENDER_RAYTRACER],

0 commit comments

Comments
 (0)