geop_ops/operation/mod.rs
1//! What an operation is.
2//!
3//! An operation is a unit struct implementing [`Operation`], with an `Args`
4//! struct holding everything a step of it needs and a `Session` holding the
5//! temporary state of editing one, if it needs any. Built, a step maps
6//!
7//! ```text
8//! (part, args) -> part apply
9//! ```
10//!
11//! and edited, it shows a [`Form`] — fields, each with what setting it
12//! does, and visuals — whose fields the editor sets:
13//!
14//! ```text
15//! (part, args, selection) -> form form
16//! (part, args, selection, field, value) -> args, selection set
17//! ```
18//!
19//! `set` is the form's: each field is described once, with its setter.
20//!
21//! Picking entities for a field, dragging handles, selecting visuals and
22//! dragging them are the editor's (see [`crate::ui::StepEditor`]), the same
23//! for every operation; an operation that draws in a canvas of its own — a
24//! sketch — also takes what the pointer and the keys do beyond that
25//! ([`Operation::event`]), with a `Session` for what it keeps between
26//! events.
27//!
28//! Arguments are plain design data — `f64` lengths, sketches — and refer to
29//! existing entities of the part only by name, never by an internal id: an
30//! id only means something inside the one build that produced it, a name
31//! means the same thing in every build of the same program (see the crate
32//! docs). Entities a step builds on directly — a sketch's plane, what a
33//! datum is built from — are [`EntityRef`]s.
34//!
35//! A set of operations is an enum with one variant `Name(NameArgs)` per
36//! operation, implementing [`Operations`] through `#[derive(Operations)]`:
37//! what a program step holds, and what serializes as `{"operation":
38//! "extrude", "args": {...}}`.
39
40mod aspects;
41mod entity;
42
43pub use aspects::{Aspects, Role, describe_roles};
44pub use entity::{EntityRef, frame_along};
45
46pub use geop_ops_derive::Operations;
47
48use std::any::Any;
49
50use geop_core_math::{geop_error::GeopResult, scalars::Scalar};
51use serde::{Serialize, de::DeserializeOwned};
52
53use crate::{
54 Part,
55 ui::{CanvasEvent, Edit, Form, Value},
56};
57
58/// An operation of a set: how a step spells it, its short name and what it
59/// does — what an editor offers it by.
60#[derive(Clone, Debug, PartialEq, Serialize)]
61pub struct OperationInfo {
62 pub kind: &'static str,
63 pub label: &'static str,
64 pub doc: &'static str,
65}
66
67/// One kind of operation on a [`Part`].
68pub trait Operation {
69 /// Everything a step needs, as plain, serializable design data.
70 type Args: Clone;
71 /// The temporary state of editing a step beyond its arguments — `()`
72 /// for every operation whose form says all there is to it. Starts
73 /// afresh whenever an editor opens a step.
74 type Session: Default + 'static;
75
76 /// The arguments of a new step inserted after `before`: sensible
77 /// defaults, taking what `before` holds into account.
78 fn new_args<S: Scalar>(&self, before: &Part<S>) -> Self::Args;
79
80 /// Applies the operation as the program step `operation_id`, consuming
81 /// `part` and returning the part it produces. Everything the operation
82 /// creates is named after `operation_id` (see the crate docs), so the id
83 /// has to be unique within a program.
84 ///
85 /// On error no part is returned — a caller that still needs the
86 /// original should clone it first.
87 fn apply<S: Scalar>(
88 &self,
89 part: Part<S>,
90 operation_id: &str,
91 args: &Self::Args,
92 ) -> GeopResult<Part<S>>;
93
94 /// What a step shows while it is edited against `before`: its fields —
95 /// numbers, choices, entities to pick — each with what setting it does,
96 /// and what it draws, with `selection` the keys of its visuals selected.
97 /// Never fails: an editor needs the form most exactly when the arguments
98 /// do not build, so whatever is wrong is said in it.
99 ///
100 /// Its setters may capture `before`, never the arguments: they are
101 /// handed the arguments to change (see [`Operation::set`]).
102 fn form<'a, S: Scalar>(
103 &self,
104 before: &'a Part<S>,
105 args: &Self::Args,
106 session: &Self::Session,
107 selection: &[String],
108 ) -> Form<'a, S, Self::Args, Self::Session>;
109
110 /// The field `key` of the form set to `value`: typed or chosen in the
111 /// dialog, picked in the viewport, dragged as a handle — by the setter
112 /// the form gave it (see [`Form`]).
113 fn set<S: Scalar>(
114 &self,
115 before: &Part<S>,
116 args: &mut Self::Args,
117 session: &mut Self::Session,
118 selection: &mut Vec<String>,
119 key: &str,
120 value: Value,
121 ) {
122 let form = self.form(before, args, session, selection);
123 let edit = Edit {
124 args,
125 session,
126 selection,
127 };
128 form.set(key, edit, value);
129 }
130
131 /// A pointer or key event the editor passed on (see [`CanvasEvent`]).
132 /// Only an operation that draws in a canvas of its own, like a sketch,
133 /// needs these.
134 fn event<S: Scalar>(
135 &self,
136 before: &Part<S>,
137 args: &mut Self::Args,
138 session: &mut Self::Session,
139 selection: &mut Vec<String>,
140 event: &CanvasEvent<S>,
141 ) {
142 let _ = (before, args, session, selection, event);
143 }
144}
145
146/// A set of operations, each together with its arguments: the enum a
147/// [`crate::Program`]'s steps hold.
148///
149/// Written by `#[derive(Operations)]` on an enum whose every variant is
150/// `Name(NameArgs)`, with `Name` the unit struct implementing [`Operation`]
151/// with `Args = NameArgs`: it dispatches to `Name`, and converts from each
152/// `NameArgs`. A variant's doc comment describes the operation, and
153/// `#[operation(label = "...")]` gives its short name if that is not the
154/// variant's. A step's session is the session of its operation, boxed:
155/// sessions differ by operation.
156pub trait Operations: Clone + std::fmt::Debug + PartialEq + Serialize + DeserializeOwned {
157 /// Every operation of the set.
158 fn infos() -> Vec<OperationInfo>;
159
160 /// A new step of the operation `kind`, inserted after `before`, see
161 /// [`Operation::new_args`].
162 fn new_step<S: Scalar>(kind: &str, before: &Part<S>) -> GeopResult<Self>;
163
164 /// See [`Operation::apply`].
165 fn apply<S: Scalar>(&self, part: Part<S>, operation_id: &str) -> GeopResult<Part<S>>;
166
167 /// A fresh session for editing this step.
168 fn new_session(&self) -> Box<dyn Any>;
169
170 /// See [`Operation::form`], as an editor reads it; `session` is one
171 /// [`Operations::new_session`] made for a step of the same operation.
172 fn form<'a, S: Scalar>(
173 &self,
174 before: &'a Part<S>,
175 session: &dyn Any,
176 selection: &[String],
177 ) -> Form<'a, S>;
178
179 /// See [`Operation::set`].
180 fn set<S: Scalar>(
181 &mut self,
182 before: &Part<S>,
183 session: &mut dyn Any,
184 selection: &mut Vec<String>,
185 key: &str,
186 value: Value,
187 );
188
189 /// See [`Operation::event`].
190 fn event<S: Scalar>(
191 &mut self,
192 before: &Part<S>,
193 session: &mut dyn Any,
194 selection: &mut Vec<String>,
195 event: &CanvasEvent<S>,
196 );
197
198 /// The operation's kind, as it is serialized: `extrude`.
199 fn kind(&self) -> &'static str;
200
201 /// The operation's short name: `Extrude`.
202 fn label(&self) -> &'static str;
203}