geop_ops_model/build.rs
1//! [`ModelOperation`]: a step that builds into the part's model, as most
2//! steps do, and [`build_model`], its run: the step's revision of the
3//! model.
4
5use geop_core_editor::part_operation::PartOperation;
6use geop_core_math::geop_error::GeopResult;
7use geop_core_program::{part::StepContext, reader::Reader};
8
9use crate::{NamedModel, model};
10
11/// A kind of step that builds into the part's model: an extrude, a
12/// boolean, a fillet. Its run is [`build_model`].
13pub trait ModelOperation: PartOperation {
14 /// Builds the step `step` — what everything it makes is named after —
15 /// into `model`, reading whatever else it builds on through `reader`,
16 /// so the step is rebuilt when that changes.
17 fn build(
18 model: &mut NamedModel,
19 reader: &Reader,
20 step: &str,
21 args: &Self::Args,
22 ) -> GeopResult<()>;
23}
24
25/// Produces the step's node of the model, a chain: `O` building `args` into
26/// the model as the steps before left it, or into an empty one, before the
27/// first step that builds any. What fails is said in the context of the
28/// step and its arguments.
29pub fn build_model<O: ModelOperation>(ctx: &mut StepContext, args: &O::Args) -> GeopResult<()> {
30 ctx.produce(
31 &model(),
32 &(ctx.step().to_string(), args.clone()),
33 generate::<O>,
34 )
35}
36
37/// The make of [`build_model`]: a function of `O` alone, so it captures
38/// nothing — the step comes with the arguments.
39fn generate<O: ModelOperation>(
40 reader: &Reader,
41 (step, args): &(String, O::Args),
42) -> GeopResult<NamedModel> {
43 let mut model: NamedModel = reader.previous()?;
44 O::build(&mut model, reader, step, args)
45 .map_err(|e| e.with_context(format!("{}({step}, {args:?})", O::KIND)))?;
46 Ok(model)
47}