GUI callbacksΒΆ
Asynchronous usage of GUI elements: we can attach callbacks that are called as soon as we get updates.
1import time
2
3import numpy as np
4from typing_extensions import assert_never
5
6import viser
7
8
9def main() -> None:
10 server = viser.ViserServer()
11
12 gui_reset_scene = server.gui.add_button("Reset Scene")
13
14 gui_plane = server.gui.add_dropdown(
15 "Grid plane", ("xz", "xy", "yx", "yz", "zx", "zy")
16 )
17
18 def update_plane() -> None:
19 server.scene.add_grid(
20 "/grid",
21 width=10.0,
22 height=20.0,
23 width_segments=10,
24 height_segments=20,
25 plane=gui_plane.value,
26 )
27
28 gui_plane.on_update(lambda _: update_plane())
29
30 with server.gui.add_folder("Control"):
31 gui_show_frame = server.gui.add_checkbox("Show Frame", initial_value=True)
32 gui_show_everything = server.gui.add_checkbox(
33 "Show Everything", initial_value=True
34 )
35 gui_axis = server.gui.add_dropdown("Axis", ("x", "y", "z"))
36 gui_include_z = server.gui.add_checkbox("Z in dropdown", initial_value=True)
37
38 @gui_include_z.on_update
39 def _(_) -> None:
40 gui_axis.options = ("x", "y", "z") if gui_include_z.value else ("x", "y")
41
42 with server.gui.add_folder("Sliders"):
43 gui_location = server.gui.add_slider(
44 "Location", min=-5.0, max=5.0, step=0.05, initial_value=0.0
45 )
46 gui_num_points = server.gui.add_slider(
47 "# Points", min=1000, max=200_000, step=1000, initial_value=10_000
48 )
49
50 def draw_frame() -> None:
51 axis = gui_axis.value
52 if axis == "x":
53 pos = (gui_location.value, 0.0, 0.0)
54 elif axis == "y":
55 pos = (0.0, gui_location.value, 0.0)
56 elif axis == "z":
57 pos = (0.0, 0.0, gui_location.value)
58 else:
59 assert_never(axis)
60
61 server.scene.add_frame(
62 "/frame",
63 wxyz=(1.0, 0.0, 0.0, 0.0),
64 position=pos,
65 show_axes=gui_show_frame.value,
66 axes_length=5.0,
67 )
68
69 def draw_points() -> None:
70 num_points = gui_num_points.value
71 server.scene.add_point_cloud(
72 "/frame/point_cloud",
73 points=np.random.normal(size=(num_points, 3)),
74 colors=np.random.randint(0, 256, size=(num_points, 3)),
75 )
76
77 # We can (optionally) also attach callbacks!
78 # Here, we update the point clouds + frames whenever any of the GUI items are updated.
79 gui_show_frame.on_update(lambda _: draw_frame())
80 gui_show_everything.on_update(
81 lambda _: server.scene.set_global_visibility(gui_show_everything.value)
82 )
83 gui_axis.on_update(lambda _: draw_frame())
84 gui_location.on_update(lambda _: draw_frame())
85 gui_num_points.on_update(lambda _: draw_points())
86
87 @gui_reset_scene.on_click
88 def _(_) -> None:
89 """Reset the scene when the reset button is clicked."""
90 gui_show_frame.value = True
91 gui_location.value = 0.0
92 gui_axis.value = "x"
93 gui_num_points.value = 10_000
94
95 draw_frame()
96 draw_points()
97
98 # Finally, let's add the initial frame + point cloud and just loop infinitely. :)
99 update_plane()
100 draw_frame()
101 draw_points()
102 while True:
103 time.sleep(1.0)
104
105
106if __name__ == "__main__":
107 main()