Skip to main content

geop_ops_parts/operation/
handle.rs

1//! Handles: how a step can be edited by dragging in a 3-D view.
2//!
3//! An operation describes, for a step, where its adjustable values sit in
4//! space and how dragging them maps back onto its arguments: a handle has a
5//! position, a way it moves (along a line, or in a plane), and the path of
6//! the argument(s) in the step it rewrites. An editor draws the handles it
7//! wants to offer, and turns a drag into new argument values at those paths
8//! — so dragging edits the program exactly like typing a value in a form
9//! does, and the editor needs to know nothing about the operation.
10//!
11//! Every step provides all of its handles; which to show is the editor's
12//! choice (see [`HandleGroup`]).
13
14use serde::Serialize;
15
16/// Where a handle writes in its step: field names into the arguments as
17/// they serialize — `["distance"]`, or `["sketch", "points", "7", "x"]`.
18pub type ArgPath = Vec<String>;
19
20/// A path from `&str` segments.
21pub fn arg_path(segments: &[&str]) -> ArgPath {
22    segments.iter().map(|s| s.to_string()).collect()
23}
24
25/// What a handle belongs to, so an editor can offer only what fits what the
26/// user is doing: a feature's parameters while looking at the part, a
27/// sketch's points while sketching.
28#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
29#[serde(rename_all = "snake_case")]
30pub enum HandleGroup {
31    Feature,
32    Sketch,
33}
34
35/// How a handle moves, and how that maps onto its step's arguments.
36#[derive(Clone, Debug, PartialEq, Serialize)]
37#[serde(tag = "motion", rename_all = "snake_case")]
38pub enum HandleMotion {
39    /// Slides along the unit vector `direction`: moving it by `d` world
40    /// units changes the number at `arg`, now `value`, by `d / scale`.
41    Linear {
42        direction: [f64; 3],
43        arg: ArgPath,
44        value: f64,
45        scale: f64,
46    },
47    /// Slides in the plane of the unit vectors `u` and `v`: moving it by
48    /// `a u + b v` changes the numbers at `x` and `y`, now `value`, by `a`
49    /// and `b`.
50    Planar {
51        u: [f64; 3],
52        v: [f64; 3],
53        x: ArgPath,
54        y: ArgPath,
55        value: [f64; 2],
56    },
57}
58
59/// One draggable value of a step.
60#[derive(Clone, Debug, PartialEq, Serialize)]
61pub struct Handle {
62    /// What it adjusts, e.g. `distance`.
63    pub label: String,
64    pub group: HandleGroup,
65    /// Where it is drawn.
66    pub position: [f64; 3],
67    #[serde(flatten)]
68    pub motion: HandleMotion,
69}