Transform
Swap or remap a field on the wireA transform moves a field the clone's descriptor declares into another one. It needs no imperfect-clone opt-in, unlike the advanced control layer.
Transforms run before rendering, so injection, riding and rendering see the transformed field. They are session state on the same lifecycle as a lock.
native report the box's semantic path the wire
X Y wheel pan --> parse --> lock --> [ field transform ] --> render --> emit
buttons/keys weigh swap
remap (X->Y, btn->btn, same report)
|
+-- btn->key / btn->media --> that interface's report| Transform a... | Exchange it with another | Move it into another field | Weigh or invert it |
|---|---|---|---|
| relative axis (X / Y / wheel / pan) | transform_swap | transform_remap | scale, at a signed percent |
| button | axes only | transform_remap, into a button, key, or media | one bit: lock or unlock |
| key or media usage | not a source | destination only, from a button | one bit, as a button |
All are fire-and-forget: one frame, no reply. transform takes any Transform built from parts, and query_transforms reads the active table.
transform
Install or overwrite one field transformfn transform(&self, t: &Transform) -> Result<()>
Fire-and-forget
| Parameter | Type | Description |
|---|---|---|
t | Transform | The operation and the source and destination fields. A pair the op cannot address, or one field named as both ends, is Error::TransformOpFields; installing one past Transforms::CAPACITY is Error::TransformTableFull; one the box refuses is absent from query_transforms. |
An entry is keyed by its (source, dest); setting one whose key exists overwrites it in place, keeping its position. Entries apply in installation order, so two that write the same field do not commute.
use medius::{Device, Axis, Transform};
let device = Device::find()?;
device.transform(&Transform::swap(Axis::X, Axis::Y))?; // the mouse's two axes, exchanged
device.transform(&Transform::remap(Axis::Wheel, Axis::Y))?; // the wheel drives vertical motiontransform_swap / transform_remap
The two transforms, one call eachfn transform_swap(&self, a: Axis, b: Axis) -> Result<()>
fn transform_remap(&self, source: impl Into<LockTarget>, dest: impl Into<LockTarget>) -> Result<()>
Fire-and-forget
Each installs the Transform its matching constructor builds, and refuses on the same terms as transform.
use medius::{Device, Axis, Button, Direction, Key};
let device = Device::find()?;
device.transform_swap(Axis::X, Axis::Y)?; // exchange the two axes
device.transform_remap(Axis::Wheel, Axis::Y)?; // the wheel drives vertical motion
device.transform_remap(Button::new(4), Key::A)?; // the fifth button emits 'A' on the keyboard interface
device.scale(Axis::Y, Direction::Both, -100)?; // and Y arrives inverteduntransform / clear_transforms
Drop one entry or the whole tablefn untransform(&self, t: &Transform) -> Result<()>
fn clear_transforms(&self) -> Result<()>
Fire-and-forget
untransform drops the entry keyed by this transform's (source, dest); its op is ignored. clear_transforms drops the whole table.
let swap = Transform::swap(Axis::X, Axis::Y);
device.transform(&swap)?;
device.untransform(&swap)?; // the same key, dropped
device.clear_transforms()?; // or drop everythingquery_transforms
Read the active tablefn query_transforms(&self) -> Result<Transforms>
Blocks
Returns a Transforms: the held entries in the order the box applies them, and a full flag. query_health reports a non-empty table in its transform_on flag.
let table = device.query_transforms()?;
println!("{} transforms{}", table.entries.len(), if table.table_full { " (full)" } else { "" });
for t in &table.entries {
println!(" {:?} {:?} -> {:?}", t.op, t.source, t.dest);
}On AsyncDevice
the transforms fire, query_transforms awaitsTransforms carry no opt-in check, so AsyncDevice keeps every setter synchronous. Only query_transforms is a future.
use futures::executor::block_on;
use medius::{AsyncDevice, Axis};
let device = AsyncDevice::open("/dev/ttyACM0")?;
device.transform_swap(Axis::X, Axis::Y)?; // sync
let table = block_on(device.query_transforms())?; // query awaits