Kinematic controls
All examples on this page assume using BeamletOptics, BeamletOpticsGUI, GLMakie and a live-rendered system hsys in an LScene ax, see live_render! in BeamletOptics.
With kinematic_controls!, the components of a live-rendered system can be grabbed and moved with the mouse. The on_change callback is invoked (at most once per frame) after every change and is the place to re-solve the system and update dependent plots:
ctrl = kinematic_controls!(ax, hsys; on_change = obj -> begin
solve_system!(system, beam; initialize = true)
update_render!(hbeam)
end)initialize = true empties the detectors of the system before the solve, see initialize! in BeamletOptics. Without it, the hits of every solve add up on them.
A click selects a component, a drag on the selected component moves or rotates it, and every other drag rotates the camera as usual, so that rotating the camera never selects or moves a component by accident. The keyboard controls apply to the selected component and depend on the mode, which is switched with m:
| Input | Move mode | Rotate mode |
|---|---|---|
| Left-click on a component | Select it | Select it |
| Left-drag on the selected component | Move in the plane of the view | Rotate around the blue axis |
| Left-drag on an arrow or a ring | Move along that arrow | Rotate around that ring |
| Left-drag elsewhere | Rotate the camera | Rotate the camera |
↑ / ↓ | Move along the green arrow | Rotate around the red ring |
→ / ← | Move along the red arrow | Rotate around the blue ring |
Page Up / Page Down | Move along the blue arrow | Rotate around the green ring |
| Input | Action |
|---|---|
m | Switch between the move and the rotate mode |
| Shift (held) | Ten times the step size |
+ / - | Increase / decrease the step size along the 1-2-5 sequence |
Backspace | Reset the selected component to its initial pose |
Ctrl/Cmd + Z | Undo the last change |
Ctrl/Cmd + Y | Redo, also Ctrl/Cmd + Shift + Z |
Ctrl/Cmd + left-click | Add a component to the selection, or remove it from it |
Esc | Select the enclosing group, or deselect at the top level |
| Left-click on empty space | Deselect |
v | Switch the spectator mode on or off |
h | Show or hide an overlay of all controls |
In the spectator mode, the selection is cleared and all mouse and keyboard input goes to the camera, such that the system can be viewed without moving a component by accident. In live_view, the spectator mode also hides the user interface besides the 3D view and the help. Components whose kinematic trait is Static can not be selected.
The selected component is marked by a box and three perpendicular axes above it: the vertical rotation axis (blue), the heading of the component in the horizontal plane (green, its local y-axis projected onto that plane) and the horizontal axis beside it (red). For a component that is only turned about the vertical, these are its local y- and x-axes; a tilted component keeps perpendicular axes. In the move mode the axes are shown as arrows, in the rotate mode as rings. The first key of each pair moves the component in the direction of the arrow, or rotates it in the direction of the ring. In the rotate mode, a drag on a ring (the ring under the cursor is highlighted) rotates the component around that ring, through its position: the angle follows the cursor around the ring, or, if the ring is seen edge-on, the movement of the cursor along it. This tilts a component out of the plane of the table with the mouse. Locked rings, see constraints below, can not be dragged. In the move mode, a drag on an arrow (highlighted under the cursor in the same way) moves the component along that arrow only, e.g. along its optical axis or straight up, without snapping; a drag on the component itself moves it in the plane of the view as before. An arrow that points at the camera can not be grabbed, nor can a locked one. The current mode and step size are shown in the hint line at the top of the 3D view.
Clicking a component inside an ObjectGroup selects the outermost group first. Clicking the same component again descends one level into the hierarchy (a subgroup, then the individual object), so that the group can still be moved as a whole, or a single part can be moved on its own. Esc goes back up one level.
A drag grabs the point under the cursor, which stays under the cursor during the drag: the component moves in the plane of the view, i.e. the plane through the grabbed point perpendicular to the direction in which the camera looks. Seen from above, it moves on the table; seen from the front, it moves sideways and in height, which is easiest in an orthographic view along an axis (see the view cube). In an oblique view, a drag changes the height as well; the keyword plane_normal, e.g. plane_normal = [0, 0, 1], moves the components in a fixed plane instead, and the constraints below lock axes. Each drag, reset and series of steps with the same key (less than 1 s apart) is one entry of the undo history, which undoes up to 100 changes. In a live_view, adding, removing and changing a component or source are entries of the same history. Ctrl+Z and Ctrl+Y are the keys with these letters in the keyboard layout, e.g. on a German keyboard, where the two are swapped.
The constraints lock axes of individual components, e.g. a mirror in a kinematic mount that can only be tilted. The axes are named after the gizmo: :x (red), :y (green) and :v (blue, the rotation_axis). Missing fields allow all axes, locked axes are shown faded:
ctrl = kinematic_controls!(ax, hsys; constraints = Dict(mirror => (; move = (), rotate = (:x, :v))))Call close(ctrl) to remove the controls.