diff --git a/packages/cadmium/src/isketch/compound.rs b/packages/cadmium/src/isketch/compound.rs index e69de29b..54b29ce5 100644 --- a/packages/cadmium/src/isketch/compound.rs +++ b/packages/cadmium/src/isketch/compound.rs @@ -0,0 +1,71 @@ +use std::cell::RefCell; +use std::fmt::Debug; +use std::rc::Rc; + +use isotope::primitives::PrimitiveCell; +use serde::{Deserialize, Serialize}; +use tsify_next::Tsify; + +use crate::message::{Identifiable, MessageHandler}; +use crate::IDType; + +use super::{compound_rectangle, ISketch}; + +pub trait CompoundLike: Debug { + fn references(&self) -> Vec; + fn created_references(&self) -> Vec; + fn populate_created_references(&self, sketch: &mut isotope::sketch::Sketch) -> anyhow::Result<()> { + for reference in self.created_references() { + sketch.add_primitive(reference)?; + } + Ok(()) + } +} + +#[derive(Tsify, Debug, Serialize, Deserialize, Clone)] +#[tsify(into_wasm_abi, from_wasm_abi)] +#[non_exhaustive] +pub enum Compound { + Rectangle(compound_rectangle::Rectangle), +} + +impl Identifiable for Rc> { + type Parent = Rc>; + const ID_NAME: &'static str = "compound_id"; + + fn from_parent_id(parent: &Self::Parent, id: IDType) -> anyhow::Result { + Ok(parent.borrow().compounds.get(&id).ok_or(anyhow::anyhow!("No feature with ID {} was found", id))?.clone()) + } +} + +impl Compound { + pub fn as_compound_like(&self) -> &dyn CompoundLike { + match self { + Compound::Rectangle(rectangle) => rectangle, + } + } +} + +#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] +#[tsify(from_wasm_abi, into_wasm_abi)] +pub struct DeleteCompound { + id: IDType, +} + +impl MessageHandler for DeleteCompound { + type Parent = Rc>; + fn handle_message(&self, sketch_ref: Rc>) -> anyhow::Result> { + let mut isketch = sketch_ref.borrow_mut(); + let mut sketch = isketch.sketch.borrow_mut(); + let compound = isketch.compounds.get(&self.id).ok_or(anyhow::anyhow!("No compound with ID {} was found", self.id))?; + + for reference in compound.borrow().as_compound_like().created_references() { + let id = sketch.get_primitive_id(&reference).ok_or(anyhow::anyhow!("Failed to find primitive with reference {:?}", reference))?; + sketch.delete_primitive(id)?; + } + drop(sketch); + + isketch.compounds.remove(&self.id); + Ok(None) + } +} diff --git a/packages/cadmium/src/isketch/compound_rectangle.rs b/packages/cadmium/src/isketch/compound_rectangle.rs new file mode 100644 index 00000000..e550b320 --- /dev/null +++ b/packages/cadmium/src/isketch/compound_rectangle.rs @@ -0,0 +1,100 @@ +use std::cell::RefCell; +use std::rc::Rc; + +use isotope::primitives::line::Line; +use isotope::primitives::point2::Point2; +use isotope::primitives::PrimitiveCell; +use serde::{Deserialize, Serialize}; +use tsify_next::Tsify; + +use crate::message::MessageHandler; +use crate::IDType; + +use super::compound::{Compound, CompoundLike}; +use super::ISketch; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Rectangle { + start: Rc>, + end: Rc>, + new_points: [Rc>; 2], + new_lines: [Rc>; 4], +} + +impl Rectangle { + pub fn new(start: Rc>, end: Rc>) -> Self { + let start_point = start.borrow().clone(); + let end_point = end.borrow().clone(); + + let other_start = Rc::new(RefCell::new(Point2::new(start_point.x(), end_point.y()))); + let other_end = Rc::new(RefCell::new(Point2::new(end_point.x(), start_point.y()))); + + let new_lines = [ + Rc::new(RefCell::new(Line::new(start.clone(), other_start.clone()))), + Rc::new(RefCell::new(Line::new(other_start.clone(), end.clone()))), + Rc::new(RefCell::new(Line::new(end.clone(), other_end.clone()))), + Rc::new(RefCell::new(Line::new(other_end.clone(), start.clone()))), + ]; + Self { + start, + end, + new_points: [other_start, other_end], + new_lines, + } + } + +} + +impl CompoundLike for Rectangle { + fn references(&self) -> Vec { + vec![ + PrimitiveCell::Point2(self.start.clone()), + PrimitiveCell::Point2(self.end.clone()), + ] + } + + fn created_references(&self) -> Vec { + vec![ + PrimitiveCell::Point2(self.new_points[0].clone()), + PrimitiveCell::Point2(self.new_points[1].clone()), + PrimitiveCell::Line(self.new_lines[0].clone()), + PrimitiveCell::Line(self.new_lines[1].clone()), + PrimitiveCell::Line(self.new_lines[2].clone()), + PrimitiveCell::Line(self.new_lines[3].clone()), + ] + } +} + +#[derive(Tsify, Debug, Clone, Serialize, Deserialize)] +#[tsify(from_wasm_abi, into_wasm_abi)] +pub struct Add { + pub start: IDType, + pub end: IDType, +} + +impl MessageHandler for Add { + type Parent = Rc>; + fn handle_message(&self, sketch_ref: Rc>) -> anyhow::Result> { + let mut isketch = sketch_ref.borrow_mut(); + let mut sketch = isketch.sketch.borrow_mut(); + + let start_point = if let PrimitiveCell::Point2(point) = sketch.get_primitive_by_id(self.start).unwrap() { + point + } else { + return Err(anyhow::anyhow!("Start point is not a point")); + }; + let end_point = if let PrimitiveCell::Point2(point) = sketch.get_primitive_by_id(self.end).unwrap() { + point + } else { + return Err(anyhow::anyhow!("End point is not a point")); + }; + + let rectangle = Rectangle::new(start_point.clone(), end_point.clone()); + rectangle.populate_created_references(&mut sketch)?; + drop(sketch); + + let point_id = isketch.compounds_next_id; + isketch.compounds.insert(point_id, Rc::new(RefCell::new(Compound::Rectangle(rectangle)))); + isketch.compounds_next_id += 1; + Ok(Some(point_id))} +} diff --git a/packages/cadmium/src/isketch/mod.rs b/packages/cadmium/src/isketch/mod.rs index aa0928b7..a9d7f15b 100644 --- a/packages/cadmium/src/isketch/mod.rs +++ b/packages/cadmium/src/isketch/mod.rs @@ -18,6 +18,7 @@ use crate::message::Identifiable; use crate::workbench::Workbench; pub mod compound; +pub mod compound_rectangle; pub mod primitive; #[derive(Tsify, Debug, Clone, Serialize, Deserialize)] @@ -27,6 +28,8 @@ pub struct ISketch { pub plane: Rc>, sketch: Rc>, + compounds: BTreeMap>>, + compounds_next_id: u64, points_3d: BTreeMap, } @@ -38,8 +41,8 @@ impl ISketch { let mut real_sketch = Self { plane: plane.clone(), points_3d: BTreeMap::new(), - // primitives: sketch.borrow().primitives().iter().map(|(id, prim)| (*id, prim.borrow().to_primitive())).collect(), - // constraints: sketch.borrow().constraints().iter().map(|c| c.borrow().get_type()).collect(), + compounds: BTreeMap::new(), + compounds_next_id: 0, sketch: Rc::new(RefCell::new(Sketch::new())), }; diff --git a/packages/cadmium/src/message/message.rs b/packages/cadmium/src/message/message.rs index 75572227..de5690de 100644 --- a/packages/cadmium/src/message/message.rs +++ b/packages/cadmium/src/message/message.rs @@ -22,6 +22,8 @@ pub enum Message { SketchAddArc(IDWrap>), SketchAddCircle(IDWrap>), SketchAddLine(IDWrap>), + SketchAddRectangle(IDWrap>), + SketchDeleteCompound(IDWrap>), SketchDeletePrimitive(IDWrap>), FeatureExtrusionAdd(IDWrap), diff --git a/packages/shared/cadmium-api.ts b/packages/shared/cadmium-api.ts index b26de674..364a16cb 100644 --- a/packages/shared/cadmium-api.ts +++ b/packages/shared/cadmium-api.ts @@ -56,6 +56,16 @@ export function sketchAddLine(workbench_id: IDType, sketch_id: IDType, start: ID const message: Message = { SketchAddLine: { workbench_id, sketch_id, start, end } } return sendWasmMessage(message) } +interface SketchAddRectangle { workbench_id: IDType, sketch_id: IDType, start: IDType, end: IDType }; +export function sketchAddRectangle( workbench_id: IDType, sketch_id: IDType, start: IDType, end: IDType ): MessageResult { + const message: Message = { SketchAddRectangle: { workbench_id, sketch_id, start, end } } + return sendWasmMessage(message) +} +interface SketchDeleteCompound { workbench_id: IDType, sketch_id: IDType, compound_id: IDType }; +export function sketchDeleteCompound(workbench_id: IDType, sketch_id: IDType, compound_id: IDType): MessageResult { + const message: Message = { SketchDeleteCompound: { workbench_id, sketch_id, compound_id } } + return sendWasmMessage(message) +} interface SketchDeletePrimitive { workbench_id: IDType, sketch_id: IDType, primitive_id: IDType }; export function sketchDeletePrimitive(workbench_id: IDType, sketch_id: IDType, primitive_id: IDType): MessageResult { const message: Message = { SketchDeletePrimitive: { workbench_id, sketch_id, primitive_id } } @@ -99,6 +109,8 @@ export type Message = { SketchAddArc: SketchAddArc } | { SketchAddCircle: SketchAddCircle } | { SketchAddLine: SketchAddLine } | + { SketchAddRectangle: SketchAddRectangle } | + { SketchDeleteCompound: SketchDeleteCompound } | { SketchDeletePrimitive: SketchDeletePrimitive } | { FeatureExtrusionAdd: FeatureExtrusionAdd } | { FeatureExtrusionUpdateFaces: FeatureExtrusionUpdateFaces } |