geop_ops_sketch/
add_sketch.rs1use geop_core_math::{
4 geop_error::{GeopError, GeopResult, WithContext},
5 scalars::Scalar,
6 with_context,
7};
8use geop_core_sketch::Sketch;
9use geop_ops::{
10 Part, PlacedSketch,
11 operation::{EntityRef, Operation},
12 ui::{CanvasEvent, Edit, Form},
13};
14use serde::{Deserialize, Serialize};
15
16use crate::editor::{self, SketchSession};
17
18#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
23pub struct AddSketch;
24
25#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
26pub struct AddSketchArgs {
27 #[serde(default)]
30 pub plane: Option<EntityRef>,
31 pub sketch: Sketch,
33}
34
35impl Operation for AddSketch {
36 type Args = AddSketchArgs;
37 type Session = SketchSession;
38
39 fn new_args<S: Scalar>(&self, _before: &Part<S>) -> AddSketchArgs {
42 AddSketchArgs {
43 plane: None,
44 sketch: Sketch::new(),
45 }
46 }
47
48 fn apply<S: Scalar>(
49 &self,
50 mut part: Part<S>,
51 operation_id: &str,
52 args: &AddSketchArgs,
53 ) -> GeopResult<Part<S>> {
54 let ctx = with_context!("add_sketch({operation_id}, plane={:?})", args.plane);
55 args.sketch.validate().with_context(ctx)?;
56 let Some(plane) = &args.plane else {
57 return Err(GeopError::new("pick a plane to sketch on")).with_context(ctx);
58 };
59 let plane = plane.resolve_plane(&part).with_context(ctx)?;
60 let placed = PlacedSketch {
61 plane,
62 sketch: args.sketch.clone(),
63 };
64 part.add_sketch(placed, operation_id).with_context(ctx)?;
65 Ok(part)
66 }
67
68 fn form<'a, S: Scalar>(
71 &self,
72 before: &'a Part<S>,
73 args: &AddSketchArgs,
74 s: &SketchSession,
75 selection: &[String],
76 ) -> Form<'a, S, AddSketchArgs, SketchSession> {
77 editor::form(before, args, s, selection)
78 }
79
80 fn event<S: Scalar>(
81 &self,
82 before: &Part<S>,
83 args: &mut AddSketchArgs,
84 session: &mut SketchSession,
85 selection: &mut Vec<String>,
86 event: &CanvasEvent<S>,
87 ) {
88 let edit = Edit {
89 args,
90 session,
91 selection,
92 };
93 editor::event(before, edit, event);
94 }
95}