Basic GUI controls¶
Create interactive controls like sliders, buttons, and text inputs.
This example demonstrates the full range of GUI controls available in viser, including:
Input Controls:
viser.GuiApi.add_number()for numeric inputviser.GuiApi.add_slider()for range selectionviser.GuiApi.add_vector2()andviser.GuiApi.add_vector3()for coordinate inputviser.GuiApi.add_text()for text inputviser.GuiApi.add_rgb()for color selection
Interactive Elements:
viser.GuiApi.add_button()with custom icons fromviser.Iconviser.GuiButtonHandle.on_hold()for continuous actions while a button is heldviser.GuiApi.add_checkbox()for boolean togglesviser.GuiApi.add_multi_slider()for multi-handle range controlsviser.GuiApi.add_upload_button()for file uploads
Layout & Organization:
viser.GuiApi.add_folder()to group related controlsviser.GuiApi.add_progress_bar()for status indication
The example shows how to read control values with .value, manage visibility with .visible, and disable controls with .disabled. GUI state automatically synchronizes with all connected clients.
Source: examples/02_gui/00_basic_controls.py
Code¶
1import time
2
3import numpy as np
4
5import viser
6
7
8def main() -> None:
9 server = viser.ViserServer()
10
11 # Add some common GUI elements: number inputs, sliders, vectors, checkboxes.
12 with server.gui.add_folder("Read-only"):
13 gui_counter = server.gui.add_number(
14 "Counter",
15 initial_value=0,
16 disabled=True,
17 )
18 gui_slider = server.gui.add_slider(
19 "Slider",
20 min=0,
21 max=100,
22 step=1,
23 initial_value=0,
24 disabled=True,
25 )
26 gui_progress = server.gui.add_progress_bar(25, animated=True)
27
28 with server.gui.add_folder("Editable"):
29 gui_vector2 = server.gui.add_vector2(
30 "Position",
31 initial_value=(0.0, 0.0),
32 step=0.1,
33 )
34 gui_vector3 = server.gui.add_vector3(
35 "Size",
36 initial_value=(1.0, 1.0, 1.0),
37 step=0.25,
38 )
39
40 # Buttons with on_hold for continuous size adjustment while held.
41 gui_grow = server.gui.add_button("Grow (hold)", icon=viser.Icon.PLUS)
42 gui_shrink = server.gui.add_button("Shrink (hold)", icon=viser.Icon.MINUS)
43
44 @gui_grow.on_hold(callback_hz=10.0)
45 def _(_: viser.GuiEvent[viser.GuiButtonHandle]) -> None:
46 x, y, z = gui_vector3.value
47 gui_vector3.value = (x + 0.05, y + 0.05, z + 0.05)
48
49 @gui_shrink.on_hold(callback_hz=10.0)
50 def _(_: viser.GuiEvent[viser.GuiButtonHandle]) -> None:
51 x, y, z = gui_vector3.value
52 gui_vector3.value = (
53 max(0.1, x - 0.05),
54 max(0.1, y - 0.05),
55 max(0.1, z - 0.05),
56 )
57
58 with server.gui.add_folder("Text toggle"):
59 gui_checkbox_hide = server.gui.add_checkbox(
60 "Hide",
61 initial_value=False,
62 )
63 gui_text = server.gui.add_text(
64 "Text",
65 initial_value="Hello world",
66 )
67 gui_button = server.gui.add_button("Button", icon=viser.Icon.MOUSE)
68 gui_checkbox_disable = server.gui.add_checkbox(
69 "Disable",
70 initial_value=False,
71 )
72 gui_rgb = server.gui.add_rgb(
73 "Color",
74 initial_value=(255, 255, 0),
75 )
76 gui_multi_slider = server.gui.add_multi_slider(
77 "Multi slider",
78 min=0,
79 max=100,
80 step=1,
81 initial_value=(0, 30, 100),
82 marks=((0, "0"), (50, "5"), (70, "7"), 99),
83 )
84 gui_slider_positions = server.gui.add_slider(
85 "# sliders",
86 min=0,
87 max=10,
88 step=1,
89 initial_value=3,
90 marks=((0, "0"), (5, "5"), (7, "7"), 10),
91 )
92 gui_upload_button = server.gui.add_upload_button(
93 "Upload", icon=viser.Icon.UPLOAD
94 )
95
96 @gui_upload_button.on_upload
97 def _(_) -> None:
98 file = gui_upload_button.value
99 print(file.name, len(file.content), "bytes")
100
101 # Pre-generate a point cloud to send.
102 point_positions = np.random.uniform(low=-1.0, high=1.0, size=(5000, 3))
103 color_coeffs = np.random.uniform(0.4, 1.0, size=(point_positions.shape[0]))
104
105 counter = 0
106 while True:
107 # We can set the value of an input to a particular value. Changes are
108 # automatically reflected in connected clients.
109 gui_counter.value = counter
110 gui_slider.value = counter % 100
111
112 # We can set the position of a scene node with `.position`, and read the value
113 # of a gui element with `.value`. Changes are automatically reflected in
114 # connected clients.
115 server.scene.add_point_cloud(
116 "/point_cloud",
117 points=point_positions * np.array(gui_vector3.value, dtype=np.float32),
118 colors=(np.array(gui_rgb.value) * color_coeffs[:, None]).astype(np.uint8),
119 position=gui_vector2.value + (0,),
120 point_shape="circle",
121 )
122 gui_button.color = gui_rgb.value
123
124 gui_progress.value = float((counter % 100))
125
126 # We can use `.visible` and `.disabled` to toggle GUI elements.
127 gui_text.visible = not gui_checkbox_hide.value
128 gui_button.visible = not gui_checkbox_hide.value
129 gui_rgb.disabled = gui_checkbox_disable.value
130 gui_multi_slider.disabled = gui_checkbox_disable.value
131 gui_slider_positions.disabled = gui_checkbox_disable.value
132 gui_button.disabled = gui_checkbox_disable.value
133 gui_upload_button.disabled = gui_checkbox_disable.value
134
135 # Update the number of handles in the multi-slider.
136 if gui_slider_positions.value != len(gui_multi_slider.value):
137 gui_multi_slider.value = np.linspace(
138 0, 100, gui_slider_positions.value, dtype=np.int64
139 )
140
141 counter += 1
142 time.sleep(0.01)
143
144
145if __name__ == "__main__":
146 main()