Replace kittycad crate with kittycad-modeling-cmds (#3909)

lib.rs/kittycad-modeling-cmds is the source of our Modeling API. It gets included in our backend APIs, and those APIs generate OpenAPI specs which are read by `openapitor` which generates the lib.rs/kittycad crate. So basically, our modeling app is using the _generated code_ instead of the _handwritten code_.

This sucks -- if you add a new field to the modeling-api crate, you have to merge PRs to the engine, api-deux, and kittycad.rs before finally you can get the new field into the modeling-app. I was pretty embarrased when @mlfarrell asked how to get a new field into the modeling app and had to explain this whole bullshit cycle. Let's fix it.

Switching to use the kittycad-modeling-cmds (aka kcmc) crate directly should speed up our dev cycle.
This commit is contained in:
Adam Chalmers
2024-09-18 17:04:04 -05:00
committed by GitHub
parent 2978e80226
commit 5cc92f0162
23 changed files with 744 additions and 510 deletions

196
src/wasm-lib/Cargo.lock generated
View File

@ -85,13 +85,19 @@ dependencies = [
"backtrace", "backtrace",
] ]
[[package]]
name = "approx"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94"
[[package]] [[package]]
name = "approx" name = "approx"
version = "0.5.1" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
dependencies = [ dependencies = [
"num-traits", "num-traits 0.2.18",
] ]
[[package]] [[package]]
@ -201,7 +207,7 @@ dependencies = [
"libm", "libm",
"num-bigint", "num-bigint",
"num-integer", "num-integer",
"num-traits", "num-traits 0.2.18",
"serde", "serde",
] ]
@ -261,7 +267,7 @@ dependencies = [
"indexmap 2.2.5", "indexmap 2.2.5",
"js-sys", "js-sys",
"once_cell", "once_cell",
"rand", "rand 0.8.5",
"serde", "serde",
"serde_bytes", "serde_bytes",
"serde_json", "serde_json",
@ -326,6 +332,18 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cgmath"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c"
dependencies = [
"approx 0.1.1",
"mint",
"num-traits 0.1.43",
"rand 0.4.6",
]
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.38" version = "0.4.38"
@ -335,7 +353,7 @@ dependencies = [
"android-tzdata", "android-tzdata",
"iana-time-zone", "iana-time-zone",
"js-sys", "js-sys",
"num-traits", "num-traits 0.2.18",
"serde", "serde",
"wasm-bindgen", "wasm-bindgen",
"windows-targets 0.52.4", "windows-targets 0.52.4",
@ -496,7 +514,7 @@ dependencies = [
"futures", "futures",
"is-terminal", "is-terminal",
"itertools 0.10.5", "itertools 0.10.5",
"num-traits", "num-traits 0.2.18",
"once_cell", "once_cell",
"oorandom", "oorandom",
"plotters", "plotters",
@ -754,6 +772,26 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "enum-iterator"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c280b9e6b3ae19e152d8e31cf47f18389781e119d4013a2a2bb0180e5facc635"
dependencies = [
"enum-iterator-derive",
]
[[package]]
name = "enum-iterator-derive"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.77",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@ -770,6 +808,16 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "euler"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f19d11568a4a46aee488bdab3a2963e5e2c3cfd6091aa0abceaddcea82c0bc1"
dependencies = [
"approx 0.1.1",
"cgmath",
]
[[package]] [[package]]
name = "expectorate" name = "expectorate"
version = "1.1.0" version = "1.1.0"
@ -834,6 +882,12 @@ dependencies = [
"unicode-segmentation", "unicode-segmentation",
] ]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]] [[package]]
name = "funty" name = "funty"
version = "2.0.0" version = "2.0.0"
@ -1211,7 +1265,7 @@ checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"byteorder-lite", "byteorder-lite",
"num-traits", "num-traits 0.2.18",
"png", "png",
] ]
@ -1348,7 +1402,7 @@ name = "kcl-lib"
version = "0.2.14" version = "0.2.14"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"approx", "approx 0.5.1",
"async-recursion", "async-recursion",
"async-trait", "async-trait",
"base64 0.22.1", "base64 0.22.1",
@ -1372,6 +1426,7 @@ dependencies = [
"itertools 0.13.0", "itertools 0.13.0",
"js-sys", "js-sys",
"kittycad", "kittycad",
"kittycad-modeling-cmds",
"lazy_static", "lazy_static",
"measurements", "measurements",
"mime_guess", "mime_guess",
@ -1449,7 +1504,7 @@ dependencies = [
"mime_guess", "mime_guess",
"parse-display", "parse-display",
"phonenumber", "phonenumber",
"rand", "rand 0.8.5",
"reqwest", "reqwest",
"reqwest-conditional-middleware", "reqwest-conditional-middleware",
"reqwest-middleware", "reqwest-middleware",
@ -1467,6 +1522,54 @@ dependencies = [
"uuid", "uuid",
] ]
[[package]]
name = "kittycad-modeling-cmds"
version = "0.2.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee900033a5804ca2354f0760478e851a0ab04d32b38a9117d0bd4f87a8867110"
dependencies = [
"anyhow",
"chrono",
"data-encoding",
"enum-iterator",
"enum-iterator-derive",
"euler",
"http 0.2.12",
"kittycad-modeling-cmds-macros",
"kittycad-unit-conversion-derive",
"measurements",
"parse-display",
"parse-display-derive",
"schemars",
"serde",
"serde_bytes",
"serde_json",
"uuid",
]
[[package]]
name = "kittycad-modeling-cmds-macros"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0cdc505a33bfffb87c317435ec41ced8f73474217cf30db685e479bf289757e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.77",
]
[[package]]
name = "kittycad-unit-conversion-derive"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7001c46a92c1edce6722a3900539b198230980799035f02d92b4e7df3fc08738"
dependencies = [
"inflections",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.5.0"
@ -1600,6 +1703,12 @@ dependencies = [
"simd-adler32", "simd-adler32",
] ]
[[package]]
name = "mint"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff"
[[package]] [[package]]
name = "mio" name = "mio"
version = "1.0.1" version = "1.0.1"
@ -1639,7 +1748,7 @@ checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"num-integer", "num-integer",
"num-traits", "num-traits 0.2.18",
] ]
[[package]] [[package]]
@ -1654,7 +1763,16 @@ version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [ dependencies = [
"num-traits", "num-traits 0.2.18",
]
[[package]]
name = "num-traits"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
dependencies = [
"num-traits 0.2.18",
] ]
[[package]] [[package]]
@ -1714,7 +1832,7 @@ dependencies = [
"lazy_static", "lazy_static",
"percent-encoding", "percent-encoding",
"pin-project", "pin-project",
"rand", "rand 0.8.5",
"thiserror", "thiserror",
] ]
@ -1873,7 +1991,7 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
dependencies = [ dependencies = [
"num-traits", "num-traits 0.2.18",
"plotters-backend", "plotters-backend",
"plotters-svg", "plotters-svg",
"wasm-bindgen", "wasm-bindgen",
@ -2056,6 +2174,19 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi",
]
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.8.5" version = "0.8.5"
@ -2064,7 +2195,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [ dependencies = [
"libc", "libc",
"rand_chacha", "rand_chacha",
"rand_core", "rand_core 0.6.4",
] ]
[[package]] [[package]]
@ -2074,9 +2205,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [ dependencies = [
"ppv-lite86", "ppv-lite86",
"rand_core", "rand_core 0.6.4",
] ]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]] [[package]]
name = "rand_core" name = "rand_core"
version = "0.6.4" version = "0.6.4"
@ -2106,6 +2252,15 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.16" version = "0.2.16"
@ -2291,7 +2446,7 @@ checksum = "e09bbcb5003282bcb688f0bae741b278e9c7e8f378f561522c9806c58e075d9b"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
"rand", "rand 0.8.5",
] ]
[[package]] [[package]]
@ -2410,9 +2565,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls-pki-types" name = "rustls-pki-types"
version = "1.4.0" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "868e20fada228fefaf6b652e00cc73623d54f8171e7352c18bb281571f2d92da" checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0"
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
@ -2550,9 +2705,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_bytes" name = "serde_bytes"
version = "0.11.14" version = "0.11.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -3306,7 +3461,7 @@ dependencies = [
"http 1.1.0", "http 1.1.0",
"httparse", "httparse",
"log", "log",
"rand", "rand 0.8.5",
"rustls 0.23.7", "rustls 0.23.7",
"rustls-pki-types", "rustls-pki-types",
"sha1", "sha1",
@ -3570,6 +3725,7 @@ dependencies = [
"js-sys", "js-sys",
"kcl-lib", "kcl-lib",
"kittycad", "kittycad",
"kittycad-modeling-cmds",
"pretty_assertions", "pretty_assertions",
"reqwest", "reqwest",
"serde_json", "serde_json",

View File

@ -27,6 +27,7 @@ anyhow = "1"
hyper = { version = "0.14.29", features = ["server", "http1"] } hyper = { version = "0.14.29", features = ["server", "http1"] }
image = { version = "0.25.1", default-features = false, features = ["png"] } image = { version = "0.25.1", default-features = false, features = ["png"] }
kittycad = { workspace = true, default-features = true } kittycad = { workspace = true, default-features = true }
kittycad-modeling-cmds = { workspace = true }
pretty_assertions = "1.4.1" pretty_assertions = "1.4.1"
reqwest = { version = "0.11.26", default-features = false } reqwest = { version = "0.11.26", default-features = false }
tokio = { version = "1.40.0", features = ["rt-multi-thread", "macros", "time"] } tokio = { version = "1.40.0", features = ["rt-multi-thread", "macros", "time"] }
@ -72,6 +73,7 @@ members = [
http = "0.2.12" http = "0.2.12"
kittycad = { version = "0.3.20", default-features = false, features = ["js", "requests"] } kittycad = { version = "0.3.20", default-features = false, features = ["js", "requests"] }
kittycad-modeling-session = "0.1.4" kittycad-modeling-session = "0.1.4"
kittycad-modeling-cmds = { version = "0.2.59", features = ["websocket"] }
[[test]] [[test]]
name = "executor" name = "executor"

View File

@ -28,6 +28,7 @@ gltf-json = "1.4.1"
http = { workspace = true } http = { workspace = true }
image = { version = "0.25.1", default-features = false, features = ["png"] } image = { version = "0.25.1", default-features = false, features = ["png"] }
kittycad = { workspace = true } kittycad = { workspace = true }
kittycad-modeling-cmds = { workspace = true }
lazy_static = "1.5.0" lazy_static = "1.5.0"
measurements = "0.11.0" measurements = "0.11.0"
mime_guess = "2.0.5" mime_guess = "2.0.5"

View File

@ -1,6 +1,11 @@
use std::sync::Arc; use std::sync::Arc;
use kittycad::types::{ModelingCmd, Point3D}; use kcmc::each_cmd as mcmd;
use kcmc::ok_response::OkModelingCmdResponse;
use kcmc::shared::PathCommand;
use kcmc::websocket::OkWebSocketResponseData;
use kcmc::ModelingCmd;
use kittycad_modeling_cmds as kcmc;
use crate::{ use crate::{
ast::types::{ ast::types::{
@ -12,13 +17,15 @@ use crate::{
executor::{Point2d, SourceRange}, executor::{Point2d, SourceRange},
}; };
type Point3d = kcmc::shared::Point3d<f64>;
#[derive(Debug)] #[derive(Debug)]
/// The control point data for a curve or line. /// The control point data for a curve or line.
pub struct ControlPointData { pub struct ControlPointData {
/// The control points for the curve or line. /// The control points for the curve or line.
pub points: Vec<kittycad::types::Point3D>, pub points: Vec<Point3d>,
/// The command that created this curve or line. /// The command that created this curve or line.
pub command: kittycad::types::PathCommand, pub command: PathCommand,
/// The id of the curve or line. /// The id of the curve or line.
pub id: uuid::Uuid, pub id: uuid::Uuid,
} }
@ -77,12 +84,12 @@ pub async fn modify_ast_for_sketch(
.send_modeling_cmd( .send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
SourceRange::default(), SourceRange::default(),
ModelingCmd::PathGetInfo { path_id: sketch_id }, ModelingCmd::PathGetInfo(mcmd::PathGetInfo { path_id: sketch_id }),
) )
.await?; .await?;
let kittycad::types::OkWebSocketResponseData::Modeling { let OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::PathGetInfo { data: path_info }, modeling_response: OkModelingCmdResponse::PathGetInfo(path_info),
} = &resp } = &resp
else { else {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {
@ -101,11 +108,13 @@ pub async fn modify_ast_for_sketch(
let h = engine.send_modeling_cmd( let h = engine.send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
SourceRange::default(), SourceRange::default(),
ModelingCmd::CurveGetControlPoints { curve_id: *command_id }, ModelingCmd::from(mcmd::CurveGetControlPoints {
curve_id: (*command_id).into(),
}),
); );
let kittycad::types::OkWebSocketResponseData::Modeling { let OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::CurveGetControlPoints { data }, modeling_response: OkModelingCmdResponse::CurveGetControlPoints(data),
} = h.await? } = h.await?
else { else {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {
@ -116,8 +125,8 @@ pub async fn modify_ast_for_sketch(
control_points.push(ControlPointData { control_points.push(ControlPointData {
points: data.control_points.clone(), points: data.control_points.clone(),
command: segment.command.clone(), command: segment.command,
id: *command_id, id: (*command_id).into(),
}); });
} }
} }
@ -143,7 +152,7 @@ pub async fn modify_ast_for_sketch(
(control_point.points[1].x - last_point.x), (control_point.points[1].x - last_point.x),
(control_point.points[1].y - last_point.y), (control_point.points[1].y - last_point.y),
]); ]);
last_point = Point3D { last_point = Point3d {
x: control_point.points[1].x, x: control_point.points[1].x,
y: control_point.points[1].y, y: control_point.points[1].y,
z: control_point.points[1].z, z: control_point.points[1].z,
@ -151,7 +160,7 @@ pub async fn modify_ast_for_sketch(
} }
// Okay now let's recalculate the sketch from the control points. // Okay now let's recalculate the sketch from the control points.
let start_sketch_at_end = Point3D { let start_sketch_at_end = Point3d {
x: (first_control_points.points[1].x - first_control_points.points[0].x), x: (first_control_points.points[1].x - first_control_points.points[0].x),
y: (first_control_points.points[1].y - first_control_points.points[0].y), y: (first_control_points.points[1].y - first_control_points.points[0].y),
z: (first_control_points.points[1].z - first_control_points.points[0].z), z: (first_control_points.points[1].z - first_control_points.points[0].z),

View File

@ -9,7 +9,12 @@ use std::{
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use dashmap::DashMap; use dashmap::DashMap;
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use kittycad::types::{ModelingSessionData, WebSocketRequest, WebSocketResponse}; use kcmc::websocket::{
BatchResponse, FailureWebSocketResponse, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData,
SuccessWebSocketResponse, WebSocketRequest, WebSocketResponse,
};
use kcmc::ModelingCmd;
use kittycad_modeling_cmds as kcmc;
use tokio::sync::{mpsc, oneshot, RwLock}; use tokio::sync::{mpsc, oneshot, RwLock};
use tokio_tungstenite::tungstenite::Message as WsMsg; use tokio_tungstenite::tungstenite::Message as WsMsg;
@ -118,10 +123,10 @@ impl EngineConnection {
async fn start_write_actor(mut tcp_write: WebSocketTcpWrite, mut engine_req_rx: mpsc::Receiver<ToEngineReq>) { async fn start_write_actor(mut tcp_write: WebSocketTcpWrite, mut engine_req_rx: mpsc::Receiver<ToEngineReq>) {
while let Some(req) = engine_req_rx.recv().await { while let Some(req) = engine_req_rx.recv().await {
let ToEngineReq { req, request_sent } = req; let ToEngineReq { req, request_sent } = req;
let res = if let kittycad::types::WebSocketRequest::ModelingCmdReq { let res = if let WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
cmd: kittycad::types::ModelingCmd::ImportFiles { .. }, cmd: ModelingCmd::ImportFiles { .. },
cmd_id: _, cmd_id: _,
} = &req }) = &req
{ {
// Send it as binary. // Send it as binary.
Self::inner_send_to_engine_binary(req, &mut tcp_write).await Self::inner_send_to_engine_binary(req, &mut tcp_write).await
@ -196,43 +201,51 @@ impl EngineConnection {
match tcp_read.read().await { match tcp_read.read().await {
Ok(ws_resp) => { Ok(ws_resp) => {
// If we got a batch response, add all the inner responses. // If we got a batch response, add all the inner responses.
match &ws_resp.resp { let id = ws_resp.request_id();
Some(kittycad::types::OkWebSocketResponseData::ModelingBatch { responses }) => { match &ws_resp {
WebSocketResponse::Success(SuccessWebSocketResponse {
resp: OkWebSocketResponseData::ModelingBatch { responses },
..
}) => {
for (resp_id, batch_response) in responses { for (resp_id, batch_response) in responses {
let id: uuid::Uuid = resp_id.parse().unwrap(); let id: uuid::Uuid = (*resp_id).into();
if let Some(response) = &batch_response.response { match batch_response {
responses_clone.insert( BatchResponse::Success { response } => {
id, responses_clone.insert(
kittycad::types::WebSocketResponse { id,
request_id: Some(id), WebSocketResponse::Success(SuccessWebSocketResponse {
resp: Some(kittycad::types::OkWebSocketResponseData::Modeling { success: true,
modeling_response: response.clone(), request_id: Some(id),
resp: OkWebSocketResponseData::Modeling {
modeling_response: response.clone(),
},
}), }),
errors: None, );
success: Some(true), }
}, BatchResponse::Failure { errors } => {
); responses_clone.insert(
} else { id,
responses_clone.insert( WebSocketResponse::Failure(FailureWebSocketResponse {
id, success: false,
kittycad::types::WebSocketResponse { request_id: Some(id),
request_id: Some(id), errors: errors.clone(),
resp: None, }),
errors: batch_response.errors.clone(), );
success: Some(false), }
},
);
} }
} }
} }
Some(kittycad::types::OkWebSocketResponseData::ModelingSessionData { session }) => { WebSocketResponse::Success(SuccessWebSocketResponse {
resp: OkWebSocketResponseData::ModelingSessionData { session },
..
}) => {
let mut sd = session_data2.lock().unwrap(); let mut sd = session_data2.lock().unwrap();
sd.replace(session.clone()); sd.replace(session.clone());
} }
_ => {} _ => {}
} }
if let Some(id) = ws_resp.request_id { if let Some(id) = id {
responses_clone.insert(id, ws_resp.clone()); responses_clone.insert(id, ws_resp.clone());
} }
} }
@ -299,7 +312,7 @@ impl EngineManager for EngineConnection {
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
source_range: crate::executor::SourceRange, source_range: crate::executor::SourceRange,
cmd: kittycad::types::WebSocketRequest, cmd: WebSocketRequest,
_id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>, _id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
) -> Result<WebSocketResponse, KclError> { ) -> Result<WebSocketResponse, KclError> {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();

View File

@ -7,7 +7,12 @@ use std::{
}; };
use anyhow::Result; use anyhow::Result;
use kittycad::types::{OkWebSocketResponseData, WebSocketRequest, WebSocketResponse}; use kcmc::ok_response::OkModelingCmdResponse;
use kcmc::websocket::{
BatchResponse, ModelingBatch, OkWebSocketResponseData, SuccessWebSocketResponse, WebSocketRequest,
WebSocketResponse,
};
use kittycad_modeling_cmds::{self as kcmc};
use crate::{errors::KclError, executor::DefaultPlanes}; use crate::{errors::KclError, executor::DefaultPlanes};
@ -48,41 +53,38 @@ impl crate::engine::EngineManager for EngineConnection {
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
_source_range: crate::executor::SourceRange, _source_range: crate::executor::SourceRange,
cmd: kittycad::types::WebSocketRequest, cmd: WebSocketRequest,
_id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>, _id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
) -> Result<WebSocketResponse, KclError> { ) -> Result<WebSocketResponse, KclError> {
match cmd { match cmd {
WebSocketRequest::ModelingCmdBatchReq { WebSocketRequest::ModelingCmdBatchReq(ModelingBatch {
ref requests, ref requests,
batch_id: _, batch_id: _,
responses: _, responses: _,
} => { }) => {
// Create the empty responses. // Create the empty responses.
let mut responses = HashMap::new(); let mut responses = HashMap::new();
for request in requests { for request in requests {
responses.insert( responses.insert(
request.cmd_id.to_string(), request.cmd_id,
kittycad::types::BatchResponse { BatchResponse::Success {
response: Some(kittycad::types::OkModelingCmdResponse::Empty {}), response: OkModelingCmdResponse::Empty {},
errors: None,
}, },
); );
} }
Ok(WebSocketResponse { Ok(WebSocketResponse::Success(SuccessWebSocketResponse {
request_id: Some(id), request_id: Some(id),
resp: Some(OkWebSocketResponseData::ModelingBatch { responses }), resp: OkWebSocketResponseData::ModelingBatch { responses },
success: Some(true), success: true,
errors: None, }))
})
} }
_ => Ok(WebSocketResponse { _ => Ok(WebSocketResponse::Success(SuccessWebSocketResponse {
request_id: Some(id), request_id: Some(id),
resp: Some(OkWebSocketResponseData::Modeling { resp: OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::Empty {}, modeling_response: OkModelingCmdResponse::Empty {},
}), },
success: Some(true), success: true,
errors: None, })),
}),
} }
} }
} }

View File

@ -6,7 +6,8 @@ use std::{
}; };
use anyhow::Result; use anyhow::Result;
use kittycad::types::WebSocketRequest; use kcmc::websocket::{WebSocketRequest, WebSocketResponse};
use kittycad_modeling_cmds as kcmc;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use crate::{ use crate::{
@ -137,9 +138,9 @@ impl crate::engine::EngineManager for EngineConnection {
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
source_range: crate::executor::SourceRange, source_range: crate::executor::SourceRange,
cmd: kittycad::types::WebSocketRequest, cmd: WebSocketRequest,
id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>, id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>,
) -> Result<kittycad::types::WebSocketResponse, KclError> { ) -> Result<WebSocketResponse, KclError> {
let source_range_str = serde_json::to_string(&source_range).map_err(|e| { let source_range_str = serde_json::to_string(&source_range).map_err(|e| {
KclError::Engine(KclErrorDetails { KclError::Engine(KclErrorDetails {
message: format!("Failed to serialize source range: {:?}", e), message: format!("Failed to serialize source range: {:?}", e),
@ -184,7 +185,7 @@ impl crate::engine::EngineManager for EngineConnection {
}) })
})?; })?;
let ws_result: kittycad::types::WebSocketResponse = serde_json::from_str(&s).map_err(|e| { let ws_result: WebSocketResponse = serde_json::from_str(&s).map_err(|e| {
KclError::Engine(KclErrorDetails { KclError::Engine(KclErrorDetails {
message: format!("Failed to deserialize response from engine: {:?}", e), message: format!("Failed to deserialize response from engine: {:?}", e),
source_ranges: vec![source_range], source_ranges: vec![source_range],

View File

@ -13,11 +13,19 @@ use std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use kittycad::types::{ use kcmc::each_cmd as mcmd;
Color, ModelingCmd, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData, WebSocketRequest, use kcmc::length_unit::LengthUnit;
use kcmc::ok_response::OkModelingCmdResponse;
use kcmc::shared::Color;
use kcmc::websocket::ModelingBatch;
use kcmc::websocket::{
BatchResponse, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData, WebSocketRequest, WebSocketResponse,
}; };
use kcmc::ModelingCmd;
use kittycad_modeling_cmds as kcmc;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::{ use crate::{
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
@ -33,12 +41,10 @@ lazy_static::lazy_static! {
#[async_trait::async_trait] #[async_trait::async_trait]
pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static { pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
/// Get the batch of commands to be sent to the engine. /// Get the batch of commands to be sent to the engine.
fn batch(&self) -> Arc<Mutex<Vec<(kittycad::types::WebSocketRequest, crate::executor::SourceRange)>>>; fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>;
/// Get the batch of end commands to be sent to the engine. /// Get the batch of end commands to be sent to the engine.
fn batch_end( fn batch_end(&self) -> Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>;
&self,
) -> Arc<Mutex<HashMap<uuid::Uuid, (kittycad::types::WebSocketRequest, crate::executor::SourceRange)>>>;
/// Get the default planes. /// Get the default planes.
async fn default_planes( async fn default_planes(
@ -58,15 +64,15 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
source_range: crate::executor::SourceRange, source_range: crate::executor::SourceRange,
cmd: kittycad::types::WebSocketRequest, cmd: WebSocketRequest,
id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>, id_to_source_range: HashMap<uuid::Uuid, crate::executor::SourceRange>,
) -> Result<kittycad::types::WebSocketResponse, crate::errors::KclError>; ) -> Result<kcmc::websocket::WebSocketResponse, crate::errors::KclError>;
async fn clear_scene(&self, source_range: crate::executor::SourceRange) -> Result<(), crate::errors::KclError> { async fn clear_scene(&self, source_range: crate::executor::SourceRange) -> Result<(), crate::errors::KclError> {
self.batch_modeling_cmd( self.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
source_range, source_range,
&kittycad::types::ModelingCmd::SceneClearAll {}, &ModelingCmd::SceneClearAll(mcmd::SceneClearAll {}),
) )
.await?; .await?;
@ -85,12 +91,12 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
source_range: crate::executor::SourceRange, source_range: crate::executor::SourceRange,
cmd: &kittycad::types::ModelingCmd, cmd: &ModelingCmd,
) -> Result<(), crate::errors::KclError> { ) -> Result<(), crate::errors::KclError> {
let req = WebSocketRequest::ModelingCmdReq { let req = WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
cmd: cmd.clone(), cmd: cmd.clone(),
cmd_id: id, cmd_id: id.into(),
}; });
// Add cmd to the batch. // Add cmd to the batch.
self.batch().lock().unwrap().push((req, source_range)); self.batch().lock().unwrap().push((req, source_range));
@ -105,12 +111,12 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
source_range: crate::executor::SourceRange, source_range: crate::executor::SourceRange,
cmd: &kittycad::types::ModelingCmd, cmd: &ModelingCmd,
) -> Result<(), crate::errors::KclError> { ) -> Result<(), crate::errors::KclError> {
let req = WebSocketRequest::ModelingCmdReq { let req = WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
cmd: cmd.clone(), cmd: cmd.clone(),
cmd_id: id, cmd_id: id.into(),
}; });
// Add cmd to the batch end. // Add cmd to the batch end.
self.batch_end().lock().unwrap().insert(id, (req, source_range)); self.batch_end().lock().unwrap().insert(id, (req, source_range));
@ -124,8 +130,8 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
source_range: crate::executor::SourceRange, source_range: crate::executor::SourceRange,
cmd: kittycad::types::ModelingCmd, cmd: ModelingCmd,
) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> { ) -> Result<OkWebSocketResponseData, crate::errors::KclError> {
self.batch_modeling_cmd(id, source_range, &cmd).await?; self.batch_modeling_cmd(id, source_range, &cmd).await?;
// Flush the batch queue. // Flush the batch queue.
@ -139,7 +145,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
// We only do this at the very end of the file. // We only do this at the very end of the file.
batch_end: bool, batch_end: bool,
source_range: crate::executor::SourceRange, source_range: crate::executor::SourceRange,
) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> { ) -> Result<OkWebSocketResponseData, crate::errors::KclError> {
let all_requests = if batch_end { let all_requests = if batch_end {
let mut requests = self.batch().lock().unwrap().clone(); let mut requests = self.batch().lock().unwrap().clone();
requests.extend(self.batch_end().lock().unwrap().values().cloned()); requests.extend(self.batch_end().lock().unwrap().values().cloned());
@ -151,14 +157,14 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
// Return early if we have no commands to send. // Return early if we have no commands to send.
if all_requests.is_empty() { if all_requests.is_empty() {
return Ok(OkWebSocketResponseData::Modeling { return Ok(OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::Empty {}, modeling_response: OkModelingCmdResponse::Empty {},
}); });
} }
let requests: Vec<ModelingCmdReq> = all_requests let requests: Vec<ModelingCmdReq> = all_requests
.iter() .iter()
.filter_map(|(val, _)| match val { .filter_map(|(val, _)| match val {
WebSocketRequest::ModelingCmdReq { cmd, cmd_id } => Some(kittycad::types::ModelingCmdReq { WebSocketRequest::ModelingCmdReq(ModelingCmdReq { cmd, cmd_id }) => Some(ModelingCmdReq {
cmd: cmd.clone(), cmd: cmd.clone(),
cmd_id: *cmd_id, cmd_id: *cmd_id,
}), }),
@ -166,11 +172,11 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
}) })
.collect(); .collect();
let batched_requests = WebSocketRequest::ModelingCmdBatchReq { let batched_requests = WebSocketRequest::ModelingCmdBatchReq(ModelingBatch {
requests, requests,
batch_id: uuid::Uuid::new_v4(), batch_id: uuid::Uuid::new_v4().into(),
responses: true, responses: true,
}; });
let final_req = if all_requests.len() == 1 { let final_req = if all_requests.len() == 1 {
// We can unwrap here because we know the batch has only one element. // We can unwrap here because we know the batch has only one element.
@ -181,11 +187,11 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
// Create the map of original command IDs to source range. // Create the map of original command IDs to source range.
// This is for the wasm side, kurt needs it for selections. // This is for the wasm side, kurt needs it for selections.
let mut id_to_source_range = std::collections::HashMap::new(); let mut id_to_source_range = HashMap::new();
for (req, range) in all_requests.iter() { for (req, range) in all_requests.iter() {
match req { match req {
WebSocketRequest::ModelingCmdReq { cmd: _, cmd_id } => { WebSocketRequest::ModelingCmdReq(ModelingCmdReq { cmd: _, cmd_id }) => {
id_to_source_range.insert(*cmd_id, *range); id_to_source_range.insert(Uuid::from(*cmd_id), *range);
} }
_ => { _ => {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {
@ -204,21 +210,22 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
// We pop off the responses to cleanup our mappings. // We pop off the responses to cleanup our mappings.
match final_req { match final_req {
WebSocketRequest::ModelingCmdBatchReq { WebSocketRequest::ModelingCmdBatchReq(ModelingBatch {
ref requests, ref requests,
batch_id, batch_id,
responses: _, responses: _,
} => { }) => {
// Get the last command ID. // Get the last command ID.
let last_id = requests.last().unwrap().cmd_id; let last_id = requests.last().unwrap().cmd_id;
let ws_resp = self let ws_resp = self
.inner_send_modeling_cmd(batch_id, source_range, final_req, id_to_source_range.clone()) .inner_send_modeling_cmd(batch_id.into(), source_range, final_req, id_to_source_range.clone())
.await?; .await?;
let response = self.parse_websocket_response(ws_resp, source_range)?; let response = self.parse_websocket_response(ws_resp, source_range)?;
// If we have a batch response, we want to return the specific id we care about. // If we have a batch response, we want to return the specific id we care about.
if let kittycad::types::OkWebSocketResponseData::ModelingBatch { responses } = &response { if let OkWebSocketResponseData::ModelingBatch { responses } = response {
self.parse_batch_responses(last_id, id_to_source_range, responses.clone()) let responses = responses.into_iter().map(|(k, v)| (Uuid::from(k), v)).collect();
self.parse_batch_responses(last_id.into(), id_to_source_range, responses)
} else { } else {
// We should never get here. // We should never get here.
Err(KclError::Engine(KclErrorDetails { Err(KclError::Engine(KclErrorDetails {
@ -227,7 +234,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
})) }))
} }
} }
WebSocketRequest::ModelingCmdReq { cmd: _, cmd_id } => { WebSocketRequest::ModelingCmdReq(ModelingCmdReq { cmd: _, cmd_id }) => {
// You are probably wondering why we can't just return the source range we were // You are probably wondering why we can't just return the source range we were
// passed with the function. Well this is actually really important. // passed with the function. Well this is actually really important.
// If this is the last command in the batch and there is only one and we've reached // If this is the last command in the batch and there is only one and we've reached
@ -235,14 +242,14 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
// send default or the end of the file as it's source range not the origin of the // send default or the end of the file as it's source range not the origin of the
// request so we need the original request source range in case the engine returns // request so we need the original request source range in case the engine returns
// an error. // an error.
let source_range = id_to_source_range.get(&cmd_id).cloned().ok_or_else(|| { let source_range = id_to_source_range.get(cmd_id.as_ref()).cloned().ok_or_else(|| {
KclError::Engine(KclErrorDetails { KclError::Engine(KclErrorDetails {
message: format!("Failed to get source range for command ID: {:?}", cmd_id), message: format!("Failed to get source range for command ID: {:?}", cmd_id),
source_ranges: vec![], source_ranges: vec![],
}) })
})?; })?;
let ws_resp = self let ws_resp = self
.inner_send_modeling_cmd(cmd_id, source_range, final_req, id_to_source_range) .inner_send_modeling_cmd(cmd_id.into(), source_range, final_req, id_to_source_range)
.await?; .await?;
self.parse_websocket_response(ws_resp, source_range) self.parse_websocket_response(ws_resp, source_range)
} }
@ -268,14 +275,14 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
self.batch_modeling_cmd( self.batch_modeling_cmd(
plane_id, plane_id,
source_range, source_range,
&ModelingCmd::MakePlane { &ModelingCmd::from(mcmd::MakePlane {
clobber: false, clobber: false,
origin: default_origin, origin: default_origin,
size: default_size, size: LengthUnit(default_size),
x_axis: x_axis.into(), x_axis: x_axis.into(),
y_axis: y_axis.into(), y_axis: y_axis.into(),
hide: Some(true), hide: Some(true),
}, }),
) )
.await?; .await?;
@ -284,7 +291,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
self.batch_modeling_cmd( self.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
source_range, source_range,
&ModelingCmd::PlaneSetColor { color, plane_id }, &ModelingCmd::from(mcmd::PlaneSetColor { color, plane_id }),
) )
.await?; .await?;
} }
@ -394,22 +401,18 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
fn parse_websocket_response( fn parse_websocket_response(
&self, &self,
response: kittycad::types::WebSocketResponse, response: WebSocketResponse,
source_range: crate::executor::SourceRange, source_range: crate::executor::SourceRange,
) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> { ) -> Result<OkWebSocketResponseData, crate::errors::KclError> {
if let Some(data) = &response.resp { match response {
Ok(data.clone()) WebSocketResponse::Success(success) => Ok(success.resp),
} else if let Some(errors) = &response.errors { WebSocketResponse::Failure(fail) => {
Err(KclError::Engine(KclErrorDetails { let _request_id = fail.request_id;
message: format!("Modeling command failed: {:?}", errors), Err(KclError::Engine(KclErrorDetails {
source_ranges: vec![source_range], message: format!("Modeling command failed: {:?}", fail.errors),
})) source_ranges: vec![source_range],
} else { }))
// We should never get here. }
Err(KclError::Engine(KclErrorDetails {
message: "Modeling command failed: no response or errors".to_string(),
source_ranges: vec![source_range],
}))
} }
} }
@ -418,41 +421,36 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
// The last response we are looking for. // The last response we are looking for.
id: uuid::Uuid, id: uuid::Uuid,
// The mapping of source ranges to command IDs. // The mapping of source ranges to command IDs.
id_to_source_range: std::collections::HashMap<uuid::Uuid, crate::executor::SourceRange>, id_to_source_range: HashMap<uuid::Uuid, crate::executor::SourceRange>,
// The response from the engine. // The response from the engine.
responses: HashMap<String, kittycad::types::BatchResponse>, responses: HashMap<uuid::Uuid, BatchResponse>,
) -> Result<kittycad::types::OkWebSocketResponseData, crate::errors::KclError> { ) -> Result<OkWebSocketResponseData, crate::errors::KclError> {
// Iterate over the responses and check for errors. // Iterate over the responses and check for errors.
for (cmd_id, resp) in responses.iter() { for (cmd_id, resp) in responses.iter() {
let cmd_id = uuid::Uuid::parse_str(cmd_id).map_err(|e| { match resp {
KclError::Engine(KclErrorDetails { BatchResponse::Success { response } => {
message: format!("Failed to parse command ID: {:?}", e), if cmd_id == &id {
source_ranges: vec![id_to_source_range[&id]], // This is the response we care about.
}) return Ok(OkWebSocketResponseData::Modeling {
})?; modeling_response: response.clone(),
});
if let Some(errors) = resp.errors.as_ref() { } else {
// Get the source range for the command. // Continue the loop if this is not the response we care about.
let source_range = id_to_source_range.get(&cmd_id).cloned().ok_or_else(|| { continue;
KclError::Engine(KclErrorDetails { }
message: format!("Failed to get source range for command ID: {:?}", cmd_id), }
source_ranges: vec![], BatchResponse::Failure { errors } => {
}) // Get the source range for the command.
})?; let source_range = id_to_source_range.get(cmd_id).cloned().ok_or_else(|| {
return Err(KclError::Engine(KclErrorDetails { KclError::Engine(KclErrorDetails {
message: format!("Modeling command failed: {:?}", errors), message: format!("Failed to get source range for command ID: {:?}", cmd_id),
source_ranges: vec![source_range], source_ranges: vec![],
})); })
} })?;
if let Some(response) = resp.response.as_ref() { return Err(KclError::Engine(KclErrorDetails {
if cmd_id == id { message: format!("Modeling command failed: {:?}", errors),
// This is the response we care about. source_ranges: vec![source_range],
return Ok(kittycad::types::OkWebSocketResponseData::Modeling { }));
modeling_response: response.clone(),
});
} else {
// Continue the loop if this is not the response we care about.
continue;
} }
} }
} }
@ -470,10 +468,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
self.batch_modeling_cmd( self.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
Default::default(), Default::default(),
&ModelingCmd::ObjectVisible { &ModelingCmd::from(mcmd::ObjectVisible {
hidden, hidden,
object_id: *GRID_OBJECT_ID, object_id: *GRID_OBJECT_ID,
}, }),
) )
.await?; .await?;
@ -481,10 +479,10 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
self.batch_modeling_cmd( self.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
Default::default(), Default::default(),
&ModelingCmd::ObjectVisible { &ModelingCmd::from(mcmd::ObjectVisible {
hidden, hidden,
object_id: *GRID_SCALE_TEXT_OBJECT_ID, object_id: *GRID_SCALE_TEXT_OBJECT_ID,
}, }),
) )
.await?; .await?;

View File

@ -4,13 +4,21 @@ use std::{collections::HashMap, sync::Arc};
use anyhow::Result; use anyhow::Result;
use async_recursion::async_recursion; use async_recursion::async_recursion;
use kittycad::types::ModelingSessionData; use kcmc::each_cmd as mcmd;
use kcmc::ok_response::{output::TakeSnapshot, OkModelingCmdResponse};
use kcmc::websocket::{ModelingSessionData, OkWebSocketResponseData};
use kcmc::{ImageFormat, ModelingCmd};
use kittycad_modeling_cmds as kcmc;
use kittycad_modeling_cmds::length_unit::LengthUnit;
use parse_display::{Display, FromStr}; use parse_display::{Display, FromStr};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value as JValue; use serde_json::Value as JValue;
use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange}; use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange};
type Point2D = kcmc::shared::Point2d<f64>;
type Point3D = kcmc::shared::Point3d<f64>;
use crate::{ use crate::{
ast::types::{ ast::types::{
human_friendly_type, BodyItem, Expr, ExpressionStatement, FunctionExpression, KclNone, Program, human_friendly_type, BodyItem, Expr, ExpressionStatement, FunctionExpression, KclNone, Program,
@ -1284,7 +1292,7 @@ impl From<Point2d> for [f64; 2] {
} }
} }
impl From<Point2d> for kittycad::types::Point2D { impl From<Point2d> for Point2D {
fn from(p: Point2d) -> Self { fn from(p: Point2d) -> Self {
Self { x: p.x, y: p.y } Self { x: p.x, y: p.y }
} }
@ -1315,11 +1323,20 @@ impl Point3d {
} }
} }
impl From<Point3d> for kittycad::types::Point3D { impl From<Point3d> for Point3D {
fn from(p: Point3d) -> Self { fn from(p: Point3d) -> Self {
Self { x: p.x, y: p.y, z: p.z } Self { x: p.x, y: p.y, z: p.z }
} }
} }
impl From<Point3d> for kittycad_modeling_cmds::shared::Point3d<LengthUnit> {
fn from(p: Point3d) -> Self {
Self {
x: LengthUnit(p.x),
y: LengthUnit(p.y),
z: LengthUnit(p.z),
}
}
}
/// Metadata. /// Metadata.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Eq)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema, Eq)]
@ -1687,9 +1704,9 @@ impl ExecutorContext {
.batch_modeling_cmd( .batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
SourceRange::default(), SourceRange::default(),
&kittycad::types::ModelingCmd::EdgeLinesVisible { &ModelingCmd::from(mcmd::EdgeLinesVisible {
hidden: !settings.highlight_edges, hidden: !settings.highlight_edges,
}, }),
) )
.await?; .await?;
@ -1774,9 +1791,16 @@ impl ExecutorContext {
.batch_modeling_cmd( .batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
SourceRange::default(), SourceRange::default(),
&kittycad::types::ModelingCmd::SetSceneUnits { &ModelingCmd::from(mcmd::SetSceneUnits {
unit: self.settings.units.into(), unit: match self.settings.units {
}, UnitLength::Cm => kcmc::units::UnitLength::Centimeters,
UnitLength::Ft => kcmc::units::UnitLength::Feet,
UnitLength::In => kcmc::units::UnitLength::Inches,
UnitLength::M => kcmc::units::UnitLength::Meters,
UnitLength::Mm => kcmc::units::UnitLength::Millimeters,
UnitLength::Yd => kcmc::units::UnitLength::Yards,
},
}),
) )
.await?; .await?;
let memory = if let Some(memory) = memory { let memory = if let Some(memory) = memory {
@ -1927,7 +1951,7 @@ impl ExecutorContext {
} }
/// Execute the program, then get a PNG screenshot. /// Execute the program, then get a PNG screenshot.
pub async fn execute_and_prepare_snapshot(&self, program: &Program) -> Result<kittycad::types::TakeSnapshot> { pub async fn execute_and_prepare_snapshot(&self, program: &Program) -> Result<TakeSnapshot> {
let _ = self.run(program, None).await?; let _ = self.run(program, None).await?;
// Zoom to fit. // Zoom to fit.
@ -1935,10 +1959,11 @@ impl ExecutorContext {
.send_modeling_cmd( .send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(), crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit { ModelingCmd::from(mcmd::ZoomToFit {
object_ids: Default::default(), object_ids: Default::default(),
animated: false,
padding: 0.1, padding: 0.1,
}, }),
) )
.await?; .await?;
@ -1948,19 +1973,19 @@ impl ExecutorContext {
.send_modeling_cmd( .send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(), crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot { ModelingCmd::from(mcmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png, format: ImageFormat::Png,
}, }),
) )
.await?; .await?;
let kittycad::types::OkWebSocketResponseData::Modeling { let OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data }, modeling_response: OkModelingCmdResponse::TakeSnapshot(contents),
} = resp } = resp
else { else {
anyhow::bail!("Unexpected response from engine: {:?}", resp); anyhow::bail!("Unexpected response from engine: {:?}", resp);
}; };
Ok(data) Ok(contents)
} }
} }

View File

@ -1,7 +1,9 @@
use std::any::type_name; use std::any::type_name;
use anyhow::Result; use anyhow::Result;
use kittycad::types::OkWebSocketResponseData; use kcmc::websocket::OkWebSocketResponseData;
use kcmc::ModelingCmd;
use kittycad_modeling_cmds as kcmc;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use crate::{ use crate::{
@ -51,7 +53,7 @@ impl Args {
pub(crate) async fn batch_modeling_cmd( pub(crate) async fn batch_modeling_cmd(
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
cmd: kittycad::types::ModelingCmd, cmd: ModelingCmd,
) -> Result<(), crate::errors::KclError> { ) -> Result<(), crate::errors::KclError> {
self.ctx.engine.batch_modeling_cmd(id, self.source_range, &cmd).await self.ctx.engine.batch_modeling_cmd(id, self.source_range, &cmd).await
} }
@ -59,11 +61,7 @@ impl Args {
// Add a modeling command to the batch that gets executed at the end of the file. // Add a modeling command to the batch that gets executed at the end of the file.
// This is good for something like fillet or chamfer where the engine would // This is good for something like fillet or chamfer where the engine would
// eat the path id if we executed it right away. // eat the path id if we executed it right away.
pub(crate) async fn batch_end_cmd( pub(crate) async fn batch_end_cmd(&self, id: uuid::Uuid, cmd: ModelingCmd) -> Result<(), crate::errors::KclError> {
&self,
id: uuid::Uuid,
cmd: kittycad::types::ModelingCmd,
) -> Result<(), crate::errors::KclError> {
self.ctx.engine.batch_end_cmd(id, self.source_range, &cmd).await self.ctx.engine.batch_end_cmd(id, self.source_range, &cmd).await
} }
@ -71,7 +69,7 @@ impl Args {
pub(crate) async fn send_modeling_cmd( pub(crate) async fn send_modeling_cmd(
&self, &self,
id: uuid::Uuid, id: uuid::Uuid,
cmd: kittycad::types::ModelingCmd, cmd: ModelingCmd,
) -> Result<OkWebSocketResponseData, KclError> { ) -> Result<OkWebSocketResponseData, KclError> {
self.ctx.engine.send_modeling_cmd(id, self.source_range, cmd).await self.ctx.engine.send_modeling_cmd(id, self.source_range, cmd).await
} }

View File

@ -2,7 +2,10 @@
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::ModelingCmd; use kcmc::each_cmd as mcmd;
use kcmc::length_unit::LengthUnit;
use kcmc::{shared::CutType, ModelingCmd};
use kittycad_modeling_cmds as kcmc;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -137,14 +140,14 @@ async fn inner_chamfer(
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
args.batch_end_cmd( args.batch_end_cmd(
id, id,
ModelingCmd::Solid3DFilletEdge { ModelingCmd::from(mcmd::Solid3dFilletEdge {
edge_id, edge_id,
object_id: extrude_group.id, object_id: extrude_group.id,
radius: data.length, radius: LengthUnit(data.length),
tolerance: DEFAULT_TOLERANCE, // We can let the user set this in the future. tolerance: LengthUnit(DEFAULT_TOLERANCE), // We can let the user set this in the future.
cut_type: Some(kittycad::types::CutType::Chamfer), cut_type: CutType::Chamfer,
face_id: Some(id), face_id: Some(id),
}, }),
) )
.await?; .await?;

View File

@ -4,7 +4,12 @@ use std::collections::HashMap;
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::{ExtrusionFaceCapType, ExtrusionFaceInfo}; use kcmc::each_cmd as mcmd;
use kcmc::length_unit::LengthUnit;
use kcmc::ok_response::OkModelingCmdResponse;
use kcmc::websocket::OkWebSocketResponseData;
use kcmc::{output::ExtrusionFaceInfo, shared::ExtrusionFaceCapType, ModelingCmd};
use kittycad_modeling_cmds as kcmc;
use schemars::JsonSchema; use schemars::JsonSchema;
use uuid::Uuid; use uuid::Uuid;
@ -86,7 +91,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
// We do this here in case extrude is called out of order. // We do this here in case extrude is called out of order.
args.batch_modeling_cmd( args.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
kittycad::types::ModelingCmd::EnableSketchMode { ModelingCmd::from(mcmd::EnableSketchMode {
animated: false, animated: false,
ortho: false, ortho: false,
entity_id: sketch_group.on.id(), entity_id: sketch_group.on.id(),
@ -97,22 +102,25 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
} else { } else {
None None
}, },
}, }),
) )
.await?; .await?;
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
kittycad::types::ModelingCmd::Extrude { ModelingCmd::from(mcmd::Extrude {
target: sketch_group.id, target: sketch_group.id.into(),
distance: length, distance: LengthUnit(length),
}, }),
) )
.await?; .await?;
// Disable the sketch mode. // Disable the sketch mode.
args.batch_modeling_cmd(uuid::Uuid::new_v4(), kittycad::types::ModelingCmd::SketchModeDisable {}) args.batch_modeling_cmd(
.await?; uuid::Uuid::new_v4(),
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
)
.await?;
extrude_groups.push(do_post_extrude(sketch_group.clone(), length, args.clone()).await?); extrude_groups.push(do_post_extrude(sketch_group.clone(), length, args.clone()).await?);
} }
@ -128,9 +136,9 @@ pub(crate) async fn do_post_extrude(
// See: https://github.com/KittyCAD/modeling-app/issues/806 // See: https://github.com/KittyCAD/modeling-app/issues/806
args.batch_modeling_cmd( args.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
kittycad::types::ModelingCmd::ObjectBringToFront { ModelingCmd::from(mcmd::ObjectBringToFront {
object_id: sketch_group.id, object_id: sketch_group.id,
}, }),
) )
.await?; .await?;
@ -166,15 +174,15 @@ pub(crate) async fn do_post_extrude(
let solid3d_info = args let solid3d_info = args
.send_modeling_cmd( .send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
kittycad::types::ModelingCmd::Solid3DGetExtrusionFaceInfo { ModelingCmd::from(mcmd::Solid3dGetExtrusionFaceInfo {
edge_id, edge_id,
object_id: sketch_group.id, object_id: sketch_group.id,
}, }),
) )
.await?; .await?;
let face_infos = if let kittycad::types::OkWebSocketResponseData::Modeling { let face_infos = if let OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::Solid3DGetExtrusionFaceInfo { data }, modeling_response: OkModelingCmdResponse::Solid3dGetExtrusionFaceInfo(data),
} = solid3d_info } = solid3d_info
{ {
data.faces data.faces
@ -199,21 +207,21 @@ pub(crate) async fn do_post_extrude(
// uses this to build the artifact graph, which the UI needs. // uses this to build the artifact graph, which the UI needs.
args.batch_modeling_cmd( args.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
kittycad::types::ModelingCmd::Solid3DGetOppositeEdge { ModelingCmd::from(mcmd::Solid3dGetOppositeEdge {
edge_id: curve_id, edge_id: curve_id,
object_id: sketch_group.id, object_id: sketch_group.id,
face_id, face_id,
}, }),
) )
.await?; .await?;
args.batch_modeling_cmd( args.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
kittycad::types::ModelingCmd::Solid3DGetPrevAdjacentEdge { ModelingCmd::from(mcmd::Solid3dGetPrevAdjacentEdge {
edge_id: curve_id, edge_id: curve_id,
object_id: sketch_group.id, object_id: sketch_group.id,
face_id, face_id,
}, }),
) )
.await?; .await?;
} }

View File

@ -2,7 +2,12 @@
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::ModelingCmd; use kcmc::each_cmd as mcmd;
use kcmc::length_unit::LengthUnit;
use kcmc::ok_response::OkModelingCmdResponse;
use kcmc::websocket::OkWebSocketResponseData;
use kcmc::{shared::CutType, ModelingCmd};
use kittycad_modeling_cmds as kcmc;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
@ -139,14 +144,14 @@ async fn inner_fillet(
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
args.batch_end_cmd( args.batch_end_cmd(
id, id,
ModelingCmd::Solid3DFilletEdge { ModelingCmd::from(mcmd::Solid3dFilletEdge {
edge_id, edge_id,
object_id: extrude_group.id, object_id: extrude_group.id,
radius: data.radius, radius: LengthUnit(data.radius),
tolerance: data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units)), tolerance: LengthUnit(data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
cut_type: Some(kittycad::types::CutType::Fillet), cut_type: CutType::Fillet,
face_id: None, face_id: None,
}, }),
) )
.await?; .await?;
@ -231,19 +236,19 @@ async fn inner_get_opposite_edge(tag: TagIdentifier, exec_state: &mut ExecState,
let resp = args let resp = args
.send_modeling_cmd( .send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
ModelingCmd::Solid3DGetOppositeEdge { ModelingCmd::from(mcmd::Solid3dGetOppositeEdge {
edge_id: tagged_path.id, edge_id: tagged_path.id,
object_id: tagged_path.sketch_group, object_id: tagged_path.sketch_group,
face_id, face_id,
}, }),
) )
.await?; .await?;
let kittycad::types::OkWebSocketResponseData::Modeling { let OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::Solid3DGetOppositeEdge { data: opposite_edge }, modeling_response: OkModelingCmdResponse::Solid3dGetOppositeEdge(opposite_edge),
} = &resp } = &resp
else { else {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {
message: format!("Solid3DGetOppositeEdge response was not as expected: {:?}", resp), message: format!("mcmd::Solid3dGetOppositeEdge response was not as expected: {:?}", resp),
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],
})); }));
}; };
@ -312,24 +317,27 @@ async fn inner_get_next_adjacent_edge(
let resp = args let resp = args
.send_modeling_cmd( .send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
ModelingCmd::Solid3DGetNextAdjacentEdge { ModelingCmd::from(mcmd::Solid3dGetNextAdjacentEdge {
edge_id: tagged_path.id, edge_id: tagged_path.id,
object_id: tagged_path.sketch_group, object_id: tagged_path.sketch_group,
face_id, face_id,
}, }),
) )
.await?; .await?;
let kittycad::types::OkWebSocketResponseData::Modeling { let OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::Solid3DGetNextAdjacentEdge { data: ajacent_edge }, modeling_response: OkModelingCmdResponse::Solid3dGetNextAdjacentEdge(adjacent_edge),
} = &resp } = &resp
else { else {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {
message: format!("Solid3DGetNextAdjacentEdge response was not as expected: {:?}", resp), message: format!(
"mcmd::Solid3dGetNextAdjacentEdge response was not as expected: {:?}",
resp
),
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],
})); }));
}; };
ajacent_edge.edge.ok_or_else(|| { adjacent_edge.edge.ok_or_else(|| {
KclError::Type(KclErrorDetails { KclError::Type(KclErrorDetails {
message: format!("No edge found next adjacent to tag: `{}`", tag.value), message: format!("No edge found next adjacent to tag: `{}`", tag.value),
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],
@ -398,24 +406,27 @@ async fn inner_get_previous_adjacent_edge(
let resp = args let resp = args
.send_modeling_cmd( .send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
ModelingCmd::Solid3DGetPrevAdjacentEdge { ModelingCmd::from(mcmd::Solid3dGetPrevAdjacentEdge {
edge_id: tagged_path.id, edge_id: tagged_path.id,
object_id: tagged_path.sketch_group, object_id: tagged_path.sketch_group,
face_id, face_id,
}, }),
) )
.await?; .await?;
let kittycad::types::OkWebSocketResponseData::Modeling { let OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::Solid3DGetPrevAdjacentEdge { data: ajacent_edge }, modeling_response: OkModelingCmdResponse::Solid3dGetPrevAdjacentEdge(adjacent_edge),
} = &resp } = &resp
else { else {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {
message: format!("Solid3DGetPrevAdjacentEdge response was not as expected: {:?}", resp), message: format!(
"mcmd::Solid3dGetPrevAdjacentEdge response was not as expected: {:?}",
resp
),
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],
})); }));
}; };
ajacent_edge.edge.ok_or_else(|| { adjacent_edge.edge.ok_or_else(|| {
KclError::Type(KclErrorDetails { KclError::Type(KclErrorDetails {
message: format!("No edge found previous adjacent to tag: `{}`", tag.value), message: format!("No edge found previous adjacent to tag: `{}`", tag.value),
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],

View File

@ -2,7 +2,11 @@
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::ModelingCmd; use kcmc::each_cmd as mcmd;
use kcmc::length_unit::LengthUnit;
use kcmc::shared::Angle;
use kcmc::ModelingCmd;
use kittycad_modeling_cmds as kcmc;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -61,13 +65,13 @@ async fn inner_helix(
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::EntityMakeHelix { ModelingCmd::from(mcmd::EntityMakeHelix {
cylinder_id: extrude_group.id, cylinder_id: extrude_group.id,
is_clockwise: !data.ccw, is_clockwise: !data.ccw,
length: data.length.unwrap_or(extrude_group.height), length: LengthUnit(data.length.unwrap_or(extrude_group.height)),
revolutions: data.revolutions, revolutions: data.revolutions,
start_angle: kittycad::types::Angle::from_degrees(data.angle_start), start_angle: Angle::from_degrees(data.angle_start),
}, }),
) )
.await?; .await?;

View File

@ -4,7 +4,15 @@ use std::str::FromStr;
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::ModelingCmd; use kcmc::coord::{Axis, AxisDirectionPair, Direction, System};
use kcmc::each_cmd as mcmd;
use kcmc::format::InputFormat;
use kcmc::ok_response::OkModelingCmdResponse;
use kcmc::shared::FileImportFormat;
use kcmc::units::UnitLength;
use kcmc::websocket::OkWebSocketResponseData;
use kcmc::{ImportFile, ModelingCmd};
use kittycad_modeling_cmds as kcmc;
use schemars::JsonSchema; use schemars::JsonSchema;
use crate::{ use crate::{
@ -19,14 +27,14 @@ use crate::{
// * Forward: -Y // * Forward: -Y
// * Up: +Z // * Up: +Z
// * Handedness: Right // * Handedness: Right
const ZOO_COORD_SYSTEM: kittycad::types::System = kittycad::types::System { const ZOO_COORD_SYSTEM: System = System {
forward: kittycad::types::AxisDirectionPair { forward: AxisDirectionPair {
axis: kittycad::types::Axis::Y, axis: Axis::Y,
direction: kittycad::types::Direction::Negative, direction: Direction::Negative,
}, },
up: kittycad::types::AxisDirectionPair { up: AxisDirectionPair {
axis: kittycad::types::Axis::Z, axis: Axis::Z,
direction: kittycad::types::Direction::Positive, direction: Direction::Positive,
}, },
}; };
@ -47,22 +55,22 @@ pub enum ImportFormat {
Obj { Obj {
/// Co-ordinate system of input data. /// Co-ordinate system of input data.
/// Defaults to the [KittyCAD co-ordinate system. /// Defaults to the [KittyCAD co-ordinate system.
coords: Option<kittycad::types::System>, coords: Option<System>,
/// The units of the input data. This is very important for correct scaling and when /// The units of the input data. This is very important for correct scaling and when
/// calculating physics properties like mass, etc. /// calculating physics properties like mass, etc.
/// Defaults to millimeters. /// Defaults to millimeters.
units: kittycad::types::UnitLength, units: UnitLength,
}, },
/// The PLY Polygon File Format. /// The PLY Polygon File Format.
#[serde(rename = "ply")] #[serde(rename = "ply")]
Ply { Ply {
/// Co-ordinate system of input data. /// Co-ordinate system of input data.
/// Defaults to the [KittyCAD co-ordinate system. /// Defaults to the [KittyCAD co-ordinate system.
coords: Option<kittycad::types::System>, coords: Option<System>,
/// The units of the input data. This is very important for correct scaling and when /// The units of the input data. This is very important for correct scaling and when
/// calculating physics properties like mass, etc. /// calculating physics properties like mass, etc.
/// Defaults to millimeters. /// Defaults to millimeters.
units: kittycad::types::UnitLength, units: UnitLength,
}, },
/// SolidWorks part (SLDPRT) format. /// SolidWorks part (SLDPRT) format.
#[serde(rename = "sldprt")] #[serde(rename = "sldprt")]
@ -75,37 +83,37 @@ pub enum ImportFormat {
Stl { Stl {
/// Co-ordinate system of input data. /// Co-ordinate system of input data.
/// Defaults to the [KittyCAD co-ordinate system. /// Defaults to the [KittyCAD co-ordinate system.
coords: Option<kittycad::types::System>, coords: Option<System>,
/// The units of the input data. This is very important for correct scaling and when /// The units of the input data. This is very important for correct scaling and when
/// calculating physics properties like mass, etc. /// calculating physics properties like mass, etc.
/// Defaults to millimeters. /// Defaults to millimeters.
units: kittycad::types::UnitLength, units: UnitLength,
}, },
} }
impl From<ImportFormat> for kittycad::types::InputFormat { impl From<ImportFormat> for InputFormat {
fn from(format: ImportFormat) -> Self { fn from(format: ImportFormat) -> Self {
match format { match format {
ImportFormat::Fbx {} => kittycad::types::InputFormat::Fbx {}, ImportFormat::Fbx {} => InputFormat::Fbx(Default::default()),
ImportFormat::Gltf {} => kittycad::types::InputFormat::Gltf {}, ImportFormat::Gltf {} => InputFormat::Gltf(Default::default()),
ImportFormat::Obj { coords, units } => kittycad::types::InputFormat::Obj { ImportFormat::Obj { coords, units } => InputFormat::Obj(kcmc::format::obj::import::Options {
coords: coords.unwrap_or(ZOO_COORD_SYSTEM), coords: coords.unwrap_or(ZOO_COORD_SYSTEM),
units, units,
}, }),
ImportFormat::Ply { coords, units } => kittycad::types::InputFormat::Ply { ImportFormat::Ply { coords, units } => InputFormat::Ply(kcmc::format::ply::import::Options {
coords: coords.unwrap_or(ZOO_COORD_SYSTEM), coords: coords.unwrap_or(ZOO_COORD_SYSTEM),
units, units,
}, }),
ImportFormat::Sldprt {} => kittycad::types::InputFormat::Sldprt { ImportFormat::Sldprt {} => InputFormat::Sldprt(kcmc::format::sldprt::import::Options {
split_closed_faces: false, split_closed_faces: false,
}, }),
ImportFormat::Step {} => kittycad::types::InputFormat::Step { ImportFormat::Step {} => InputFormat::Step(kcmc::format::step::import::Options {
split_closed_faces: false, split_closed_faces: false,
}, }),
ImportFormat::Stl { coords, units } => kittycad::types::InputFormat::Stl { ImportFormat::Stl { coords, units } => InputFormat::Stl(kcmc::format::stl::import::Options {
coords: coords.unwrap_or(ZOO_COORD_SYSTEM), coords: coords.unwrap_or(ZOO_COORD_SYSTEM),
units, units,
}, }),
} }
} }
} }
@ -194,7 +202,7 @@ async fn inner_import(
// Get the format type from the extension of the file. // Get the format type from the extension of the file.
let format = if let Some(options) = options { let format = if let Some(options) = options {
// Validate the given format with the extension format. // Validate the given format with the extension format.
let format: kittycad::types::InputFormat = options.into(); let format: InputFormat = options.into();
validate_extension_format(ext_format, format.clone()).map_err(|e| { validate_extension_format(ext_format, format.clone()).map_err(|e| {
KclError::Semantic(KclErrorDetails { KclError::Semantic(KclErrorDetails {
message: e.to_string(), message: e.to_string(),
@ -224,14 +232,14 @@ async fn inner_import(
source_ranges: vec![args.source_range], source_ranges: vec![args.source_range],
}) })
})?; })?;
let mut import_files = vec![kittycad::types::ImportFile { let mut import_files = vec![kcmc::ImportFile {
path: file_name.to_string(), path: file_name.to_string(),
data: file_contents.clone(), data: file_contents.clone(),
}]; }];
// In the case of a gltf importing a bin file we need to handle that! and figure out where the // In the case of a gltf importing a bin file we need to handle that! and figure out where the
// file is relative to our current file. // file is relative to our current file.
if let kittycad::types::InputFormat::Gltf {} = format { if let InputFormat::Gltf(..) = format {
// Check if the file is a binary gltf file, in that case we don't need to import the bin // Check if the file is a binary gltf file, in that case we don't need to import the bin
// file. // file.
if !file_contents.starts_with(b"glTF") { if !file_contents.starts_with(b"glTF") {
@ -265,7 +273,7 @@ async fn inner_import(
}) })
})?; })?;
import_files.push(kittycad::types::ImportFile { import_files.push(ImportFile {
path: uri.to_string(), path: uri.to_string(),
data: bin_contents, data: bin_contents,
}); });
@ -287,15 +295,15 @@ async fn inner_import(
let resp = args let resp = args
.send_modeling_cmd( .send_modeling_cmd(
id, id,
ModelingCmd::ImportFiles { ModelingCmd::from(mcmd::ImportFiles {
files: import_files.clone(), files: import_files.clone(),
format, format,
}, }),
) )
.await?; .await?;
let kittycad::types::OkWebSocketResponseData::Modeling { let OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::ImportFiles { data: imported_files }, modeling_response: OkModelingCmdResponse::ImportFiles(imported_files),
} = &resp } = &resp
else { else {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {
@ -312,14 +320,14 @@ async fn inner_import(
} }
/// Get the source format from the extension. /// Get the source format from the extension.
fn get_import_format_from_extension(ext: &str) -> Result<kittycad::types::InputFormat> { fn get_import_format_from_extension(ext: &str) -> Result<InputFormat> {
let format = match kittycad::types::FileImportFormat::from_str(ext) { let format = match FileImportFormat::from_str(ext) {
Ok(format) => format, Ok(format) => format,
Err(_) => { Err(_) => {
if ext == "stp" { if ext == "stp" {
kittycad::types::FileImportFormat::Step FileImportFormat::Step
} else if ext == "glb" { } else if ext == "glb" {
kittycad::types::FileImportFormat::Gltf FileImportFormat::Gltf
} else { } else {
anyhow::bail!("unknown source format for file extension: {}. Try setting the `--src-format` flag explicitly or use a valid format.", ext) anyhow::bail!("unknown source format for file extension: {}. Try setting the `--src-format` flag explicitly or use a valid format.", ext)
} }
@ -327,7 +335,7 @@ fn get_import_format_from_extension(ext: &str) -> Result<kittycad::types::InputF
}; };
// Make the default units millimeters. // Make the default units millimeters.
let ul = kittycad::types::UnitLength::Mm; let ul = UnitLength::Millimeters;
// Zoo co-ordinate system. // Zoo co-ordinate system.
// //
@ -335,44 +343,44 @@ fn get_import_format_from_extension(ext: &str) -> Result<kittycad::types::InputF
// * Up: +Z // * Up: +Z
// * Handedness: Right // * Handedness: Right
match format { match format {
kittycad::types::FileImportFormat::Step => Ok(kittycad::types::InputFormat::Step { FileImportFormat::Step => Ok(InputFormat::Step(kcmc::format::step::import::Options {
split_closed_faces: false, split_closed_faces: false,
}), })),
kittycad::types::FileImportFormat::Stl => Ok(kittycad::types::InputFormat::Stl { FileImportFormat::Stl => Ok(InputFormat::Stl(kcmc::format::stl::import::Options {
coords: ZOO_COORD_SYSTEM, coords: ZOO_COORD_SYSTEM,
units: ul, units: ul,
}), })),
kittycad::types::FileImportFormat::Obj => Ok(kittycad::types::InputFormat::Obj { FileImportFormat::Obj => Ok(InputFormat::Obj(kcmc::format::obj::import::Options {
coords: ZOO_COORD_SYSTEM, coords: ZOO_COORD_SYSTEM,
units: ul, units: ul,
}), })),
kittycad::types::FileImportFormat::Gltf => Ok(kittycad::types::InputFormat::Gltf {}), FileImportFormat::Gltf => Ok(InputFormat::Gltf(kcmc::format::gltf::import::Options {})),
kittycad::types::FileImportFormat::Ply => Ok(kittycad::types::InputFormat::Ply { FileImportFormat::Ply => Ok(InputFormat::Ply(kcmc::format::ply::import::Options {
coords: ZOO_COORD_SYSTEM, coords: ZOO_COORD_SYSTEM,
units: ul, units: ul,
}), })),
kittycad::types::FileImportFormat::Fbx => Ok(kittycad::types::InputFormat::Fbx {}), FileImportFormat::Fbx => Ok(InputFormat::Fbx(kcmc::format::fbx::import::Options {})),
kittycad::types::FileImportFormat::Sldprt => Ok(kittycad::types::InputFormat::Sldprt { FileImportFormat::Sldprt => Ok(InputFormat::Sldprt(kcmc::format::sldprt::import::Options {
split_closed_faces: false, split_closed_faces: false,
}), })),
} }
} }
fn validate_extension_format(ext: kittycad::types::InputFormat, given: kittycad::types::InputFormat) -> Result<()> { fn validate_extension_format(ext: InputFormat, given: InputFormat) -> Result<()> {
if let kittycad::types::InputFormat::Stl { coords: _, units: _ } = ext { if let InputFormat::Stl(_) = ext {
if let kittycad::types::InputFormat::Stl { coords: _, units: _ } = given { if let InputFormat::Stl(_) = given {
return Ok(()); return Ok(());
} }
} }
if let kittycad::types::InputFormat::Obj { coords: _, units: _ } = ext { if let InputFormat::Obj(_) = ext {
if let kittycad::types::InputFormat::Obj { coords: _, units: _ } = given { if let InputFormat::Obj(_) = given {
return Ok(()); return Ok(());
} }
} }
if let kittycad::types::InputFormat::Ply { coords: _, units: _ } = ext { if let InputFormat::Ply(_) = ext {
if let kittycad::types::InputFormat::Ply { coords: _, units: _ } = given { if let InputFormat::Ply(_) = given {
return Ok(()); return Ok(());
} }
} }
@ -388,14 +396,14 @@ fn validate_extension_format(ext: kittycad::types::InputFormat, given: kittycad:
) )
} }
fn get_name_of_format(type_: kittycad::types::InputFormat) -> String { fn get_name_of_format(type_: InputFormat) -> &'static str {
match type_ { match type_ {
kittycad::types::InputFormat::Fbx {} => "fbx".to_string(), InputFormat::Fbx(_) => "fbx",
kittycad::types::InputFormat::Gltf {} => "gltf".to_string(), InputFormat::Gltf(_) => "gltf",
kittycad::types::InputFormat::Obj { coords: _, units: _ } => "obj".to_string(), InputFormat::Obj(_) => "obj",
kittycad::types::InputFormat::Ply { coords: _, units: _ } => "ply".to_string(), InputFormat::Ply(_) => "ply",
kittycad::types::InputFormat::Sldprt { split_closed_faces: _ } => "sldprt".to_string(), InputFormat::Sldprt(_) => "sldprt",
kittycad::types::InputFormat::Step { split_closed_faces: _ } => "step".to_string(), InputFormat::Step(_) => "step",
kittycad::types::InputFormat::Stl { coords: _, units: _ } => "stl".to_string(), InputFormat::Stl(_) => "stl",
} }
} }

View File

@ -2,7 +2,10 @@
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::ModelingCmd; use kcmc::each_cmd as mcmd;
use kcmc::length_unit::LengthUnit;
use kcmc::ModelingCmd;
use kittycad_modeling_cmds as kcmc;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -156,16 +159,15 @@ async fn inner_loft(
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::Loft { ModelingCmd::from(mcmd::Loft {
section_ids: sketch_groups.iter().map(|group| group.id).collect(), section_ids: sketch_groups.iter().map(|group| group.id).collect(),
base_curve_index: data.base_curve_index, base_curve_index: data.base_curve_index,
bez_approximate_rational: data.bez_approximate_rational.unwrap_or(false), bez_approximate_rational: data.bez_approximate_rational.unwrap_or(false),
tolerance: data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units)), tolerance: LengthUnit(data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
v_degree: data v_degree: data
.v_degree .v_degree
.unwrap_or_else(|| std::num::NonZeroU32::new(DEFAULT_V_DEGREE).unwrap()) .unwrap_or_else(|| std::num::NonZeroU32::new(DEFAULT_V_DEGREE).unwrap()),
.into(), }),
},
) )
.await?; .await?;

View File

@ -2,7 +2,13 @@
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::ModelingCmd; use kcmc::each_cmd as mcmd;
use kcmc::length_unit::LengthUnit;
use kcmc::ok_response::OkModelingCmdResponse;
use kcmc::shared::Transform;
use kcmc::websocket::OkWebSocketResponseData;
use kcmc::ModelingCmd;
use kittycad_modeling_cmds::{self as kcmc};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -163,7 +169,7 @@ async fn inner_pattern_transform<'a>(
async fn send_pattern_transform( async fn send_pattern_transform(
// This should be passed via reference, see // This should be passed via reference, see
// https://github.com/KittyCAD/modeling-app/issues/2821 // https://github.com/KittyCAD/modeling-app/issues/2821
transform: Vec<kittycad::types::Transform>, transform: Vec<Transform>,
extrude_group: &ExtrudeGroup, extrude_group: &ExtrudeGroup,
args: &Args, args: &Args,
) -> Result<Vec<Box<ExtrudeGroup>>, KclError> { ) -> Result<Vec<Box<ExtrudeGroup>>, KclError> {
@ -172,15 +178,15 @@ async fn send_pattern_transform(
let resp = args let resp = args
.send_modeling_cmd( .send_modeling_cmd(
id, id,
ModelingCmd::EntityLinearPatternTransform { ModelingCmd::from(mcmd::EntityLinearPatternTransform {
entity_id: extrude_group.id, entity_id: extrude_group.id,
transform, transform,
}, }),
) )
.await?; .await?;
let kittycad::types::OkWebSocketResponseData::Modeling { let OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::EntityLinearPatternTransform { data: pattern_info }, modeling_response: OkModelingCmdResponse::EntityLinearPatternTransform(pattern_info),
} = &resp } = &resp
else { else {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {
@ -203,7 +209,7 @@ async fn make_transform<'a>(
transform_function: &FunctionParam<'a>, transform_function: &FunctionParam<'a>,
source_range: SourceRange, source_range: SourceRange,
exec_state: &mut ExecState, exec_state: &mut ExecState,
) -> Result<kittycad::types::Transform, KclError> { ) -> Result<Transform, KclError> {
// Call the transform fn for this repetition. // Call the transform fn for this repetition.
let repetition_num = KclValue::UserVal(UserVal { let repetition_num = KclValue::UserVal(UserVal {
value: serde_json::Value::Number(i.into()), value: serde_json::Value::Number(i.into()),
@ -247,12 +253,12 @@ async fn make_transform<'a>(
Some(x) => array_to_point3d(x, source_ranges.clone())?, Some(x) => array_to_point3d(x, source_ranges.clone())?,
None => Point3d { x: 0.0, y: 0.0, z: 0.0 }, None => Point3d { x: 0.0, y: 0.0, z: 0.0 },
}; };
let t = kittycad::types::Transform { let t = Transform {
replicate, replicate,
scale: Some(scale.into()), scale: scale.into(),
translate: Some(translate.into()), translate: translate.into(),
// TODO: chalmers to pipe thru to kcl. // TODO: chalmers to pipe thru to kcl.
rotation: None, rotation: Default::default(),
}; };
Ok(t) Ok(t)
} }
@ -451,21 +457,17 @@ async fn pattern_linear(data: LinearPattern, geometry: Geometry, args: Args) ->
let resp = args let resp = args
.send_modeling_cmd( .send_modeling_cmd(
id, id,
ModelingCmd::EntityLinearPattern { ModelingCmd::from(mcmd::EntityLinearPattern {
axis: kittycad::types::Point3D { axis: kcmc::shared::Point3d::from(data.axis()),
x: data.axis()[0],
y: data.axis()[1],
z: data.axis()[2],
},
entity_id: geometry.id(), entity_id: geometry.id(),
num_repetitions: data.repetitions(), num_repetitions: data.repetitions(),
spacing: data.distance(), spacing: LengthUnit(data.distance()),
}, }),
) )
.await?; .await?;
let kittycad::types::OkWebSocketResponseData::Modeling { let OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::EntityLinearPattern { data: pattern_info }, modeling_response: OkModelingCmdResponse::EntityLinearPattern(pattern_info),
} = &resp } = &resp
else { else {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {
@ -713,26 +715,27 @@ async fn inner_pattern_circular_3d(
async fn pattern_circular(data: CircularPattern, geometry: Geometry, args: Args) -> Result<Geometries, KclError> { async fn pattern_circular(data: CircularPattern, geometry: Geometry, args: Args) -> Result<Geometries, KclError> {
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
let center = data.center();
let resp = args let resp = args
.send_modeling_cmd( .send_modeling_cmd(
id, id,
ModelingCmd::EntityCircularPattern { ModelingCmd::from(mcmd::EntityCircularPattern {
axis: kittycad::types::Point3D { axis: kcmc::shared::Point3d::from(data.axis()),
x: data.axis()[0],
y: data.axis()[1],
z: data.axis()[2],
},
entity_id: geometry.id(), entity_id: geometry.id(),
center: data.center().into(), center: kcmc::shared::Point3d {
x: LengthUnit(center[0]),
y: LengthUnit(center[1]),
z: LengthUnit(center[2]),
},
num_repetitions: data.repetitions(), num_repetitions: data.repetitions(),
arc_degrees: data.arc_degrees(), arc_degrees: data.arc_degrees(),
rotate_duplicates: data.rotate_duplicates(), rotate_duplicates: data.rotate_duplicates(),
}, }),
) )
.await?; .await?;
let kittycad::types::OkWebSocketResponseData::Modeling { let OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::EntityCircularPattern { data: pattern_info }, modeling_response: OkModelingCmdResponse::EntityCircularPattern(pattern_info),
} = &resp } = &resp
else { else {
return Err(KclError::Engine(KclErrorDetails { return Err(KclError::Engine(KclErrorDetails {

View File

@ -2,7 +2,11 @@
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::ModelingCmd; use kcmc::each_cmd as mcmd;
use kcmc::length_unit::LengthUnit;
use kcmc::shared::Angle;
use kcmc::ModelingCmd;
use kittycad_modeling_cmds::{self as kcmc};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -74,7 +78,7 @@ pub enum RevolveAxisAndOrigin {
impl RevolveAxisAndOrigin { impl RevolveAxisAndOrigin {
/// Get the axis and origin. /// Get the axis and origin.
pub fn axis_and_origin(&self) -> Result<(kittycad::types::Point3D, kittycad::types::Point3D), KclError> { pub fn axis_and_origin(&self) -> Result<(kcmc::shared::Point3d<f64>, kcmc::shared::Point3d<LengthUnit>), KclError> {
let (axis, origin) = match self { let (axis, origin) = match self {
RevolveAxisAndOrigin::X => ([1.0, 0.0, 0.0], [0.0, 0.0, 0.0]), RevolveAxisAndOrigin::X => ([1.0, 0.0, 0.0], [0.0, 0.0, 0.0]),
RevolveAxisAndOrigin::Y => ([0.0, 1.0, 0.0], [0.0, 0.0, 0.0]), RevolveAxisAndOrigin::Y => ([0.0, 1.0, 0.0], [0.0, 0.0, 0.0]),
@ -86,15 +90,15 @@ impl RevolveAxisAndOrigin {
}; };
Ok(( Ok((
kittycad::types::Point3D { kcmc::shared::Point3d {
x: axis[0], x: axis[0],
y: axis[1], y: axis[1],
z: axis[2], z: axis[2],
}, },
kittycad::types::Point3D { kcmc::shared::Point3d {
x: origin[0], x: LengthUnit(origin[0]),
y: origin[1], y: LengthUnit(origin[1]),
z: origin[2], z: LengthUnit(origin[2]),
}, },
)) ))
} }
@ -263,7 +267,7 @@ async fn inner_revolve(
} }
} }
let angle = kittycad::types::Angle::from_degrees(data.angle.unwrap_or(360.0)); let angle = Angle::from_degrees(data.angle.unwrap_or(360.0));
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
match data.axis { match data.axis {
@ -271,14 +275,14 @@ async fn inner_revolve(
let (axis, origin) = axis.axis_and_origin()?; let (axis, origin) = axis.axis_and_origin()?;
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::Revolve { ModelingCmd::from(mcmd::Revolve {
angle, angle,
target: sketch_group.id, target: sketch_group.id.into(),
axis, axis,
origin, origin,
tolerance: data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units)), tolerance: LengthUnit(data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
axis_is_2d: true, axis_is_2d: true,
}, }),
) )
.await?; .await?;
} }
@ -289,12 +293,12 @@ async fn inner_revolve(
}; };
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::RevolveAboutEdge { ModelingCmd::from(mcmd::RevolveAboutEdge {
angle, angle,
target: sketch_group.id, target: sketch_group.id.into(),
edge_id, edge_id,
tolerance: data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units)), tolerance: LengthUnit(data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
}, }),
) )
.await?; .await?;
} }

View File

@ -251,7 +251,7 @@ fn inner_segment_angle(tag: &TagIdentifier, exec_state: &mut ExecState, args: Ar
let result = between(path.from.into(), path.to.into()); let result = between(path.from.into(), path.to.into());
Ok(result.degrees()) Ok(result.to_degrees())
} }
/// Returns the angle to match the given length for x. /// Returns the angle to match the given length for x.

View File

@ -2,7 +2,10 @@
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::ModelingCmd; use kcmc::each_cmd as mcmd;
use kcmc::length_unit::LengthUnit;
use kcmc::ModelingCmd;
use kittycad_modeling_cmds as kcmc;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -230,12 +233,12 @@ async fn inner_shell(
args.batch_modeling_cmd( args.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
ModelingCmd::Solid3DShellFace { ModelingCmd::from(mcmd::Solid3dShellFace {
hollow: false, hollow: false,
face_ids, face_ids,
object_id: extrude_groups[0].id, object_id: extrude_groups[0].id,
shell_thickness: data.thickness, shell_thickness: LengthUnit(data.thickness),
}, }),
) )
.await?; .await?;
@ -316,12 +319,12 @@ async fn inner_hollow(
args.batch_modeling_cmd( args.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
ModelingCmd::Solid3DShellFace { ModelingCmd::from(mcmd::Solid3dShellFace {
hollow: true, hollow: true,
face_ids: Vec::new(), // This is empty because we want to hollow the entire object. face_ids: Vec::new(), // This is empty because we want to hollow the entire object.
object_id: extrude_group.id, object_id: extrude_group.id,
shell_thickness: thickness, shell_thickness: LengthUnit(thickness),
}, }),
) )
.await?; .await?;

View File

@ -4,7 +4,13 @@ use std::collections::HashMap;
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::{Angle, ModelingCmd, Point3D}; use kcmc::each_cmd as mcmd;
use kcmc::length_unit::LengthUnit;
use kcmc::shared::Angle;
use kcmc::shared::Point2d as KPoint2d; // Point2d is already defined in this pkg, to impl ts_rs traits.
use kcmc::ModelingCmd;
use kittycad_modeling_cmds as kcmc;
use kittycad_modeling_cmds::shared::PathSegment;
use parse_display::{Display, FromStr}; use parse_display::{Display, FromStr};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -124,17 +130,13 @@ async fn inner_line_to(
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::ExtendPath { ModelingCmd::from(mcmd::ExtendPath {
path: sketch_group.id, path: sketch_group.id.into(),
segment: kittycad::types::PathSegment::Line { segment: PathSegment::Line {
end: Point3D { end: KPoint2d::from(to).with_z(0.0).map(LengthUnit),
x: to[0],
y: to[1],
z: 0.0,
},
relative: false, relative: false,
}, },
}, }),
) )
.await?; .await?;
@ -297,17 +299,13 @@ async fn inner_line(
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::ExtendPath { ModelingCmd::from(mcmd::ExtendPath {
path: sketch_group.id, path: sketch_group.id.into(),
segment: kittycad::types::PathSegment::Line { segment: PathSegment::Line {
end: Point3D { end: KPoint2d::from(delta).with_z(0.0).map(LengthUnit),
x: delta[0],
y: delta[1],
z: 0.0,
},
relative: true, relative: true,
}, },
}, }),
) )
.await?; .await?;
@ -484,17 +482,13 @@ async fn inner_angled_line(
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::ExtendPath { ModelingCmd::from(mcmd::ExtendPath {
path: sketch_group.id, path: sketch_group.id.into(),
segment: kittycad::types::PathSegment::Line { segment: PathSegment::Line {
end: Point3D { end: KPoint2d::from(delta).with_z(0.0).map(LengthUnit),
x: delta[0],
y: delta[1],
z: 0.0,
},
relative, relative,
}, },
}, }),
) )
.await?; .await?;
@ -1192,14 +1186,14 @@ async fn start_sketch_on_plane(data: PlaneData, args: &Args) -> Result<Box<Plane
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::MakePlane { ModelingCmd::from(mcmd::MakePlane {
clobber: false, clobber: false,
origin: (*origin).into(), origin: (*origin).into(),
size: 60.0, size: LengthUnit(60.0),
x_axis: (*x_axis).into(), x_axis: (*x_axis).into(),
y_axis: (*y_axis).into(), y_axis: (*y_axis).into(),
hide: Some(true), hide: Some(true),
}, }),
) )
.await?; .await?;
@ -1275,7 +1269,7 @@ pub(crate) async fn inner_start_profile_at(
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::EnableSketchMode { ModelingCmd::from(mcmd::EnableSketchMode {
animated: false, animated: false,
ortho: false, ortho: false,
entity_id: sketch_surface.id(), entity_id: sketch_surface.id(),
@ -1286,24 +1280,21 @@ pub(crate) async fn inner_start_profile_at(
} else { } else {
None None
}, },
}, }),
) )
.await?; .await?;
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
let path_id = uuid::Uuid::new_v4(); let path_id = uuid::Uuid::new_v4();
args.batch_modeling_cmd(path_id, ModelingCmd::StartPath {}).await?; args.batch_modeling_cmd(path_id, ModelingCmd::from(mcmd::StartPath {}))
.await?;
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::MovePathPen { ModelingCmd::from(mcmd::MovePathPen {
path: path_id, path: path_id.into(),
to: Point3D { to: KPoint2d::from(to).with_z(0.0).map(LengthUnit),
x: to[0], }),
y: to[1],
z: 0.0,
},
},
) )
.await?; .await?;
@ -1466,17 +1457,20 @@ pub(crate) async fn inner_close(
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::ClosePath { ModelingCmd::from(mcmd::ClosePath {
path_id: sketch_group.id, path_id: sketch_group.id,
}, }),
) )
.await?; .await?;
// If we are sketching on a plane we can close the sketch group now. // If we are sketching on a plane we can close the sketch group now.
if let SketchSurface::Plane(_) = sketch_group.on { if let SketchSurface::Plane(_) = sketch_group.on {
// We were on a plane, disable the sketch mode. // We were on a plane, disable the sketch mode.
args.batch_modeling_cmd(uuid::Uuid::new_v4(), kittycad::types::ModelingCmd::SketchModeDisable {}) args.batch_modeling_cmd(
.await?; uuid::Uuid::new_v4(),
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
)
.await?;
} }
let current_path = Path::ToPoint { let current_path = Path::ToPoint {
@ -1600,16 +1594,16 @@ pub(crate) async fn inner_arc(
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::ExtendPath { ModelingCmd::from(mcmd::ExtendPath {
path: sketch_group.id, path: sketch_group.id.into(),
segment: kittycad::types::PathSegment::Arc { segment: PathSegment::Arc {
start: angle_start, start: angle_start,
end: angle_end, end: angle_end,
center: center.into(), center: KPoint2d::from(center).map(LengthUnit),
radius, radius: LengthUnit(radius),
relative: false, relative: false,
}, },
}, }),
) )
.await?; .await?;
@ -1715,7 +1709,7 @@ async fn inner_tangential_arc(
)); ));
// make sure the arc center is on the correct side to guarantee deterministic behavior // make sure the arc center is on the correct side to guarantee deterministic behavior
// note the engine automatically rejects an offset of zero, if we want to flag that at KCL too to avoid engine errors // note the engine automatically rejects an offset of zero, if we want to flag that at KCL too to avoid engine errors
let ccw = offset.degrees() > 0.0; let ccw = offset.to_degrees() > 0.0;
let tangent_to_arc_start_angle = if ccw { let tangent_to_arc_start_angle = if ccw {
// CCW turn // CCW turn
Angle::from_degrees(-90.0) Angle::from_degrees(-90.0)
@ -1731,10 +1725,13 @@ async fn inner_tangential_arc(
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::ExtendPath { ModelingCmd::from(mcmd::ExtendPath {
path: sketch_group.id, path: sketch_group.id.into(),
segment: kittycad::types::PathSegment::TangentialArc { radius, offset }, segment: PathSegment::TangentialArc {
}, radius: LengthUnit(radius),
offset,
},
}),
) )
.await?; .await?;
(center, to.into(), ccw) (center, to.into(), ccw)
@ -1766,17 +1763,13 @@ async fn inner_tangential_arc(
} }
fn tan_arc_to(sketch_group: &SketchGroup, to: &[f64; 2]) -> ModelingCmd { fn tan_arc_to(sketch_group: &SketchGroup, to: &[f64; 2]) -> ModelingCmd {
ModelingCmd::ExtendPath { ModelingCmd::from(mcmd::ExtendPath {
path: sketch_group.id, path: sketch_group.id.into(),
segment: kittycad::types::PathSegment::TangentialArcTo { segment: PathSegment::TangentialArcTo {
angle_snap_increment: None, angle_snap_increment: None,
to: Point3D { to: KPoint2d::from(*to).with_z(0.0).map(LengthUnit),
x: to[0],
y: to[1],
z: 0.0,
},
}, },
} })
} }
/// Draw a tangential arc to a specific point. /// Draw a tangential arc to a specific point.
@ -1936,7 +1929,7 @@ async fn inner_tangential_arc_to_relative(
metadata: args.source_range.into(), metadata: args.source_range.into(),
}, },
}, },
center: dbg!(result.center), center: result.center,
ccw: result.ccw > 0, ccw: result.ccw > 0,
}; };
@ -2009,27 +2002,15 @@ async fn inner_bezier_curve(
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::ExtendPath { ModelingCmd::from(mcmd::ExtendPath {
path: sketch_group.id, path: sketch_group.id.into(),
segment: kittycad::types::PathSegment::Bezier { segment: PathSegment::Bezier {
control_1: Point3D { control1: KPoint2d::from(data.control1).with_z(0.0).map(LengthUnit),
x: data.control1[0], control2: KPoint2d::from(data.control2).with_z(0.0).map(LengthUnit),
y: data.control1[1], end: KPoint2d::from(delta).with_z(0.0).map(LengthUnit),
z: 0.0,
},
control_2: Point3D {
x: data.control2[0],
y: data.control2[1],
z: 0.0,
},
end: Point3D {
x: delta[0],
y: delta[1],
z: 0.0,
},
relative, relative,
}, },
}, }),
) )
.await?; .await?;
@ -2106,10 +2087,10 @@ async fn inner_hole(
for hole_sketch_group in hole_sketch_groups { for hole_sketch_group in hole_sketch_groups {
args.batch_modeling_cmd( args.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
ModelingCmd::Solid2DAddHole { ModelingCmd::from(mcmd::Solid2dAddHole {
object_id: sketch_group.id, object_id: sketch_group.id,
hole_id: hole_sketch_group.id, hole_id: hole_sketch_group.id,
}, }),
) )
.await?; .await?;
@ -2117,10 +2098,10 @@ async fn inner_hole(
// we also hide the source hole since its essentially "consumed" by this operation // we also hide the source hole since its essentially "consumed" by this operation
args.batch_modeling_cmd( args.batch_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
ModelingCmd::ObjectVisible { ModelingCmd::from(mcmd::ObjectVisible {
object_id: hole_sketch_group.id, object_id: hole_sketch_group.id,
hidden: true, hidden: true,
}, }),
) )
.await?; .await?;
} }

View File

@ -1,6 +1,6 @@
use std::f64::consts::PI; use std::f64::consts::PI;
use kittycad::types::Angle; use kittycad_modeling_cmds::shared::Angle;
use crate::{ use crate::{
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
@ -16,7 +16,7 @@ pub fn between(a: Point2d, b: Point2d) -> Angle {
/// Normalize the angle /// Normalize the angle
pub fn normalize(angle: Angle) -> Angle { pub fn normalize(angle: Angle) -> Angle {
let deg = angle.degrees(); let deg = angle.to_degrees();
let result = ((deg % 360.0) + 360.0) % 360.0; let result = ((deg % 360.0) + 360.0) % 360.0;
Angle::from_degrees(if result > 180.0 { result - 360.0 } else { result }) Angle::from_degrees(if result > 180.0 { result - 360.0 } else { result })
} }
@ -37,8 +37,8 @@ pub fn normalize(angle: Angle) -> Angle {
/// ); /// );
/// ``` /// ```
pub fn delta(from_angle: Angle, to_angle: Angle) -> Angle { pub fn delta(from_angle: Angle, to_angle: Angle) -> Angle {
let norm_from_angle = normalize_rad(from_angle.radians()); let norm_from_angle = normalize_rad(from_angle.to_radians());
let norm_to_angle = normalize_rad(to_angle.radians()); let norm_to_angle = normalize_rad(to_angle.to_radians());
let provisional = norm_to_angle - norm_from_angle; let provisional = norm_to_angle - norm_from_angle;
if provisional > -PI && provisional <= PI { if provisional > -PI && provisional <= PI {
@ -50,7 +50,7 @@ pub fn delta(from_angle: Angle, to_angle: Angle) -> Angle {
if provisional < -PI { if provisional < -PI {
return Angle::from_radians(provisional + 2.0 * PI); return Angle::from_radians(provisional + 2.0 * PI);
} }
Angle::ZERO Angle::default()
} }
pub fn clockwise_sign(points: &[Point2d]) -> i32 { pub fn clockwise_sign(points: &[Point2d]) -> i32 {
@ -183,7 +183,7 @@ fn offset_line(offset: f64, p1: Point2d, p2: Point2d) -> [Point2d; 2] {
} }
pub fn get_y_component(angle: Angle, x: f64) -> Point2d { pub fn get_y_component(angle: Angle, x: f64) -> Point2d {
let normalised_angle = ((angle.degrees() % 360.0) + 360.0) % 360.0; // between 0 and 360 let normalised_angle = ((angle.to_degrees() % 360.0) + 360.0) % 360.0; // between 0 and 360
let y = x * f64::tan(normalised_angle.to_radians()); let y = x * f64::tan(normalised_angle.to_radians());
let sign = if normalised_angle > 90.0 && normalised_angle <= 270.0 { let sign = if normalised_angle > 90.0 && normalised_angle <= 270.0 {
-1.0 -1.0
@ -194,7 +194,7 @@ pub fn get_y_component(angle: Angle, x: f64) -> Point2d {
} }
pub fn get_x_component(angle: Angle, y: f64) -> Point2d { pub fn get_x_component(angle: Angle, y: f64) -> Point2d {
let normalised_angle = ((angle.degrees() % 360.0) + 360.0) % 360.0; // between 0 and 360 let normalised_angle = ((angle.to_degrees() % 360.0) + 360.0) % 360.0; // between 0 and 360
let x = y / f64::tan(normalised_angle.to_radians()); let x = y / f64::tan(normalised_angle.to_radians());
let sign = if normalised_angle > 180.0 && normalised_angle <= 360.0 { let sign = if normalised_angle > 180.0 && normalised_angle <= 360.0 {
-1.0 -1.0
@ -205,8 +205,8 @@ pub fn get_x_component(angle: Angle, y: f64) -> Point2d {
} }
pub fn arc_center_and_end(from: Point2d, start_angle: Angle, end_angle: Angle, radius: f64) -> (Point2d, Point2d) { pub fn arc_center_and_end(from: Point2d, start_angle: Angle, end_angle: Angle, radius: f64) -> (Point2d, Point2d) {
let start_angle = start_angle.radians(); let start_angle = start_angle.to_radians();
let end_angle = end_angle.radians(); let end_angle = end_angle.to_radians();
let center = Point2d { let center = Point2d {
x: -1.0 * (radius * start_angle.cos() - from.x), x: -1.0 * (radius * start_angle.cos() - from.x),
@ -304,7 +304,7 @@ mod tests {
assert_eq!(results, expected); assert_eq!(results, expected);
let result = get_y_component(Angle::ZERO, 1.0); let result = get_y_component(Angle::zero(), 1.0);
assert_eq!(result.x as i32, 1); assert_eq!(result.x as i32, 1);
assert_eq!(result.y as i32, 0); assert_eq!(result.y as i32, 0);
@ -334,7 +334,7 @@ mod tests {
assert_eq!(results, expected); assert_eq!(results, expected);
let result = get_x_component(Angle::ZERO, 1.0); let result = get_x_component(Angle::zero(), 1.0);
assert!(result.x > 100000.0); assert!(result.x > 100000.0);
assert_eq!(result.y as i32, 1); assert_eq!(result.y as i32, 1);
@ -355,7 +355,7 @@ mod tests {
fn test_arc_center_and_end() { fn test_arc_center_and_end() {
let (center, end) = super::arc_center_and_end( let (center, end) = super::arc_center_and_end(
super::Point2d { x: 0.0, y: 0.0 }, super::Point2d { x: 0.0, y: 0.0 },
Angle::ZERO, Angle::zero(),
Angle::from_degrees(90.0), Angle::from_degrees(90.0),
1.0, 1.0,
); );
@ -366,7 +366,7 @@ mod tests {
let (center, end) = super::arc_center_and_end( let (center, end) = super::arc_center_and_end(
super::Point2d { x: 0.0, y: 0.0 }, super::Point2d { x: 0.0, y: 0.0 },
Angle::ZERO, Angle::zero(),
Angle::from_degrees(180.0), Angle::from_degrees(180.0),
1.0, 1.0,
); );
@ -377,7 +377,7 @@ mod tests {
let (center, end) = super::arc_center_and_end( let (center, end) = super::arc_center_and_end(
super::Point2d { x: 0.0, y: 0.0 }, super::Point2d { x: 0.0, y: 0.0 },
Angle::ZERO, Angle::zero(),
Angle::from_degrees(180.0), Angle::from_degrees(180.0),
10.0, 10.0,
); );
@ -397,8 +397,8 @@ mod tests {
SourceRange(Default::default()), SourceRange(Default::default()),
) )
.unwrap(); .unwrap();
assert_eq!(angle_start.degrees().round(), 0.0); assert_eq!(angle_start.to_degrees().round(), 0.0);
assert_eq!(angle_end.degrees().round(), 90.0); assert_eq!(angle_end.to_degrees().round(), 90.0);
let (angle_start, angle_end) = super::arc_angles( let (angle_start, angle_end) = super::arc_angles(
super::Point2d { x: 0.0, y: 0.0 }, super::Point2d { x: 0.0, y: 0.0 },
@ -408,8 +408,8 @@ mod tests {
SourceRange(Default::default()), SourceRange(Default::default()),
) )
.unwrap(); .unwrap();
assert_eq!(angle_start.degrees().round(), 0.0); assert_eq!(angle_start.to_degrees().round(), 0.0);
assert_eq!(angle_end.degrees().round(), 180.0); assert_eq!(angle_end.to_degrees().round(), 180.0);
let (angle_start, angle_end) = super::arc_angles( let (angle_start, angle_end) = super::arc_angles(
super::Point2d { x: 0.0, y: 0.0 }, super::Point2d { x: 0.0, y: 0.0 },
@ -419,8 +419,8 @@ mod tests {
SourceRange(Default::default()), SourceRange(Default::default()),
) )
.unwrap(); .unwrap();
assert_eq!(angle_start.degrees().round(), 0.0); assert_eq!(angle_start.to_degrees().round(), 0.0);
assert_eq!(angle_end.degrees().round(), 180.0); assert_eq!(angle_end.to_degrees().round(), 180.0);
let result = super::arc_angles( let result = super::arc_angles(
super::Point2d { x: 0.0, y: 5.0 }, super::Point2d { x: 0.0, y: 5.0 },
@ -435,8 +435,8 @@ mod tests {
} else { } else {
panic!("Expected error"); panic!("Expected error");
} }
assert_eq!(angle_start.degrees().round(), 0.0); assert_eq!(angle_start.to_degrees().round(), 0.0);
assert_eq!(angle_end.degrees().round(), 180.0); assert_eq!(angle_end.to_degrees().round(), 180.0);
} }
} }
@ -631,11 +631,11 @@ pub fn get_tangential_arc_to_info(input: TangentialArcInfoInput) -> TangentialAr
let arc_mid_angle = (arc_mid_point[1] - center[1]).atan2(arc_mid_point[0] - center[0]); let arc_mid_angle = (arc_mid_point[1] - center[1]).atan2(arc_mid_point[0] - center[0]);
let start_to_mid_arc_length = radius let start_to_mid_arc_length = radius
* delta(Angle::from_radians(start_angle), Angle::from_radians(arc_mid_angle)) * delta(Angle::from_radians(start_angle), Angle::from_radians(arc_mid_angle))
.radians() .to_radians()
.abs(); .abs();
let mid_to_end_arc_length = radius let mid_to_end_arc_length = radius
* delta(Angle::from_radians(arc_mid_angle), Angle::from_radians(end_angle)) * delta(Angle::from_radians(arc_mid_angle), Angle::from_radians(end_angle))
.radians() .to_radians()
.abs(); .abs();
let arc_length = start_to_mid_arc_length + mid_to_end_arc_length; let arc_length = start_to_mid_arc_length + mid_to_end_arc_length;

View File

@ -3,7 +3,9 @@ use kcl_lib::{
ast::{modify::modify_ast_for_sketch, types::Program}, ast::{modify::modify_ast_for_sketch, types::Program},
executor::{ExecutorContext, KclValue, PlaneType, SketchGroup, SourceRange}, executor::{ExecutorContext, KclValue, PlaneType, SketchGroup, SourceRange},
}; };
use kittycad::types::{ModelingCmd, Point3D}; use kittycad_modeling_cmds::shared::Point3d;
use kittycad_modeling_cmds::ModelingCmd;
use kittycad_modeling_cmds::{each_cmd as mcmd, length_unit::LengthUnit};
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
/// Setup the engine and parse code for an ast. /// Setup the engine and parse code for an ast.
@ -52,14 +54,14 @@ async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, uuid
.send_modeling_cmd( .send_modeling_cmd(
plane_id, plane_id,
SourceRange::default(), SourceRange::default(),
ModelingCmd::MakePlane { ModelingCmd::from(mcmd::MakePlane {
clobber: false, clobber: false,
origin: Point3D { x: 0.0, y: 0.0, z: 0.0 }, origin: Point3d::default(),
size: 60.0, size: LengthUnit(60.0),
x_axis: Point3D { x: 1.0, y: 0.0, z: 0.0 }, x_axis: Point3d { x: 1.0, y: 0.0, z: 0.0 },
y_axis: Point3D { x: 0.0, y: 1.0, z: 0.0 }, y_axis: Point3d { x: 0.0, y: 1.0, z: 0.0 },
hide: Some(true), hide: Some(true),
}, }),
) )
.await?; .await?;
@ -70,13 +72,13 @@ async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, uuid
.send_modeling_cmd( .send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
SourceRange::default(), SourceRange::default(),
ModelingCmd::EnableSketchMode { ModelingCmd::from(mcmd::EnableSketchMode {
animated: false, animated: false,
ortho: true, ortho: true,
entity_id: plane_id, entity_id: plane_id,
planar_normal: Some(Point3D { x: 0.0, y: 0.0, z: 1.0 }), planar_normal: Some(Point3d { x: 0.0, y: 0.0, z: 1.0 }),
adjust_camera: false, adjust_camera: false,
}, }),
) )
.await?; .await?;