graphic design tool
git clone https://git.lucas.co/cce-designer.git
src/curve_tool.rs (2.4K)
1 //! The curve viewer state: the `curve` node's control points as draggable
2 //! handles, entered from the node's context menu ("Edit Handles").
3 //!
4 //! This is now one [`HandleSource`] on the framework in
5 //! [`crate::viewer_state`], which owns everything that used to live here:
6 //! projection, hit-testing, the drag model, per-gesture undo, snapping, the
7 //! HUD, and write-back through the SetParam resync sequence. What is left is
8 //! the part that is actually about curves — an open-ended list of world
9 //! positions in the "Points" parameter, which the pointer may extend and trim.
10 //!
11 //! The behaviour that survives the move, because it is the framework's now:
12 //!
13 //! - **left press on a handle** grabs it; dragging moves the point on the
14 //! camera-facing plane at its own depth, so orbiting between edits never
15 //! makes a drag jump;
16 //! - **left press on empty space** appends a point there, at the depth of the
17 //! last one, and immediately drags it;
18 //! - **right press on a handle** deletes it; Delete/Backspace deletes the
19 //! selected one;
20 //! - **undo / redo** step one gesture at a time — a whole drag is one step,
21 //! an add-and-drag is one step, a delete is one step;
22 //! - **Escape** exits.
23
24 use crate::app::FsNode;
25 use crate::geometry::{format_curve_points, node_param_str, parse_curve_points};
26 use crate::viewer_state::HandleSource;
27 use glam::Vec3;
28
29 /// Re-exported for the call sites that predate the framework. The projection
30 /// helpers are the framework's; this module is only the curve's handles.
31 pub use crate::viewer_state::{
32 find_node_by_id, find_node_by_id_mut, project_point, unproject_point, HANDLE_HIT_RADIUS,
33 };
34
35 pub struct CurveHandles;
36
37 impl HandleSource for CurveHandles {
38 fn name(&self) -> &'static str {
39 "Curve Points"
40 }
41
42 fn accepts(&self, node_type: &str) -> bool {
43 node_type.eq_ignore_ascii_case("curve")
44 }
45
46 fn read(&self, node: &FsNode) -> Vec<Vec3> {
47 parse_curve_points(&node_param_str(node, "Points", ""))
48 }
49
50 fn write(&self, node: &mut FsNode, handles: &[Vec3]) {
51 let formatted = format_curve_points(handles);
52 if let Some(p) = node.params.iter_mut().find(|p| p.name == "Points") {
53 p.default = formatted;
54 }
55 }
56
57 fn extensible(&self) -> bool {
58 true
59 }
60
61 fn hints(&self) -> &'static str {
62 "drag to move, click to add, right-click or Del to remove"
63 }
64 }