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:
196
src/wasm-lib/Cargo.lock
generated
196
src/wasm-lib/Cargo.lock
generated
@ -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",
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
@ -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),
|
||||||
|
@ -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();
|
||||||
|
@ -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,
|
})),
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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],
|
||||||
|
@ -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?;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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?;
|
||||||
|
|
||||||
|
@ -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?;
|
||||||
}
|
}
|
||||||
|
@ -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],
|
||||||
|
@ -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?;
|
||||||
|
|
||||||
|
@ -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",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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?;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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?;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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?;
|
||||||
|
|
||||||
|
@ -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?;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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?;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user