Compare commits

...

13 Commits

Author SHA1 Message Date
888104080e bump v0.9.0 (#673) 2023-09-21 10:38:40 +10:00
b6769889e3 Handle relative paths at kcl level (#506)
* handle relative paths at kcl level

* fmt

* update kittycad

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* bump

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2023-09-21 10:36:26 +10:00
a32258dac4 Engine manager can be cloned (#671) 2023-09-20 16:22:47 -07:00
18dbbad244 Use an actor to manage the Tokio engine connection (#669)
* Use an actor to manage the Tokio engine connection

This means EngineManager trait's methods take &self not &mut self, and the tokio implementation can be cloned.

* Clean up code
2023-09-20 16:59:03 -05:00
b67c16cc9d Benchmark for KCL parser (#664)
* KCL benchmarks

* CI for benchmarks

* More specific name for benchmark

* Benchmark the right directory

* Format
2023-09-20 13:15:28 -05:00
ad482641ef Unit test for zero-param programs (#663) 2023-09-20 10:51:49 -05:00
9ee24845a1 Bump to v0.8.2 (#656)
Co-authored-by: Frank Noirot <frank@kittycad.io>
2023-09-20 14:41:23 +00:00
e69d263252 Revert swapping setCode for deferredSetCode in App (#662)
This fix was implemented in https://github.com/KittyCAD/modeling-app/pull/649
to try and address https://github.com/KittyCAD/modeling-app/issues/545.
However, we need to run `setCode` to execute immediately here or else
files will not render in the 3D view when opened, as reported by @pierremtb.

Reverting for now to allow for a timely release https://github.com/KittyCAD/modeling-app/pull/656

Signed-off-by: Frank Noirot <frank@kittycad.io>
2023-09-20 10:32:36 -04:00
111738f38e Fix the debug panel overflow (#653) 2023-09-20 05:36:29 -04:00
e34501cc5a Ast fixes (#650)
* allow using member expressions for memory items

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes pi in binary expressions

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add fix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-19 16:05:53 -07:00
c767c1c3a6 Replace setCode with deferredSetCode in App (#649)
* Replace `setCode` with `deferredSetCode` in App

* Remove unused OpenFileButton component
2023-09-19 22:07:54 +00:00
e399a8f938 Franknoirot/ux papercuts 4 (#640)
* Add Cmd + / to support windows, update walkthrough

* Fix #628 dark mode <select> bg color

* Fix #621 by narrowing margins and moving to left

---------

Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2023-09-19 18:06:13 -04:00
59d5f2524a fix function inside show not executing (#641)
* start of heap changes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix show bug

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* cleanup

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* new images

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2023-09-19 14:20:14 -07:00
41 changed files with 1273 additions and 213 deletions

View File

@ -54,4 +54,4 @@ jobs:
- name: Run clippy
run: |
cd "${{ matrix.dir }}"
cargo clippy --all --tests -- -D warnings
cargo clippy --all --tests --benches -- -D warnings

37
.github/workflows/cargo-criterion.yml vendored Normal file
View File

@ -0,0 +1,37 @@
on:
push:
branches:
- main
paths:
- '**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-criterion.yml
pull_request:
paths:
- '**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-criterion.yml
workflow_dispatch:
permissions: read-all
name: cargo criterion
jobs:
cargocriterion:
name: cargo criterion
runs-on: ubuntu-latest-8-cores
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: |
cargo install cargo-criterion
- name: Rust Cache
uses: Swatinem/rust-cache@v2.6.1
- name: Benchmark kcl library
shell: bash
run: |-
cd src/wasm-lib/kcl; cargo criterion

2
.gitignore vendored
View File

@ -22,6 +22,8 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
src/wasm-lib/.idea
# rust
src/wasm-lib/target
src/wasm-lib/bindings

View File

@ -1,6 +1,6 @@
{
"name": "untitled-app",
"version": "0.8.1",
"version": "0.9.0",
"private": true,
"dependencies": {
"@codemirror/autocomplete": "^6.9.0",
@ -10,7 +10,7 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.13",
"@headlessui/tailwindcss": "^0.2.0",
"@kittycad/lib": "^0.0.37",
"@kittycad/lib": "^0.0.38",
"@lezer/javascript": "^1.4.7",
"@open-rpc/client-js": "^1.8.1",
"@react-hook/resize-observer": "^1.2.6",
@ -65,7 +65,7 @@
"pretest": "yarn remove-importmeta",
"test": "vitest --mode development",
"test:nowatch": "vitest run --mode development",
"test:rust": "(cd src/wasm-lib && cargo test --all && cargo clippy --all --tests)",
"test:rust": "(cd src/wasm-lib && cargo test --all && cargo clippy --all --tests --benches)",
"test:cov": "vitest run --coverage --mode development",
"simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &",
"simpleserver": "yarn pretest && http-server ./public --cors -p 3000",

26
src-tauri/Cargo.lock generated
View File

@ -2182,6 +2182,17 @@ dependencies = [
"thiserror",
]
[[package]]
name = "os_info"
version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e"
dependencies = [
"log",
"serde",
"winapi",
]
[[package]]
name = "overload"
version = "0.1.1"
@ -3469,6 +3480,19 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "sys-locale"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8a11bd9c338fdba09f7881ab41551932ad42e405f61d01e8406baea71c07aee"
dependencies = [
"js-sys",
"libc",
"wasm-bindgen",
"web-sys",
"windows-sys 0.45.0",
]
[[package]]
name = "system-deps"
version = "5.0.0"
@ -3604,6 +3628,7 @@ dependencies = [
"objc",
"once_cell",
"open",
"os_info",
"percent-encoding",
"rand 0.8.5",
"raw-window-handle",
@ -3616,6 +3641,7 @@ dependencies = [
"serde_repr",
"serialize-to-javascript",
"state",
"sys-locale",
"tar",
"tauri-macros",
"tauri-runtime",

View File

@ -20,7 +20,7 @@ kittycad = "0.2.25"
oauth2 = "4.4.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tauri = { version = "1.4.1", features = ["dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "updater", "devtools"] }
tauri = { version = "1.4.1", features = [ "os-all", "dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "updater", "devtools"] }
tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
tokio = { version = "1.32.0", features = ["time"] }
toml = "0.8.0"

View File

@ -8,7 +8,7 @@
},
"package": {
"productName": "kittycad-modeling",
"version": "0.8.1"
"version": "0.9.0"
},
"tauri": {
"allowlist": {
@ -36,6 +36,9 @@
"https://api.dev.kittycad.io/*"
]
},
"os": {
"all": true
},
"shell": {
"open": true
},

View File

@ -62,7 +62,7 @@ export const CommandBarProvider = ({
const CommandBar = () => {
const { commands, commandBarOpen, setCommandBarOpen } = useCommandsContext()
useHotkeys('meta+k', () => {
useHotkeys(['meta+k', 'meta+/'], () => {
if (commands.length === 0) return
setCommandBarOpen(!commandBarOpen)
})
@ -221,10 +221,10 @@ const CommandBar = () => {
<Combobox
value={selectedCommand}
onChange={handleCommandSelection}
className="rounded relative mx-auto p-2 bg-chalkboard-10 dark:bg-chalkboard-100 border dark:border-chalkboard-70 max-w-xl w-full shadow-lg"
className="relative w-full max-w-xl p-2 mx-auto border rounded shadow-lg bg-chalkboard-10 dark:bg-chalkboard-100 dark:border-chalkboard-70"
as="div"
>
<div className="flex gap-2 items-center">
<div className="flex items-center gap-2">
<ActionIcon icon={faSearch} size="xl" className="rounded-sm" />
<div>
{inSubCommand && (
@ -235,7 +235,7 @@ const CommandBar = () => {
)}
<Combobox.Input
onChange={(event) => setQuery(event.target.value)}
className="bg-transparent focus:outline-none w-full"
className="w-full bg-transparent focus:outline-none"
onKeyDown={(event) => {
if (event.metaKey && event.key === 'k')
setCommandBarOpen(false)
@ -264,12 +264,12 @@ const CommandBar = () => {
/>
</div>
</div>
<Combobox.Options static className="max-h-96 overflow-y-auto">
<Combobox.Options static className="overflow-y-auto max-h-96">
{filteredCommands?.map((commandResult) => (
<Combobox.Option
key={commandResult.item.name}
value={commandResult}
className="my-2 first:mt-4 last:mb-4 ui-active:bg-liquid-10 dark:ui-active:bg-liquid-90 py-1 px-2"
className="px-2 py-1 my-2 first:mt-4 last:mb-4 ui-active:bg-liquid-10 dark:ui-active:bg-liquid-90"
>
<p>{commandResult.item.name}</p>
{(commandResult.item as SubCommand).description && (

View File

@ -30,7 +30,11 @@ export const DebugPanel = ({ className, ...props }: CollapsiblePanelProps) => {
return (
<CollapsiblePanel
{...props}
className={'!absolute !h-auto bottom-5 right-5 ' + className}
className={
'!absolute overflow-hidden !h-auto bottom-5 right-5 ' + className
}
// header height, top-5, and bottom-5
style={{ maxHeight: 'calc(100% - 3rem - 1.25rem - 1.25rem)' }}
>
<section className="p-4 flex flex-col gap-4">
<Xyz

View File

@ -1,42 +0,0 @@
import { invoke } from '@tauri-apps/api/tauri'
import { open } from '@tauri-apps/api/dialog'
import { useStore } from '../useStore'
export const OpenFileButton = () => {
const { setCode } = useStore((s) => ({
setCode: s.setCode,
}))
const handleClick = async () => {
const selected = await open({
multiple: false,
directory: false,
filters: [
{
name: 'CAD',
extensions: ['toml'],
},
],
})
if (Array.isArray(selected)) {
// User selected multiple files
// We should not get here, since multiple is false.
} else if (selected === null) {
// User cancelled the selection
// Do nothing.
} else {
// User selected a single file
// We want to invoke our command to read the file.
const json: string = await invoke('read_toml', { path: selected })
const packageDetails = JSON.parse(json).package
if (packageDetails.main) {
const absPath = [
...selected.split('/').slice(0, -1),
packageDetails.main,
].join('/')
const file: string = await invoke('read_txt_file', { path: absPath })
setCode(file)
}
}
}
return <button onClick={() => handleClick()}>Open File</button>
}

View File

@ -31,6 +31,14 @@ body.dark {
@apply text-chalkboard-10;
}
select {
@apply bg-chalkboard-20;
}
.dark select {
@apply bg-chalkboard-90;
}
::-webkit-scrollbar {
@apply w-2 h-2 rounded-sm;
@apply bg-chalkboard-20;

View File

@ -26,7 +26,7 @@ export default function Units() {
} = useGlobalStateContext()
return (
<div className="fixed grid justify-center items-end inset-0 z-50 pointer-events-none">
<div className="fixed inset-0 z-50 grid items-end justify-start px-4 pointer-events-none">
<div
className={
'max-w-2xl flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded' +
@ -36,10 +36,11 @@ export default function Units() {
<SettingsSection
title="Camera Controls"
description="How you want to control the camera in the 3D view. Try them out above and choose the one that feels most comfortable to you."
className="my-4 last-of-type:mb-12"
>
<select
id="camera-controls"
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
className="block w-full px-3 py-1 bg-transparent border border-chalkboard-30"
value={cameraControls}
onChange={(e) => {
send({
@ -54,7 +55,7 @@ export default function Units() {
</option>
))}
</select>
<ul className="text-sm my-2 mx-4 leading-relaxed">
<ul className="mx-4 my-2 text-sm leading-relaxed">
<li>
<strong>Pan:</strong>{' '}
{cameraMouseDragGuards[cameraControls].pan.description}

View File

@ -2,6 +2,8 @@ import { faArrowRight, faXmark } from '@fortawesome/free-solid-svg-icons'
import { ActionButton } from '../../components/ActionButton'
import { onboardingPaths, useDismiss, useNextClick } from '.'
import { useStore } from '../../useStore'
import { Platform, platform } from '@tauri-apps/api/os'
import { useEffect, useState } from 'react'
export default function CmdK() {
const { buttonDownInStream } = useStore((s) => ({
@ -9,9 +11,17 @@ export default function CmdK() {
}))
const dismiss = useDismiss()
const next = useNextClick(onboardingPaths.USER_MENU)
const [platformName, setPlatformName] = useState<Platform | ''>('')
useEffect(() => {
async function getPlatform() {
setPlatformName(await platform())
}
getPlatform()
}, [setPlatformName])
return (
<div className="fixed grid justify-center items-end inset-0 z-50 pointer-events-none">
<div className="fixed inset-0 z-50 grid items-end justify-center pointer-events-none">
<div
className={
'max-w-full xl:max-w-4xl flex flex-col justify-center bg-chalkboard-10 dark:bg-chalkboard-90 p-8 rounded' +
@ -20,8 +30,17 @@ export default function CmdK() {
>
<h2 className="text-2xl">Command Bar</h2>
<p className="my-4">
Press <kbd>Cmd/Win</kbd> + <kbd>K</kbd> to open the command bar. Try
changing your theme with it.
Press{' '}
{platformName === 'win32' ? (
<>
<kbd>Win</kbd> + <kbd>/</kbd>
</>
) : (
<>
<kbd>OS</kbd> + <kbd>K</kbd>
</>
)}{' '}
to open the command bar. Try changing your theme with it.
</p>
<p className="my-4">
We are working on a command bar that will allow you to quickly see and

View File

@ -64,7 +64,7 @@ export const Settings = () => {
}
return (
<div className="body-bg fixed inset-0 z-40 overflow-auto">
<div className="fixed inset-0 z-40 overflow-auto body-bg">
<AppHeader showToolbar={false} project={loaderData?.project}>
<ActionButton
Element="link"
@ -80,9 +80,9 @@ export const Settings = () => {
Close
</ActionButton>
</AppHeader>
<div className="my-24 max-w-5xl mx-auto">
<div className="max-w-5xl mx-auto my-24">
<h1 className="text-4xl font-bold">User Settings</h1>
<p className="mt-6 max-w-2xl">
<p className="max-w-2xl mt-6">
Don't see the feature you want? Check to see if it's on{' '}
<a
href="https://github.com/KittyCAD/modeling-app/discussions"
@ -100,7 +100,7 @@ export const Settings = () => {
>
<select
id="camera-controls"
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
className="block w-full px-3 py-1 bg-transparent border border-chalkboard-30"
value={cameraControls}
onChange={(e) => {
send({
@ -115,7 +115,7 @@ export const Settings = () => {
</option>
))}
</select>
<ul className="text-sm my-2 mx-4 leading-relaxed">
<ul className="mx-4 my-2 text-sm leading-relaxed">
<li>
<strong>Pan:</strong>{' '}
{cameraMouseDragGuards[cameraControls].pan.description}
@ -136,7 +136,7 @@ export const Settings = () => {
title="Default Directory"
description="Where newly-created projects are saved on your local computer"
>
<div className="w-full flex gap-4 p-1 rounded border border-chalkboard-30">
<div className="flex w-full gap-4 p-1 border rounded border-chalkboard-30">
<input
className="flex-1 px-2 bg-transparent"
value={defaultDirectory}
@ -163,7 +163,7 @@ export const Settings = () => {
description="Name template for new projects. Use $n to include an incrementing index"
>
<input
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
className="block w-full px-3 py-1 bg-transparent border border-chalkboard-30"
defaultValue={defaultProjectName}
onBlur={(e) => {
const newValue = e.target.value.trim() || DEFAULT_PROJECT_NAME
@ -207,7 +207,7 @@ export const Settings = () => {
>
<select
id="base-unit"
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
className="block w-full px-3 py-1 bg-transparent border border-chalkboard-30"
value={baseUnit}
onChange={(e) => {
send({
@ -241,7 +241,7 @@ export const Settings = () => {
>
<select
id="settings-theme"
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
className="block w-full px-3 py-1 bg-transparent border border-chalkboard-30"
value={theme}
onChange={(e) => {
send({
@ -285,15 +285,22 @@ export const Settings = () => {
interface SettingsSectionProps extends React.PropsWithChildren {
title: string
description?: string
className?: string
}
export function SettingsSection({
title,
description,
className,
children,
}: SettingsSectionProps) {
return (
<section className="my-16 last-of-type:mb-24 grid grid-cols-2 gap-12 items-start">
<section
className={
'my-16 last-of-type:mb-24 grid grid-cols-2 gap-12 items-start ' +
className
}
>
<div className="w-80">
<h2 className="text-2xl">{title}</h2>
<p className="mt-2 text-sm">{description}</p>

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

@ -63,6 +63,12 @@ dependencies = [
"libc",
]
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
version = "0.5.0"
@ -220,6 +226,20 @@ dependencies = [
"num-traits",
]
[[package]]
name = "bigdecimal"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "454bca3db10617b88b566f205ed190aedb0e0e6dd4cad61d3988a72e8c5594cb"
dependencies = [
"autocfg",
"libm",
"num-bigint",
"num-integer",
"num-traits",
"serde",
]
[[package]]
name = "bincode"
version = "1.3.3"
@ -337,6 +357,12 @@ dependencies = [
"serde",
]
[[package]]
name = "cast"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.0.83"
@ -374,6 +400,33 @@ dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "ciborium"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
[[package]]
name = "ciborium-ll"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"
dependencies = [
"ciborium-io",
"half 1.8.2",
]
[[package]]
name = "clang-sys"
version = "1.6.1"
@ -507,6 +560,42 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "criterion"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
dependencies = [
"anes",
"cast",
"ciborium",
"clap",
"criterion-plot",
"is-terminal",
"itertools 0.10.5",
"num-traits",
"once_cell",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
dependencies = [
"cast",
"itertools 0.10.5",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.8"
@ -593,7 +682,7 @@ checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946"
[[package]]
name = "derive-docs"
version = "0.1.3"
version = "0.1.4"
dependencies = [
"convert_case",
"expectorate",
@ -606,20 +695,6 @@ dependencies = [
"syn 2.0.37",
]
[[package]]
name = "derive-docs"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fe5c5ea065cfabc5a7c5e8ed616e369fbf108c4be01e0e5609bc9846a732664"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"serde",
"serde_tokenstream",
"syn 2.0.37",
]
[[package]]
name = "diff"
version = "0.1.13"
@ -730,7 +805,7 @@ checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8"
dependencies = [
"bit_field",
"flume",
"half",
"half 2.2.1",
"lebe",
"miniz_oxide",
"rayon-core",
@ -997,6 +1072,12 @@ dependencies = [
"tracing",
]
[[package]]
name = "half"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]]
name = "half"
version = "2.2.1"
@ -1301,8 +1382,9 @@ dependencies = [
"async-trait",
"bson",
"clap",
"criterion",
"dashmap",
"derive-docs 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"derive-docs",
"expectorate",
"futures",
"itertools 0.11.0",
@ -1329,13 +1411,14 @@ dependencies = [
[[package]]
name = "kittycad"
version = "0.2.25"
version = "0.2.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9cf962b1e81a0b4eb923a727e761b40672cbacc7f5f0b75e13579d346352bc7"
checksum = "e2623ee601ce203476229df3f9d3a14664cb43e3f7455e9ac8ed91aacaa6163d"
dependencies = [
"anyhow",
"async-trait",
"base64 0.21.4",
"bigdecimal 0.4.1",
"bytes",
"chrono",
"data-encoding",
@ -1397,6 +1480,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "libm"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
@ -1620,6 +1709,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d11de466f4a3006fe8a5e7ec84e93b79c70cb992ae0aa0eb631ad2df8abfe2"
[[package]]
name = "oorandom"
version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "openapitor"
version = "0.0.9"
@ -1853,6 +1948,34 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "plotters"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
[[package]]
name = "plotters-svg"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
dependencies = [
"plotters-backend",
]
[[package]]
name = "png"
version = "0.17.10"
@ -2327,7 +2450,8 @@ version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c"
dependencies = [
"bigdecimal",
"bigdecimal 0.3.1",
"bigdecimal 0.4.1",
"bytes",
"chrono",
"dyn-clone",
@ -2867,6 +2991,16 @@ dependencies = [
"time-core",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "tinyvec"
version = "1.6.0"

View File

@ -1,7 +1,7 @@
[package]
name = "derive-docs"
description = "A tool for generating documentation from Rust derive macros"
version = "0.1.3"
version = "0.1.4"
edition = "2021"
license = "MIT"

View File

@ -212,6 +212,12 @@ fn do_stdlib_inner(
quote! {
Vec<#ty_ident>
}
} else if ty_string.starts_with("Box<") {
let ty_string = ty_string.trim_start_matches("Box<").trim_end_matches('>');
let ty_ident = format_ident!("{}", ty_string);
quote! {
#ty_ident
}
} else {
let ty_ident = format_ident!("{}", ty_string);
quote! {
@ -250,7 +256,15 @@ fn do_stdlib_inner(
.replace("Result < ", "")
.replace(", KclError >", "");
let return_type = if !ret_ty_string.is_empty() {
let ret_ty_string = ret_ty_string.trim().to_string();
let ret_ty_string = if ret_ty_string.starts_with("Box <") {
ret_ty_string
.trim_start_matches("Box <")
.trim_end_matches('>')
.trim()
.to_string()
} else {
ret_ty_string.trim().to_string()
};
let ret_ty_ident = format_ident!("{}", ret_ty_string);
let ret_ty_string = clean_type(&ret_ty_string);
quote! {
@ -475,6 +489,9 @@ fn clean_type(t: &str) -> String {
if t.starts_with("Vec<") {
t = t.replace("Vec<", "[").replace('>', "]");
}
if t.starts_with("Box<") {
t = t.replace("Box<", "").replace('>', "");
}
if t == "f64" {
return "number".to_string();
@ -564,4 +581,26 @@ mod tests {
assert!(errors.is_empty());
expectorate::assert_contents("tests/show.gen", &openapitor::types::get_text_fmt(&item).unwrap());
}
#[test]
fn test_stdlib_box() {
let (item, errors) = do_stdlib(
quote! {
name = "show",
},
quote! {
fn inner_show(
/// The args to do shit to.
args: Box<f64>
) -> Box<f64> {
args
}
},
)
.unwrap();
let _expected = quote! {};
assert!(errors.is_empty());
expectorate::assert_contents("tests/box.gen", &openapitor::types::get_text_fmt(&item).unwrap());
}
}

View File

@ -0,0 +1,70 @@
#[allow(non_camel_case_types, missing_docs)]
#[doc = "Std lib function: show"]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, schemars :: JsonSchema, ts_rs :: TS)]
#[ts(export)]
pub(crate) struct Show {}
#[allow(non_upper_case_globals, missing_docs)]
#[doc = "Std lib function: show"]
pub(crate) const Show: Show = Show {};
impl crate::docs::StdLibFn for Show {
fn name(&self) -> String {
"show".to_string()
}
fn summary(&self) -> String {
"".to_string()
}
fn description(&self) -> String {
"".to_string()
}
fn tags(&self) -> Vec<String> {
vec![]
}
fn args(&self) -> Vec<crate::docs::StdLibFnArg> {
let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = true;
let mut generator = schemars::gen::SchemaGenerator::new(settings);
vec![crate::docs::StdLibFnArg {
name: "args".to_string(),
type_: "number".to_string(),
schema: f64::json_schema(&mut generator),
required: true,
}]
}
fn return_value(&self) -> Option<crate::docs::StdLibFnArg> {
let mut settings = schemars::gen::SchemaSettings::openapi3();
settings.inline_subschemas = true;
let mut generator = schemars::gen::SchemaGenerator::new(settings);
Some(crate::docs::StdLibFnArg {
name: "".to_string(),
type_: "number".to_string(),
schema: f64::json_schema(&mut generator),
required: true,
})
}
fn unpublished(&self) -> bool {
false
}
fn deprecated(&self) -> bool {
false
}
fn std_lib_fn(&self) -> crate::std::StdFn {
show
}
fn clone_box(&self) -> Box<dyn crate::docs::StdLibFn> {
Box::new(self.clone())
}
}
fn inner_show(#[doc = r" The args to do shit to."] args: Box<f64>) -> Box<f64> {
args
}

View File

@ -12,8 +12,8 @@ anyhow = { version = "1.0.75", features = ["backtrace"] }
async-trait = "0.1.73"
clap = { version = "4.4.3", features = ["cargo", "derive", "env", "unicode"], optional = true }
dashmap = "5.5.3"
derive-docs = { version = "0.1.3" }
#derive-docs = { path = "../derive-docs" }
#derive-docs = { version = "0.1.4" }
derive-docs = { path = "../derive-docs" }
kittycad = { version = "0.2.25", default-features = false, features = ["js"] }
lazy_static = "1.4.0"
parse-display = "0.8.2"
@ -50,7 +50,12 @@ panic = "abort"
debug = true
[dev-dependencies]
criterion = "0.5.1"
expectorate = "1.0.7"
itertools = "0.11.0"
pretty_assertions = "1.4.0"
tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros", "time"] }
[[bench]]
name = "compiler_benchmark"
harness = false

View File

@ -0,0 +1,27 @@
use criterion::{criterion_group, criterion_main, Criterion};
pub fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("parse + lex cube program", |b| b.iter(lex_and_parse_cube));
}
fn lex_and_parse_cube() {
let program = r#"
fn cube = (pos, scale) => {
const sg = startSketchAt(pos)
|> line([0, scale], %)
|> line([scale, 0], %)
|> line([0, -scale], %)
return sg
}
const b1 = cube([0,0], 10)
const pt1 = b1[0]
show(b1)"#;
let tokens = kcl_lib::tokeniser::lexer(program);
let parser = kcl_lib::parser::Parser::new(tokens);
parser.ast().unwrap();
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

View File

@ -871,6 +871,11 @@ impl CallExpression {
match &self.function {
Function::StdLib { func } => {
/* let source_range: SourceRange = self.into();
println!(
"Calling stdlib function: {}, source_range: {:?}, args: {:?}",
fn_name, source_range, fn_args
);*/
// Attempt to call the function.
let mut args = crate::std::Args::new(fn_args, self.into(), engine);
let result = func.std_lib_fn()(&mut args)?;
@ -1815,10 +1820,11 @@ impl MemberExpression {
let value = memory.get(&identifier.name, identifier.into())?;
value.clone()
}
}
.get_json_value()?;
};
if let serde_json::Value::Array(array) = array {
let array_json = array.get_json_value()?;
if let serde_json::Value::Array(array) = array_json {
if let Some(value) = array.get(index) {
Ok(MemoryItem::UserVal(UserVal {
value: value.clone(),
@ -1866,10 +1872,11 @@ impl MemberExpression {
let value = memory.get(&identifier.name, identifier.into())?;
value.clone()
}
}
.get_json_value()?;
};
if let serde_json::Value::Object(map) = object {
let object_json = object.get_json_value()?;
if let serde_json::Value::Object(map) = object_json {
if let Some(value) = map.get(&property_name) {
Ok(MemoryItem::UserVal(UserVal {
value: value.clone(),

View File

@ -3,10 +3,11 @@
use std::sync::Arc;
use anyhow::Result;
use anyhow::{anyhow, Result};
use dashmap::DashMap;
use futures::{SinkExt, StreamExt};
use kittycad::types::{OkWebSocketResponseData, WebSocketRequest, WebSocketResponse};
use tokio::sync::{mpsc, oneshot};
use tokio_tungstenite::tungstenite::Message as WsMsg;
use crate::{
@ -14,10 +15,11 @@ use crate::{
errors::{KclError, KclErrorDetails},
};
#[derive(Debug)]
type WebSocketTcpWrite = futures::stream::SplitSink<tokio_tungstenite::WebSocketStream<reqwest::Upgraded>, WsMsg>;
#[derive(Debug, Clone)]
pub struct EngineConnection {
tcp_write: futures::stream::SplitSink<tokio_tungstenite::WebSocketStream<reqwest::Upgraded>, WsMsg>,
tcp_read_handle: tokio::task::JoinHandle<Result<()>>,
engine_req_tx: mpsc::Sender<ToEngineReq>,
tcp_read_handle: Arc<tokio::task::JoinHandle<Result<()>>>,
responses: Arc<DashMap<uuid::Uuid, WebSocketResponse>>,
}
@ -46,7 +48,36 @@ impl TcpRead {
}
}
/// Requests to send to the engine, and a way to await a response.
struct ToEngineReq {
/// The request to send
req: WebSocketRequest,
/// If this resolves to Ok, the request was sent.
/// If this resolves to Err, the request could not be sent.
/// If this has not yet resolved, the request has not been sent yet.
request_sent: oneshot::Sender<Result<()>>,
}
impl EngineConnection {
/// Start waiting for incoming engine requests, and send each one over the WebSocket to the engine.
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 {
let ToEngineReq { req, request_sent } = req;
let res = Self::inner_send_to_engine(req, &mut tcp_write).await;
let _ = request_sent.send(res);
}
}
/// Send the given `request` to the engine via the WebSocket connection `tcp_write`.
async fn inner_send_to_engine(request: WebSocketRequest, tcp_write: &mut WebSocketTcpWrite) -> Result<()> {
let msg = serde_json::to_string(&request).map_err(|e| anyhow!("could not serialize json: {e}"))?;
tcp_write
.send(WsMsg::Text(msg))
.await
.map_err(|e| anyhow!("could not send json over websocket: {e}"))?;
Ok(())
}
pub async fn new(ws: reqwest::Upgraded) -> Result<EngineConnection> {
let ws_stream = tokio_tungstenite::WebSocketStream::from_raw_socket(
ws,
@ -56,6 +87,8 @@ impl EngineConnection {
.await;
let (tcp_write, tcp_read) = ws_stream.split();
let (engine_req_tx, engine_req_rx) = mpsc::channel(10);
tokio::task::spawn(Self::start_write_actor(tcp_write, engine_req_rx));
let mut tcp_read = TcpRead { stream: tcp_read };
@ -80,18 +113,11 @@ impl EngineConnection {
});
Ok(EngineConnection {
tcp_write,
tcp_read_handle,
engine_req_tx,
tcp_read_handle: Arc::new(tcp_read_handle),
responses,
})
}
pub async fn tcp_send(&mut self, msg: WebSocketRequest) -> Result<()> {
let msg = serde_json::to_string(&msg)?;
self.tcp_write.send(WsMsg::Text(msg)).await?;
Ok(())
}
}
#[async_trait::async_trait(?Send)]
@ -99,7 +125,7 @@ impl EngineManager for EngineConnection {
/// Send a modeling command.
/// Do not wait for the response message.
fn send_modeling_cmd(
&mut self,
&self,
id: uuid::Uuid,
source_range: crate::executor::SourceRange,
cmd: kittycad::types::ModelingCmd,
@ -110,12 +136,19 @@ impl EngineManager for EngineConnection {
/// Send a modeling command and wait for the response message.
async fn send_modeling_cmd_get_response(
&mut self,
&self,
id: uuid::Uuid,
source_range: crate::executor::SourceRange,
cmd: kittycad::types::ModelingCmd,
) -> Result<OkWebSocketResponseData, KclError> {
self.tcp_send(WebSocketRequest::ModelingCmdReq { cmd, cmd_id: id })
let (tx, rx) = oneshot::channel();
// Send the request to the engine, via the actor.
self.engine_req_tx
.send(ToEngineReq {
req: WebSocketRequest::ModelingCmdReq { cmd, cmd_id: id },
request_sent: tx,
})
.await
.map_err(|e| {
KclError::Engine(KclErrorDetails {
@ -124,17 +157,32 @@ impl EngineManager for EngineConnection {
})
})?;
// Wait for the request to be sent.
rx.await
.map_err(|e| {
KclError::Engine(KclErrorDetails {
message: format!("could not send request to the engine actor: {e}"),
source_ranges: vec![source_range],
})
})?
.map_err(|e| {
KclError::Engine(KclErrorDetails {
message: format!("could not send request to the engine: {e}"),
source_ranges: vec![source_range],
})
})?;
// Wait for the response.
loop {
if let Some(resp) = self.responses.get(&id) {
if let Some(data) = &resp.resp {
return Ok(data.clone());
return if let Some(data) = &resp.resp {
Ok(data.clone())
} else {
return Err(KclError::Engine(KclErrorDetails {
Err(KclError::Engine(KclErrorDetails {
message: format!("Modeling command failed: {:?}", resp.errors),
source_ranges: vec![source_range],
}));
}
}))
};
}
}
}

View File

@ -6,7 +6,7 @@ use kittycad::types::OkWebSocketResponseData;
use crate::errors::KclError;
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct EngineConnection {}
impl EngineConnection {
@ -18,7 +18,7 @@ impl EngineConnection {
#[async_trait::async_trait(?Send)]
impl crate::engine::EngineManager for EngineConnection {
fn send_modeling_cmd(
&mut self,
&self,
_id: uuid::Uuid,
_source_range: crate::executor::SourceRange,
_cmd: kittycad::types::ModelingCmd,
@ -27,7 +27,7 @@ impl crate::engine::EngineManager for EngineConnection {
}
async fn send_modeling_cmd_get_response(
&mut self,
&self,
_id: uuid::Uuid,
_source_range: crate::executor::SourceRange,
_cmd: kittycad::types::ModelingCmd,

View File

@ -35,7 +35,7 @@ impl EngineConnection {
#[async_trait::async_trait(?Send)]
impl crate::engine::EngineManager for EngineConnection {
fn send_modeling_cmd(
&mut self,
&self,
id: uuid::Uuid,
source_range: crate::executor::SourceRange,
cmd: kittycad::types::ModelingCmd,
@ -60,7 +60,7 @@ impl crate::engine::EngineManager for EngineConnection {
}
async fn send_modeling_cmd_get_response(
&mut self,
&self,
id: uuid::Uuid,
source_range: crate::executor::SourceRange,
cmd: kittycad::types::ModelingCmd,

View File

@ -32,11 +32,11 @@ use anyhow::Result;
pub use conn_mock::EngineConnection;
#[async_trait::async_trait(?Send)]
pub trait EngineManager {
pub trait EngineManager: Clone {
/// Send a modeling command.
/// Do not wait for the response message.
fn send_modeling_cmd(
&mut self,
&self,
id: uuid::Uuid,
source_range: crate::executor::SourceRange,
cmd: kittycad::types::ModelingCmd,
@ -44,7 +44,7 @@ pub trait EngineManager {
/// Send a modeling command and wait for the response message.
async fn send_modeling_cmd_get_response(
&mut self,
&self,
id: uuid::Uuid,
source_range: crate::executor::SourceRange,
cmd: kittycad::types::ModelingCmd,

View File

@ -101,8 +101,8 @@ impl ProgramReturn {
#[serde(tag = "type")]
pub enum MemoryItem {
UserVal(UserVal),
SketchGroup(SketchGroup),
ExtrudeGroup(ExtrudeGroup),
SketchGroup(Box<SketchGroup>),
ExtrudeGroup(Box<ExtrudeGroup>),
#[ts(skip)]
ExtrudeTransform(ExtrudeTransform),
#[ts(skip)]
@ -159,10 +159,12 @@ impl MemoryItem {
if let MemoryItem::UserVal(user_val) = self {
Ok(user_val.value.clone())
} else {
Err(KclError::Semantic(KclErrorDetails {
message: format!("Not a user value: {:?}", self),
source_ranges: self.clone().into(),
}))
serde_json::to_value(self).map_err(|err| {
KclError::Semantic(KclErrorDetails {
message: format!("Cannot convert memory item to json value: {:?}", err),
source_ranges: self.clone().into(),
})
})
}
}
@ -599,6 +601,10 @@ pub fn execute(
let memory_item = memory.get(&identifier.name, identifier.into())?;
args.push(memory_item.clone());
}
Value::CallExpression(call_expr) => {
let result = call_expr.execute(memory, &mut pipe_info, engine)?;
args.push(result);
}
// We do nothing for the rest.
_ => (),
}
@ -1173,6 +1179,16 @@ show(thisBox)
);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_math_execute_with_pi() {
let ast = r#"const myVar = pi() * 2"#;
let memory = parse_execute(ast).await.unwrap();
assert_eq!(
serde_json::json!(std::f64::consts::TAU),
memory.root.get("myVar").unwrap().get_json_value().unwrap()
);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_math_define_decimal_without_leading_zero() {
let ast = r#"let thing = .4 + 7"#;
@ -1183,6 +1199,22 @@ show(thisBox)
);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_zero_param_fn() {
let ast = r#"const sigmaAllow = 35000 // psi
const leg1 = 5 // inches
const leg2 = 8 // inches
fn thickness = () => { return 0.56 }
const bracket = startSketchAt([0,0])
|> line([0, leg1], %)
|> line([leg2, 0], %)
|> line([0, -thickness()], %)
|> line([-leg2 + thickness(), 0], %)
"#;
parse_execute(ast).await.unwrap();
}
#[tokio::test(flavor = "multi_thread")]
async fn test_math_negative_variable_in_binary_expression() {
let ast = r#"const sigmaAllow = 35000 // psi

View File

@ -1,3 +1,5 @@
#![recursion_limit = "1024"]
pub mod ast;
pub mod docs;
pub mod engine;

View File

@ -422,9 +422,8 @@ impl ReversePolishNotation {
{
let closing_brace = self.parser.find_closing_brace(1, 0, "")?;
let mut new_stack = stack;
new_stack.push(MathExpression::CallExpression(Box::new(
self.parser.make_call_expression(0)?.expression,
)));
let call_expression = self.parser.make_call_expression(0)?;
new_stack.push(MathExpression::CallExpression(Box::new(call_expression.expression)));
return self.build_tree(&reverse_polish_notation_tokens[closing_brace + 1..], new_stack);
}
if reverse_polish_notation_tokens[1].token_type == TokenType::Period

View File

@ -777,6 +777,7 @@ impl Parser {
});
}
}
if current_token.token_type == TokenType::Word
|| current_token.token_type == TokenType::Number
|| current_token.token_type == TokenType::String
@ -1249,7 +1250,15 @@ impl Parser {
})
})?;
let closing_brace_token = self.get_token(closing_brace_index)?;
let args = self.make_arguments(brace_token.index, vec![])?;
// Account for if we have no args.
let args = if brace_token.index + 1 == closing_brace_index {
ArgumentsReturn {
arguments: vec![],
last_index: closing_brace_index,
}
} else {
self.make_arguments(brace_token.index, vec![])?
};
let function = if let Some(stdlib_fn) = self.stdlib.get(&callee.name) {
crate::ast::types::Function::StdLib { func: stdlib_fn }
} else {
@ -3356,6 +3365,19 @@ e
);
}
#[test]
fn zero_param_function() {
let program = r#"
fn firstPrimeNumber = () => {
return 2
}
firstPrimeNumber()
"#;
let tokens = crate::tokeniser::lexer(program);
let parser = crate::parser::Parser::new(tokens);
let _ast = parser.ast().unwrap();
}
#[test]
fn test_keyword_ok_in_fn_args_return() {
let some_program_string = r#"fn thing = (param) => {
@ -3408,4 +3430,47 @@ thing(false)
r#"syntax: KclErrorDetails { source_ranges: [SourceRange([0, 2])], message: "Expected a `let` variable kind, found: `fn`" }"#
);
}
#[test]
fn test_member_expression_sketch_group() {
let some_program_string = r#"fn cube = (pos, scale) => {
const sg = startSketchAt(pos)
|> line([0, scale], %)
|> line([scale, 0], %)
|> line([0, -scale], %)
return sg
}
const b1 = cube([0,0], 10)
const b2 = cube([3,3], 4)
const pt1 = b1[0]
const pt2 = b2[0]
show(b1)
show(b2)"#;
let tokens = crate::tokeniser::lexer(some_program_string);
let parser = crate::parser::Parser::new(tokens);
parser.ast().unwrap();
}
#[test]
fn test_math_with_stdlib() {
let some_program_string = r#"const d2r = pi() / 2
let other_thing = 2 * cos(3)"#;
let tokens = crate::tokeniser::lexer(some_program_string);
let parser = crate::parser::Parser::new(tokens);
parser.ast().unwrap();
}
#[test]
#[ignore] // ignore until more stack fixes
fn test_parse_pipes_on_pipes() {
let code = include_str!("../../tests/executor/inputs/pipes_on_pipes.kcl");
let tokens = crate::tokeniser::lexer(code);
let parser = crate::parser::Parser::new(tokens);
parser.ast().unwrap();
}
}

View File

@ -23,7 +23,7 @@ pub fn extrude(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "extrude"
}]
fn inner_extrude(length: f64, sketch_group: SketchGroup, args: &mut Args) -> Result<ExtrudeGroup, KclError> {
fn inner_extrude(length: f64, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<Box<ExtrudeGroup>, KclError> {
let id = uuid::Uuid::new_v4();
let cmd = kittycad::types::ModelingCmd::Extrude {
@ -33,7 +33,7 @@ fn inner_extrude(length: f64, sketch_group: SketchGroup, args: &mut Args) -> Res
};
args.send_modeling_cmd(id, cmd)?;
Ok(ExtrudeGroup {
Ok(Box::new(ExtrudeGroup {
id,
// TODO, this is just an empty array now, should be deleted. This
// comment was originally in the JS code.
@ -42,13 +42,13 @@ fn inner_extrude(length: f64, sketch_group: SketchGroup, args: &mut Args) -> Res
position: sketch_group.position,
rotation: sketch_group.rotation,
meta: sketch_group.meta,
})
}))
}
/// Returns the extrude wall transform.
pub fn get_extrude_wall_transform(args: &mut Args) -> Result<MemoryItem, KclError> {
let (surface_name, extrude_group) = args.get_path_name_extrude_group()?;
let result = inner_get_extrude_wall_transform(&surface_name, extrude_group, args)?;
let result = inner_get_extrude_wall_transform(&surface_name, *extrude_group, args)?;
Ok(MemoryItem::ExtrudeTransform(result))
}

View File

@ -179,7 +179,7 @@ impl<'a> Args<'a> {
Ok((numbers[0], numbers[1]))
}
fn get_segment_name_sketch_group(&self) -> Result<(String, SketchGroup), KclError> {
fn get_segment_name_sketch_group(&self) -> Result<(String, Box<SketchGroup>), KclError> {
// Iterate over our args, the first argument should be a UserVal with a string value.
// The second argument should be a SketchGroup.
let first_value = self
@ -221,7 +221,7 @@ impl<'a> Args<'a> {
Ok((segment_name, sketch_group))
}
fn get_sketch_group(&self) -> Result<SketchGroup, KclError> {
fn get_sketch_group(&self) -> Result<Box<SketchGroup>, KclError> {
let first_value = self.args.first().ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a SketchGroup as the first argument, found `{:?}`", self.args),
@ -263,7 +263,7 @@ impl<'a> Args<'a> {
Ok(data)
}
fn get_data_and_sketch_group<T: serde::de::DeserializeOwned>(&self) -> Result<(T, SketchGroup), KclError> {
fn get_data_and_sketch_group<T: serde::de::DeserializeOwned>(&self) -> Result<(T, Box<SketchGroup>), KclError> {
let first_value = self
.args
.first()
@ -301,7 +301,7 @@ impl<'a> Args<'a> {
Ok((data, sketch_group))
}
fn get_segment_name_to_number_sketch_group(&self) -> Result<(String, f64, SketchGroup), KclError> {
fn get_segment_name_to_number_sketch_group(&self) -> Result<(String, f64, Box<SketchGroup>), KclError> {
// Iterate over our args, the first argument should be a UserVal with a string value.
// The second argument should be a number.
// The third argument should be a SketchGroup.
@ -357,7 +357,7 @@ impl<'a> Args<'a> {
Ok((segment_name, to_number, sketch_group))
}
fn get_number_sketch_group(&self) -> Result<(f64, SketchGroup), KclError> {
fn get_number_sketch_group(&self) -> Result<(f64, Box<SketchGroup>), KclError> {
// Iterate over our args, the first argument should be a number.
// The second argument should be a SketchGroup.
let first_value = self
@ -392,7 +392,7 @@ impl<'a> Args<'a> {
Ok((number, sketch_group))
}
fn get_path_name_extrude_group(&self) -> Result<(String, ExtrudeGroup), KclError> {
fn get_path_name_extrude_group(&self) -> Result<(String, Box<ExtrudeGroup>), KclError> {
// Iterate over our args, the first argument should be a UserVal with a string value.
// The second argument should be a ExtrudeGroup.
let first_value = self
@ -454,7 +454,7 @@ pub fn show(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "show",
}]
fn inner_show(_sketch: SketchGroup) {}
fn inner_show(_sketch: Box<SketchGroup>) {}
/// Returns the length of the given leg.
pub fn leg_length(args: &mut Args) -> Result<MemoryItem, KclError> {

View File

@ -22,7 +22,7 @@ pub fn segment_end_x(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "segEndX",
}]
fn inner_segment_end_x(segment_name: &str, sketch_group: SketchGroup, args: &mut Args) -> Result<f64, KclError> {
fn inner_segment_end_x(segment_name: &str, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> {
let line = sketch_group.get_base_by_name_or_start(segment_name).ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!(
@ -48,7 +48,7 @@ pub fn segment_end_y(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "segEndY",
}]
fn inner_segment_end_y(segment_name: &str, sketch_group: SketchGroup, args: &mut Args) -> Result<f64, KclError> {
fn inner_segment_end_y(segment_name: &str, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> {
let line = sketch_group.get_base_by_name_or_start(segment_name).ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!(
@ -74,7 +74,7 @@ pub fn last_segment_x(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "lastSegX",
}]
fn inner_last_segment_x(sketch_group: SketchGroup, args: &mut Args) -> Result<f64, KclError> {
fn inner_last_segment_x(sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> {
let last_line = sketch_group
.value
.last()
@ -104,7 +104,7 @@ pub fn last_segment_y(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "lastSegY",
}]
fn inner_last_segment_y(sketch_group: SketchGroup, args: &mut Args) -> Result<f64, KclError> {
fn inner_last_segment_y(sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> {
let last_line = sketch_group
.value
.last()
@ -133,7 +133,7 @@ pub fn segment_length(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "segLen",
}]
fn inner_segment_length(segment_name: &str, sketch_group: SketchGroup, args: &mut Args) -> Result<f64, KclError> {
fn inner_segment_length(segment_name: &str, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> {
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!(
@ -162,7 +162,7 @@ pub fn segment_angle(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "segAng",
}]
fn inner_segment_angle(segment_name: &str, sketch_group: SketchGroup, args: &mut Args) -> Result<f64, KclError> {
fn inner_segment_angle(segment_name: &str, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<f64, KclError> {
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!(
@ -193,7 +193,7 @@ pub fn angle_to_match_length_x(args: &mut Args) -> Result<MemoryItem, KclError>
fn inner_angle_to_match_length_x(
segment_name: &str,
to: f64,
sketch_group: SketchGroup,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<f64, KclError> {
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {
@ -248,7 +248,7 @@ pub fn angle_to_match_length_y(args: &mut Args) -> Result<MemoryItem, KclError>
fn inner_angle_to_match_length_y(
segment_name: &str,
to: f64,
sketch_group: SketchGroup,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<f64, KclError> {
let path = sketch_group.get_path_by_name(segment_name).ok_or_else(|| {

View File

@ -34,7 +34,7 @@ pub enum LineToData {
/// Draw a line to a point.
pub fn line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (LineToData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (LineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_line_to(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -44,7 +44,11 @@ pub fn line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "lineTo",
}]
fn inner_line_to(data: LineToData, sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
fn inner_line_to(
data: LineToData,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?;
let to = match data {
LineToData::PointWithTag { to, .. } => to,
@ -63,6 +67,7 @@ fn inner_line_to(data: LineToData, sketch_group: SketchGroup, args: &mut Args) -
y: to[1],
z: 0.0,
},
relative: false,
},
},
)?;
@ -107,7 +112,7 @@ pub enum AxisLineToData {
/// Draw a line to a point on the x-axis.
pub fn x_line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AxisLineToData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (AxisLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_x_line_to(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -117,7 +122,11 @@ pub fn x_line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "xLineTo",
}]
fn inner_x_line_to(data: AxisLineToData, sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
fn inner_x_line_to(
data: AxisLineToData,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?;
let line_to_data = match data {
@ -132,7 +141,7 @@ fn inner_x_line_to(data: AxisLineToData, sketch_group: SketchGroup, args: &mut A
/// Draw a line to a point on the y-axis.
pub fn y_line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AxisLineToData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (AxisLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_y_line_to(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -142,7 +151,11 @@ pub fn y_line_to(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "yLineTo",
}]
fn inner_y_line_to(data: AxisLineToData, sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
fn inner_y_line_to(
data: AxisLineToData,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?;
let line_to_data = match data {
@ -172,7 +185,7 @@ pub enum LineData {
/// Draw a line.
pub fn line(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (LineData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (LineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_line(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -182,13 +195,14 @@ pub fn line(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "line",
}]
fn inner_line(data: LineData, sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
fn inner_line(data: LineData, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?;
let inner_args = match &data {
LineData::PointWithTag { to, .. } => *to,
LineData::Point(to) => *to,
};
let delta = inner_args;
let to = [from.x + inner_args[0], from.y + inner_args[1]];
let id = uuid::Uuid::new_v4();
@ -199,10 +213,11 @@ fn inner_line(data: LineData, sketch_group: SketchGroup, args: &mut Args) -> Res
path: sketch_group.id,
segment: kittycad::types::PathSegment::Line {
end: Point3D {
x: to[0],
y: to[1],
x: delta[0],
y: delta[1],
z: 0.0,
},
relative: true,
},
},
)?;
@ -247,7 +262,7 @@ pub enum AxisLineData {
/// Draw a line on the x-axis.
pub fn x_line(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AxisLineData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (AxisLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_x_line(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -257,7 +272,11 @@ pub fn x_line(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "xLine",
}]
fn inner_x_line(data: AxisLineData, sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
fn inner_x_line(
data: AxisLineData,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<Box<SketchGroup>, KclError> {
let line_data = match data {
AxisLineData::LengthWithTag { length, tag } => LineData::PointWithTag { to: [length, 0.0], tag },
AxisLineData::Length(length) => LineData::Point([length, 0.0]),
@ -269,7 +288,7 @@ fn inner_x_line(data: AxisLineData, sketch_group: SketchGroup, args: &mut Args)
/// Draw a line on the y-axis.
pub fn y_line(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AxisLineData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (AxisLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_y_line(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -279,7 +298,11 @@ pub fn y_line(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "yLine",
}]
fn inner_y_line(data: AxisLineData, sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
fn inner_y_line(
data: AxisLineData,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<Box<SketchGroup>, KclError> {
let line_data = match data {
AxisLineData::LengthWithTag { length, tag } => LineData::PointWithTag { to: [0.0, length], tag },
AxisLineData::Length(length) => LineData::Point([0.0, length]),
@ -309,7 +332,7 @@ pub enum AngledLineData {
/// Draw an angled line.
pub fn angled_line(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngledLineData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (AngledLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -321,18 +344,23 @@ pub fn angled_line(args: &mut Args) -> Result<MemoryItem, KclError> {
}]
fn inner_angled_line(
data: AngledLineData,
sketch_group: SketchGroup,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<SketchGroup, KclError> {
) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?;
let (angle, length) = match &data {
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
AngledLineData::AngleAndLength(angle_and_length) => (angle_and_length[0], angle_and_length[1]),
};
let to: [f64; 2] = [
from.x + length * f64::cos(angle.to_radians()),
from.y + length * f64::sin(angle.to_radians()),
//double check me on this one - mike
let delta: [f64; 2] = [
length * f64::cos(angle.to_radians()),
length * f64::sin(angle.to_radians()),
];
let relative = true;
let to: [f64; 2] = [from.x + delta[0], from.y + delta[1]];
let id = uuid::Uuid::new_v4();
@ -358,10 +386,11 @@ fn inner_angled_line(
path: sketch_group.id,
segment: kittycad::types::PathSegment::Line {
end: Point3D {
x: to[0],
y: to[1],
x: delta[0],
y: delta[1],
z: 0.0,
},
relative,
},
},
)?;
@ -373,7 +402,7 @@ fn inner_angled_line(
/// Draw an angled line of a given x length.
pub fn angled_line_of_x_length(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngledLineData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (AngledLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line_of_x_length(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -385,9 +414,9 @@ pub fn angled_line_of_x_length(args: &mut Args) -> Result<MemoryItem, KclError>
}]
fn inner_angled_line_of_x_length(
data: AngledLineData,
sketch_group: SketchGroup,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<SketchGroup, KclError> {
) -> Result<Box<SketchGroup>, KclError> {
let (angle, length) = match &data {
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
AngledLineData::AngleAndLength(angle_and_length) => (angle_and_length[0], angle_and_length[1]),
@ -428,7 +457,7 @@ pub enum AngledLineToData {
/// Draw an angled line to a given x coordinate.
pub fn angled_line_to_x(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngledLineToData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (AngledLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line_to_x(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -440,9 +469,9 @@ pub fn angled_line_to_x(args: &mut Args) -> Result<MemoryItem, KclError> {
}]
fn inner_angled_line_to_x(
data: AngledLineToData,
sketch_group: SketchGroup,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<SketchGroup, KclError> {
) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?;
let (angle, x_to) = match &data {
AngledLineToData::AngleWithTag { angle, to, .. } => (*angle, *to),
@ -467,7 +496,7 @@ fn inner_angled_line_to_x(
/// Draw an angled line of a given y length.
pub fn angled_line_of_y_length(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngledLineData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (AngledLineData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line_of_y_length(data, sketch_group, args)?;
@ -480,9 +509,9 @@ pub fn angled_line_of_y_length(args: &mut Args) -> Result<MemoryItem, KclError>
}]
fn inner_angled_line_of_y_length(
data: AngledLineData,
sketch_group: SketchGroup,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<SketchGroup, KclError> {
) -> Result<Box<SketchGroup>, KclError> {
let (angle, length) = match &data {
AngledLineData::AngleWithTag { angle, length, .. } => (*angle, *length),
AngledLineData::AngleAndLength(angle_and_length) => (angle_and_length[0], angle_and_length[1]),
@ -505,7 +534,7 @@ fn inner_angled_line_of_y_length(
/// Draw an angled line to a given y coordinate.
pub fn angled_line_to_y(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngledLineToData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (AngledLineToData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line_to_y(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -517,9 +546,9 @@ pub fn angled_line_to_y(args: &mut Args) -> Result<MemoryItem, KclError> {
}]
fn inner_angled_line_to_y(
data: AngledLineToData,
sketch_group: SketchGroup,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<SketchGroup, KclError> {
) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?;
let (angle, y_to) = match &data {
AngledLineToData::AngleWithTag { angle, to, .. } => (*angle, *to),
@ -560,7 +589,7 @@ pub struct AngeledLineThatIntersectsData {
/// Draw an angled line that intersects with a given line.
pub fn angled_line_that_intersects(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (AngeledLineThatIntersectsData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (AngeledLineThatIntersectsData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_angled_line_that_intersects(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
}
@ -571,9 +600,9 @@ pub fn angled_line_that_intersects(args: &mut Args) -> Result<MemoryItem, KclErr
}]
fn inner_angled_line_that_intersects(
data: AngeledLineThatIntersectsData,
sketch_group: SketchGroup,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<SketchGroup, KclError> {
) -> Result<Box<SketchGroup>, KclError> {
let intersect_path = sketch_group
.get_path_by_name(&data.intersect_tag)
.ok_or_else(|| {
@ -617,7 +646,7 @@ pub fn start_sketch_at(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "startSketchAt",
}]
fn inner_start_sketch_at(data: LineData, args: &mut Args) -> Result<SketchGroup, KclError> {
fn inner_start_sketch_at(data: LineData, args: &mut Args) -> Result<Box<SketchGroup>, KclError> {
let to = match &data {
LineData::PointWithTag { to, .. } => *to,
LineData::Point(to) => *to,
@ -661,7 +690,7 @@ fn inner_start_sketch_at(data: LineData, args: &mut Args) -> Result<SketchGroup,
start: current_path,
meta: vec![args.source_range.into()],
};
Ok(sketch_group)
Ok(Box::new(sketch_group))
}
/// Close the current sketch.
@ -677,7 +706,7 @@ pub fn close(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "close",
}]
fn inner_close(sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
fn inner_close(sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?;
let to: Point2d = sketch_group.start.from.into();
@ -756,7 +785,7 @@ pub enum ArcData {
/// Draw an arc.
pub fn arc(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (ArcData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (ArcData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_arc(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -766,7 +795,7 @@ pub fn arc(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "arc",
}]
fn inner_arc(data: ArcData, sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
fn inner_arc(data: ArcData, sketch_group: Box<SketchGroup>, args: &mut Args) -> Result<Box<SketchGroup>, KclError> {
let from: Point2d = sketch_group.get_coords_from_paths()?;
let (center, angle_start, angle_end, radius, end) = match &data {
@ -812,9 +841,14 @@ fn inner_arc(data: ArcData, sketch_group: SketchGroup, args: &mut Args) -> Resul
angle_end: angle_end.degrees(),
center: center.into(),
radius,
relative: false,
},
},
)?;
// TODO: Dont do this (move path pen) - mike
// lets review what the needs are here and see if any existing arc endpoints can accomplish this
// Move the path pen to the end of the arc.
// Since that is where we want to draw the next path.
// TODO: the engine should automatically move the pen to the end of the arc.
@ -883,7 +917,7 @@ pub enum BezierData {
/// Draw a bezier curve.
pub fn bezier_curve(args: &mut Args) -> Result<MemoryItem, KclError> {
let (data, sketch_group): (BezierData, SketchGroup) = args.get_data_and_sketch_group()?;
let (data, sketch_group): (BezierData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
let new_sketch_group = inner_bezier_curve(data, sketch_group, args)?;
Ok(MemoryItem::SketchGroup(new_sketch_group))
@ -893,7 +927,11 @@ pub fn bezier_curve(args: &mut Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "bezierCurve",
}]
fn inner_bezier_curve(data: BezierData, sketch_group: SketchGroup, args: &mut Args) -> Result<SketchGroup, KclError> {
fn inner_bezier_curve(
data: BezierData,
sketch_group: Box<SketchGroup>,
args: &mut Args,
) -> Result<Box<SketchGroup>, KclError> {
let from = sketch_group.get_coords_from_paths()?;
let (to, control1, control2) = match &data {
@ -903,6 +941,8 @@ fn inner_bezier_curve(data: BezierData, sketch_group: SketchGroup, args: &mut Ar
BezierData::Points { to, control1, control2 } => (to, control1, control2),
};
let relative = true;
let delta = to;
let to = [from.x + to[0], from.y + to[1]];
let id = uuid::Uuid::new_v4();
@ -913,20 +953,21 @@ fn inner_bezier_curve(data: BezierData, sketch_group: SketchGroup, args: &mut Ar
path: sketch_group.id,
segment: kittycad::types::PathSegment::Bezier {
control1: Point3D {
x: from.x + control1[0],
y: from.y + control1[1],
x: control1[0],
y: control1[1],
z: 0.0,
},
control2: Point3D {
x: from.x + control2[0],
y: from.y + control2[1],
x: control2[0],
y: control2[1],
z: 0.0,
},
end: Point3D {
x: to[0],
y: to[1],
x: delta[0],
y: delta[1],
z: 0.0,
},
relative,
},
},
)?;

View File

@ -0,0 +1,470 @@
const svg = startSketchAt([0, 0])
|> lineTo([22.687663, -2.7664351], %) // MoveRelative
|> lineTo([15.687664000000002, -5.7664351], %) // MoveRelative
|> bezierCurve({ control1: [9.6876636, -13.766435], control2: [12.350729000000001, -9.156355099999999], to: [12.350729000000001, -9.156355099999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [3.6876636000000005, -32.766435], control2: [6.962245000000001, -20.186315], to: [4.8344949, -25.885455]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [5.0392261000000005, -58.571125], control2: [2.9675173000000004, -41.612785], to: [3.0190312000000006, -49.894795]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [10.687664000000002, -73.766435], control2: [6.693877800000001, -63.826655], to: [8.2887432, -68.804835]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [20.375163, -80.578935], control2: [16.045534000000004, -78.630635], to: [16.045534000000004, -78.630635]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [30.062663, -82.266435], control2: [24.812782, -81.936245], to: [24.812782, -81.936245]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [41.125163, -79.516435], control2: [35.794902, -82.039475], to: [35.794902, -82.039475]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [49.687663, -72.766435], control2: [45.867323, -76.907555], to: [45.867323, -76.907555]}, %) // CubicBezierRelative
|> lineTo([50.687663, -69.766435], %) // LineRelative
|> lineTo([50.687663, -62.766435], %) // VerticalLineHorizonal
|> lineTo([48.687663, -57.891435], %) // LineRelative
|> bezierCurve({ control1: [46.351725, -31.692225], control2: [46.191183, -48.997725], to: [46.295503000000004, -40.884555000000006]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [47.7736, -20.934404999999998], control2: [46.687663, -25.766435], to: [46.687663, -25.766435]}, %) // CubicBezierRelative
|> lineTo([48.687663, -16.766434999999998], %) // LineRelative
|> lineTo([47.687663, -9.766435099999999], %) // LineRelative
|> bezierCurve({ control1: [40.687663, -3.766435099999999], control2: [44.488820000000004, -6.310115099999999], to: [44.488820000000004, -6.310115099999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [22.687663, -2.766435099999999], control2: [34.632213, -2.2525750999999987], to: [28.903189, -2.550245099999999]}, %) // CubicBezierRelative
// StopRelative
|> lineTo([116.68767, -9.766435099999999], %) // MoveRelative
|> bezierCurve({ control1: [108.68767, -15.766434999999998], control2: [112.22719, -12.236704999999999], to: [112.22719, -12.236704999999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [102.37517, -28.953934999999998], control2: [105.79825, -20.100575], to: [103.93048, -23.991764999999997]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [101.68767, -47.766435], control2: [101.45837999999999, -35.371444999999994], to: [101.28287, -41.289805]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [110.31267, -61.203935], control2: [103.94304, -53.097335], to: [106.65406999999999, -56.725305]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [116.68767, -66.766435], control2: [113.42043, -64.74899500000001], to: [113.42043, -64.74899500000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [134.68767, -64.766435], control2: [123.4012, -67.124495], to: [128.03363, -66.429955]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [143.68767, -60.766435], control2: [139.37985, -63.042205], to: [139.37985, -63.042205]}, %) // CubicBezierRelative
|> lineTo([148.68767, -55.766435], %) // LineRelative
|> lineTo([149.68767, -54.766435], %) // LineRelative
|> bezierCurve({ control1: [149.75017, -46.078935], control2: [149.71427, -51.870655], to: [149.73387, -48.974805]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [150.68767, -36.766435], control2: [149.97673, -41.121905], to: [149.97673, -41.121905]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [158.68767, -30.766435], control2: [154.62517, -32.891435], to: [154.62517, -32.891435]}, %) // CubicBezierRelative
|> lineTo([160.68767, -26.766435], %) // LineRelative
|> lineTo([160.68767, -20.766435], %) // VerticalLineHorizonal
|> bezierCurve({ control1: [149.68767, -9.8289351], control2: [157.40521999999999, -16.321455], to: [154.13992, -13.098555000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [145.68767, -7.766435100000001], control2: [148.36767, -9.148315100000001], to: [147.04767, -8.4676851]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [116.68767, -9.7664351], control2: [135.27527, -6.278955100000001], to: [126.6914, -6.2357151]}, %) // CubicBezierRelative
// StopRelative
|> lineTo([60.687663, -9.7664351], %) // MoveRelative
|> lineTo([54.687663, -13.766435000000001], %) // MoveRelative
|> bezierCurve({ control1: [48.937663, -25.516435], control2: [50.481933, -19.450155000000002], to: [50.481933, -19.450155000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [47.687663, -41.766435], control2: [47.773086, -31.339325000000002], to: [47.261382, -35.869545]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [50.687663, -56.766435], control2: [48.8286, -49.471785000000004], to: [48.8286, -49.471785000000004]}, %) // CubicBezierRelative
|> lineTo([54.687663, -62.766435], %) // LineRelative
|> lineTo([60.687663, -66.766435], %) // LineRelative
|> bezierCurve({ control1: [69.562663, -67.203935], control2: [64.985029, -67.361225], to: [64.985029, -67.361225]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [74.17985, -67.199935], control2: [71.84817100000001, -67.201935], to: [71.84817100000001, -67.201935]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [86.687663, -63.766335], control2: [78.823333, -66.75328499999999], to: [82.418032, -65.599655]}, %) // CubicBezierRelative
|> lineTo([86.687663, -61.766335], %) // VerticalLineHorizonal
|> lineTo([90.687663, -60.766335], %) // LineRelative
|> lineTo([95.687663, -56.766335], %) // LineRelative
|> lineTo([98.687663, -49.766335], %) // LineRelative
|> bezierCurve({ control1: [97.562663, -37.578835], control2: [98.934927, -43.021825], to: [98.934927, -43.021825]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [95.687663, -32.766335], control2: [96.943913, -35.990714999999994], to: [96.325163, -34.402584999999995]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [86.687663, -27.766334999999998], control2: [90.389309, -28.854045], to: [90.389309, -28.854045]}, %) // CubicBezierRelative
|> lineTo([84.687663, -23.766334999999998], %) // LineRelative
|> lineTo([82.687663, -22.766334999999998], %) // LineRelative
|> lineTo([79.687663, -17.766334999999998], %) // LineRelative
|> lineTo([77.687663, -17.766334999999998], %) // HorizontalLineRelative
|> lineTo([75.687663, -13.766334999999998], %) // LineRelative
|> bezierCurve({ control1: [67.687663, -9.766335099999997], control2: [72.005138, -11.383034999999998], to: [72.005138, -11.383034999999998]}, %) // CubicBezierRelative
|> lineTo([60.687663, -9.766335099999997], %) // HorizontalLineRelative
// StopRelative
|> lineTo([295.68767, -33.766435], %) // MoveAbsolute
|> bezierCurve({ control1: [286.31267, -36.578935], control2: [292.56461, -34.710375], to: [289.43947000000003, -35.647445000000005]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [242.00408000000002, -50.172685], control2: [271.51088000000004, -41.004795], to: [256.74729, -45.555595000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [234.31267000000003, -52.578935], control2: [239.46591, -50.966755], to: [236.92775, -51.760815]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [227.28923000000003, -54.785975], control2: [231.99494, -53.307255], to: [229.67720000000003, -54.035585000000005]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [208.68767000000003, -59.766435], control2: [221.12295000000003, -56.635855], to: [214.94597000000005, -58.261215]}, %) // CubicBezierRelative
|> lineTo([208.68767000000003, -57.766435], %) // VerticalLineHorizonal
|> lineTo([212.68767000000003, -55.766435], %) // LineRelative
|> bezierCurve({ control1: [217.68767000000003, -48.766435], control2: [215.57281000000003, -52.830805], to: [215.57281000000003, -52.830805]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [218.68767000000003, -37.766435], control2: [218.84802000000002, -43.253935], to: [218.84802000000002, -43.253935]}, %) // CubicBezierRelative
|> lineTo([215.68767000000003, -31.766435], %) // LineRelative
|> bezierCurve({ control1: [208.68767000000003, -26.766435], control2: [212.58234000000002, -28.940575000000003], to: [212.58234000000002, -28.940575000000003]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [192.68767000000003, -22.766435], control2: [203.18777000000003, -24.627585], to: [198.58520000000001, -23.608945000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [174.68767000000003, -24.766435], control2: [186.30665000000002, -22.492965], to: [180.86041000000003, -23.137525]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [170.12517000000003, -25.953935], control2: [173.18205000000003, -25.158315], to: [171.67642000000004, -25.550185000000003]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [161.43767000000003, -31.016435], control2: [165.49678000000003, -27.618325000000002], to: [165.49678000000003, -27.618325000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [152.68767000000003, -41.766435], control2: [157.93412000000004, -34.519995], to: [155.07957000000002, -37.431115]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [152.68767000000003, -50.766435], control2: [151.93767000000003, -46.266435], to: [151.93767000000003, -46.266435]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [160.43767000000003, -61.578935], control2: [156.18761000000003, -57.582325], to: [156.18761000000003, -57.582325]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [164.68767000000003, -64.766435], control2: [162.54142000000002, -63.156755000000004], to: [162.54142000000002, -63.156755000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [180.68767000000003, -67.766435], control2: [172.62751000000003, -66.921865], to: [172.62751000000003, -66.921865]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [158.81267000000003, -75.266435], control2: [173.47790000000003, -70.856345], to: [166.33463000000003, -73.047575]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [138.52752000000004, -81.543785], control2: [148.62236000000001, -78.25548500000001], to: [148.62236000000001, -78.25548500000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [130.12517000000003, -82.828935], control2: [134.68767000000003, -82.766435], to: [134.68767000000003, -82.766435]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [125.68767000000003, -81.766435], control2: [128.66080000000002, -82.478315], to: [127.19642000000003, -82.127685]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [117.68767000000003, -75.766435], control2: [122.99559000000002, -79.800785], to: [120.32975000000002, -77.798805]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [107.68767000000003, -72.766435], control2: [113.16586000000002, -73.682455], to: [113.16586000000002, -73.682455]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [84.93766300000003, -73.953935], control2: [99.87842800000003, -72.226315], to: [92.61523300000002, -72.36835500000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [80.68766300000003, -75.766435], control2: [83.53516300000003, -74.552065], to: [82.13266300000002, -75.15018500000001]}, %) // CubicBezierRelative
|> lineTo([75.68766300000003, -80.766435], %) // LineRelative
|> lineTo([76.68766300000003, -84.766435], %) // LineRelative
|> lineTo([81.68766300000003, -87.766435], %) // LineRelative
|> bezierCurve({ control1: [93.93766300000003, -87.891435], control2: [85.76704300000003, -87.950845], to: [89.85495700000003, -87.974265]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [105.68767000000003, -87.766435], control2: [97.85393000000003, -87.821635], to: [101.77078000000003, -87.772355]}, %) // CubicBezierRelative
|> lineTo([106.68767000000003, -88.766435], %) // LineRelative
|> lineTo([99.68766300000003, -90.766435], %) // LineRelative
|> lineTo([95.75016300000003, -93.266435], %) // LineRelative
|> bezierCurve({ control1: [83.68766300000003, -97.766435], control2: [91.68766300000003, -95.766435], to: [91.68766300000003, -95.766435]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [68.68766300000003, -102.76643], control2: [78.56377900000003, -99.248045], to: [73.64162800000003, -100.78485]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [52.68766300000003, -101.76643], control2: [63.09091200000003, -102.95723], to: [58.18407400000003, -102.86573]}, %) // CubicBezierRelative
|> lineTo([48.68766300000003, -106.76643], %) // LineRelative
|> lineTo([48.68766300000003, -114.76643], %) // VerticalLineHorizonal
|> lineTo([51.68766300000003, -121.76643], %) // LineRelative
|> lineTo([56.68766300000003, -123.76643], %) // LineRelative
|> lineTo([61.68766300000003, -123.76643], %) // HorizontalLineRelative
|> lineTo([64.68766300000003, -118.76643], %) // LineRelative
|> lineTo([69.68766300000003, -115.76643], %) // LineRelative
|> lineTo([69.68766300000003, -113.76643], %) // VerticalLineHorizonal
|> lineTo([75.68766300000003, -113.76643], %) // HorizontalLineRelative
|> lineTo([79.68766300000003, -110.76643], %) // LineRelative
|> lineTo([79.68766300000003, -108.76643], %) // VerticalLineHorizonal
|> lineTo([85.68766300000003, -109.76643], %) // LineRelative
|> lineTo([88.68766300000003, -106.76643], %) // LineRelative
|> lineTo([88.68766300000003, -102.76643], %) // VerticalLineHorizonal
|> bezierCurve({ control1: [99.68766300000003, -101.76643], control2: [93.93766300000003, -102.01643], to: [93.93766300000003, -102.01643]}, %) // CubicBezierRelative
|> lineTo([103.68767000000003, -105.76643], %) // LineRelative
|> lineTo([106.68767000000003, -106.76643], %) // LineRelative
|> bezierCurve({ control1: [107.68767000000003, -102.76643], control2: [107.18267000000003, -104.78643], to: [107.18267000000003, -104.78643]}, %) // CubicBezierRelative
|> lineTo([116.68767000000003, -102.76643], %) // HorizontalLineRelative
|> lineTo([113.68767000000003, -108.76643], %) // LineRelative
|> bezierCurve({ control1: [101.68767000000003, -114.76643], control2: [109.73020000000002, -110.84932], to: [105.72846000000003, -112.85018]}, %) // CubicBezierRelative
|> lineTo([97.68766300000003, -118.76643], %) // LineRelative
|> lineTo([97.68766300000003, -125.76643], %) // VerticalLineHorizonal
|> lineTo([101.68767000000003, -128.76643], %) // LineRelative
|> bezierCurve({ control1: [115.75017000000003, -126.57893000000001], control2: [106.58566000000002, -128.61801000000003], to: [110.98125000000003, -127.69757000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [124.93767000000003, -122.01643000000001], control2: [120.74370000000002, -124.95192000000002], to: [120.74370000000002, -124.95192000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [134.68767000000003, -111.76643000000001], control2: [128.66063000000003, -118.78987000000001], to: [131.76465000000002, -115.73339000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [136.68767000000003, -96.76643500000002], control2: [137.05397000000002, -104.69775000000001], to: [137.05397000000002, -104.69775000000001]}, %) // CubicBezierRelative
|> lineTo([135.68767000000003, -95.76643500000002], %) // LineRelative
|> lineTo([144.68767000000003, -91.76643500000002], %) // LineRelative
|> lineTo([144.68767000000003, -89.76643500000002], %) // VerticalLineHorizonal
|> bezierCurve({ control1: [149.18767000000003, -88.95393500000002], control2: [146.91517000000002, -89.36425500000001], to: [146.91517000000002, -89.36425500000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [158.81267000000003, -86.20393500000002], control2: [154.52930000000003, -87.94347500000002], to: [154.52930000000003, -87.94347500000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [170.68767000000003, -83.76643500000002], control2: [162.68767000000003, -84.76643500000002], to: [162.68767000000003, -84.76643500000002]}, %) // CubicBezierRelative
|> lineTo([169.68767000000003, -87.76643500000002], %) // LineRelative
|> bezierCurve({ control1: [173.81267000000003, -124.20393000000001], control2: [169.31325000000004, -100.37193000000002], to: [170.34211000000002, -112.05696000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [175.68767000000003, -129.76643], control2: [174.43142000000003, -126.03956000000001], to: [175.05017000000004, -127.87518000000001]}, %) // CubicBezierRelative
|> lineTo([177.68767000000003, -129.76643], %) // HorizontalLineRelative
|> lineTo([179.68767000000003, -133.76643], %) // LineRelative
|> lineTo([185.68767000000003, -138.76643], %) // LineRelative
|> bezierCurve({ control1: [202.68767000000003, -139.76643], control2: [191.47452, -140.21315], to: [196.74116000000004, -140.04174]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [210.68767000000003, -135.76643], control2: [207.25921000000002, -138.23436], to: [207.25921000000002, -138.23436]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [215.35564000000002, -128.27815], control2: [213.71484000000004, -132.0027], to: [213.71484000000004, -132.0027]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [216.91033000000002, -104.88753000000001], control2: [217.63118000000003, -120.57069000000001], to: [217.01741, -112.86275]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [214.68767000000003, -85.76643500000002], control2: [216.67209000000003, -98.33796500000001], to: [216.17402, -92.15775500000001]}, %) // CubicBezierRelative
|> lineTo([210.68767000000003, -78.76643500000002], %) // LineRelative
|> lineTo([207.68767000000003, -78.76643500000002], %) // HorizontalLineRelative
|> lineTo([207.68767000000003, -75.76643500000002], %) // VerticalLineHorizonal
|> lineTo([203.68767000000003, -74.76643500000002], %) // LineRelative
|> lineTo([204.68767000000003, -70.76643500000002], %) // LineRelative
|> lineTo([209.50017000000003, -70.01643500000002], %) // LineRelative
|> bezierCurve({ control1: [226.68767000000003, -64.76643500000002], control2: [215.57464000000002, -68.78927500000002], to: [220.89892000000003, -66.95330500000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [247.31267000000003, -58.578935000000016], control2: [233.53624000000002, -62.60005500000001], to: [240.40800000000002, -60.55978500000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [277.21111, -48.92659500000001], control2: [257.37096, -55.63882500000002], to: [267.2794, -52.26503500000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [299.68767, -41.766435000000016], control2: [284.67443000000003, -46.437325000000016], to: [292.16675000000004, -44.07484500000001]}, %) // CubicBezierRelative
|> lineTo([299.68767, -39.766435000000016], %) // VerticalLineHorizonal
|> bezierCurve({ control1: [306.50017, -39.328935000000016], control2: [301.93580000000003, -39.62206500000001], to: [304.18392, -39.477685000000015]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [316.68767, -37.766435000000016], control2: [313.07319, -39.10529500000001], to: [313.07319, -39.10529500000001]}, %) // CubicBezierRelative
|> lineTo([316.68767, -35.766435000000016], %) // VerticalLineHorizonal
|> lineTo([320.56267, -35.016435000000016], %) // LineRelative
|> bezierCurve({ control1: [335.68767, -29.766435000000016], control2: [325.89187000000004, -33.71663500000002], to: [330.60815, -31.833685000000017]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [343.56267, -27.266435000000016], control2: [339.5858, -28.528935000000015], to: [339.5858, -28.528935000000015]}, %) // CubicBezierRelative
|> lineTo([350.68767, -24.766435000000016], %) // LineRelative
|> lineTo([354.68767, -20.766435000000016], %) // LineRelative
|> bezierCurve({ control1: [295.68767, -33.766435000000016], control2: [334.809, -20.766435000000016], to: [314.44364, -27.758665000000015]}, %) // CubicBezierRelative
// StopRelative
|> lineTo([299.68767, -66.76643500000002], %) // MoveRelative
|> bezierCurve({ control1: [285.00017, -76.64143500000002], control2: [293.75788, -69.23718500000001], to: [289.90768, -72.43500500000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [276.37517, -85.70393500000002], control2: [279.86247000000003, -81.42042500000002], to: [279.86247000000003, -81.42042500000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [273.68767, -88.76643500000002], control2: [275.48830000000004, -86.71456500000002], to: [274.60142, -87.72518500000001]}, %) // CubicBezierRelative
|> lineTo([267.68767, -91.76643500000002], %) // LineRelative
|> lineTo([264.68767, -96.76643500000002], %) // LineRelative
|> bezierCurve({ control1: [266.68767, -111.76643000000001], control2: [264.32138000000003, -104.69775000000001], to: [264.32138000000003, -104.69775000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [278.68767, -123.76643000000001], control2: [270.61411000000004, -116.17816000000002], to: [274.2035, -120.01380000000002]}, %) // CubicBezierRelative
|> lineTo([282.93767, -126.01643000000001], %) // LineRelative
|> bezierCurve({ control1: [303.68767, -126.76643000000001], control2: [289.896, -127.11512000000002], to: [296.66137000000003, -126.99871000000002]}, %) // CubicBezierRelative
|> lineTo([305.68767, -125.76643000000001], %) // LineRelative
|> lineTo([310.68767, -124.76643000000001], %) // LineRelative
|> lineTo([317.68767, -122.76643000000001], %) // LineRelative
|> bezierCurve({ control1: [324.37517, -113.14143000000001], control2: [322.56495, -117.43458000000001], to: [322.56495, -117.43458000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [327.68767, -96.76643500000002], control2: [326.02173000000005, -107.65292000000001], to: [327.05405, -102.46899000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [323.37517, -79.39143500000002], control2: [327.04242000000005, -90.45732500000001], to: [325.54155000000003, -85.36362500000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [320.68767, -73.76643500000002], control2: [322.48830000000004, -77.53518500000001], to: [321.60142, -75.67893500000001]}, %) // CubicBezierRelative
|> lineTo([315.68767, -68.76643500000002], %) // LineRelative
|> bezierCurve({ control1: [305.43767, -66.32893500000002], control2: [310.76687000000004, -66.51488500000002], to: [310.76687000000004, -66.51488500000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [299.68767, -66.76643500000002], control2: [302.59142, -66.54550500000002], to: [302.59142, -66.54550500000002]}, %) // CubicBezierRelative
// StopRelative
|> lineTo([240.68767000000003, -68.76643500000002], %) // MoveRelative
|> bezierCurve({ control1: [222.68767000000003, -80.76643500000002], control2: [233.66999, -72.11131500000002], to: [228.65800000000002, -75.79116500000002]}, %) // CubicBezierRelative
|> lineTo([219.68767000000003, -86.76643500000002], %) // LineRelative
|> bezierCurve({ control1: [222.55095000000003, -116.67268000000001], control2: [219.05386000000001, -97.26953500000002], to: [220.04332000000002, -106.46619000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [227.68767000000003, -130.76643], control2: [223.91824000000003, -121.59681000000002], to: [225.39892000000003, -126.18894000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [236.43377000000004, -136.4969], control2: [232.25590000000003, -134.74853000000002], to: [232.25590000000003, -134.74853000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [249.75017000000003, -138.07893], control2: [241.08415000000005, -137.88476], to: [244.90570000000002, -138.13253]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [254.34783000000002, -138.06723000000002], control2: [251.26740000000004, -138.07493000000002], to: [252.78463000000002, -138.07093]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [265.68767, -135.76644000000002], control2: [259.20097000000004, -137.88174000000004], to: [259.20097000000004, -137.88174000000004]}, %) // CubicBezierRelative
|> lineTo([265.68767, -132.76644000000002], %) // VerticalLineHorizonal
|> lineTo([267.68767, -132.76644000000002], %) // HorizontalLineRelative
|> bezierCurve({ control1: [268.56267, -122.32894000000002], control2: [268.96128000000004, -128.41242000000003], to: [268.96128000000004, -128.41242000000003]}, %) // CubicBezierRelative
|> lineTo([267.68767, -115.76644000000002], %) // LineRelative
|> lineTo([262.68767, -110.76644000000002], %) // LineRelative
|> lineTo([259.68767, -104.76644000000002], %) // LineRelative
|> lineTo([259.68767, -96.76644500000002], %) // VerticalLineHorizonal
|> lineTo([263.68767, -91.76644500000002], %) // LineRelative
|> lineTo([263.68767, -88.76644500000002], %) // VerticalLineHorizonal
|> lineTo([265.68767, -88.76644500000002], %) // HorizontalLineRelative
|> bezierCurve({ control1: [265.68767, -74.76644500000002], control2: [265.77327, -84.10056500000002], to: [265.76887000000005, -79.43241500000002]}, %) // CubicBezierRelative
|> lineTo([263.68767, -71.76644500000002], %) // LineRelative
|> lineTo([257.68767, -68.76644500000002], %) // LineRelative
|> bezierCurve({ control1: [240.68767000000003, -68.76644500000002], control2: [251.63750000000002, -68.30105500000002], to: [246.62747000000002, -68.01396500000001]}, %) // CubicBezierRelative
// StopRelative
|> lineTo([348.06267, -71.45394500000002], %) // MoveRelative
|> bezierCurve({ control1: [336.68767, -78.76644500000002], control2: [342.24112, -73.65657500000002], to: [342.24112, -73.65657500000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [331.68767, -85.76644500000002], control2: [333.86052, -82.22373500000002], to: [333.86052, -82.22373500000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [330.68767, -113.76644000000002], control2: [329.44062, -94.75465500000001], to: [330.36224000000004, -104.56387000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [333.68767, -125.76644000000002], control2: [331.54987, -120.49367000000002], to: [331.54987, -120.49367000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [339.68767, -134.76644000000002], control2: [336.35378000000003, -130.85268000000002], to: [336.35378000000003, -130.85268000000002]}, %) // CubicBezierRelative
|> lineTo([344.68767, -136.76644000000002], %) // LineRelative
|> bezierCurve({ control1: [354.50017, -136.89144000000002], control2: [347.95588000000004, -136.90388000000002], to: [351.22938000000005, -136.93595000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [359.7072, -136.83674000000002], control2: [357.07765, -136.86434000000003], to: [357.07765, -136.86434000000003]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [363.68767, -136.76644000000002], control2: [361.02076, -136.81354000000002], to: [362.33431, -136.79034000000001]}, %) // CubicBezierRelative
|> lineTo([364.68767, -133.76644000000002], %) // LineRelative
|> lineTo([369.68767, -132.76644000000002], %) // LineRelative
|> lineTo([374.68767, -127.76644000000002], %) // LineRelative
|> lineTo([375.68767, -125.76644000000002], %) // LineRelative
|> lineTo([378.68767, -124.76644000000002], %) // LineRelative
|> lineTo([381.68767, -119.76644000000002], %) // LineRelative
|> bezierCurve({ control1: [383.68767, -90.76644500000002], control2: [383.35291, -110.03795000000002], to: [384.23553000000004, -100.62782000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [376.68767, -74.76644500000002], control2: [381.89678000000004, -84.77624500000002], to: [379.89992, -80.12019500000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [361.68767, -69.76644500000002], control2: [371.66314, -72.44743500000001], to: [367.11478000000005, -70.85187500000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [348.06267, -71.45394500000002], control2: [353.98599, -69.38331500000002], to: [353.98599, -69.38331500000002]}, %) // CubicBezierRelative
// StopRelative
|> lineTo([420.68767, -75.76644500000002], %) // MoveRelative
|> lineTo([414.68767, -78.76644500000002], %) // MoveRelative
|> lineTo([411.68767, -81.76644500000002], %) // MoveRelative
|> bezierCurve({ control1: [394.68767, -89.76644500000002], control2: [406.10302, -84.70574500000002], to: [400.49226000000004, -87.27876500000002]}, %) // CubicBezierRelative
|> lineTo([390.68767, -93.76644500000002], %) // LineRelative
|> bezierCurve({ control1: [387.00017, -105.95394000000002], control2: [388.81932, -97.84915500000002], to: [387.7277, -101.52261000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [386.68767, -123.76644000000002], control2: [386.61176, -111.93554000000002], to: [386.45034000000004, -117.77373000000001]}, %) // CubicBezierRelative
|> lineTo([389.68767, -129.76644000000002], %) // LineRelative
|> bezierCurve({ control1: [401.68767, -140.76644000000002], control2: [393.59112000000005, -133.6699], to: [397.39354000000003, -137.31580000000002]}, %) // CubicBezierRelative
|> lineTo([406.68767, -142.76644000000002], %) // LineRelative
|> bezierCurve({ control1: [419.18767, -141.64144000000002], control2: [414.16723, -143.08983], to: [414.16723, -143.08983]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [431.68767, -133.76644000000002], control2: [424.08865000000003, -139.59937000000002], to: [427.61672000000004, -137.15890000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [438.81267, -125.32894000000002], control2: [436.54426, -129.29261000000002], to: [436.54426, -129.29261000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [443.68767, -106.76644000000002], control2: [441.36597, -119.11592000000002], to: [442.65924, -113.42420000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [442.68767, -87.76644500000002], control2: [443.82181, -100.36380000000001], to: [443.70527000000004, -94.09420500000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [438.68767, -79.76644500000002], control2: [441.01966000000004, -83.40792500000002], to: [441.01966000000004, -83.40792500000002]}, %) // CubicBezierRelative
|> lineTo([434.68767, -76.76644500000002], %) // LineRelative
|> bezierCurve({ control1: [420.68767, -75.76644500000002], control2: [428.38627, -75.54725500000002], to: [428.38627, -75.54725500000002]}, %) // CubicBezierRelative
|> lineTo([119.83194, -25.193075], %) // MoveRelative
|> bezierCurve({ control1: [126.83194, -26.193075], control2: [122.14194, -25.523075], to: [124.45194000000001, -25.853075]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [129.83194, -32.193075], control2: [127.82194, -28.173075], to: [128.81194, -30.153075]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [130.83194, -33.193075], control2: [130.16194000000002, -32.523075], to: [130.49194, -32.853075]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [131.83194, -41.193075], control2: [131.16194000000002, -35.833075], to: [131.49194, -38.473075]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [133.83194, -38.193075], control2: [132.49194, -40.203075], to: [133.15194, -39.213075]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [135.26944, -32.068075], control2: [134.30631, -36.171825], to: [134.78069, -34.150575]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [136.83194, -26.193075], control2: [135.78506000000002, -30.129325], to: [136.30069, -28.190575]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [139.83194, -25.193075], control2: [137.82194, -25.863075000000002], to: [138.81194, -25.533075]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [137.39444, -44.318075], control2: [139.51153, -31.793465], to: [139.18359, -37.939365]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [133.83194, -52.193075], control2: [135.83194, -48.193075], to: [135.83194, -48.193075]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [129.83194, -51.193075], control2: [132.51194, -51.863075], to: [131.19194000000002, -51.533075000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [124.83194, -41.193075], control2: [126.83194, -46.193075], to: [126.83194, -46.193075]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [120.83194, -51.193075], control2: [123.51194000000001, -44.493075], to: [122.19194, -47.793075]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [117.83194, -51.193075], control2: [119.84194000000001, -51.193075], to: [118.85194, -51.193075]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [116.83194, -50.193075], control2: [117.50194, -50.863075], to: [117.17194, -50.533075000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [118.83194, -26.193075], control2: [116.5899, -41.883314999999996], to: [116.78264, -34.269515]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [119.83194, -25.193075], control2: [119.16194, -25.863075000000002], to: [119.49194, -25.533075]}, %) // CubicBezierRelative
|> lineTo([65.254392, -26.686845], %) // MoveRelative
|> bezierCurve({ control1: [69.254392, -26.686845], control2: [66.57439199999999, -26.686845], to: [67.894392, -26.686845]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [70.254392, -32.686845000000005], control2: [69.584392, -28.666845000000002], to: [69.91439199999999, -30.646845000000003]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [69.254392, -35.686845000000005], control2: [69.924392, -33.67684500000001], to: [69.594392, -34.666845]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [69.254392, -44.686845000000005], control2: [69.21439199999999, -38.686575000000005], to: [69.210922, -41.687155000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [72.629392, -39.374345000000005], control2: [70.36814199999999, -42.93371500000001], to: [71.481892, -41.180595000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [78.254392, -30.686845000000005], control2: [74.483601, -36.465155], to: [76.34075899999999, -33.557295]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [81.254392, -30.686845000000005], control2: [79.24439199999999, -30.686845000000005], to: [80.234392, -30.686845000000005]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [80.004392, -42.811845000000005], control2: [81.254392, -38.686845000000005], to: [81.254392, -38.686845000000005]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [74.254392, -52.686845000000005], control2: [78.254392, -46.686845000000005], to: [78.254392, -46.686845000000005]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [73.254392, -53.686845000000005], control2: [73.924392, -53.016845], to: [73.594392, -53.346845]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [67.254392, -53.686845000000005], control2: [71.27439199999999, -53.686845000000005], to: [69.294392, -53.686845000000005]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [61.254391999999996, -48.686845000000005], control2: [65.27439199999999, -52.03684500000001], to: [63.294391999999995, -50.38684500000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [60.254391999999996, -46.686845000000005], control2: [60.924392, -48.02684500000001], to: [60.594392, -47.366845000000005]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [61.254391999999996, -28.686845000000005], control2: [60.10475399999999, -40.47687500000001], to: [60.373141, -34.855605000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [65.254392, -26.686845000000005], control2: [62.574391999999996, -28.026845000000005], to: [63.894391999999996, -27.366845000000005]}, %) // CubicBezierRelative
|> lineTo([185.48371, -31.108985], %) // MoveRelative
|> bezierCurve({ control1: [197.48371, -31.108985], control2: [189.48289, -31.028185], to: [193.48463, -31.022985000000002]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [198.48371, -36.108985000000004], control2: [197.81371000000001, -32.758985], to: [198.14371, -34.408985]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [197.48371, -38.108985000000004], control2: [198.15371, -36.768985], to: [197.82371, -37.428985000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [189.48371, -38.108985000000004], control2: [194.84371000000002, -38.108985000000004], to: [192.20371, -38.108985000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [188.48371, -42.108985000000004], control2: [189.15371, -39.428985000000004], to: [188.82371, -40.748985000000005]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [196.48371, -43.108985000000004], control2: [191.12371, -42.438985], to: [193.76371, -42.768985]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [196.48371, -47.108985000000004], control2: [196.48371, -44.428985000000004], to: [196.48371, -45.748985000000005]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [191.54621, -48.983985000000004], control2: [194.85433, -47.727735], to: [193.22496, -48.346485]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [186.48371, -51.108985000000004], control2: [189.87558, -49.685235000000006], to: [188.20496, -50.38648500000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [185.48371, -53.108985000000004], control2: [186.15371, -51.768985], to: [185.82371, -52.428985000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [195.48371, -52.108985000000004], control2: [188.78371, -52.778985000000006], to: [192.08371, -52.44898500000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [193.48371, -56.108985000000004], control2: [194.82371, -53.428985000000004], to: [194.16371, -54.748985000000005]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [188.48371, -58.108985000000004], control2: [191.83371, -56.768985], to: [190.18371, -57.428985000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [183.48371, -58.108985000000004], control2: [186.83371, -58.108985000000004], to: [185.18371, -58.108985000000004]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [179.48371, -55.108985000000004], control2: [182.16371, -57.118985], to: [180.84371000000002, -56.12898500000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [180.79621, -38.046485000000004], control2: [178.95086, -49.019255], to: [179.50181, -44.025395]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [182.48371, -33.108985000000004], control2: [181.35308, -36.41710500000001], to: [181.90996, -34.787735000000005]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [185.48371, -31.108985000000004], control2: [183.47371, -32.44898500000001], to: [184.46371, -31.788985000000004]}, %) // CubicBezierRelative
|> lineTo([248.52117, -92.100105], %) // MoveRelative
|> bezierCurve({ control1: [252.52117, -92.100105], control2: [249.84117, -92.100105], to: [251.16117, -92.100105]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [253.52117, -99.100105], control2: [252.85117000000002, -94.410105], to: [253.18117, -96.720105]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [248.89617, -100.8501], control2: [251.99492, -99.677605], to: [250.46867, -100.2551]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [237.52117, -107.1001], control2: [243.22058, -103.02548], to: [243.22058, -103.02548]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [236.52117, -109.1001], control2: [237.19117, -107.7601], to: [236.86117000000002, -108.42009999999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [252.52117, -108.1001], control2: [241.80117, -108.7701], to: [247.08117000000001, -108.4401]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [253.52117, -112.1001], control2: [252.85117000000002, -109.42009999999999], to: [253.18117, -110.7401]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [248.52117, -117.1001], control2: [251.87117, -113.7501], to: [250.22117, -115.4001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [234.52117, -118.1001], control2: [242.52117, -118.1001], to: [242.52117, -118.1001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [231.52117, -112.1001], control2: [233.53117, -116.1201], to: [232.54117000000002, -114.1401]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [231.52117, -104.1001], control2: [231.52117, -109.4601], to: [231.52117, -106.8201]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [236.52117, -99.100105], control2: [233.17117000000002, -102.45009999999999], to: [234.82117000000002, -100.8001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [236.52117, -97.100105], control2: [236.52117, -98.440105], to: [236.52117, -97.780105]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [248.52117, -92.100105], control2: [240.49514000000002, -95.372295], to: [244.49777, -93.709465]}, %) // CubicBezierRelative
|> lineTo([299.09756, -85.781585], %) // MoveRelative
|> bezierCurve({ control1: [305.09756, -85.781585], control2: [301.07756, -85.781585], to: [303.05755999999997, -85.781585]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [307.09756, -86.781585], control2: [305.75756, -86.111585], to: [306.41756, -86.441585]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [308.09756, -97.781585], control2: [307.48978999999997, -90.442425], to: [307.81822999999997, -94.110415]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [309.09756, -102.78158], control2: [308.42755999999997, -99.43158500000001], to: [308.75756, -101.08158]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [307.09756, -104.78158], control2: [308.43755999999996, -103.44158], to: [307.77756, -104.10158]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [306.09756, -108.78158], control2: [306.76756, -106.10158], to: [306.43755999999996, -107.42158]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [301.09756, -113.78158], control2: [304.43089, -110.44825], to: [302.76423, -112.11491000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [301.09756, -105.78158], control2: [301.09756, -111.14158], to: [301.09756, -108.50158]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [298.09756, -106.78158], control2: [300.10756, -106.11158], to: [299.11755999999997, -106.44158]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [294.09756, -105.78158], control2: [296.77756, -106.45158], to: [295.45756, -106.12158000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [293.09756, -111.78158], control2: [293.76756, -107.76158000000001], to: [293.43755999999996, -109.74158]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [290.09756, -114.78158], control2: [292.10756, -112.77158], to: [291.11755999999997, -113.76158000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [290.09756, -100.78158], control2: [290.09756, -110.16158], to: [290.09756, -105.54158000000001]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [292.09756, -100.78158], control2: [290.75756, -100.78158], to: [291.41756, -100.78158]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [293.34756, -95.531585], control2: [292.51006, -99.049085], to: [292.92256, -97.316585]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [295.09756, -89.781585], control2: [293.92506, -93.63408500000001], to: [294.50255999999996, -91.736585]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [299.09756, -85.781585], control2: [296.41756, -88.46158500000001], to: [297.73756, -87.141585]}, %) // CubicBezierRelative
|> lineTo([419.93938, -96.155625], %) // MoveRelative
|> bezierCurve({ control1: [424.75188, -96.218125], control2: [422.32157, -96.186525], to: [422.32157, -96.186525]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [425.75188, -102.21812], control2: [425.08188, -98.198125], to: [425.41188000000005, -100.17812]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [417.75188, -104.21812], control2: [423.11188000000004, -102.87812], to: [420.47188000000006, -103.53811999999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [415.75188, -107.21812], control2: [416.76188, -105.70312], to: [416.76188, -105.70312]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [422.75188, -108.21812], control2: [418.06188000000003, -107.54812], to: [420.37188000000003, -107.87812]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [423.75188, -112.21812], control2: [423.08188, -109.53811999999999], to: [423.41188000000005, -110.85812]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [413.75188, -117.21812], control2: [418.80188000000004, -114.69312], to: [418.80188000000004, -114.69312]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [422.75188, -117.21812], control2: [416.72188000000006, -117.21812], to: [419.69188, -117.21812]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [421.75188, -120.21812], control2: [422.42188000000004, -118.20812], to: [422.09188, -119.19812]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [418.75188, -122.21812], control2: [420.76188, -120.87812], to: [419.77188, -121.53811999999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [411.75188, -123.21812], control2: [416.44188, -122.54812], to: [414.13188, -122.87812]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [407.75188, -121.21812], control2: [410.43188000000004, -122.55812], to: [409.11188000000004, -121.89812]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [409.18938, -103.59312], control2: [407.53385000000003, -114.968], to: [407.63543000000004, -109.67378]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [411.75188, -97.218125], control2: [410.75188, -99.218125], to: [410.75188, -99.218125]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [419.93938, -96.155625], control2: [414.75188, -96.218125], to: [414.75188, -96.218125]}, %) // CubicBezierRelative
|> lineTo([198.29461, -92.109945], %) // MoveRelative
|> bezierCurve({ control1: [202.29461, -92.109945], control2: [199.61461, -92.109945], to: [200.93461, -92.109945]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [205.29461, -97.109945], control2: [203.28461000000001, -93.759945], to: [204.27461, -95.409945]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [205.29461, -104.10994], control2: [205.29461, -99.419945], to: [205.29461, -101.72994]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [203.29461, -103.10994], control2: [204.63461, -103.77994], to: [203.97461, -103.44994]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [203.29461, -101.10994], control2: [203.29461, -102.44994], to: [203.29461, -101.78994]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [195.29461, -105.10994], control2: [200.58634, -102.35660999999999], to: [197.91966, -103.69645]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [194.29461, -108.10994], control2: [194.96461, -106.09993999999999], to: [194.63461, -107.08994]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [201.29461, -110.10994], control2: [196.60461, -108.76993999999999], to: [198.91461, -109.42993999999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [203.29461, -112.10994], control2: [201.95461, -110.76993999999999], to: [202.61461, -111.42993999999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [203.29461, -117.10994], control2: [203.29461, -113.75994], to: [203.29461, -115.40993999999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [195.29461, -120.10994], control2: [200.65652, -118.18306], to: [197.98453, -119.17430999999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [190.29461, -120.10994], control2: [193.64461, -120.10994], to: [191.99461, -120.10994]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [188.29461, -117.10994], control2: [189.63461, -119.11994], to: [188.97461, -118.12993999999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [194.29461, -114.10994], control2: [190.27461, -116.11994], to: [192.25461, -115.12993999999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [188.29461, -110.10994], control2: [192.31461000000002, -112.78994], to: [190.33461, -111.46994]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [186.29461, -107.10994], control2: [187.63461, -109.11994], to: [186.97461, -108.12993999999999]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [187.29461, -101.10994], control2: [186.62461000000002, -105.12993999999999], to: [186.95461, -103.14994]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [191.29461, -96.109945], control2: [188.61461, -99.45994499999999], to: [189.93461, -97.809945]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [198.29461, -92.109945], control2: [193.60461, -94.789945], to: [195.91461, -93.469945]}, %) // CubicBezierRelative
|> lineTo([0, -0], %) // MoveRelative
|> bezierCurve({ control1: [3, -1], control2: [0.99, -0.33], to: [1.98, -0.66]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [3, -4], control2: [3, -1.99], to: [3, -2.98]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [8, -4], control2: [4.65, -4], to: [6.3, -4]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [13, -6], control2: [10.475, -4.99], to: [10.475, -4.99]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [13, -10], control2: [13, -7.32], to: [13, -8.64]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [7, -12], control2: [11.02, -10.66], to: [9.04, -11.32]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [3, -12], control2: [5.68, -12], to: [4.36, -12] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [0, -19], control2: [2.01, -14.31], to: [1.02, -16.62] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [-2, -18], control2: [-0.66, -18.67], to: [-1.32, -18.34] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [-3, -8], control2: [-2.383986, -14.672121], to: [-2.7150643, -11.337819] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [-4, -5], control2: [-3.33, -7.01], to: [-3.66, -6.02] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [-1, -5], control2: [-3.01, -5], to: [-2.02, -5]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [0, -0], control2: [-0.6699999999999999, -3.35], to: [-0.33999999999999997, -1.7000000000000002]}, %) // CubicBezierRelative
|> lineTo([0, -0], %) // MoveRelative
|> bezierCurve({ control1: [7, -0], control2: [2.31, -0], to: [4.62, -0]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [17, -5], control2: [12.3125, -2.3125], to: [12.3125, -2.3125]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [19, -8], control2: [17.99, -6.485], to: [17.99, -6.485]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [17, -14], control2: [18.333333, -10], to: [17.666667, -12]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [15, -14], control2: [16.34, -14], to: [15.68, -14]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [14, -9], control2: [14.67, -12.35], to: [14.34, -10.7] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [6, -8], control2: [11.36, -8.67], to: [8.72, -8.34] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [6, -6], control2: [6, -7.34], to: [6, -6.68] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [1, -5], control2: [4.35, -5.67], to: [2.7, -5.34] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [0, -0], control2: [0.67, -3.35], to: [0.34, -1.7] }, %) // CubicBezierAbsolute
|> lineTo([-19.467588, -31.053017], %) // MoveRelative
|> bezierCurve({ control1: [-12.467588, -32.053017], control2: [-17.157588, -31.383017], to: [-14.847587999999998, -31.713017]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [-10.467588, -34.053017], control2: [-11.807587999999999, -32.713016999999994], to: [-11.147587999999999, -33.373017]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [-10.467588, -39.053017], control2: [-10.467588, -35.703016999999996], to: [-10.467588, -37.353016999999994]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [-14.467588, -37.053017], control2: [-11.787588, -38.393017], to: [-13.107588, -37.733017]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [-14.467588, -40.053017], control2: [-14.467588, -38.043017], to: [-14.467588, -39.033016999999994]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [-26.467588, -40.053017], control2: [-18.427588, -40.053017], to: [-22.387588, -40.053017]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [-24.467588, -38.053017], control2: [-25.807588, -39.393017], to: [-25.147588, -38.733017]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [-17.467588, -36.053017], control2: [-22.157588, -37.393017], to: [-19.847588, -36.733017]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [-21.467588, -34.053017], control2: [-18.787588, -35.393017], to: [-20.107588, -34.733017]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [-21.467588, -32.053017], control2: [-21.467588, -33.393017], to: [-21.467588, -32.733017]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [-19.467588, -31.053016999999997], control2: [-20.807588, -31.723017], to: [-20.147588, -31.393016999999997]}, %) // CubicBezierRelative
|> lineTo([0, -0], %) // MoveRelative
|> bezierCurve({ control1: [16, -3], control2: [5.4494016, -0.77848594], to: [10.65681, -1.7240142]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [18, -4], control2: [16.66, -3.33], to: [17.32, -3.66]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [18, -6], control2: [18, -4.66], to: [18, -5.32]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [14, -8], control2: [16.02, -6.99], to: [16.02, -6.99] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [7, -7], control2: [11.69, -7.67], to: [9.38, -7.34] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [1, -3], control2: [5.02, -5.68], to: [3.04, -4.36] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [1, -8], control2: [1, -4.65], to: [1, -6.3] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [-3, -7], control2: [-0.32, -7.67], to: [-1.64, -7.34] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [-4, -3], control2: [-3.33, -5.68], to: [-3.66, -4.36] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [0, -0], control2: [-2.68, -2.01], to: [-1.36, -1.02] }, %) // CubicBezierAbsolute
|> lineTo([0, -0], %) // MoveAbsolute
|> bezierCurve({ control1: [7, -0], control2: [2.31, -0], to: [4.62, -0] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [7, -4], control2: [7, -1.32], to: [7, -2.64] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [9, -5], control2: [7.66, -4.33], to: [8.32, -4.66] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [5, -7], control2: [7.02, -5.99], to: [7.02, -5.99] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [8, -8], control2: [5.99, -7.33], to: [6.98, -7.66] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [5, -12], control2: [7.01, -9.32], to: [6.02, -10.64] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [6, -18], control2: [5.33, -13.98], to: [5.66, -15.96] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [2, -21], control2: [4.68, -18.99], to: [3.36, -19.98] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [0, -21], control2: [1.34, -21], to: [0.68, -21] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [2, -3], control2: [-0.18556857, -14.319532], to: [0.34378347, -9.6248661] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [0, -3], control2: [1.34, -3], to: [0.68, -3] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [0, -0], control2: [0, -2.01], to: [0, -1.02] }, %) // CubicBezierAbsolute
|> lineTo([0, -0], %) // MoveRelative
|> bezierCurve({ control1: [1, -4], control2: [0.33, -1.32], to: [0.66, -2.64]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [9, -4], control2: [3.64, -4], to: [6.28, -4]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [12, -1], control2: [9.99, -3.01], to: [10.98, -2.02]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [12, -3], control2: [12, -1.6600000000000001], to: [12, -2.3200000000000003]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [15, -4], control2: [12.99, -3.33], to: [13.98, -3.66]}, %) // CubicBezierRelative
|> bezierCurve({ control1: [12, -6], control2: [14.01, -4.66], to: [13.02, -5.32] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [2, -7], control2: [8.6740937, -6.4007116], to: [5.3398344, -6.7397532] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [9, -11], control2: [5.465, -8.98], to: [5.465, -8.98] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [9, -12], control2: [9, -11.33], to: [9, -11.66] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [1, -11], control2: [6.36, -11.67], to: [3.72, -11.34] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [-2, -9], control2: [0.01, -10.34], to: [-0.98, -9.68] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [-2, -4], control2: [-2, -7.35], to: [-2, -5.7] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [-4, -3], control2: [-2.66, -3.67], to: [-3.32, -3.34] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [0, -2], control2: [-2.68, -2.67], to: [-1.36, -2.34] }, %) // CubicBezierAbsolute
|> bezierCurve({ control1: [0, -0], control2: [0, -1.34], to: [0, -0.68] }, %) // CubicBezierAbsolute
|> close(%);
show(svg);

View File

@ -85,6 +85,25 @@ show(fnBox)"#;
twenty_twenty::assert_image("tests/executor/outputs/function_sketch.png", &result, 1.0);
}
#[tokio::test(flavor = "multi_thread")]
async fn serial_test_execute_with_function_sketch_with_position() {
let code = r#"fn box = (p, h, l, w) => {
const myBox = startSketchAt(p)
|> line([0, l], %)
|> line([w, 0], %)
|> line([0, -l], %)
|> close(%)
|> extrude(h, %)
return myBox
}
show(box([0,0], 3, 6, 10))"#;
let result = execute_and_snapshot(code).await.unwrap();
twenty_twenty::assert_image("tests/executor/outputs/function_sketch_with_position.png", &result, 1.0);
}
#[tokio::test(flavor = "multi_thread")]
async fn serial_test_execute_with_angled_line() {
let code = r#"const part001 = startSketchAt([4.83, 12.56])
@ -145,3 +164,40 @@ async fn serial_test_execute_engine_error_return() {
r#"engine: KclErrorDetails { source_ranges: [SourceRange([193, 206])], message: "Modeling command failed: Some([ApiError { error_code: BadRequest, message: \"The path is not closed. Solid2D construction requires a closed path!\" }])" }"#,
);
}
#[tokio::test(flavor = "multi_thread")]
#[ignore] // ignore until more stack fixes
async fn serial_test_execute_pipes_on_pipes() {
let code = include_str!("inputs/pipes_on_pipes.kcl");
let result = execute_and_snapshot(code).await.unwrap();
twenty_twenty::assert_image("tests/executor/outputs/pipes_on_pipes.png", &result, 1.0);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_member_expression_sketch_group() {
let code = r#"fn cube = (pos, scale) => {
const sg = startSketchAt(pos)
|> line([0, scale], %)
|> line([scale, 0], %)
|> line([0, -scale], %)
return sg
}
const b1 = cube([0,0], 10)
const b2 = cube([3,3], 4)
const pt1 = b1.value[0]
const pt2 = b2.value[0]
show(b1)
show(b2)"#;
let result = execute_and_snapshot(code).await.unwrap();
twenty_twenty::assert_image(
"tests/executor/outputs/member_expression_sketch_group.png",
&result,
1.0,
);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -1530,10 +1530,10 @@
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
"@kittycad/lib@^0.0.37":
version "0.0.37"
resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.0.37.tgz#ec4f6c4fb5d06402a19339f3374036b6582d2265"
integrity sha512-P8p9FeLV79/0Lfd0RioBta1drzhmpROnU4YV38+zsAA4LhibQCTjeekRkxVvHztGumPxz9pPsAeeLJyuz2RWKQ==
"@kittycad/lib@^0.0.38":
version "0.0.38"
resolved "https://registry.yarnpkg.com/@kittycad/lib/-/lib-0.0.38.tgz#50474266f679990bd414c30f884f2d42a0d5dba9"
integrity sha512-Lv9P7jqVRoGgOnCsRCsG8OwZH5n3scxXYrElR+5/Rsd6/KIarLB4bSBngJrXebOnmTw5md0OPeY+b3ZDbZFDeg==
dependencies:
node-fetch "3.3.2"
openapi-types "^12.0.0"