GUI layouts¶
Organize GUI controls using folders, forms, tabs, and nested structures for better user experience.
Features:
viser.GuiApi.add_folder()for grouping related controlsviser.GuiApi.add_form()for groups that commit together on submitviser.GuiApi.add_tab_group()andviser.GuiTabGroupHandle.add_tab()for tabbed interfacesviser.GuiApi.add_divider()for separating sections with a horizontal lineNested folder hierarchies for complex layouts
Context managers for automatic grouping
Source: examples/02_gui/02_layouts.py
Code¶
1import time
2
3import viser
4
5
6def main() -> None:
7 server = viser.ViserServer()
8
9 # A form groups inputs that are committed together. on_update callbacks on
10 # child inputs still fire per-keystroke, but on_submit only fires when the
11 # user presses Enter or clicks the button. A dirty indicator (*) appears
12 # next to the label whenever any input has been edited since the last submit.
13 with server.gui.add_form("Camera Controls") as camera_form:
14 cam_x = server.gui.add_number("X", initial_value=3.0, step=0.01)
15 cam_y = server.gui.add_number("Y", initial_value=3.0, step=0.01)
16 cam_z = server.gui.add_number("Z", initial_value=3.0, step=0.01)
17 go_button = server.gui.add_button("Go")
18
19 go_button.on_click(lambda _: camera_form.submit())
20
21 @camera_form.on_submit
22 def _(_) -> None:
23 for client in server.get_clients().values():
24 client.camera.position = (cam_x.value, cam_y.value, cam_z.value)
25 client.camera.look_at = (0.0, 0.0, 0.0)
26
27 # Example 2: Scene objects organization
28 with server.gui.add_folder("Scene Objects"):
29 server.gui.add_checkbox("Enable Lighting", initial_value=True)
30 server.gui.add_slider(
31 "Intensity", min=0.0, max=2.0, step=0.1, initial_value=1.0
32 )
33 server.gui.add_rgb("Color", initial_value=(255, 255, 255))
34
35 server.gui.add_divider()
36
37 show_axes = server.gui.add_checkbox("Show Coordinate Axes", initial_value=True)
38 server.gui.add_checkbox("Show Grid", initial_value=False)
39
40 with server.gui.add_folder("Sphere"):
41 sphere_radius = server.gui.add_slider(
42 "Radius", min=0.1, max=2.0, step=0.1, initial_value=0.5
43 )
44 sphere_color = server.gui.add_rgb("Color", initial_value=(255, 0, 0))
45 sphere_visible = server.gui.add_checkbox("Visible", initial_value=True)
46
47 # Example 3: Settings and preferences
48 with server.gui.add_folder("Settings"):
49 server.gui.add_rgb("Background", initial_value=(40, 40, 40))
50 server.gui.add_checkbox("Wireframe Mode", initial_value=False)
51
52 server.gui.add_divider()
53
54 server.gui.add_slider("FPS Limit", min=30, max=120, step=10, initial_value=60)
55 server.gui.add_dropdown(
56 "Quality", options=["Low", "Medium", "High"], initial_value="Medium"
57 )
58
59 # Add some visual objects to demonstrate the controls
60 server.scene.add_icosphere(
61 name="demo_sphere",
62 radius=sphere_radius.value,
63 color=(
64 sphere_color.value[0] / 255.0,
65 sphere_color.value[1] / 255.0,
66 sphere_color.value[2] / 255.0,
67 ),
68 position=(0.0, 0.0, 0.0),
69 visible=sphere_visible.value,
70 )
71
72 if show_axes.value:
73 server.scene.add_frame("axes", axes_length=1.0, axes_radius=0.02)
74
75 while True:
76 time.sleep(0.1)
77
78
79if __name__ == "__main__":
80 main()