Commands¶
Register commands that users can discover and trigger from a command palette.
Press Ctrl/Cmd+K to open the palette, then search for commands by name. (Ctrl/Cmd+Shift+P also works on browsers that don’t reserve it, e.g. everything except Firefox.) Commands can also be bound to keyboard hotkeys.
Key methods:
viser.GuiApi.add_command()to register a named commandviser.CommandHandle.on_trigger()to attach a callbackviser.CommandHandle.remove()to unregister a command
Features demonstrated:
Registering commands with labels, descriptions, icons, and hotkeys
Fuzzy search filtering in the palette
Dynamic command updates (label, description, icon changes)
Removing commands at runtime
Source: examples/02_gui/10_commands.py
Code¶
1import time
2
3import viser
4
5
6def main() -> None:
7 server = viser.ViserServer()
8
9 # Basic command.
10 hello_cmd = server.gui.add_command(
11 "Say Hello",
12 description="Show a greeting notification",
13 icon=viser.Icon.MESSAGE,
14 )
15
16 @hello_cmd.on_trigger
17 def _(event: viser.CommandEvent) -> None:
18 assert event.client is not None
19 event.client.add_notification(
20 title="Hello!",
21 body="You triggered the Say Hello command.",
22 color="teal",
23 )
24
25 # Command with a hotkey.
26 reset_cmd = server.gui.add_command(
27 "Reset Camera",
28 description="Move the camera back to the default view",
29 hotkey=("cmd/ctrl", "shift", "R"),
30 icon=viser.Icon.REFRESH,
31 )
32
33 @reset_cmd.on_trigger
34 def _(event: viser.CommandEvent) -> None:
35 assert event.client is not None
36 event.client.camera.position = (3.0, 3.0, 3.0)
37 event.client.camera.look_at = (0.0, 0.0, 0.0)
38 event.client.add_notification(
39 title="Camera Reset",
40 body="Camera position has been reset.",
41 color="blue",
42 )
43
44 # Toggle command (changes label/icon on each trigger).
45 grid_visible = True
46 grid_handle = server.scene.add_grid("/grid", width=10.0, height=10.0)
47
48 toggle_cmd = server.gui.add_command(
49 "Hide Grid",
50 description="Toggle grid visibility",
51 icon=viser.Icon.EYE_OFF,
52 )
53
54 @toggle_cmd.on_trigger
55 def _(event: viser.CommandEvent) -> None:
56 nonlocal grid_visible
57 grid_visible = not grid_visible
58 grid_handle.visible = grid_visible
59
60 if grid_visible:
61 toggle_cmd.label = "Hide Grid"
62 toggle_cmd.icon = viser.Icon.EYE_OFF
63 else:
64 toggle_cmd.label = "Show Grid"
65 toggle_cmd.icon = viser.Icon.EYE
66
67 # Removable command.
68 counter = 0
69 removable_cmd = server.gui.add_command(
70 "Self-Destruct",
71 description="This command removes itself after being triggered",
72 icon=viser.Icon.BOMB,
73 )
74
75 @removable_cmd.on_trigger
76 def _(event: viser.CommandEvent) -> None:
77 nonlocal counter
78 counter += 1
79 assert event.client is not None
80 event.client.add_notification(
81 title="Boom!",
82 body=f"Triggered {counter} time(s). Removing command...",
83 color="red",
84 )
85 removable_cmd.remove()
86
87 server.scene.add_frame("/frame", show_axes=True, axes_length=2.0)
88 toggle_cmd_disabled = server.gui.add_button("Toggle grid command disabled")
89
90 @toggle_cmd_disabled.on_click
91 def _(_) -> None:
92 toggle_cmd.disabled = not toggle_cmd.disabled
93
94 while True:
95 time.sleep(1.0)
96
97
98if __name__ == "__main__":
99 main()