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_indices PointCloud: 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 |