Viewer Events
Panopti exposes several event callbacks through Python decorators, which are accessible through viewer.events, the usage pattern looks like:
import panopti
viewer = panopti.connect(server_url="http://localhost:8080", viewer_id='client')
@viewer.events.camera(throttle=100)
def my_camera_event(viewer, camera_info):
# this function is triggered when the viewer camera is manipulated
# it can be triggered at most once every 100 milliseconds (see throttle argument)
...
Throttling event callbacks
Many of the event decorators accept an optional throttle: int argument, which limits the frequency at which the callback can be triggered. This is extremely useful when a callback is compute heavy, or if large updates are being propagated from the callback (e.g. updating a mesh's vertex array). This argument accepts an integer time in milliseconds.
Note that many events have an innate throttle defined in Panopti's configuration file (see Customization). Any throttle specified in event decorators acts in tandem with those in the configuration file.
Available event decorators:
Camera - @viewer.events.camera()
Camera Event
The camera event is triggered when the user manipulates the viewer
camera (e.g. orbit, pan, zoom). This event provides a CameraInfo object
containing information about the camera's current state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
throttle
|
int
|
Throttle interval in milliseconds. If provided, the callback will only be called at most once per throttle interval. |
None
|
Example usage:
@viewer.events.camera()
def camera_event(viewer, camera_info):
print('Camera was updated!')
# swivel scene mesh to always face the camera (in Y-axis):
mesh = viewer.get('myMesh')
mx, my, mz = mesh.position
cx, cy, cz = camera_info.position # dot-access notation
yaw = math.atan2(cx - mx, cz - mz)
mesh.rotation = [0, yaw, 0]
mesh.update(rotation=[0, yaw, 0])
# Or with throttling (100ms interval)
@viewer.events.camera(throttle=100)
def throttled_camera_event(viewer, camera_info):
print('Throttled camera update!')
camera_info is a CameraInfo object with the following attributes:
| attribute | meaning | type |
|---|---|---|
| position | camera world coords | ndarray |
| rotation | camera XYZ euler rotation | ndarray |
| quaternion | camera rotation as quaternion | ndarray |
| up | camera up-vector | ndarray |
| target | point the camera is looking at | ndarray |
| fov | vertical field-of-view (degrees) | float |
| near | near-plane distance | float |
| far | far-plane distance | float |
| aspect | viewport aspect ratio (w / h) | float |
| projection_mode | 'perspective' or 'orthographic' | str |
Inspect - @viewer.events.inspect()
Inspection Event
The inspect event is triggered when the inspection tool is used in the viewer (e.g. when clicking on a mesh to inspect its local vertex indices).
Example usage:
@viewer.events.inspect()
def inspect_event(viewer, inspect_info):
print(f"User clicked on a {inspect_info.object_type} object.")
if inspect_info.object_type == 'mesh':
print('Selected face index: ', inspect_info.inspect_result.face_index)
inspect_info is an InspectInfo object with the following attributes:
| attribute | meaning | type |
|---|---|---|
| object_name | name attribute of selected object |
str |
| object_type | type of Panopti object selected (e.g., 'mesh', 'points') |
str |
| world_coords | XYZ world coordinates of the pick point | ndarray |
| screen_coords | integer pixel coordinates of the pick point | ndarray |
| inspect_result | geometry-specific data at the pick point: Mesh / AnimatedMesh: MeshInspectResult holding face_index and vertex_indicesPointCloud: PointCloudInspectResult holding point_index |
Union[MeshInspectResult, PointCloudInspectResult] |
Select Object - @viewer.events.select_object()
Select Object Event
The select_object event is triggered when a geometric structure is selected in the viewer -- either by clicking on the object directly or selecting it in the layers panel.
Example usage:
@viewer.events.object_selection()
def object_selection_event(viewer, object_name):
print(f"User selected {object_name}")
object_name: str is the selected object's name.
Control - @viewer.events.control()
Control Event
The control event is triggered when any control element is interacted with,
e.g. when a slider is moved or a checkbox is toggled.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
throttle
|
int
|
Throttle interval in milliseconds. If provided, the callback will only be called at most once per throttle interval. |
None
|
Example usage:
@viewer.events.control()
def control_event(viewer, control_name, value):
print(f"User updated {control_name} to {value}")
# Or with throttling (50ms interval)
@viewer.events.control(throttle=50)
def throttled_control_event(viewer, control_name, value):
print(f"Throttled control update: {control_name} = {value}")
control_name: str is the name of the control element
value is the control element's new value
Update Object - @viewer.events.update_object()
Update Object Event
The update_object event is triggered when any geometric object has
an attribute updated, e.g. through .update(...) or when the transformation
panel is used.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
throttle
|
int
|
Throttle interval in milliseconds. If provided, the callback will only be called at most once per throttle interval. |
None
|
Example usage:
@viewer.events.update_object()
def update_object_event(viewer, object_name, data):
print(f"Object {object_name} updated with attributes: {data.keys()}")
# Or with throttling (100ms interval)
@viewer.events.update_object(throttle=100)
def throttled_update_event(viewer, object_name, data):
print(f"Throttled object update: {object_name}")
object_name: str is the updated object's name
data: dict holds the updated attributes of the object, e.g. {'vertices': ...}
Gizmo - @viewer.events.gizmo()
Gizmo Event
The gizmo event is triggered when the gizmo is used to transform an object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
throttle
|
int
|
Throttle interval in milliseconds. If provided, the callback will only be called at most once per throttle interval. |
None
|
Example usage:
@viewer.events.gizmo()
def gizmo_event(viewer, gizmo_info):
print(f"Gizmo was used to transform {gizmo_info.object_name}")
# Or with throttling (50ms interval)
@viewer.events.gizmo(throttle=50)
def throttled_gizmo_event(viewer, gizmo_info):
print(f"Throttled gizmo transform: {gizmo_info.object_name}")
gizmo_info is a GizmoInfo object with the following attributes:
| Attribute | Type | Description |
|---|---|---|
| object_name | str | Name of the transformed object |
| object_type | str | Type of Panopti object being transformed (e.g. 'mesh', 'points') |
| trans | TransformData | New transformation values with position, rotation, scale |
| prev_trans | TransformData | Previous transformation values when the drag event started |