diff --git a/src/wasm-lib/Cargo.lock b/src/wasm-lib/Cargo.lock index 93cafa515..e211b5819 100644 --- a/src/wasm-lib/Cargo.lock +++ b/src/wasm-lib/Cargo.lock @@ -1854,7 +1854,7 @@ dependencies = [ [[package]] name = "kcl-lib" -version = "0.1.49" +version = "0.1.50" dependencies = [ "anyhow", "approx 0.5.1", diff --git a/src/wasm-lib/kcl/Cargo.toml b/src/wasm-lib/kcl/Cargo.toml index c10897c4b..64ad710d0 100644 --- a/src/wasm-lib/kcl/Cargo.toml +++ b/src/wasm-lib/kcl/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "kcl-lib" description = "KittyCAD Language implementation and tools" -version = "0.1.49" +version = "0.1.50" edition = "2021" license = "MIT" repository = "https://github.com/KittyCAD/modeling-app" diff --git a/src/wasm-lib/kcl/src/docs.rs b/src/wasm-lib/kcl/src/docs.rs index 0fd252bc4..fc2ca51cc 100644 --- a/src/wasm-lib/kcl/src/docs.rs +++ b/src/wasm-lib/kcl/src/docs.rs @@ -323,7 +323,12 @@ pub fn get_type_string_from_schema(schema: &schemars::schema::Schema) -> Result< if let Some(format) = &o.format { if format == "uuid" { return Ok((Primitive::Uuid.to_string(), false)); - } else if format == "double" || format == "uint" || format == "int64" || format == "uint32" { + } else if format == "double" + || format == "uint" + || format == "int64" + || format == "uint32" + || format == "uint64" + { return Ok((Primitive::Number.to_string(), false)); } else { anyhow::bail!("unknown format: {}", format); @@ -460,7 +465,12 @@ pub fn get_autocomplete_snippet_from_schema( if let Some(format) = &o.format { if format == "uuid" { return Ok(Some((index, format!(r#"${{{}:"tag_or_edge_fn"}}"#, index)))); - } else if format == "double" || format == "uint" || format == "int64" || format == "uint32" { + } else if format == "double" + || format == "uint" + || format == "int64" + || format == "uint32" + || format == "uint64" + { return Ok(Some((index, format!(r#"${{{}:3.14}}"#, index)))); } else { anyhow::bail!("unknown format: {}", format); @@ -614,7 +624,12 @@ pub fn get_autocomplete_string_from_schema(schema: &schemars::schema::Schema) -> if let Some(format) = &o.format { if format == "uuid" { return Ok(Primitive::Uuid.to_string()); - } else if format == "double" || format == "uint" || format == "int64" || format == "uint32" { + } else if format == "double" + || format == "uint" + || format == "int64" + || format == "uint32" + || format == "uint64" + { return Ok(Primitive::Number.to_string()); } else { anyhow::bail!("unknown format: {}", format); diff --git a/src/wasm-lib/kcl/src/std/mod.rs b/src/wasm-lib/kcl/src/std/mod.rs index 47623c2a2..c75e44544 100644 --- a/src/wasm-lib/kcl/src/std/mod.rs +++ b/src/wasm-lib/kcl/src/std/mod.rs @@ -11,6 +11,7 @@ pub mod revolve; pub mod segment; pub mod shapes; pub mod sketch; +pub mod types; pub mod utils; use std::collections::HashMap; diff --git a/src/wasm-lib/kcl/src/std/patterns.rs b/src/wasm-lib/kcl/src/std/patterns.rs index 8c4a708a0..9e7c91fad 100644 --- a/src/wasm-lib/kcl/src/std/patterns.rs +++ b/src/wasm-lib/kcl/src/std/patterns.rs @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; use crate::{ errors::{KclError, KclErrorDetails}, executor::{ExtrudeGroup, Geometries, Geometry, MemoryItem, SketchGroup, SketchGroupSet}, - std::Args, + std::{types::Uint, Args}, }; /// Data for a linear pattern on a 2D sketch. @@ -20,7 +20,7 @@ pub struct LinearPattern2dData { /// The number of repetitions. Must be greater than 0. /// This excludes the original entity. For example, if `repetitions` is 1, /// the original entity will be copied once. - pub repetitions: u32, + pub repetitions: Uint, /// The distance between each repetition. This can also be referred to as spacing. pub distance: f64, /// The axis of the pattern. This is a 2D vector. @@ -35,7 +35,7 @@ pub struct LinearPattern3dData { /// The number of repetitions. Must be greater than 0. /// This excludes the original entity. For example, if `repetitions` is 1, /// the original entity will be copied once. - pub repetitions: u32, + pub repetitions: Uint, /// The distance between each repetition. This can also be referred to as spacing. pub distance: f64, /// The axis of the pattern. @@ -57,8 +57,8 @@ impl LinearPattern { pub fn repetitions(&self) -> u32 { match self { - LinearPattern::TwoD(lp) => lp.repetitions, - LinearPattern::ThreeD(lp) => lp.repetitions, + LinearPattern::TwoD(lp) => lp.repetitions.u32(), + LinearPattern::ThreeD(lp) => lp.repetitions.u32(), } } @@ -185,6 +185,19 @@ async fn inner_pattern_linear_3d( async fn pattern_linear(data: LinearPattern, geometry: Geometry, args: Args) -> Result { let id = uuid::Uuid::new_v4(); + println!( + "id: {:#?}", + ModelingCmd::EntityLinearPattern { + axis: kittycad::types::Point3D { + x: data.axis()[0], + y: data.axis()[1], + z: data.axis()[2], + }, + entity_id: geometry.id(), + num_repetitions: data.repetitions(), + spacing: data.distance(), + } + ); let resp = args .send_modeling_cmd( @@ -244,7 +257,7 @@ pub struct CircularPattern2dData { /// The number of repetitions. Must be greater than 0. /// This excludes the original entity. For example, if `repetitions` is 1, /// the original entity will be copied once. - pub repetitions: u32, + pub repetitions: Uint, /// The center about which to make the pattern. This is a 2D vector. pub center: [f64; 2], /// The arc angle (in degrees) to place the repetitions. Must be greater than 0. @@ -261,7 +274,7 @@ pub struct CircularPattern3dData { /// The number of repetitions. Must be greater than 0. /// This excludes the original entity. For example, if `repetitions` is 1, /// the original entity will be copied once. - pub repetitions: u32, + pub repetitions: Uint, /// The axis around which to make the pattern. This is a 3D vector. pub axis: [f64; 3], /// The center about which to make the pattern. This is a 3D vector. @@ -294,8 +307,8 @@ impl CircularPattern { pub fn repetitions(&self) -> u32 { match self { - CircularPattern::TwoD(lp) => lp.repetitions, - CircularPattern::ThreeD(lp) => lp.repetitions, + CircularPattern::TwoD(lp) => lp.repetitions.u32(), + CircularPattern::ThreeD(lp) => lp.repetitions.u32(), } } diff --git a/src/wasm-lib/kcl/src/std/types.rs b/src/wasm-lib/kcl/src/std/types.rs new file mode 100644 index 000000000..53ae98916 --- /dev/null +++ b/src/wasm-lib/kcl/src/std/types.rs @@ -0,0 +1,40 @@ +//! Custom types for various standard library types. + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +/// A Uint that allows us to do math but rounds to a uint. +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize, ts_rs::TS)] +#[ts(export)] +pub struct Uint(f64); + +impl Uint { + pub fn new(value: f64) -> Self { + if value < 0.0 { + panic!("Uint cannot be negative"); + } + Self(value) + } + + pub fn value(&self) -> f64 { + self.0 + } + + pub fn u32(&self) -> u32 { + self.0.round() as u32 + } + + pub fn u64(&self) -> u64 { + self.0.round() as u64 + } +} + +impl JsonSchema for Uint { + fn schema_name() -> String { + "Uint".to_string() + } + + fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + gen.subschema_for::() + } +} diff --git a/src/wasm-lib/tests/executor/main.rs b/src/wasm-lib/tests/executor/main.rs index 0f13db06c..243c57bfc 100644 --- a/src/wasm-lib/tests/executor/main.rs +++ b/src/wasm-lib/tests/executor/main.rs @@ -939,11 +939,32 @@ async fn serial_test_top_level_expression() { twenty_twenty::assert_image("tests/executor/outputs/top_level_expression.png", &result, 0.999); } +#[tokio::test(flavor = "multi_thread")] +async fn serial_test_patterns_linear_basic_with_math() { + let code = r#"const num = 12 +const distance = 5 +const part = startSketchOn('XY') + |> circle([0,0], 2, %) + |> patternLinear2d({axis: [0,1], repetitions: num -1, distance: distance - 1}, %) + |> extrude(1, %) +"#; + + let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) + .await + .unwrap(); + twenty_twenty::assert_image( + "tests/executor/outputs/patterns_linear_basic_with_math.png", + &result, + 0.999, + ); +} + #[tokio::test(flavor = "multi_thread")] async fn serial_test_patterns_linear_basic() { let code = r#"const part = startSketchOn('XY') |> circle([0,0], 2, %) - |> patternLinear2d({axis: [0,1], repetitions: 12, distance: 2}, %) + |> patternLinear2d({axis: [0,1], repetitions: 12, distance: 4}, %) + |> extrude(1, %) "#; let result = execute_and_snapshot(code, kittycad::types::UnitLength::Mm) diff --git a/src/wasm-lib/tests/executor/outputs/patterns_linear_basic.png b/src/wasm-lib/tests/executor/outputs/patterns_linear_basic.png index f002231c3..e2a575ef7 100644 Binary files a/src/wasm-lib/tests/executor/outputs/patterns_linear_basic.png and b/src/wasm-lib/tests/executor/outputs/patterns_linear_basic.png differ diff --git a/src/wasm-lib/tests/executor/outputs/patterns_linear_basic_with_math.png b/src/wasm-lib/tests/executor/outputs/patterns_linear_basic_with_math.png new file mode 100644 index 000000000..0fb30f9fc Binary files /dev/null and b/src/wasm-lib/tests/executor/outputs/patterns_linear_basic_with_math.png differ