Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
33822b5a19 | |||
a2a4daebe3 | |||
a17ede50bd | |||
2d452f80d1 | |||
cf39c08428 | |||
2f25564fcc | |||
fd2ed8acbd | |||
5f3e1cfb6c | |||
ee767afc3f | |||
8071eb6f8a | |||
11f789e980 | |||
3f82522fe9 | |||
c5cb0e2fd4 |
@ -1,6 +1,6 @@
|
|||||||
VITE_KC_API_WS_MODELING_URL=wss://api.dev.kittycad.io/ws/modeling/commands
|
VITE_KC_API_WS_MODELING_URL=wss://api.kittycad.io/ws/modeling/commands
|
||||||
VITE_KC_API_BASE_URL=https://api.dev.kittycad.io
|
VITE_KC_API_BASE_URL=https://api.kittycad.io
|
||||||
VITE_KC_SITE_BASE_URL=https://dev.kittycad.io
|
VITE_KC_SITE_BASE_URL=https://kittycad.io
|
||||||
VITE_KC_SKIP_AUTH=false
|
VITE_KC_SKIP_AUTH=false
|
||||||
VITE_KC_CONNECTION_TIMEOUT_MS=5000
|
VITE_KC_CONNECTION_TIMEOUT_MS=15000
|
||||||
VITE_KC_SENTRY_DSN=
|
VITE_KC_SENTRY_DSN=
|
||||||
|
11
.github/workflows/cargo-clippy.yml
vendored
11
.github/workflows/cargo-clippy.yml
vendored
@ -40,6 +40,17 @@ jobs:
|
|||||||
- name: Rust Cache
|
- name: Rust Cache
|
||||||
uses: Swatinem/rust-cache@v2.6.1
|
uses: Swatinem/rust-cache@v2.6.1
|
||||||
|
|
||||||
|
- name: Install ffmpeg
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install \
|
||||||
|
ffmpeg \
|
||||||
|
libavformat-dev \
|
||||||
|
libavutil-dev \
|
||||||
|
libclang-dev \
|
||||||
|
libswscale-dev \
|
||||||
|
--no-install-recommends
|
||||||
|
|
||||||
- name: Run clippy
|
- name: Run clippy
|
||||||
run: |
|
run: |
|
||||||
cd "${{ matrix.dir }}"
|
cd "${{ matrix.dir }}"
|
||||||
|
10
.github/workflows/cargo-test.yml
vendored
10
.github/workflows/cargo-test.yml
vendored
@ -41,6 +41,16 @@ jobs:
|
|||||||
- uses: taiki-e/install-action@nextest
|
- uses: taiki-e/install-action@nextest
|
||||||
- name: Rust Cache
|
- name: Rust Cache
|
||||||
uses: Swatinem/rust-cache@v2.6.1
|
uses: Swatinem/rust-cache@v2.6.1
|
||||||
|
- name: Install ffmpeg
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install \
|
||||||
|
ffmpeg \
|
||||||
|
libavformat-dev \
|
||||||
|
libavutil-dev \
|
||||||
|
libclang-dev \
|
||||||
|
libswscale-dev \
|
||||||
|
--no-install-recommends
|
||||||
- name: cargo test
|
- name: cargo test
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |-
|
run: |-
|
||||||
|
40
.github/workflows/ci.yml
vendored
40
.github/workflows/ci.yml
vendored
@ -153,6 +153,8 @@ jobs:
|
|||||||
needs: [build-test-web, build-apps]
|
needs: [build-test-web, build-apps]
|
||||||
env:
|
env:
|
||||||
VERSION_NO_V: ${{ needs.build-test-web.outputs.version }}
|
VERSION_NO_V: ${{ needs.build-test-web.outputs.version }}
|
||||||
|
PUB_DATE: ${{ github.event.release.created_at }}
|
||||||
|
NOTES: ${{ github.event.release.body }}
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v3
|
||||||
@ -166,6 +168,8 @@ jobs:
|
|||||||
RELEASE_DIR=https://dl.kittycad.io/releases/modeling-app/v${VERSION_NO_V}
|
RELEASE_DIR=https://dl.kittycad.io/releases/modeling-app/v${VERSION_NO_V}
|
||||||
jq --null-input \
|
jq --null-input \
|
||||||
--arg version "v${VERSION_NO_V}" \
|
--arg version "v${VERSION_NO_V}" \
|
||||||
|
--arg pub_date "${PUB_DATE}" \
|
||||||
|
--arg notes "${NOTES}" \
|
||||||
--arg darwin_sig "$DARWIN_SIG" \
|
--arg darwin_sig "$DARWIN_SIG" \
|
||||||
--arg darwin_url "$RELEASE_DIR/macos/KittyCAD%20Modeling.app.tar.gz" \
|
--arg darwin_url "$RELEASE_DIR/macos/KittyCAD%20Modeling.app.tar.gz" \
|
||||||
--arg linux_sig "$LINUX_SIG" \
|
--arg linux_sig "$LINUX_SIG" \
|
||||||
@ -174,6 +178,8 @@ jobs:
|
|||||||
--arg windows_url "$RELEASE_DIR/nsis/KittyCAD%20Modeling_${VERSION_NO_V}_x64-setup.nsis.zip" \
|
--arg windows_url "$RELEASE_DIR/nsis/KittyCAD%20Modeling_${VERSION_NO_V}_x64-setup.nsis.zip" \
|
||||||
'{
|
'{
|
||||||
"version": $version,
|
"version": $version,
|
||||||
|
"pub_date": $pub_date,
|
||||||
|
"notes": $notes,
|
||||||
"platforms": {
|
"platforms": {
|
||||||
"darwin-x86_64": {
|
"darwin-x86_64": {
|
||||||
"signature": $darwin_sig,
|
"signature": $darwin_sig,
|
||||||
@ -195,6 +201,34 @@ jobs:
|
|||||||
}' > last_update.json
|
}' > last_update.json
|
||||||
cat last_update.json
|
cat last_update.json
|
||||||
|
|
||||||
|
- name: Generate the download static endpoint
|
||||||
|
run: |
|
||||||
|
RELEASE_DIR=https://dl.kittycad.io/releases/modeling-app/v${VERSION_NO_V}
|
||||||
|
jq --null-input \
|
||||||
|
--arg version "v${VERSION_NO_V}" \
|
||||||
|
--arg pub_date "${PUB_DATE}" \
|
||||||
|
--arg notes "${NOTES}" \
|
||||||
|
--arg darwin_url "$RELEASE_DIR/dmg/KittyCAD%20Modeling_${VERSION_NO_V}_universal.dmg" \
|
||||||
|
--arg linux_url "$RELEASE_DIR/appimage/kittycad-modeling_${VERSION_NO_V}_amd64.AppImage" \
|
||||||
|
--arg windows_url "$RELEASE_DIR/msi/KittyCAD%20Modeling_${VERSION_NO_V}_x64_en-US.msi.zip" \
|
||||||
|
'{
|
||||||
|
"version": $version,
|
||||||
|
"pub_date": $pub_date,
|
||||||
|
"notes": $notes,
|
||||||
|
"platforms": {
|
||||||
|
"dmg-universal": {
|
||||||
|
"url": $darwin_url
|
||||||
|
},
|
||||||
|
"appimage-x86_64": {
|
||||||
|
"url": $linux_url
|
||||||
|
},
|
||||||
|
"msi-x86_64": {
|
||||||
|
"url": $windows_url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}' > last_download.json
|
||||||
|
cat last_download.json
|
||||||
|
|
||||||
- name: Authenticate to Google Cloud
|
- name: Authenticate to Google Cloud
|
||||||
uses: 'google-github-actions/auth@v1.1.1'
|
uses: 'google-github-actions/auth@v1.1.1'
|
||||||
with:
|
with:
|
||||||
@ -219,6 +253,12 @@ jobs:
|
|||||||
path: last_update.json
|
path: last_update.json
|
||||||
destination: dl.kittycad.io/releases/modeling-app
|
destination: dl.kittycad.io/releases/modeling-app
|
||||||
|
|
||||||
|
- name: Upload download endpoint to public bucket
|
||||||
|
uses: google-github-actions/upload-cloud-storage@v1.0.3
|
||||||
|
with:
|
||||||
|
path: last_download.json
|
||||||
|
destination: dl.kittycad.io/releases/modeling-app
|
||||||
|
|
||||||
- name: Upload release files to Github
|
- name: Upload release files to Github
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "untitled-app",
|
"name": "untitled-app",
|
||||||
"version": "0.5.0",
|
"version": "0.6.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.9.0",
|
"@codemirror/autocomplete": "^6.9.0",
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "kittycad-modeling",
|
"productName": "kittycad-modeling",
|
||||||
"version": "0.5.0"
|
"version": "0.6.1"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
|
82
src/App.tsx
82
src/App.tsx
@ -73,7 +73,9 @@ export function App() {
|
|||||||
streamDimensions,
|
streamDimensions,
|
||||||
setIsExecuting,
|
setIsExecuting,
|
||||||
defferedCode,
|
defferedCode,
|
||||||
|
guiMode,
|
||||||
} = useStore((s) => ({
|
} = useStore((s) => ({
|
||||||
|
guiMode: s.guiMode,
|
||||||
addLog: s.addLog,
|
addLog: s.addLog,
|
||||||
defferedCode: s.defferedCode,
|
defferedCode: s.defferedCode,
|
||||||
setCode: s.setCode,
|
setCode: s.setCode,
|
||||||
@ -181,7 +183,18 @@ export function App() {
|
|||||||
const asyncWrap = async () => {
|
const asyncWrap = async () => {
|
||||||
try {
|
try {
|
||||||
if (!defferedCode) {
|
if (!defferedCode) {
|
||||||
setAst(null)
|
setAst({
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
body: [],
|
||||||
|
nonCodeMeta: {
|
||||||
|
noneCodeNodes: {},
|
||||||
|
start: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
setProgramMemory({ root: {}, return: null })
|
||||||
|
engineCommandManager.endSession()
|
||||||
|
engineCommandManager.startNewSession()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const _ast = await asyncParser(defferedCode)
|
const _ast = await asyncParser(defferedCode)
|
||||||
@ -196,26 +209,27 @@ export function App() {
|
|||||||
{
|
{
|
||||||
root: {
|
root: {
|
||||||
_0: {
|
_0: {
|
||||||
type: 'userVal',
|
type: 'UserVal',
|
||||||
value: 0,
|
value: 0,
|
||||||
__meta: [],
|
__meta: [],
|
||||||
},
|
},
|
||||||
_90: {
|
_90: {
|
||||||
type: 'userVal',
|
type: 'UserVal',
|
||||||
value: 90,
|
value: 90,
|
||||||
__meta: [],
|
__meta: [],
|
||||||
},
|
},
|
||||||
_180: {
|
_180: {
|
||||||
type: 'userVal',
|
type: 'UserVal',
|
||||||
value: 180,
|
value: 180,
|
||||||
__meta: [],
|
__meta: [],
|
||||||
},
|
},
|
||||||
_270: {
|
_270: {
|
||||||
type: 'userVal',
|
type: 'UserVal',
|
||||||
value: 270,
|
value: 270,
|
||||||
__meta: [],
|
__meta: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
return: null,
|
||||||
},
|
},
|
||||||
engineCommandManager
|
engineCommandManager
|
||||||
)
|
)
|
||||||
@ -223,6 +237,9 @@ export function App() {
|
|||||||
const { artifactMap, sourceRangeMap } =
|
const { artifactMap, sourceRangeMap } =
|
||||||
await engineCommandManager.waitForAllCommands()
|
await engineCommandManager.waitForAllCommands()
|
||||||
setIsExecuting(false)
|
setIsExecuting(false)
|
||||||
|
if (programMemory !== undefined) {
|
||||||
|
setProgramMemory(programMemory)
|
||||||
|
}
|
||||||
|
|
||||||
setArtifactMap({ artifactMap, sourceRangeMap })
|
setArtifactMap({ artifactMap, sourceRangeMap })
|
||||||
const unSubHover = engineCommandManager.subscribeToUnreliable({
|
const unSubHover = engineCommandManager.subscribeToUnreliable({
|
||||||
@ -251,9 +268,6 @@ export function App() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
unsubFn.push(unSubHover, unSubClick)
|
unsubFn.push(unSubHover, unSubClick)
|
||||||
if (programMemory !== undefined) {
|
|
||||||
setProgramMemory(programMemory)
|
|
||||||
}
|
|
||||||
|
|
||||||
setError()
|
setError()
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
@ -287,8 +301,41 @@ export function App() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const newCmdId = uuidv4()
|
const newCmdId = uuidv4()
|
||||||
|
if (buttonDownInStream === undefined) {
|
||||||
if (buttonDownInStream) {
|
if (
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === ('sketch_line' as any)
|
||||||
|
) {
|
||||||
|
debounceSocketSend({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: newCmdId,
|
||||||
|
cmd: {
|
||||||
|
type: 'mouse_move',
|
||||||
|
window: { x, y },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
debounceSocketSend({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd: {
|
||||||
|
type: 'highlight_set_entity',
|
||||||
|
selected_at_window: { x, y },
|
||||||
|
},
|
||||||
|
cmd_id: newCmdId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (guiMode.mode === 'sketch' && guiMode.sketchMode === ('move' as any)) {
|
||||||
|
debounceSocketSend({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: newCmdId,
|
||||||
|
cmd: {
|
||||||
|
type: 'handle_mouse_drag_move',
|
||||||
|
window: { x, y },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
const interactionGuards = cameraMouseDragGuards[cameraControls]
|
const interactionGuards = cameraMouseDragGuards[cameraControls]
|
||||||
let interaction: CameraDragInteractionType_type
|
let interaction: CameraDragInteractionType_type
|
||||||
|
|
||||||
@ -301,8 +348,10 @@ export function App() {
|
|||||||
} else if (interactionGuards.zoom.dragCallback(eWithButton)) {
|
} else if (interactionGuards.zoom.dragCallback(eWithButton)) {
|
||||||
interaction = 'zoom'
|
interaction = 'zoom'
|
||||||
} else {
|
} else {
|
||||||
|
console.log('none')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
debounceSocketSend({
|
debounceSocketSend({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd: {
|
cmd: {
|
||||||
@ -312,15 +361,6 @@ export function App() {
|
|||||||
},
|
},
|
||||||
cmd_id: newCmdId,
|
cmd_id: newCmdId,
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
debounceSocketSend({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd: {
|
|
||||||
type: 'highlight_set_entity',
|
|
||||||
selected_at_window: { x, y },
|
|
||||||
},
|
|
||||||
cmd_id: newCmdId,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -349,11 +389,11 @@ export function App() {
|
|||||||
paneOpacity
|
paneOpacity
|
||||||
}
|
}
|
||||||
defaultSize={{
|
defaultSize={{
|
||||||
width: '400px',
|
width: '550px',
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
}}
|
}}
|
||||||
minWidth={200}
|
minWidth={200}
|
||||||
maxWidth={600}
|
maxWidth={800}
|
||||||
minHeight={'auto'}
|
minHeight={'auto'}
|
||||||
maxHeight={'auto'}
|
maxHeight={'auto'}
|
||||||
handleClasses={{
|
handleClasses={{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useStore, toolTips } from './useStore'
|
import { useStore, toolTips, Selections } from './useStore'
|
||||||
import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst'
|
import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst'
|
||||||
import { getNodePathFromSourceRange } from './lang/queryAst'
|
import { getNodePathFromSourceRange } from './lang/queryAst'
|
||||||
import { HorzVert } from './components/Toolbar/HorzVert'
|
import { HorzVert } from './components/Toolbar/HorzVert'
|
||||||
@ -15,6 +15,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|||||||
import { faSearch, faX } from '@fortawesome/free-solid-svg-icons'
|
import { faSearch, faX } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { Popover, Transition } from '@headlessui/react'
|
import { Popover, Transition } from '@headlessui/react'
|
||||||
import styles from './Toolbar.module.css'
|
import styles from './Toolbar.module.css'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import { useAppMode } from 'hooks/useAppMode'
|
||||||
|
|
||||||
export const Toolbar = () => {
|
export const Toolbar = () => {
|
||||||
const {
|
const {
|
||||||
@ -24,6 +26,7 @@ export const Toolbar = () => {
|
|||||||
ast,
|
ast,
|
||||||
updateAst,
|
updateAst,
|
||||||
programMemory,
|
programMemory,
|
||||||
|
engineCommandManager,
|
||||||
} = useStore((s) => ({
|
} = useStore((s) => ({
|
||||||
guiMode: s.guiMode,
|
guiMode: s.guiMode,
|
||||||
setGuiMode: s.setGuiMode,
|
setGuiMode: s.setGuiMode,
|
||||||
@ -31,7 +34,9 @@ export const Toolbar = () => {
|
|||||||
ast: s.ast,
|
ast: s.ast,
|
||||||
updateAst: s.updateAst,
|
updateAst: s.updateAst,
|
||||||
programMemory: s.programMemory,
|
programMemory: s.programMemory,
|
||||||
|
engineCommandManager: s.engineCommandManager,
|
||||||
}))
|
}))
|
||||||
|
useAppMode()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('guiMode', guiMode)
|
console.log('guiMode', guiMode)
|
||||||
@ -39,7 +44,7 @@ export const Toolbar = () => {
|
|||||||
|
|
||||||
function ToolbarButtons() {
|
function ToolbarButtons() {
|
||||||
return (
|
return (
|
||||||
<>
|
<span className="overflow-x-auto">
|
||||||
{guiMode.mode === 'default' && (
|
{guiMode.mode === 'default' && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -71,9 +76,18 @@ export const Toolbar = () => {
|
|||||||
SketchOnFace
|
SketchOnFace
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{(guiMode.mode === 'canEditSketch' || false) && (
|
{guiMode.mode === 'canEditSketch' && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
console.log('guiMode.pathId', guiMode.pathId)
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'edit_mode_enter',
|
||||||
|
target: guiMode.pathId,
|
||||||
|
},
|
||||||
|
})
|
||||||
setGuiMode({
|
setGuiMode({
|
||||||
mode: 'sketch',
|
mode: 'sketch',
|
||||||
sketchMode: 'sketchEdit',
|
sketchMode: 'sketchEdit',
|
||||||
@ -125,14 +139,23 @@ export const Toolbar = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{guiMode.mode === 'sketch' && (
|
{guiMode.mode === 'sketch' && (
|
||||||
<button onClick={() => setGuiMode({ mode: 'default' })}>
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: { type: 'edit_mode_exit' },
|
||||||
|
})
|
||||||
|
setGuiMode({ mode: 'default' })
|
||||||
|
}}
|
||||||
|
>
|
||||||
Exit sketch
|
Exit sketch
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{toolTips
|
{toolTips
|
||||||
.filter(
|
.filter(
|
||||||
// (sketchFnName) => !['angledLineThatIntersects'].includes(sketchFnName)
|
// (sketchFnName) => !['angledLineThatIntersects'].includes(sketchFnName)
|
||||||
(sketchFnName) => ['line'].includes(sketchFnName)
|
(sketchFnName) => ['sketch_line', 'move'].includes(sketchFnName)
|
||||||
)
|
)
|
||||||
.map((sketchFnName) => {
|
.map((sketchFnName) => {
|
||||||
if (
|
if (
|
||||||
@ -143,7 +166,18 @@ export const Toolbar = () => {
|
|||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={sketchFnName}
|
key={sketchFnName}
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'set_tool',
|
||||||
|
tool:
|
||||||
|
guiMode.sketchMode === sketchFnName
|
||||||
|
? 'select'
|
||||||
|
: (sketchFnName as any),
|
||||||
|
},
|
||||||
|
})
|
||||||
setGuiMode({
|
setGuiMode({
|
||||||
...guiMode,
|
...guiMode,
|
||||||
...(guiMode.sketchMode === sketchFnName
|
...(guiMode.sketchMode === sketchFnName
|
||||||
@ -153,10 +187,11 @@ export const Toolbar = () => {
|
|||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
sketchMode: sketchFnName,
|
sketchMode: sketchFnName,
|
||||||
|
waitingFirstClick: true,
|
||||||
isTooltip: true,
|
isTooltip: true,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}}
|
||||||
>
|
>
|
||||||
{sketchFnName}
|
{sketchFnName}
|
||||||
{guiMode.sketchMode === sketchFnName && '✅'}
|
{guiMode.sketchMode === sketchFnName && '✅'}
|
||||||
@ -180,7 +215,7 @@ export const Toolbar = () => {
|
|||||||
<Intersect />
|
<Intersect />
|
||||||
<RemoveConstrainingValues />
|
<RemoveConstrainingValues />
|
||||||
<SetAngleBetween />
|
<SetAngleBetween />
|
||||||
</>
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { ProjectWithEntryPointMetadata } from '../Router'
|
|||||||
import ProjectSidebarMenu from './ProjectSidebarMenu'
|
import ProjectSidebarMenu from './ProjectSidebarMenu'
|
||||||
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
||||||
import styles from './AppHeader.module.css'
|
import styles from './AppHeader.module.css'
|
||||||
|
import { NetworkHealthIndicator } from './NetworkHealthIndicator'
|
||||||
|
|
||||||
interface AppHeaderProps extends React.PropsWithChildren {
|
interface AppHeaderProps extends React.PropsWithChildren {
|
||||||
showToolbar?: boolean
|
showToolbar?: boolean
|
||||||
@ -43,7 +44,8 @@ export const AppHeader = ({
|
|||||||
)}
|
)}
|
||||||
{/* If there are children, show them, otherwise show User menu */}
|
{/* If there are children, show them, otherwise show User menu */}
|
||||||
{children || (
|
{children || (
|
||||||
<div className="ml-auto">
|
<div className="ml-auto flex items-center gap-1">
|
||||||
|
<NetworkHealthIndicator />
|
||||||
<UserSidebarMenu user={user} />
|
<UserSidebarMenu user={user} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -144,7 +144,7 @@ export function useCalc({
|
|||||||
try {
|
try {
|
||||||
const code = `const __result__ = ${value}\nshow(__result__)`
|
const code = `const __result__ = ${value}\nshow(__result__)`
|
||||||
const ast = parser_wasm(code)
|
const ast = parser_wasm(code)
|
||||||
const _programMem: any = { root: {} }
|
const _programMem: any = { root: {}, return: null }
|
||||||
availableVarInfo.variables.forEach(({ key, value }) => {
|
availableVarInfo.variables.forEach(({ key, value }) => {
|
||||||
_programMem.root[key] = { type: 'userVal', value, __meta: [] }
|
_programMem.root[key] = { type: 'userVal', value, __meta: [] }
|
||||||
})
|
})
|
||||||
|
@ -29,6 +29,7 @@ describe('processMemory', () => {
|
|||||||
const ast = parser_wasm(code)
|
const ast = parser_wasm(code)
|
||||||
const programMemory = await enginelessExecutor(ast, {
|
const programMemory = await enginelessExecutor(ast, {
|
||||||
root: {},
|
root: {},
|
||||||
|
return: null,
|
||||||
})
|
})
|
||||||
const output = processMemory(programMemory)
|
const output = processMemory(programMemory)
|
||||||
expect(output.myVar).toEqual(5)
|
expect(output.myVar).toEqual(5)
|
||||||
|
@ -2,7 +2,7 @@ import ReactJson from 'react-json-view'
|
|||||||
import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel'
|
import { CollapsiblePanel, CollapsiblePanelProps } from './CollapsiblePanel'
|
||||||
import { useStore } from '../useStore'
|
import { useStore } from '../useStore'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { ProgramMemory } from '../lang/executor'
|
import { ProgramMemory, Path, ExtrudeSurface } from '../lang/executor'
|
||||||
import { Themes } from '../lib/theme'
|
import { Themes } from '../lib/theme'
|
||||||
|
|
||||||
interface MemoryPanelProps extends CollapsiblePanelProps {
|
interface MemoryPanelProps extends CollapsiblePanelProps {
|
||||||
@ -49,8 +49,12 @@ export const processMemory = (programMemory: ProgramMemory) => {
|
|||||||
Object.keys(programMemory.root).forEach((key) => {
|
Object.keys(programMemory.root).forEach((key) => {
|
||||||
const val = programMemory.root[key]
|
const val = programMemory.root[key]
|
||||||
if (typeof val.value !== 'function') {
|
if (typeof val.value !== 'function') {
|
||||||
if (val.type === 'sketchGroup' || val.type === 'extrudeGroup') {
|
if (val.type === 'SketchGroup') {
|
||||||
processedMemory[key] = val.value.map(({ __geoMeta, ...rest }) => {
|
processedMemory[key] = val.value.map(({ __geoMeta, ...rest }: Path) => {
|
||||||
|
return rest
|
||||||
|
})
|
||||||
|
} else if (val.type === 'ExtrudeGroup') {
|
||||||
|
processedMemory[key] = val.value.map(({ ...rest }: ExtrudeSurface) => {
|
||||||
return rest
|
return rest
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
51
src/components/NetworkHealthIndicator.test.tsx
Normal file
51
src/components/NetworkHealthIndicator.test.tsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { fireEvent, render, screen } from '@testing-library/react'
|
||||||
|
import UserSidebarMenu from './UserSidebarMenu'
|
||||||
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
|
import { GlobalStateProvider } from './GlobalStateProvider'
|
||||||
|
import CommandBarProvider from './CommandBar'
|
||||||
|
import {
|
||||||
|
NETWORK_CONTENT,
|
||||||
|
NetworkHealthIndicator,
|
||||||
|
} from './NetworkHealthIndicator'
|
||||||
|
|
||||||
|
function TestWrap({ children }: { children: React.ReactNode }) {
|
||||||
|
// wrap in router and xState context
|
||||||
|
return (
|
||||||
|
<BrowserRouter>
|
||||||
|
<CommandBarProvider>
|
||||||
|
<GlobalStateProvider>{children}</GlobalStateProvider>
|
||||||
|
</CommandBarProvider>
|
||||||
|
</BrowserRouter>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('NetworkHealthIndicator tests', () => {
|
||||||
|
test('Renders the network indicator', () => {
|
||||||
|
render(
|
||||||
|
<TestWrap>
|
||||||
|
<NetworkHealthIndicator />
|
||||||
|
</TestWrap>
|
||||||
|
)
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByTestId('network-toggle'))
|
||||||
|
|
||||||
|
expect(screen.getByTestId('network-good')).toHaveTextContent(
|
||||||
|
NETWORK_CONTENT.good
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Responds to network changes', () => {
|
||||||
|
render(
|
||||||
|
<TestWrap>
|
||||||
|
<NetworkHealthIndicator />
|
||||||
|
</TestWrap>
|
||||||
|
)
|
||||||
|
|
||||||
|
fireEvent.offline(window)
|
||||||
|
fireEvent.click(screen.getByTestId('network-toggle'))
|
||||||
|
|
||||||
|
expect(screen.getByTestId('network-bad')).toHaveTextContent(
|
||||||
|
NETWORK_CONTENT.bad
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
112
src/components/NetworkHealthIndicator.tsx
Normal file
112
src/components/NetworkHealthIndicator.tsx
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
import {
|
||||||
|
faCheck,
|
||||||
|
faExclamation,
|
||||||
|
faWifi,
|
||||||
|
} from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { Popover } from '@headlessui/react'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { ActionIcon } from './ActionIcon'
|
||||||
|
|
||||||
|
export const NETWORK_CONTENT = {
|
||||||
|
good: 'Network health is good',
|
||||||
|
bad: 'Network issue',
|
||||||
|
}
|
||||||
|
|
||||||
|
const NETWORK_MESSAGES = {
|
||||||
|
offline: 'You are offline',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NetworkHealthIndicator = () => {
|
||||||
|
const [networkIssues, setNetworkIssues] = useState<string[]>([])
|
||||||
|
const hasIssues = [...networkIssues.values()].length > 0
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const offlineListener = () =>
|
||||||
|
setNetworkIssues((issues) => {
|
||||||
|
return [
|
||||||
|
...issues.filter((issue) => issue !== NETWORK_MESSAGES.offline),
|
||||||
|
NETWORK_MESSAGES.offline,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
window.addEventListener('offline', offlineListener)
|
||||||
|
|
||||||
|
const onlineListener = () =>
|
||||||
|
setNetworkIssues((issues) => {
|
||||||
|
return [...issues.filter((issue) => issue !== NETWORK_MESSAGES.offline)]
|
||||||
|
})
|
||||||
|
window.addEventListener('online', onlineListener)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('offline', offlineListener)
|
||||||
|
window.removeEventListener('online', onlineListener)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover className="relative">
|
||||||
|
<Popover.Button
|
||||||
|
className={
|
||||||
|
'p-0 border-none relative ' +
|
||||||
|
(hasIssues
|
||||||
|
? 'focus-visible:outline-destroy-80'
|
||||||
|
: 'focus-visible:outline-succeed-80')
|
||||||
|
}
|
||||||
|
data-testid="network-toggle"
|
||||||
|
>
|
||||||
|
<span className="sr-only">Network Health</span>
|
||||||
|
<ActionIcon
|
||||||
|
icon={faWifi}
|
||||||
|
iconClassName={
|
||||||
|
hasIssues
|
||||||
|
? 'text-destroy-80 dark:text-destroy-30'
|
||||||
|
: 'text-succeed-80 dark:text-succeed-30'
|
||||||
|
}
|
||||||
|
bgClassName={
|
||||||
|
hasIssues
|
||||||
|
? 'hover:bg-destroy-10/50 hover:dark:bg-destroy-80/50 rounded'
|
||||||
|
: 'hover:bg-succeed-10/50 hover:dark:bg-succeed-80/50 rounded'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Popover.Button>
|
||||||
|
<Popover.Panel className="absolute right-0 left-auto top-full mt-1 w-56 flex flex-col gap-1 divide-y divide-chalkboard-20 dark:divide-chalkboard-70 align-stretch py-2 bg-chalkboard-10 dark:bg-chalkboard-90 rounded shadow-lg border border-solid border-chalkboard-20/50 dark:border-chalkboard-80/50 text-sm">
|
||||||
|
{!hasIssues ? (
|
||||||
|
<span
|
||||||
|
className="flex items-center justify-center gap-1 px-4"
|
||||||
|
data-testid="network-good"
|
||||||
|
>
|
||||||
|
<ActionIcon
|
||||||
|
icon={faCheck}
|
||||||
|
bgClassName={'bg-succeed-10/50 dark:bg-succeed-80/50 rounded'}
|
||||||
|
iconClassName={'text-succeed-80 dark:text-succeed-30'}
|
||||||
|
/>
|
||||||
|
{NETWORK_CONTENT.good}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<ul className="divide-y divide-chalkboard-20 dark:divide-chalkboard-80">
|
||||||
|
<span
|
||||||
|
className="font-bold text-xs uppercase text-destroy-60 dark:text-destroy-50 px-4"
|
||||||
|
data-testid="network-bad"
|
||||||
|
>
|
||||||
|
{NETWORK_CONTENT.bad}
|
||||||
|
{networkIssues.length > 1 ? 's' : ''}
|
||||||
|
</span>
|
||||||
|
{networkIssues.map((issue) => (
|
||||||
|
<li
|
||||||
|
key={issue}
|
||||||
|
className="flex items-center gap-1 py-2 my-2 last:mb-0"
|
||||||
|
>
|
||||||
|
<ActionIcon
|
||||||
|
icon={faExclamation}
|
||||||
|
bgClassName={'bg-destroy-10/50 dark:bg-destroy-80/50 rounded'}
|
||||||
|
iconClassName={'text-destroy-80 dark:text-destroy-30'}
|
||||||
|
className="ml-4"
|
||||||
|
/>
|
||||||
|
<p className="flex-1 mr-4">{issue}</p>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</Popover.Panel>
|
||||||
|
</Popover>
|
||||||
|
)
|
||||||
|
}
|
@ -7,11 +7,14 @@ import {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { useStore } from '../useStore'
|
import { useStore } from '../useStore'
|
||||||
import { getNormalisedCoordinates } from '../lib/utils'
|
import { getNormalisedCoordinates, roundOff } from '../lib/utils'
|
||||||
import Loading from './Loading'
|
import Loading from './Loading'
|
||||||
import { cameraMouseDragGuards } from 'lib/cameraControls'
|
import { cameraMouseDragGuards } from 'lib/cameraControls'
|
||||||
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
||||||
import { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/models'
|
import { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/models'
|
||||||
|
import { Models } from '@kittycad/lib'
|
||||||
|
import { addStartSketch } from 'lang/modifyAst'
|
||||||
|
import { addNewSketchLn } from 'lang/std/sketch'
|
||||||
|
|
||||||
export const Stream = ({ className = '' }) => {
|
export const Stream = ({ className = '' }) => {
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
@ -25,6 +28,11 @@ export const Stream = ({ className = '' }) => {
|
|||||||
setDidDragInStream,
|
setDidDragInStream,
|
||||||
streamDimensions,
|
streamDimensions,
|
||||||
isExecuting,
|
isExecuting,
|
||||||
|
guiMode,
|
||||||
|
ast,
|
||||||
|
updateAst,
|
||||||
|
setGuiMode,
|
||||||
|
programMemory,
|
||||||
} = useStore((s) => ({
|
} = useStore((s) => ({
|
||||||
mediaStream: s.mediaStream,
|
mediaStream: s.mediaStream,
|
||||||
engineCommandManager: s.engineCommandManager,
|
engineCommandManager: s.engineCommandManager,
|
||||||
@ -34,6 +42,11 @@ export const Stream = ({ className = '' }) => {
|
|||||||
setDidDragInStream: s.setDidDragInStream,
|
setDidDragInStream: s.setDidDragInStream,
|
||||||
streamDimensions: s.streamDimensions,
|
streamDimensions: s.streamDimensions,
|
||||||
isExecuting: s.isExecuting,
|
isExecuting: s.isExecuting,
|
||||||
|
guiMode: s.guiMode,
|
||||||
|
ast: s.ast,
|
||||||
|
updateAst: s.updateAst,
|
||||||
|
setGuiMode: s.setGuiMode,
|
||||||
|
programMemory: s.programMemory,
|
||||||
}))
|
}))
|
||||||
const {
|
const {
|
||||||
settings: {
|
settings: {
|
||||||
@ -64,27 +77,50 @@ export const Stream = ({ className = '' }) => {
|
|||||||
const newId = uuidv4()
|
const newId = uuidv4()
|
||||||
|
|
||||||
const interactionGuards = cameraMouseDragGuards[cameraControls]
|
const interactionGuards = cameraMouseDragGuards[cameraControls]
|
||||||
let interaction: CameraDragInteractionType_type
|
let interaction: CameraDragInteractionType_type = 'rotate'
|
||||||
|
|
||||||
if (interactionGuards.pan.callback(e)) {
|
if (
|
||||||
|
interactionGuards.pan.callback(e) ||
|
||||||
|
interactionGuards.pan.lenientDragStartButton === e.button
|
||||||
|
) {
|
||||||
interaction = 'pan'
|
interaction = 'pan'
|
||||||
} else if (interactionGuards.rotate.callback(e)) {
|
} else if (
|
||||||
|
interactionGuards.rotate.callback(e) ||
|
||||||
|
interactionGuards.rotate.lenientDragStartButton === e.button
|
||||||
|
) {
|
||||||
interaction = 'rotate'
|
interaction = 'rotate'
|
||||||
} else if (interactionGuards.zoom.dragCallback(e)) {
|
} else if (
|
||||||
|
interactionGuards.zoom.dragCallback(e) ||
|
||||||
|
interactionGuards.zoom.lenientDragStartButton === e.button
|
||||||
|
) {
|
||||||
interaction = 'zoom'
|
interaction = 'zoom'
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
engineCommandManager?.sendSceneCommand({
|
if (guiMode.mode === 'sketch' && guiMode.sketchMode === ('move' as any)) {
|
||||||
type: 'modeling_cmd_req',
|
engineCommandManager?.sendSceneCommand({
|
||||||
cmd: {
|
type: 'modeling_cmd_req',
|
||||||
type: 'camera_drag_start',
|
cmd: {
|
||||||
interaction,
|
type: 'handle_mouse_drag_start',
|
||||||
window: { x, y },
|
window: { x, y },
|
||||||
},
|
},
|
||||||
cmd_id: newId,
|
cmd_id: newId,
|
||||||
})
|
})
|
||||||
|
} else if (
|
||||||
|
!(
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === ('sketch_line' as any)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd: {
|
||||||
|
type: 'camera_drag_start',
|
||||||
|
interaction,
|
||||||
|
window: { x, y },
|
||||||
|
},
|
||||||
|
cmd_id: newId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
setButtonDownInStream(e.button)
|
setButtonDownInStream(e.button)
|
||||||
setClickCoords({ x, y })
|
setClickCoords({ x, y })
|
||||||
@ -93,7 +129,6 @@ export const Stream = ({ className = '' }) => {
|
|||||||
const handleScroll: WheelEventHandler<HTMLVideoElement> = (e) => {
|
const handleScroll: WheelEventHandler<HTMLVideoElement> = (e) => {
|
||||||
if (!cameraMouseDragGuards[cameraControls].zoom.scrollCallback(e)) return
|
if (!cameraMouseDragGuards[cameraControls].zoom.scrollCallback(e)) return
|
||||||
|
|
||||||
e.preventDefault()
|
|
||||||
engineCommandManager?.sendSceneCommand({
|
engineCommandManager?.sendSceneCommand({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd: {
|
cmd: {
|
||||||
@ -110,6 +145,7 @@ export const Stream = ({ className = '' }) => {
|
|||||||
ctrlKey,
|
ctrlKey,
|
||||||
}) => {
|
}) => {
|
||||||
if (!videoRef.current) return
|
if (!videoRef.current) return
|
||||||
|
setButtonDownInStream(undefined)
|
||||||
const { x, y } = getNormalisedCoordinates({
|
const { x, y } = getNormalisedCoordinates({
|
||||||
clientX,
|
clientX,
|
||||||
clientY,
|
clientY,
|
||||||
@ -120,7 +156,7 @@ export const Stream = ({ className = '' }) => {
|
|||||||
const newCmdId = uuidv4()
|
const newCmdId = uuidv4()
|
||||||
const interaction = ctrlKey ? 'pan' : 'rotate'
|
const interaction = ctrlKey ? 'pan' : 'rotate'
|
||||||
|
|
||||||
engineCommandManager?.sendSceneCommand({
|
const command: Models['WebSocketRequest_type'] = {
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd: {
|
cmd: {
|
||||||
type: 'camera_drag_end',
|
type: 'camera_drag_end',
|
||||||
@ -128,9 +164,8 @@ export const Stream = ({ className = '' }) => {
|
|||||||
window: { x, y },
|
window: { x, y },
|
||||||
},
|
},
|
||||||
cmd_id: newCmdId,
|
cmd_id: newCmdId,
|
||||||
})
|
}
|
||||||
|
|
||||||
setButtonDownInStream(0)
|
|
||||||
if (!didDragInStream) {
|
if (!didDragInStream) {
|
||||||
engineCommandManager?.sendSceneCommand({
|
engineCommandManager?.sendSceneCommand({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
@ -142,6 +177,95 @@ export const Stream = ({ className = '' }) => {
|
|||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!didDragInStream && guiMode.mode === 'default') {
|
||||||
|
command.cmd = {
|
||||||
|
type: 'select_with_point',
|
||||||
|
selection_type: 'add',
|
||||||
|
selected_at_window: { x, y },
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
(!didDragInStream &&
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
['move', 'select'].includes(guiMode.sketchMode)) ||
|
||||||
|
(guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === ('sketch_line' as any))
|
||||||
|
) {
|
||||||
|
command.cmd = {
|
||||||
|
type: 'mouse_click',
|
||||||
|
window: { x, y },
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === ('move' as any)
|
||||||
|
) {
|
||||||
|
command.cmd = {
|
||||||
|
type: 'handle_mouse_drag_end',
|
||||||
|
window: { x, y },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
engineCommandManager?.sendSceneCommand(command).then(async ({ data }) => {
|
||||||
|
if (command.cmd.type !== 'mouse_click' || !ast) return
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === ('sketch_line' as any as 'line')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (data?.data?.entities_modified?.length && guiMode.waitingFirstClick) {
|
||||||
|
const curve = await engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'curve_get_control_points',
|
||||||
|
curve_id: data?.data?.entities_modified[0],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const coords: { x: number; y: number }[] =
|
||||||
|
curve.data.data.control_points
|
||||||
|
const _addStartSketch = addStartSketch(
|
||||||
|
ast,
|
||||||
|
[roundOff(coords[0].x), roundOff(coords[0].y)],
|
||||||
|
[
|
||||||
|
roundOff(coords[1].x - coords[0].x),
|
||||||
|
roundOff(coords[1].y - coords[0].y),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
const _modifiedAst = _addStartSketch.modifiedAst
|
||||||
|
const _pathToNode = _addStartSketch.pathToNode
|
||||||
|
|
||||||
|
setGuiMode({
|
||||||
|
...guiMode,
|
||||||
|
pathToNode: _pathToNode,
|
||||||
|
waitingFirstClick: false,
|
||||||
|
})
|
||||||
|
updateAst(_modifiedAst)
|
||||||
|
} else if (
|
||||||
|
data?.data?.entities_modified?.length &&
|
||||||
|
!guiMode.waitingFirstClick
|
||||||
|
) {
|
||||||
|
const curve = await engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'curve_get_control_points',
|
||||||
|
curve_id: data?.data?.entities_modified[0],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const coords: { x: number; y: number }[] =
|
||||||
|
curve.data.data.control_points
|
||||||
|
const _modifiedAst = addNewSketchLn({
|
||||||
|
node: ast,
|
||||||
|
programMemory,
|
||||||
|
to: [coords[1].x, coords[1].y],
|
||||||
|
fnName: 'line',
|
||||||
|
pathToNode: guiMode.pathToNode,
|
||||||
|
}).modifiedAst
|
||||||
|
updateAst(_modifiedAst)
|
||||||
|
}
|
||||||
|
})
|
||||||
setDidDragInStream(false)
|
setDidDragInStream(false)
|
||||||
setClickCoords(undefined)
|
setClickCoords(undefined)
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,6 @@ export const TextEditor = ({
|
|||||||
sourceRangeMap,
|
sourceRangeMap,
|
||||||
} = useStore((s) => ({
|
} = useStore((s) => ({
|
||||||
code: s.code,
|
code: s.code,
|
||||||
defferedCode: s.defferedCode,
|
|
||||||
defferedSetCode: s.defferedSetCode,
|
defferedSetCode: s.defferedSetCode,
|
||||||
editorView: s.editorView,
|
editorView: s.editorView,
|
||||||
engineCommandManager: s.engineCommandManager,
|
engineCommandManager: s.engineCommandManager,
|
||||||
@ -70,7 +69,6 @@ export const TextEditor = ({
|
|||||||
isLSPServerReady: s.isLSPServerReady,
|
isLSPServerReady: s.isLSPServerReady,
|
||||||
selectionRanges: s.selectionRanges,
|
selectionRanges: s.selectionRanges,
|
||||||
selectionRangeTypeMap: s.selectionRangeTypeMap,
|
selectionRangeTypeMap: s.selectionRangeTypeMap,
|
||||||
setCode: s.setCode,
|
|
||||||
setEditorView: s.setEditorView,
|
setEditorView: s.setEditorView,
|
||||||
setIsLSPServerReady: s.setIsLSPServerReady,
|
setIsLSPServerReady: s.setIsLSPServerReady,
|
||||||
setSelectionRanges: s.setSelectionRanges,
|
setSelectionRanges: s.setSelectionRanges,
|
||||||
|
243
src/hooks/useAppMode.ts
Normal file
243
src/hooks/useAppMode.ts
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
// needed somewhere to dump this logic,
|
||||||
|
// Once we have xState this should be removed
|
||||||
|
|
||||||
|
import { useStore, Selections } from 'useStore'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import { ArtifactMap, EngineCommandManager } from 'lang/std/engineConnection'
|
||||||
|
import { Models } from '@kittycad/lib/dist/types/src'
|
||||||
|
import { isReducedMotion } from 'lang/util'
|
||||||
|
import { isOverlap } from 'lib/utils'
|
||||||
|
|
||||||
|
interface DefaultPlanes {
|
||||||
|
xy: string
|
||||||
|
yz: string
|
||||||
|
xz: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAppMode() {
|
||||||
|
const {
|
||||||
|
guiMode,
|
||||||
|
setGuiMode,
|
||||||
|
selectionRanges,
|
||||||
|
engineCommandManager,
|
||||||
|
selectionRangeTypeMap,
|
||||||
|
} = useStore((s) => ({
|
||||||
|
guiMode: s.guiMode,
|
||||||
|
setGuiMode: s.setGuiMode,
|
||||||
|
selectionRanges: s.selectionRanges,
|
||||||
|
engineCommandManager: s.engineCommandManager,
|
||||||
|
selectionRangeTypeMap: s.selectionRangeTypeMap,
|
||||||
|
}))
|
||||||
|
const [defaultPlanes, setDefaultPlanes] = useState<DefaultPlanes | null>(null)
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
guiMode.mode === 'sketch' &&
|
||||||
|
guiMode.sketchMode === 'selectFace' &&
|
||||||
|
engineCommandManager
|
||||||
|
) {
|
||||||
|
if (!defaultPlanes) {
|
||||||
|
const xy = createPlane(engineCommandManager, {
|
||||||
|
x_axis: { x: 1, y: 0, z: 0 },
|
||||||
|
y_axis: { x: 0, y: 1, z: 0 },
|
||||||
|
color: { r: 0.7, g: 0.28, b: 0.28, a: 0.4 },
|
||||||
|
})
|
||||||
|
const yz = createPlane(engineCommandManager, {
|
||||||
|
x_axis: { x: 0, y: 1, z: 0 },
|
||||||
|
y_axis: { x: 0, y: 0, z: 1 },
|
||||||
|
color: { r: 0.28, g: 0.7, b: 0.28, a: 0.4 },
|
||||||
|
})
|
||||||
|
const xz = createPlane(engineCommandManager, {
|
||||||
|
x_axis: { x: 1, y: 0, z: 0 },
|
||||||
|
y_axis: { x: 0, y: 0, z: 1 },
|
||||||
|
color: { r: 0.28, g: 0.28, b: 0.7, a: 0.4 },
|
||||||
|
})
|
||||||
|
setDefaultPlanes({ xy, yz, xz })
|
||||||
|
} else {
|
||||||
|
hideDefaultPlanes(engineCommandManager, defaultPlanes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (guiMode.mode !== 'sketch' && defaultPlanes) {
|
||||||
|
Object.values(defaultPlanes).forEach((planeId) => {
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'object_visible',
|
||||||
|
object_id: planeId,
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else if (guiMode.mode === 'default') {
|
||||||
|
const pathId =
|
||||||
|
engineCommandManager &&
|
||||||
|
isCursorInSketchCommandRange(
|
||||||
|
engineCommandManager.artifactMap,
|
||||||
|
selectionRanges
|
||||||
|
)
|
||||||
|
if (pathId) {
|
||||||
|
setGuiMode({
|
||||||
|
mode: 'canEditSketch',
|
||||||
|
rotation: [0, 0, 0, 1],
|
||||||
|
position: [0, 0, 0],
|
||||||
|
pathToNode: [],
|
||||||
|
pathId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else if (guiMode.mode === 'canEditSketch') {
|
||||||
|
if (
|
||||||
|
!engineCommandManager ||
|
||||||
|
!isCursorInSketchCommandRange(
|
||||||
|
engineCommandManager.artifactMap,
|
||||||
|
selectionRanges
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
setGuiMode({
|
||||||
|
mode: 'default',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
guiMode,
|
||||||
|
guiMode.mode,
|
||||||
|
engineCommandManager,
|
||||||
|
selectionRanges,
|
||||||
|
selectionRangeTypeMap,
|
||||||
|
])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const unSub = engineCommandManager?.subscribeTo({
|
||||||
|
event: 'select_with_point',
|
||||||
|
callback: async ({ data }) => {
|
||||||
|
if (!data.entity_id) return
|
||||||
|
if (!defaultPlanes) return
|
||||||
|
if (!Object.values(defaultPlanes || {}).includes(data.entity_id)) {
|
||||||
|
// user clicked something else in the scene
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const sketchModeResponse = await engineCommandManager?.sendSceneCommand(
|
||||||
|
{
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'sketch_mode_enable',
|
||||||
|
plane_id: data.entity_id,
|
||||||
|
ortho: true,
|
||||||
|
animated: !isReducedMotion(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
hideDefaultPlanes(engineCommandManager, defaultPlanes)
|
||||||
|
const sketchUuid = uuidv4()
|
||||||
|
const proms: any[] = []
|
||||||
|
proms.push(
|
||||||
|
engineCommandManager.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: sketchUuid,
|
||||||
|
cmd: {
|
||||||
|
type: 'start_path',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
proms.push(
|
||||||
|
engineCommandManager.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'edit_mode_enter',
|
||||||
|
target: sketchUuid,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
const res = await Promise.all(proms)
|
||||||
|
console.log('res', res)
|
||||||
|
setGuiMode({
|
||||||
|
mode: 'sketch',
|
||||||
|
sketchMode: 'sketchEdit',
|
||||||
|
rotation: [0, 0, 0, 1],
|
||||||
|
position: [0, 0, 0],
|
||||||
|
pathToNode: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('sketchModeResponse', sketchModeResponse)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return unSub
|
||||||
|
}, [engineCommandManager, defaultPlanes])
|
||||||
|
}
|
||||||
|
|
||||||
|
function createPlane(
|
||||||
|
engineCommandManager: EngineCommandManager,
|
||||||
|
{
|
||||||
|
x_axis,
|
||||||
|
y_axis,
|
||||||
|
color,
|
||||||
|
}: {
|
||||||
|
x_axis: Models['Point3d_type']
|
||||||
|
y_axis: Models['Point3d_type']
|
||||||
|
color: Models['Color_type']
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
const planeId = uuidv4()
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd: {
|
||||||
|
type: 'make_plane',
|
||||||
|
size: 60,
|
||||||
|
origin: { x: 0, y: 0, z: 0 },
|
||||||
|
x_axis,
|
||||||
|
y_axis,
|
||||||
|
clobber: false,
|
||||||
|
},
|
||||||
|
cmd_id: planeId,
|
||||||
|
})
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd: {
|
||||||
|
type: 'plane_set_color',
|
||||||
|
plane_id: planeId,
|
||||||
|
color,
|
||||||
|
},
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
})
|
||||||
|
return planeId
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideDefaultPlanes(
|
||||||
|
engineCommandManager: EngineCommandManager,
|
||||||
|
defaultPlanes: DefaultPlanes
|
||||||
|
) {
|
||||||
|
Object.values(defaultPlanes).forEach((planeId) => {
|
||||||
|
engineCommandManager?.sendSceneCommand({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'object_visible',
|
||||||
|
object_id: planeId,
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCursorInSketchCommandRange(
|
||||||
|
artifactMap: ArtifactMap,
|
||||||
|
selectionRanges: Selections
|
||||||
|
): string | false {
|
||||||
|
const overlapingEntries = Object.entries(artifactMap || {}).filter(
|
||||||
|
([id, artifact]) =>
|
||||||
|
selectionRanges.codeBasedSelections.some(
|
||||||
|
(selection) =>
|
||||||
|
Array.isArray(selection.range) &&
|
||||||
|
Array.isArray(artifact.range) &&
|
||||||
|
isOverlap(selection.range, artifact.range) &&
|
||||||
|
(artifact.commandType === 'start_path' ||
|
||||||
|
artifact.commandType === 'extend_path' ||
|
||||||
|
'close_path')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return overlapingEntries.length === 1 && overlapingEntries[0][1].parentId
|
||||||
|
? overlapingEntries[0][1].parentId
|
||||||
|
: false
|
||||||
|
}
|
@ -21,7 +21,7 @@ show(mySketch001)`
|
|||||||
)
|
)
|
||||||
expect(shown).toEqual([
|
expect(shown).toEqual([
|
||||||
{
|
{
|
||||||
type: 'sketchGroup',
|
type: 'SketchGroup',
|
||||||
start: {
|
start: {
|
||||||
to: [0, 0],
|
to: [0, 0],
|
||||||
from: [0, 0],
|
from: [0, 0],
|
||||||
@ -77,7 +77,7 @@ show(mySketch001)`
|
|||||||
)
|
)
|
||||||
expect(shown).toEqual([
|
expect(shown).toEqual([
|
||||||
{
|
{
|
||||||
type: 'extrudeGroup',
|
type: 'ExtrudeGroup',
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
value: [],
|
value: [],
|
||||||
height: 2,
|
height: 2,
|
||||||
@ -117,7 +117,7 @@ show(theExtrude, sk2)`
|
|||||||
)
|
)
|
||||||
expect(geos).toEqual([
|
expect(geos).toEqual([
|
||||||
{
|
{
|
||||||
type: 'extrudeGroup',
|
type: 'ExtrudeGroup',
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
value: [],
|
value: [],
|
||||||
height: 2,
|
height: 2,
|
||||||
@ -126,7 +126,7 @@ show(theExtrude, sk2)`
|
|||||||
__meta: [{ sourceRange: [13, 34] }],
|
__meta: [{ sourceRange: [13, 34] }],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'extrudeGroup',
|
type: 'ExtrudeGroup',
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
value: [],
|
value: [],
|
||||||
height: 2,
|
height: 2,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
|
|
||||||
import { parser_wasm } from './abstractSyntaxTree'
|
import { parser_wasm } from './abstractSyntaxTree'
|
||||||
import { ProgramMemory } from './executor'
|
import { ProgramMemory, SketchGroup } from './executor'
|
||||||
import { initPromise } from './rust'
|
import { initPromise } from './rust'
|
||||||
import { enginelessExecutor } from '../lib/testHelpers'
|
import { enginelessExecutor } from '../lib/testHelpers'
|
||||||
import { vi } from 'vitest'
|
import { vi } from 'vitest'
|
||||||
@ -117,10 +117,10 @@ show(mySketch)
|
|||||||
// ].join('\n')
|
// ].join('\n')
|
||||||
// const { root } = await exe(code)
|
// const { root } = await exe(code)
|
||||||
// expect(root.mySk1.value).toHaveLength(3)
|
// expect(root.mySk1.value).toHaveLength(3)
|
||||||
// expect(root?.rotated?.type).toBe('sketchGroup')
|
// expect(root?.rotated?.type).toBe('SketchGroup')
|
||||||
// if (
|
// if (
|
||||||
// root?.mySk1?.type !== 'sketchGroup' ||
|
// root?.mySk1?.type !== 'SketchGroup' ||
|
||||||
// root?.rotated?.type !== 'sketchGroup'
|
// root?.rotated?.type !== 'SketchGroup'
|
||||||
// )
|
// )
|
||||||
// throw new Error('not a sketch group')
|
// throw new Error('not a sketch group')
|
||||||
// expect(root.mySk1.rotation).toEqual([0, 0, 0, 1])
|
// expect(root.mySk1.rotation).toEqual([0, 0, 0, 1])
|
||||||
@ -143,7 +143,7 @@ show(mySketch)
|
|||||||
].join('\n')
|
].join('\n')
|
||||||
const { root } = await exe(code)
|
const { root } = await exe(code)
|
||||||
expect(root.mySk1).toEqual({
|
expect(root.mySk1).toEqual({
|
||||||
type: 'sketchGroup',
|
type: 'SketchGroup',
|
||||||
start: {
|
start: {
|
||||||
to: [0, 0],
|
to: [0, 0],
|
||||||
from: [0, 0],
|
from: [0, 0],
|
||||||
@ -199,7 +199,7 @@ show(mySketch)
|
|||||||
// TODO path to node is probably wrong here, zero indexes are not correct
|
// TODO path to node is probably wrong here, zero indexes are not correct
|
||||||
expect(root).toEqual({
|
expect(root).toEqual({
|
||||||
three: {
|
three: {
|
||||||
type: 'userVal',
|
type: 'UserVal',
|
||||||
value: 3,
|
value: 3,
|
||||||
__meta: [
|
__meta: [
|
||||||
{
|
{
|
||||||
@ -208,7 +208,7 @@ show(mySketch)
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
yo: {
|
yo: {
|
||||||
type: 'userVal',
|
type: 'UserVal',
|
||||||
value: [1, '2', 3, 9],
|
value: [1, '2', 3, 9],
|
||||||
__meta: [
|
__meta: [
|
||||||
{
|
{
|
||||||
@ -225,7 +225,7 @@ show(mySketch)
|
|||||||
].join('\n')
|
].join('\n')
|
||||||
const { root } = await exe(code)
|
const { root } = await exe(code)
|
||||||
expect(root.yo).toEqual({
|
expect(root.yo).toEqual({
|
||||||
type: 'userVal',
|
type: 'UserVal',
|
||||||
value: { aStr: 'str', anum: 2, identifier: 3, binExp: 9 },
|
value: { aStr: 'str', anum: 2, identifier: 3, binExp: 9 },
|
||||||
__meta: [
|
__meta: [
|
||||||
{
|
{
|
||||||
@ -240,7 +240,7 @@ show(mySketch)
|
|||||||
)
|
)
|
||||||
const { root } = await exe(code)
|
const { root } = await exe(code)
|
||||||
expect(root.myVar).toEqual({
|
expect(root.myVar).toEqual({
|
||||||
type: 'userVal',
|
type: 'UserVal',
|
||||||
value: '123',
|
value: '123',
|
||||||
__meta: [
|
__meta: [
|
||||||
{
|
{
|
||||||
@ -338,7 +338,7 @@ describe('testing math operators', () => {
|
|||||||
const { root } = await exe(code)
|
const { root } = await exe(code)
|
||||||
const sketch = root.part001
|
const sketch = root.part001
|
||||||
// result of `-legLen(5, min(3, 999))` should be -4
|
// result of `-legLen(5, min(3, 999))` should be -4
|
||||||
const yVal = sketch.value?.[0]?.to?.[1]
|
const yVal = (sketch as SketchGroup).value?.[0]?.to?.[1]
|
||||||
expect(yVal).toBe(-4)
|
expect(yVal).toBe(-4)
|
||||||
})
|
})
|
||||||
it('test that % substitution feeds down CallExp->ArrExp->UnaryExp->CallExp', async () => {
|
it('test that % substitution feeds down CallExp->ArrExp->UnaryExp->CallExp', async () => {
|
||||||
@ -356,8 +356,8 @@ describe('testing math operators', () => {
|
|||||||
const { root } = await exe(code)
|
const { root } = await exe(code)
|
||||||
const sketch = root.part001
|
const sketch = root.part001
|
||||||
// expect -legLen(segLen('seg01', %), myVar) to equal -4 setting the y value back to 0
|
// expect -legLen(segLen('seg01', %), myVar) to equal -4 setting the y value back to 0
|
||||||
expect(sketch.value?.[1]?.from).toEqual([3, 4])
|
expect((sketch as SketchGroup).value?.[1]?.from).toEqual([3, 4])
|
||||||
expect(sketch.value?.[1]?.to).toEqual([6, 0])
|
expect((sketch as SketchGroup).value?.[1]?.to).toEqual([6, 0])
|
||||||
const removedUnaryExp = code.replace(
|
const removedUnaryExp = code.replace(
|
||||||
`-legLen(segLen('seg01', %), myVar)`,
|
`-legLen(segLen('seg01', %), myVar)`,
|
||||||
`legLen(segLen('seg01', %), myVar)`
|
`legLen(segLen('seg01', %), myVar)`
|
||||||
@ -366,7 +366,9 @@ describe('testing math operators', () => {
|
|||||||
const removedUnaryExpRootSketch = removedUnaryExpRoot.part001
|
const removedUnaryExpRootSketch = removedUnaryExpRoot.part001
|
||||||
|
|
||||||
// without the minus sign, the y value should be 8
|
// without the minus sign, the y value should be 8
|
||||||
expect(removedUnaryExpRootSketch.value?.[1]?.to).toEqual([6, 8])
|
expect((removedUnaryExpRootSketch as SketchGroup).value?.[1]?.to).toEqual([
|
||||||
|
6, 8,
|
||||||
|
])
|
||||||
})
|
})
|
||||||
it('with nested callExpression and binaryExpression', async () => {
|
it('with nested callExpression and binaryExpression', async () => {
|
||||||
const code = 'const myVar = 2 + min(100, -1 + legLen(5, 3))'
|
const code = 'const myVar = 2 + min(100, -1 + legLen(5, 3))'
|
||||||
@ -397,7 +399,10 @@ show(theExtrude)`
|
|||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
|
|
||||||
async function exe(code: string, programMemory: ProgramMemory = { root: {} }) {
|
async function exe(
|
||||||
|
code: string,
|
||||||
|
programMemory: ProgramMemory = { root: {}, return: null }
|
||||||
|
) {
|
||||||
const ast = parser_wasm(code)
|
const ast = parser_wasm(code)
|
||||||
|
|
||||||
const result = await enginelessExecutor(ast, programMemory)
|
const result = await enginelessExecutor(ast, programMemory)
|
||||||
|
@ -5,96 +5,21 @@ import {
|
|||||||
SourceRangeMap,
|
SourceRangeMap,
|
||||||
} from './std/engineConnection'
|
} from './std/engineConnection'
|
||||||
import { ProgramReturn } from '../wasm-lib/kcl/bindings/ProgramReturn'
|
import { ProgramReturn } from '../wasm-lib/kcl/bindings/ProgramReturn'
|
||||||
|
import { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
|
||||||
import { execute_wasm } from '../wasm-lib/pkg/wasm_lib'
|
import { execute_wasm } from '../wasm-lib/pkg/wasm_lib'
|
||||||
import { KCLError } from './errors'
|
import { KCLError } from './errors'
|
||||||
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
|
import { KclError as RustKclError } from '../wasm-lib/kcl/bindings/KclError'
|
||||||
import { rangeTypeFix } from './abstractSyntaxTree'
|
import { rangeTypeFix } from './abstractSyntaxTree'
|
||||||
|
|
||||||
export type SourceRange = [number, number]
|
export type { SourceRange } from '../wasm-lib/kcl/bindings/SourceRange'
|
||||||
export type PathToNode = [string | number, string][] // [pathKey, nodeType][]
|
export type { Position } from '../wasm-lib/kcl/bindings/Position'
|
||||||
export type Metadata = {
|
export type { Rotation } from '../wasm-lib/kcl/bindings/Rotation'
|
||||||
sourceRange: SourceRange
|
export type { Path } from '../wasm-lib/kcl/bindings/Path'
|
||||||
}
|
export type { SketchGroup } from '../wasm-lib/kcl/bindings/SketchGroup'
|
||||||
export type Position = [number, number, number]
|
export type { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
|
||||||
export type Rotation = [number, number, number, number]
|
export type { ExtrudeSurface } from '../wasm-lib/kcl/bindings/ExtrudeSurface'
|
||||||
|
|
||||||
interface BasePath {
|
export type PathToNode = [string | number, string][]
|
||||||
from: [number, number]
|
|
||||||
to: [number, number]
|
|
||||||
name?: string
|
|
||||||
__geoMeta: {
|
|
||||||
id: string
|
|
||||||
sourceRange: SourceRange
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ToPoint extends BasePath {
|
|
||||||
type: 'toPoint'
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Base extends BasePath {
|
|
||||||
type: 'base'
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HorizontalLineTo extends BasePath {
|
|
||||||
type: 'horizontalLineTo'
|
|
||||||
x: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AngledLineTo extends BasePath {
|
|
||||||
type: 'angledLineTo'
|
|
||||||
angle: number
|
|
||||||
x?: number
|
|
||||||
y?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GeoMeta {
|
|
||||||
__geoMeta: {
|
|
||||||
id: string
|
|
||||||
sourceRange: SourceRange
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Path = ToPoint | HorizontalLineTo | AngledLineTo | Base
|
|
||||||
|
|
||||||
export interface SketchGroup {
|
|
||||||
type: 'sketchGroup'
|
|
||||||
id: string
|
|
||||||
value: Path[]
|
|
||||||
start?: Base
|
|
||||||
position: Position
|
|
||||||
rotation: Rotation
|
|
||||||
__meta: Metadata[]
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ExtrudePlane {
|
|
||||||
type: 'extrudePlane'
|
|
||||||
position: Position
|
|
||||||
rotation: Rotation
|
|
||||||
name?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ExtrudeSurface = GeoMeta &
|
|
||||||
ExtrudePlane /* | ExtrudeRadius | ExtrudeSpline */
|
|
||||||
|
|
||||||
export interface ExtrudeGroup {
|
|
||||||
type: 'extrudeGroup'
|
|
||||||
id: string
|
|
||||||
value: ExtrudeSurface[]
|
|
||||||
height: number
|
|
||||||
position: Position
|
|
||||||
rotation: Rotation
|
|
||||||
__meta: Metadata[]
|
|
||||||
}
|
|
||||||
|
|
||||||
/** UserVal not produced by one of our internal functions */
|
|
||||||
export interface UserVal {
|
|
||||||
type: 'userVal'
|
|
||||||
value: any
|
|
||||||
__meta: Metadata[]
|
|
||||||
}
|
|
||||||
|
|
||||||
type MemoryItem = UserVal | SketchGroup | ExtrudeGroup
|
|
||||||
|
|
||||||
interface Memory {
|
interface Memory {
|
||||||
[key: string]: MemoryItem
|
[key: string]: MemoryItem
|
||||||
@ -102,12 +27,12 @@ interface Memory {
|
|||||||
|
|
||||||
export interface ProgramMemory {
|
export interface ProgramMemory {
|
||||||
root: Memory
|
root: Memory
|
||||||
return?: ProgramReturn
|
return: ProgramReturn | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const executor = async (
|
export const executor = async (
|
||||||
node: Program,
|
node: Program,
|
||||||
programMemory: ProgramMemory = { root: {} },
|
programMemory: ProgramMemory = { root: {}, return: null },
|
||||||
engineCommandManager: EngineCommandManager,
|
engineCommandManager: EngineCommandManager,
|
||||||
// work around while the gemotry is still be stored on the frontend
|
// work around while the gemotry is still be stored on the frontend
|
||||||
// will be removed when the stream UI is added.
|
// will be removed when the stream UI is added.
|
||||||
@ -132,7 +57,7 @@ export const executor = async (
|
|||||||
|
|
||||||
export const _executor = async (
|
export const _executor = async (
|
||||||
node: Program,
|
node: Program,
|
||||||
programMemory: ProgramMemory = { root: {} },
|
programMemory: ProgramMemory = { root: {}, return: null },
|
||||||
engineCommandManager: EngineCommandManager
|
engineCommandManager: EngineCommandManager
|
||||||
): Promise<ProgramMemory> => {
|
): Promise<ProgramMemory> => {
|
||||||
try {
|
try {
|
||||||
|
@ -114,7 +114,8 @@ describe('Testing addSketchTo', () => {
|
|||||||
expect(str).toBe(`const part001 = startSketchAt('default')
|
expect(str).toBe(`const part001 = startSketchAt('default')
|
||||||
|> ry(90, %)
|
|> ry(90, %)
|
||||||
|> line('default', %)
|
|> line('default', %)
|
||||||
show(part001)`)
|
show(part001)
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -179,7 +180,10 @@ describe('Testing moveValueIntoNewVariable', () => {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const code = `${fn('def')}${fn('ghi')}${fn('jkl')}${fn('hmm')}
|
const code = `${fn('def')}${fn('jkl')}${fn('hmm')}
|
||||||
|
fn ghi = (x) => {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
const abc = 3
|
const abc = 3
|
||||||
const identifierGuy = 5
|
const identifierGuy = 5
|
||||||
const yo = 5 + 6
|
const yo = 5 + 6
|
||||||
|
@ -28,6 +28,46 @@ import {
|
|||||||
createFirstArg,
|
createFirstArg,
|
||||||
} from './std/sketch'
|
} from './std/sketch'
|
||||||
|
|
||||||
|
export function addStartSketch(
|
||||||
|
node: Program,
|
||||||
|
start: [number, number],
|
||||||
|
end: [number, number]
|
||||||
|
): { modifiedAst: Program; id: string; pathToNode: PathToNode } {
|
||||||
|
const _node = { ...node }
|
||||||
|
const _name = findUniqueName(node, 'part')
|
||||||
|
|
||||||
|
const startSketchAt = createCallExpression('startSketchAt', [
|
||||||
|
createArrayExpression([createLiteral(start[0]), createLiteral(start[1])]),
|
||||||
|
])
|
||||||
|
const initialLineTo = createCallExpression('line', [
|
||||||
|
createArrayExpression([createLiteral(end[0]), createLiteral(end[1])]),
|
||||||
|
createPipeSubstitution(),
|
||||||
|
])
|
||||||
|
|
||||||
|
const pipeBody = [startSketchAt, initialLineTo]
|
||||||
|
|
||||||
|
const variableDeclaration = createVariableDeclaration(
|
||||||
|
_name,
|
||||||
|
createPipeExpression(pipeBody)
|
||||||
|
)
|
||||||
|
|
||||||
|
_node.body = [...node.body, variableDeclaration]
|
||||||
|
|
||||||
|
let pathToNode: PathToNode = [
|
||||||
|
['body', ''],
|
||||||
|
['0', 'index'],
|
||||||
|
['declarations', 'VariableDeclaration'],
|
||||||
|
['0', 'index'],
|
||||||
|
['init', 'VariableDeclarator'],
|
||||||
|
]
|
||||||
|
|
||||||
|
return {
|
||||||
|
modifiedAst: _node,
|
||||||
|
id: _name,
|
||||||
|
pathToNode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function addSketchTo(
|
export function addSketchTo(
|
||||||
node: Program,
|
node: Program,
|
||||||
axis: 'xy' | 'xz' | 'yz',
|
axis: 'xy' | 'xz' | 'yz',
|
||||||
|
@ -11,26 +11,27 @@ describe('recast', () => {
|
|||||||
const code = '1 + 2'
|
const code = '1 + 2'
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('variable declaration', () => {
|
it('variable declaration', () => {
|
||||||
const code = 'const myVar = 5'
|
const code = 'const myVar = 5'
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it("variable declaration that's binary with string", () => {
|
it("variable declaration that's binary with string", () => {
|
||||||
const code = "const myVar = 5 + 'yo'"
|
const code = "const myVar = 5 + 'yo'"
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
const codeWithOtherQuotes = 'const myVar = 5 + "yo"'
|
const codeWithOtherQuotes = 'const myVar = 5 + "yo"'
|
||||||
const { ast: ast2 } = code2ast(codeWithOtherQuotes)
|
const { ast: ast2 } = code2ast(codeWithOtherQuotes)
|
||||||
expect(recast(ast2)).toBe(codeWithOtherQuotes)
|
expect(recast(ast2).trim()).toBe(codeWithOtherQuotes)
|
||||||
})
|
})
|
||||||
it('test assigning two variables, the second summing with the first', () => {
|
it('test assigning two variables, the second summing with the first', () => {
|
||||||
const code = `const myVar = 5
|
const code = `const myVar = 5
|
||||||
const newVar = myVar + 1`
|
const newVar = myVar + 1
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
@ -42,11 +43,12 @@ const newVar = myVar + 1`
|
|||||||
)
|
)
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('test with function call', () => {
|
it('test with function call', () => {
|
||||||
const code = `const myVar = "hello"
|
const code = `const myVar = "hello"
|
||||||
log(5, myVar)`
|
log(5, myVar)
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
@ -61,7 +63,7 @@ log(5, myVar)`
|
|||||||
].join('\n')
|
].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('recast sketch declaration', () => {
|
it('recast sketch declaration', () => {
|
||||||
let code = `const mySketch = startSketchAt([0, 0])
|
let code = `const mySketch = startSketchAt([0, 0])
|
||||||
@ -70,10 +72,11 @@ log(5, myVar)`
|
|||||||
|> lineTo({ to: [1, 0], tag: "rightPath" }, %)
|
|> lineTo({ to: [1, 0], tag: "rightPath" }, %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|
|
||||||
show(mySketch)`
|
show(mySketch)
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted).toBe(code)
|
||||||
})
|
})
|
||||||
it('sketch piped into callExpression', () => {
|
it('sketch piped into callExpression', () => {
|
||||||
const code = [
|
const code = [
|
||||||
@ -85,7 +88,7 @@ show(mySketch)`
|
|||||||
].join('\n')
|
].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('recast BinaryExpression piped into CallExpression', () => {
|
it('recast BinaryExpression piped into CallExpression', () => {
|
||||||
const code = [
|
const code = [
|
||||||
@ -97,37 +100,37 @@ show(mySketch)`
|
|||||||
].join('\n')
|
].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('recast nested binary expression', () => {
|
it('recast nested binary expression', () => {
|
||||||
const code = ['const myVar = 1 + 2 * 5'].join('\n')
|
const code = ['const myVar = 1 + 2 * 5'].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('recast nested binary expression with parans', () => {
|
it('recast nested binary expression with parans', () => {
|
||||||
const code = ['const myVar = 1 + (1 + 2) * 5'].join('\n')
|
const code = ['const myVar = 1 + (1 + 2) * 5'].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('unnecessary paran wrap will be remove', () => {
|
it('unnecessary paran wrap will be remove', () => {
|
||||||
const code = ['const myVar = 1 + (2 * 5)'].join('\n')
|
const code = ['const myVar = 1 + (2 * 5)'].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.replace('(', '').replace(')', ''))
|
expect(recasted.trim()).toBe(code.replace('(', '').replace(')', ''))
|
||||||
})
|
})
|
||||||
it('complex nested binary expression', () => {
|
it('complex nested binary expression', () => {
|
||||||
const code = ['1 * ((2 + 3) / 4 + 5)'].join('\n')
|
const code = ['1 * ((2 + 3) / 4 + 5)'].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('multiplied paren expressions', () => {
|
it('multiplied paren expressions', () => {
|
||||||
const code = ['3 + (1 + 2) * (3 + 4)'].join('\n')
|
const code = ['3 + (1 + 2) * (3 + 4)'].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('recast array declaration', () => {
|
it('recast array declaration', () => {
|
||||||
const code = ['const three = 3', "const yo = [1, '2', three, 4 + 5]"].join(
|
const code = ['const three = 3', "const yo = [1, '2', three, 4 + 5]"].join(
|
||||||
@ -135,7 +138,7 @@ show(mySketch)`
|
|||||||
)
|
)
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('recast long array declaration', () => {
|
it('recast long array declaration', () => {
|
||||||
const code = [
|
const code = [
|
||||||
@ -150,7 +153,7 @@ show(mySketch)`
|
|||||||
].join('\n')
|
].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('recast long object exectution', () => {
|
it('recast long object exectution', () => {
|
||||||
const code = `const three = 3
|
const code = `const three = 3
|
||||||
@ -159,26 +162,29 @@ const yo = {
|
|||||||
anum: 2,
|
anum: 2,
|
||||||
identifier: three,
|
identifier: three,
|
||||||
binExp: 4 + 5
|
binExp: 4 + 5
|
||||||
}`
|
}
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted).toBe(code)
|
||||||
})
|
})
|
||||||
it('recast short object exectution', () => {
|
it('recast short object exectution', () => {
|
||||||
const code = `const yo = { key: 'val' }`
|
const code = `const yo = { key: 'val' }
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted).toBe(code)
|
||||||
})
|
})
|
||||||
it('recast object execution with member expression', () => {
|
it('recast object execution with member expression', () => {
|
||||||
const code = `const yo = { a: { b: { c: '123' } } }
|
const code = `const yo = { a: { b: { c: '123' } } }
|
||||||
const key = 'c'
|
const key = 'c'
|
||||||
const myVar = yo.a['b'][key]
|
const myVar = yo.a['b'][key]
|
||||||
const key2 = 'b'
|
const key2 = 'b'
|
||||||
const myVar2 = yo['a'][key2].c`
|
const myVar2 = yo['a'][key2].c
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code.trim())
|
expect(recasted).toBe(code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -186,7 +192,8 @@ describe('testing recasting with comments and whitespace', () => {
|
|||||||
it('code with comments', () => {
|
it('code with comments', () => {
|
||||||
const code = `const yo = { a: { b: { c: '123' } } }
|
const code = `const yo = { a: { b: { c: '123' } } }
|
||||||
// this is a comment
|
// this is a comment
|
||||||
const key = 'c'`
|
const key = 'c'
|
||||||
|
`
|
||||||
|
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
@ -199,7 +206,8 @@ const key = 'c'`
|
|||||||
/* this is
|
/* this is
|
||||||
a
|
a
|
||||||
comment */
|
comment */
|
||||||
const yo = 'bing'`
|
const yo = 'bing'
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
@ -209,7 +217,8 @@ const yo = 'bing'`
|
|||||||
const yo = { a: { b: { c: '123' } } }
|
const yo = { a: { b: { c: '123' } } }
|
||||||
const key = 'c'
|
const key = 'c'
|
||||||
|
|
||||||
// this is also a comment`
|
// this is also a comment
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
@ -223,7 +232,8 @@ const key = 'c'
|
|||||||
comment */
|
comment */
|
||||||
const key = 'c'
|
const key = 'c'
|
||||||
// this is also a comment
|
// this is also a comment
|
||||||
}`
|
}
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
@ -239,7 +249,7 @@ const key = 'c'
|
|||||||
].join('\n')
|
].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('comments sprinkled in all over the place', () => {
|
it('comments sprinkled in all over the place', () => {
|
||||||
const code = `
|
const code = `
|
||||||
@ -261,7 +271,8 @@ const mySk1 = startSketchAt([0, 0])
|
|||||||
|> rx(45, %)
|
|> rx(45, %)
|
||||||
/*
|
/*
|
||||||
one more for good measure
|
one more for good measure
|
||||||
*/`
|
*/
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(`// comment at start
|
expect(recasted).toBe(`// comment at start
|
||||||
@ -278,7 +289,8 @@ a comment between pipe expression statements */
|
|||||||
// and another with just white space between others below
|
// and another with just white space between others below
|
||||||
|> ry(45, %)
|
|> ry(45, %)
|
||||||
|> rx(45, %)
|
|> rx(45, %)
|
||||||
// one more for good measure`)
|
// one more for good measure
|
||||||
|
`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -287,19 +299,19 @@ describe('testing call Expressions in BinaryExpressions and UnaryExpressions', (
|
|||||||
const code = 'const myVar = 2 + min(100, legLen(5, 3))'
|
const code = 'const myVar = 2 + min(100, legLen(5, 3))'
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('nested callExpression in unaryExpression', () => {
|
it('nested callExpression in unaryExpression', () => {
|
||||||
const code = 'const myVar = -min(100, legLen(5, 3))'
|
const code = 'const myVar = -min(100, legLen(5, 3))'
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('with unaryExpression in callExpression', () => {
|
it('with unaryExpression in callExpression', () => {
|
||||||
const code = 'const myVar = min(5, -legLen(5, 4))'
|
const code = 'const myVar = min(5, -legLen(5, 4))'
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('with unaryExpression in sketch situation', () => {
|
it('with unaryExpression in sketch situation', () => {
|
||||||
const code = [
|
const code = [
|
||||||
@ -308,7 +320,7 @@ describe('testing call Expressions in BinaryExpressions and UnaryExpressions', (
|
|||||||
].join('\n')
|
].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -323,7 +335,8 @@ describe('it recasts wrapped object expressions in pipe bodies with correct inde
|
|||||||
intersectTag: 'seg01'
|
intersectTag: 'seg01'
|
||||||
}, %)
|
}, %)
|
||||||
|> line([-0.42, -1.72], %)
|
|> line([-0.42, -1.72], %)
|
||||||
show(part001)`
|
show(part001)
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
@ -333,7 +346,8 @@ show(part001)`
|
|||||||
angle: 201,
|
angle: 201,
|
||||||
offset: -1.35,
|
offset: -1.35,
|
||||||
intersectTag: 'seg01'
|
intersectTag: 'seg01'
|
||||||
}, %)`
|
}, %)
|
||||||
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
@ -342,7 +356,8 @@ show(part001)`
|
|||||||
|
|
||||||
describe('it recasts binary expression using brackets where needed', () => {
|
describe('it recasts binary expression using brackets where needed', () => {
|
||||||
it('when there are two minus in a row', () => {
|
it('when there are two minus in a row', () => {
|
||||||
const code = `const part001 = 1 - (def - abc)`
|
const code = `const part001 = 1 - (def - abc)
|
||||||
|
`
|
||||||
const recasted = recast(code2ast(code).ast)
|
const recasted = recast(code2ast(code).ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
})
|
})
|
||||||
|
@ -6,6 +6,8 @@ import { exportSave } from 'lib/exportSave'
|
|||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import * as Sentry from '@sentry/react'
|
import * as Sentry from '@sentry/react'
|
||||||
|
|
||||||
|
let lastMessage = ''
|
||||||
|
|
||||||
interface CommandInfo {
|
interface CommandInfo {
|
||||||
commandType: CommandTypes
|
commandType: CommandTypes
|
||||||
range: SourceRange
|
range: SourceRange
|
||||||
@ -754,6 +756,13 @@ export class EngineCommandManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
sendSceneCommand(command: EngineCommand): Promise<any> {
|
sendSceneCommand(command: EngineCommand): Promise<any> {
|
||||||
|
if (
|
||||||
|
command.type === 'modeling_cmd_req' &&
|
||||||
|
command.cmd.type !== lastMessage
|
||||||
|
) {
|
||||||
|
console.log('sending command', command.cmd.type)
|
||||||
|
lastMessage = command.cmd.type
|
||||||
|
}
|
||||||
if (!this.engineConnection?.isReady()) {
|
if (!this.engineConnection?.isReady()) {
|
||||||
console.log('socket not ready')
|
console.log('socket not ready')
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
@ -761,7 +770,8 @@ export class EngineCommandManager {
|
|||||||
if (command.type !== 'modeling_cmd_req') return Promise.resolve()
|
if (command.type !== 'modeling_cmd_req') return Promise.resolve()
|
||||||
const cmd = command.cmd
|
const cmd = command.cmd
|
||||||
if (
|
if (
|
||||||
cmd.type === 'camera_drag_move' &&
|
(cmd.type === 'camera_drag_move' ||
|
||||||
|
cmd.type === 'handle_mouse_drag_move') &&
|
||||||
this.engineConnection?.unreliableDataChannel
|
this.engineConnection?.unreliableDataChannel
|
||||||
) {
|
) {
|
||||||
cmd.sequence = this.outSequence
|
cmd.sequence = this.outSequence
|
||||||
|
@ -101,7 +101,8 @@ describe('testing changeSketchArguments', () => {
|
|||||||
|> ${line}
|
|> ${line}
|
||||||
|> lineTo([0.46, -5.82], %)
|
|> lineTo([0.46, -5.82], %)
|
||||||
// |> rx(45, %)
|
// |> rx(45, %)
|
||||||
show(mySketch001)`
|
show(mySketch001)
|
||||||
|
`
|
||||||
const code = genCode(lineToChange)
|
const code = genCode(lineToChange)
|
||||||
const expectedCode = genCode(lineAfterChange)
|
const expectedCode = genCode(lineAfterChange)
|
||||||
const ast = parser_wasm(code)
|
const ast = parser_wasm(code)
|
||||||
@ -164,7 +165,8 @@ show(mySketch001)`
|
|||||||
|> lineTo([-1.59, -1.54], %)
|
|> lineTo([-1.59, -1.54], %)
|
||||||
|> lineTo([0.46, -5.82], %)
|
|> lineTo([0.46, -5.82], %)
|
||||||
|> lineTo([2, 3], %)
|
|> lineTo([2, 3], %)
|
||||||
show(mySketch001)`
|
show(mySketch001)
|
||||||
|
`
|
||||||
expect(recast(modifiedAst)).toBe(expectedCode)
|
expect(recast(modifiedAst)).toBe(expectedCode)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -177,7 +179,8 @@ describe('testing addTagForSketchOnFace', () => {
|
|||||||
// |> rx(45, %)
|
// |> rx(45, %)
|
||||||
|> ${line}
|
|> ${line}
|
||||||
|> lineTo([0.46, -5.82], %)
|
|> lineTo([0.46, -5.82], %)
|
||||||
show(mySketch001)`
|
show(mySketch001)
|
||||||
|
`
|
||||||
const code = genCode(originalLine)
|
const code = genCode(originalLine)
|
||||||
const ast = parser_wasm(code)
|
const ast = parser_wasm(code)
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const programMemory = await enginelessExecutor(ast)
|
||||||
|
@ -4,6 +4,7 @@ import {
|
|||||||
SketchGroup,
|
SketchGroup,
|
||||||
SourceRange,
|
SourceRange,
|
||||||
PathToNode,
|
PathToNode,
|
||||||
|
MemoryItem,
|
||||||
} from '../executor'
|
} from '../executor'
|
||||||
import {
|
import {
|
||||||
Program,
|
Program,
|
||||||
@ -20,7 +21,7 @@ import {
|
|||||||
getNodePathFromSourceRange,
|
getNodePathFromSourceRange,
|
||||||
} from '../queryAst'
|
} from '../queryAst'
|
||||||
import { GuiModes, toolTips, TooTip } from '../../useStore'
|
import { GuiModes, toolTips, TooTip } from '../../useStore'
|
||||||
import { splitPathAtPipeExpression } from '../modifyAst'
|
import { createPipeExpression, splitPathAtPipeExpression } from '../modifyAst'
|
||||||
import { generateUuidFromHashSeed } from '../../lib/uuid'
|
import { generateUuidFromHashSeed } from '../../lib/uuid'
|
||||||
|
|
||||||
import { SketchLineHelper, ModifyAstBase, TransformCallback } from './stdTypes'
|
import { SketchLineHelper, ModifyAstBase, TransformCallback } from './stdTypes'
|
||||||
@ -185,7 +186,7 @@ export const line: SketchLineHelper = {
|
|||||||
createCallback,
|
createCallback,
|
||||||
}) => {
|
}) => {
|
||||||
const _node = { ...node }
|
const _node = { ...node }
|
||||||
const { node: pipe } = getNodeFromPath<PipeExpression>(
|
const { node: pipe } = getNodeFromPath<PipeExpression | CallExpression>(
|
||||||
_node,
|
_node,
|
||||||
pathToNode,
|
pathToNode,
|
||||||
'PipeExpression'
|
'PipeExpression'
|
||||||
@ -197,12 +198,12 @@ export const line: SketchLineHelper = {
|
|||||||
)
|
)
|
||||||
const variableName = varDec.id.name
|
const variableName = varDec.id.name
|
||||||
const sketch = previousProgramMemory?.root?.[variableName]
|
const sketch = previousProgramMemory?.root?.[variableName]
|
||||||
if (sketch.type !== 'sketchGroup') throw new Error('not a sketchGroup')
|
if (sketch.type !== 'SketchGroup') throw new Error('not a SketchGroup')
|
||||||
|
|
||||||
const newXVal = createLiteral(roundOff(to[0] - from[0], 2))
|
const newXVal = createLiteral(roundOff(to[0] - from[0], 2))
|
||||||
const newYVal = createLiteral(roundOff(to[1] - from[1], 2))
|
const newYVal = createLiteral(roundOff(to[1] - from[1], 2))
|
||||||
|
|
||||||
if (replaceExisting && createCallback) {
|
if (replaceExisting && createCallback && pipe.type !== 'CallExpression') {
|
||||||
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
|
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
|
||||||
const { callExp, valueUsedInTransform } = createCallback(
|
const { callExp, valueUsedInTransform } = createCallback(
|
||||||
[newXVal, newYVal],
|
[newXVal, newYVal],
|
||||||
@ -220,7 +221,11 @@ export const line: SketchLineHelper = {
|
|||||||
createArrayExpression([newXVal, newYVal]),
|
createArrayExpression([newXVal, newYVal]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
])
|
])
|
||||||
pipe.body = [...pipe.body, callExp]
|
if (pipe.type === 'PipeExpression') {
|
||||||
|
pipe.body = [...pipe.body, callExp]
|
||||||
|
} else {
|
||||||
|
varDec.init = createPipeExpression([varDec.init, callExp])
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
modifiedAst: _node,
|
modifiedAst: _node,
|
||||||
pathToNode,
|
pathToNode,
|
||||||
@ -238,22 +243,10 @@ export const line: SketchLineHelper = {
|
|||||||
createLiteral(roundOff(to[1] - from[1], 2)),
|
createLiteral(roundOff(to[1] - from[1], 2)),
|
||||||
])
|
])
|
||||||
|
|
||||||
if (
|
if (callExpression.arguments?.[0].type === 'ObjectExpression') {
|
||||||
callExpression.arguments?.[0].type === 'Literal' &&
|
|
||||||
callExpression.arguments?.[0].value === 'default'
|
|
||||||
) {
|
|
||||||
callExpression.arguments[0] = toArrExp
|
|
||||||
} else if (callExpression.arguments?.[0].type === 'ObjectExpression') {
|
|
||||||
const toProp = callExpression.arguments?.[0].properties?.find(
|
const toProp = callExpression.arguments?.[0].properties?.find(
|
||||||
({ key }) => key.name === 'to'
|
({ key }) => key.name === 'to'
|
||||||
)
|
)
|
||||||
if (
|
|
||||||
toProp &&
|
|
||||||
toProp.value.type === 'Literal' &&
|
|
||||||
toProp.value.value === 'default'
|
|
||||||
) {
|
|
||||||
toProp.value = toArrExp
|
|
||||||
}
|
|
||||||
mutateObjExpProp(callExpression.arguments?.[0], toArrExp, 'to')
|
mutateObjExpProp(callExpression.arguments?.[0], toArrExp, 'to')
|
||||||
} else {
|
} else {
|
||||||
mutateArrExp(callExpression.arguments?.[0], toArrExp)
|
mutateArrExp(callExpression.arguments?.[0], toArrExp)
|
||||||
@ -546,7 +539,7 @@ export const angledLineOfXLength: SketchLineHelper = {
|
|||||||
)
|
)
|
||||||
const variableName = varDec.id.name
|
const variableName = varDec.id.name
|
||||||
const sketch = previousProgramMemory?.root?.[variableName]
|
const sketch = previousProgramMemory?.root?.[variableName]
|
||||||
if (sketch.type !== 'sketchGroup') throw new Error('not a sketchGroup')
|
if (sketch.type !== 'SketchGroup') throw new Error('not a SketchGroup')
|
||||||
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
||||||
const xLength = createLiteral(roundOff(Math.abs(from[0] - to[0]), 2) || 0.1)
|
const xLength = createLiteral(roundOff(Math.abs(from[0] - to[0]), 2) || 0.1)
|
||||||
const newLine = createCallback
|
const newLine = createCallback
|
||||||
@ -619,7 +612,7 @@ export const angledLineOfYLength: SketchLineHelper = {
|
|||||||
)
|
)
|
||||||
const variableName = varDec.id.name
|
const variableName = varDec.id.name
|
||||||
const sketch = previousProgramMemory?.root?.[variableName]
|
const sketch = previousProgramMemory?.root?.[variableName]
|
||||||
if (sketch.type !== 'sketchGroup') throw new Error('not a sketchGroup')
|
if (sketch.type !== 'SketchGroup') throw new Error('not a SketchGroup')
|
||||||
|
|
||||||
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
||||||
const yLength = createLiteral(roundOff(Math.abs(from[1] - to[1]), 2) || 0.1)
|
const yLength = createLiteral(roundOff(Math.abs(from[1] - to[1]), 2) || 0.1)
|
||||||
@ -876,7 +869,7 @@ export const angledLineThatIntersects: SketchLineHelper = {
|
|||||||
const varName = varDec.declarations[0].id.name
|
const varName = varDec.declarations[0].id.name
|
||||||
const sketchGroup = previousProgramMemory.root[varName] as SketchGroup
|
const sketchGroup = previousProgramMemory.root[varName] as SketchGroup
|
||||||
const intersectPath = sketchGroup.value.find(
|
const intersectPath = sketchGroup.value.find(
|
||||||
({ name }) => name === intersectTagName
|
({ name }: Path) => name === intersectTagName
|
||||||
)
|
)
|
||||||
let offset = 0
|
let offset = 0
|
||||||
if (intersectPath) {
|
if (intersectPath) {
|
||||||
@ -968,60 +961,14 @@ export function addNewSketchLn({
|
|||||||
pathToNode,
|
pathToNode,
|
||||||
'VariableDeclarator'
|
'VariableDeclarator'
|
||||||
)
|
)
|
||||||
const { node: pipeExp, shallowPath: pipePath } =
|
const { node: pipeExp, shallowPath: pipePath } = getNodeFromPath<
|
||||||
getNodeFromPath<PipeExpression>(node, pathToNode, 'PipeExpression')
|
PipeExpression | CallExpression
|
||||||
const maybeStartSketchAt = pipeExp.body.find(
|
>(node, pathToNode, 'PipeExpression')
|
||||||
(exp) =>
|
|
||||||
exp.type === 'CallExpression' &&
|
|
||||||
exp.callee.name === 'startSketchAt' &&
|
|
||||||
exp.arguments[0].type === 'Literal' &&
|
|
||||||
exp.arguments[0].value === 'default'
|
|
||||||
)
|
|
||||||
const maybeDefaultLine = pipeExp.body.findIndex(
|
|
||||||
(exp) =>
|
|
||||||
exp.type === 'CallExpression' &&
|
|
||||||
exp.callee.name === 'line' &&
|
|
||||||
exp.arguments[0].type === 'Literal' &&
|
|
||||||
exp.arguments[0].value === 'default'
|
|
||||||
)
|
|
||||||
const defaultLinePath: PathToNode = [
|
|
||||||
...pipePath,
|
|
||||||
['body', ''],
|
|
||||||
[maybeDefaultLine, ''],
|
|
||||||
]
|
|
||||||
const variableName = varDec.id.name
|
const variableName = varDec.id.name
|
||||||
const sketch = previousProgramMemory?.root?.[variableName]
|
const sketch = previousProgramMemory?.root?.[variableName]
|
||||||
if (sketch.type !== 'sketchGroup') throw new Error('not a sketchGroup')
|
if (sketch.type !== 'SketchGroup') throw new Error('not a SketchGroup')
|
||||||
|
|
||||||
if (maybeStartSketchAt) {
|
const last = sketch.value[sketch.value.length - 1] || sketch.start
|
||||||
const startSketchAt = maybeStartSketchAt as any
|
|
||||||
startSketchAt.arguments[0] = createArrayExpression([
|
|
||||||
createLiteral(to[0]),
|
|
||||||
createLiteral(to[1]),
|
|
||||||
])
|
|
||||||
return {
|
|
||||||
modifiedAst: node,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (maybeDefaultLine !== -1) {
|
|
||||||
const defaultLine = getNodeFromPath<CallExpression>(
|
|
||||||
node,
|
|
||||||
defaultLinePath
|
|
||||||
).node
|
|
||||||
const { from } = getSketchSegmentFromSourceRange(sketch, [
|
|
||||||
defaultLine.start,
|
|
||||||
defaultLine.end,
|
|
||||||
]).segment
|
|
||||||
return updateArgs({
|
|
||||||
node,
|
|
||||||
previousProgramMemory,
|
|
||||||
pathToNode: defaultLinePath,
|
|
||||||
to,
|
|
||||||
from,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const last = sketch.value[sketch.value.length - 1]
|
|
||||||
const from = last.to
|
const from = last.to
|
||||||
|
|
||||||
return add({
|
return add({
|
||||||
@ -1198,14 +1145,6 @@ function getFirstArgValuesForXYFns(callExpression: CallExpression): {
|
|||||||
} {
|
} {
|
||||||
// used for lineTo, line
|
// used for lineTo, line
|
||||||
const firstArg = callExpression.arguments[0]
|
const firstArg = callExpression.arguments[0]
|
||||||
if (firstArg.type === 'Literal' && firstArg.value === 'default') {
|
|
||||||
return {
|
|
||||||
val:
|
|
||||||
callExpression.callee.name === 'startSketchAt'
|
|
||||||
? [createLiteral(0), createLiteral(0)]
|
|
||||||
: [createLiteral(1), createLiteral(1)],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (firstArg.type === 'ArrayExpression') {
|
if (firstArg.type === 'ArrayExpression') {
|
||||||
return { val: [firstArg.elements[0], firstArg.elements[1]] }
|
return { val: [firstArg.elements[0], firstArg.elements[1]] }
|
||||||
}
|
}
|
||||||
@ -1215,8 +1154,6 @@ function getFirstArgValuesForXYFns(callExpression: CallExpression): {
|
|||||||
if (to?.type === 'ArrayExpression') {
|
if (to?.type === 'ArrayExpression') {
|
||||||
const [x, y] = to.elements
|
const [x, y] = to.elements
|
||||||
return { val: [x, y], tag }
|
return { val: [x, y], tag }
|
||||||
} else if (to?.type === 'Literal' && to.value === 'default') {
|
|
||||||
return { val: [createLiteral(0), createLiteral(0)], tag }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Error('expected ArrayExpression or ObjectExpression')
|
throw new Error('expected ArrayExpression or ObjectExpression')
|
||||||
|
@ -401,6 +401,11 @@ show(part001)`
|
|||||||
programMemory.root['part001'] as SketchGroup,
|
programMemory.root['part001'] as SketchGroup,
|
||||||
[index, index]
|
[index, index]
|
||||||
).segment
|
).segment
|
||||||
expect(segment).toEqual({ to: [0, 0.04], from: [0, 0.04], name: '' })
|
expect(segment).toEqual({
|
||||||
|
to: [0, 0.04],
|
||||||
|
from: [0, 0.04],
|
||||||
|
name: '',
|
||||||
|
type: 'base',
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -4,7 +4,7 @@ import {
|
|||||||
VariableDeclarator,
|
VariableDeclarator,
|
||||||
CallExpression,
|
CallExpression,
|
||||||
} from '../abstractSyntaxTreeTypes'
|
} from '../abstractSyntaxTreeTypes'
|
||||||
import { SketchGroup, SourceRange } from '../executor'
|
import { SketchGroup, SourceRange, Path } from '../executor'
|
||||||
|
|
||||||
export function getSketchSegmentFromSourceRange(
|
export function getSketchSegmentFromSourceRange(
|
||||||
sketchGroup: SketchGroup,
|
sketchGroup: SketchGroup,
|
||||||
@ -20,10 +20,10 @@ export function getSketchSegmentFromSourceRange(
|
|||||||
startSourceRange[1] >= rangeEnd &&
|
startSourceRange[1] >= rangeEnd &&
|
||||||
sketchGroup.start
|
sketchGroup.start
|
||||||
)
|
)
|
||||||
return { segment: sketchGroup.start, index: -1 }
|
return { segment: { ...sketchGroup.start, type: 'base' }, index: -1 }
|
||||||
|
|
||||||
const lineIndex = sketchGroup.value.findIndex(
|
const lineIndex = sketchGroup.value.findIndex(
|
||||||
({ __geoMeta: { sourceRange } }) =>
|
({ __geoMeta: { sourceRange } }: Path) =>
|
||||||
sourceRange[0] <= rangeStart && sourceRange[1] >= rangeEnd
|
sourceRange[0] <= rangeStart && sourceRange[1] >= rangeEnd
|
||||||
)
|
)
|
||||||
const line = sketchGroup.value[lineIndex]
|
const line = sketchGroup.value[lineIndex]
|
||||||
|
@ -124,7 +124,8 @@ const part001 = startSketchAt([0, 0])
|
|||||||
|> yLine(1.04, %) // ln-yLine-free should sub in segLen
|
|> yLine(1.04, %) // ln-yLine-free should sub in segLen
|
||||||
|> xLineTo(30, %) // ln-xLineTo-free should convert to xLine
|
|> xLineTo(30, %) // ln-xLineTo-free should convert to xLine
|
||||||
|> yLineTo(20, %) // ln-yLineTo-free should convert to yLine
|
|> yLineTo(20, %) // ln-yLineTo-free should convert to yLine
|
||||||
show(part001)`
|
show(part001)
|
||||||
|
`
|
||||||
const expectModifiedScript = `const myVar = 3
|
const expectModifiedScript = `const myVar = 3
|
||||||
const myVar2 = 5
|
const myVar2 = 5
|
||||||
const myVar3 = 6
|
const myVar3 = 6
|
||||||
@ -195,7 +196,8 @@ const part001 = startSketchAt([0, 0])
|
|||||||
|> yLine(segLen('seg01', %), %) // ln-yLine-free should sub in segLen
|
|> yLine(segLen('seg01', %), %) // ln-yLine-free should sub in segLen
|
||||||
|> xLine(segLen('seg01', %), %) // ln-xLineTo-free should convert to xLine
|
|> xLine(segLen('seg01', %), %) // ln-xLineTo-free should convert to xLine
|
||||||
|> yLine(segLen('seg01', %), %) // ln-yLineTo-free should convert to yLine
|
|> yLine(segLen('seg01', %), %) // ln-yLineTo-free should convert to yLine
|
||||||
show(part001)`
|
show(part001)
|
||||||
|
`
|
||||||
it('should transform the ast', async () => {
|
it('should transform the ast', async () => {
|
||||||
const ast = parser_wasm(inputScript)
|
const ast = parser_wasm(inputScript)
|
||||||
const selectionRanges: Selections['codeBasedSelections'] = inputScript
|
const selectionRanges: Selections['codeBasedSelections'] = inputScript
|
||||||
@ -254,7 +256,8 @@ const part001 = startSketchAt([0, 0])
|
|||||||
|> angledLineToY([223, 7.68], %) // select for vertical constraint 9
|
|> angledLineToY([223, 7.68], %) // select for vertical constraint 9
|
||||||
|> angledLineToX([333, myVar3], %) // select for horizontal constraint 10
|
|> angledLineToX([333, myVar3], %) // select for horizontal constraint 10
|
||||||
|> angledLineToY([301, myVar], %) // select for vertical constraint 10
|
|> angledLineToY([301, myVar], %) // select for vertical constraint 10
|
||||||
show(part001)`
|
show(part001)
|
||||||
|
`
|
||||||
it('should transform horizontal lines the ast', async () => {
|
it('should transform horizontal lines the ast', async () => {
|
||||||
const expectModifiedScript = `const myVar = 2
|
const expectModifiedScript = `const myVar = 2
|
||||||
const myVar2 = 12
|
const myVar2 = 12
|
||||||
@ -281,7 +284,8 @@ const part001 = startSketchAt([0, 0])
|
|||||||
|> angledLineToY([223, 7.68], %) // select for vertical constraint 9
|
|> angledLineToY([223, 7.68], %) // select for vertical constraint 9
|
||||||
|> xLineTo(myVar3, %) // select for horizontal constraint 10
|
|> xLineTo(myVar3, %) // select for horizontal constraint 10
|
||||||
|> angledLineToY([301, myVar], %) // select for vertical constraint 10
|
|> angledLineToY([301, myVar], %) // select for vertical constraint 10
|
||||||
show(part001)`
|
show(part001)
|
||||||
|
`
|
||||||
const ast = parser_wasm(inputScript)
|
const ast = parser_wasm(inputScript)
|
||||||
const selectionRanges: Selections['codeBasedSelections'] = inputScript
|
const selectionRanges: Selections['codeBasedSelections'] = inputScript
|
||||||
.split('\n')
|
.split('\n')
|
||||||
@ -338,7 +342,8 @@ const part001 = startSketchAt([0, 0])
|
|||||||
|> yLineTo(7.68, %) // select for vertical constraint 9
|
|> yLineTo(7.68, %) // select for vertical constraint 9
|
||||||
|> angledLineToX([333, myVar3], %) // select for horizontal constraint 10
|
|> angledLineToX([333, myVar3], %) // select for horizontal constraint 10
|
||||||
|> yLineTo(myVar, %) // select for vertical constraint 10
|
|> yLineTo(myVar, %) // select for vertical constraint 10
|
||||||
show(part001)`
|
show(part001)
|
||||||
|
`
|
||||||
const ast = parser_wasm(inputScript)
|
const ast = parser_wasm(inputScript)
|
||||||
const selectionRanges: Selections['codeBasedSelections'] = inputScript
|
const selectionRanges: Selections['codeBasedSelections'] = inputScript
|
||||||
.split('\n')
|
.split('\n')
|
||||||
@ -380,7 +385,8 @@ const part001 = startSketchAt([0, 0])
|
|||||||
|> line([0.45, 1.46], %) // free
|
|> line([0.45, 1.46], %) // free
|
||||||
|> line([myVar, 0.01], %) // xRelative
|
|> line([myVar, 0.01], %) // xRelative
|
||||||
|> line([0.7, myVar], %) // yRelative
|
|> line([0.7, myVar], %) // yRelative
|
||||||
show(part001)`
|
show(part001)
|
||||||
|
`
|
||||||
it('testing for free to horizontal and vertical distance', async () => {
|
it('testing for free to horizontal and vertical distance', async () => {
|
||||||
const expectedHorizontalCode = await helperThing(
|
const expectedHorizontalCode = await helperThing(
|
||||||
inputScript,
|
inputScript,
|
||||||
|
@ -28,6 +28,7 @@ import { createFirstArg, getFirstArg, replaceSketchLine } from './sketch'
|
|||||||
import { PathToNode, ProgramMemory } from '../executor'
|
import { PathToNode, ProgramMemory } from '../executor'
|
||||||
import { getSketchSegmentFromSourceRange } from './sketchConstraints'
|
import { getSketchSegmentFromSourceRange } from './sketchConstraints'
|
||||||
import { getAngle, roundOff, normaliseAngle } from '../../lib/utils'
|
import { getAngle, roundOff, normaliseAngle } from '../../lib/utils'
|
||||||
|
import { MemoryItem } from 'wasm-lib/kcl/bindings/MemoryItem'
|
||||||
|
|
||||||
type LineInputsType =
|
type LineInputsType =
|
||||||
| 'xAbsolute'
|
| 'xAbsolute'
|
||||||
@ -1452,7 +1453,7 @@ export function transformAstSketchLines({
|
|||||||
|
|
||||||
const varName = varDec.id.name
|
const varName = varDec.id.name
|
||||||
const sketchGroup = programMemory.root?.[varName]
|
const sketchGroup = programMemory.root?.[varName]
|
||||||
if (!sketchGroup || sketchGroup.type !== 'sketchGroup')
|
if (!sketchGroup || sketchGroup.type !== 'SketchGroup')
|
||||||
throw new Error('not a sketch group')
|
throw new Error('not a sketch group')
|
||||||
const seg = getSketchSegmentFromSourceRange(sketchGroup, range).segment
|
const seg = getSketchSegmentFromSourceRange(sketchGroup, range).segment
|
||||||
const referencedSegment = referencedSegmentRange
|
const referencedSegment = referencedSegmentRange
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
const noModifiersPressed = (e: React.MouseEvent) =>
|
const noModifiersPressed = (e: React.MouseEvent) =>
|
||||||
!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey
|
!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey
|
||||||
|
|
||||||
export type CADProgram =
|
export type CameraSystem =
|
||||||
| 'KittyCAD'
|
| 'KittyCAD'
|
||||||
| 'OnShape'
|
| 'OnShape'
|
||||||
|
| 'Trackpad Friendly'
|
||||||
| 'Solidworks'
|
| 'Solidworks'
|
||||||
| 'NX'
|
| 'NX'
|
||||||
| 'Creo'
|
| 'Creo'
|
||||||
| 'AutoCAD'
|
| 'AutoCAD'
|
||||||
|
|
||||||
export const cadPrograms: CADProgram[] = [
|
export const cameraSystems: CameraSystem[] = [
|
||||||
'KittyCAD',
|
'KittyCAD',
|
||||||
'OnShape',
|
'OnShape',
|
||||||
|
'Trackpad Friendly',
|
||||||
'Solidworks',
|
'Solidworks',
|
||||||
'NX',
|
'NX',
|
||||||
'Creo',
|
'Creo',
|
||||||
@ -21,12 +23,14 @@ export const cadPrograms: CADProgram[] = [
|
|||||||
interface MouseGuardHandler {
|
interface MouseGuardHandler {
|
||||||
description: string
|
description: string
|
||||||
callback: (e: React.MouseEvent) => boolean
|
callback: (e: React.MouseEvent) => boolean
|
||||||
|
lenientDragStartButton?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MouseGuardZoomHandler {
|
interface MouseGuardZoomHandler {
|
||||||
description: string
|
description: string
|
||||||
dragCallback: (e: React.MouseEvent) => boolean
|
dragCallback: (e: React.MouseEvent) => boolean
|
||||||
scrollCallback: (e: React.MouseEvent) => boolean
|
scrollCallback: (e: React.MouseEvent) => boolean
|
||||||
|
lenientDragStartButton?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MouseGuard {
|
interface MouseGuard {
|
||||||
@ -35,12 +39,12 @@ interface MouseGuard {
|
|||||||
rotate: MouseGuardHandler
|
rotate: MouseGuardHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
export const cameraMouseDragGuards: Record<CADProgram, MouseGuard> = {
|
export const cameraMouseDragGuards: Record<CameraSystem, MouseGuard> = {
|
||||||
KittyCAD: {
|
KittyCAD: {
|
||||||
pan: {
|
pan: {
|
||||||
description: 'Right click + Shift + drag or middle click + drag',
|
description: 'Right click + Shift + drag or middle click + drag',
|
||||||
callback: (e) =>
|
callback: (e) =>
|
||||||
(e.button === 3 && noModifiersPressed(e)) ||
|
(e.button === 1 && noModifiersPressed(e)) ||
|
||||||
(e.button === 2 && e.shiftKey),
|
(e.button === 2 && e.shiftKey),
|
||||||
},
|
},
|
||||||
zoom: {
|
zoom: {
|
||||||
@ -58,7 +62,7 @@ export const cameraMouseDragGuards: Record<CADProgram, MouseGuard> = {
|
|||||||
description: 'Right click + Ctrl + drag or middle click + drag',
|
description: 'Right click + Ctrl + drag or middle click + drag',
|
||||||
callback: (e) =>
|
callback: (e) =>
|
||||||
(e.button === 2 && e.ctrlKey) ||
|
(e.button === 2 && e.ctrlKey) ||
|
||||||
(e.button === 3 && noModifiersPressed(e)),
|
(e.button === 1 && noModifiersPressed(e)),
|
||||||
},
|
},
|
||||||
zoom: {
|
zoom: {
|
||||||
description: 'Scroll wheel',
|
description: 'Scroll wheel',
|
||||||
@ -70,55 +74,74 @@ export const cameraMouseDragGuards: Record<CADProgram, MouseGuard> = {
|
|||||||
callback: (e) => e.button === 2 && noModifiersPressed(e),
|
callback: (e) => e.button === 2 && noModifiersPressed(e),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'Trackpad Friendly': {
|
||||||
|
pan: {
|
||||||
|
description: 'Left click + Alt + Shift + drag or middle click + drag',
|
||||||
|
callback: (e) =>
|
||||||
|
(e.button === 0 && e.altKey && e.shiftKey && !e.metaKey) ||
|
||||||
|
(e.button === 1 && noModifiersPressed(e)),
|
||||||
|
},
|
||||||
|
zoom: {
|
||||||
|
description: 'Scroll wheel or Left click + Alt + OS + drag',
|
||||||
|
dragCallback: (e) => e.button === 0 && e.altKey && e.metaKey,
|
||||||
|
scrollCallback: () => true,
|
||||||
|
},
|
||||||
|
rotate: {
|
||||||
|
description: 'Left click + Alt + drag',
|
||||||
|
callback: (e) => e.button === 0 && e.altKey && !e.shiftKey && !e.metaKey,
|
||||||
|
lenientDragStartButton: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
Solidworks: {
|
Solidworks: {
|
||||||
pan: {
|
pan: {
|
||||||
description: 'Right click + Ctrl + drag',
|
description: 'Right click + Ctrl + drag',
|
||||||
callback: (e) => e.button === 2 && e.ctrlKey,
|
callback: (e) => e.button === 2 && e.ctrlKey,
|
||||||
|
lenientDragStartButton: 2,
|
||||||
},
|
},
|
||||||
zoom: {
|
zoom: {
|
||||||
description: 'Scroll wheel or Middle click + Shift + drag',
|
description: 'Scroll wheel or Middle click + Shift + drag',
|
||||||
dragCallback: (e) => e.button === 3 && e.shiftKey,
|
dragCallback: (e) => e.button === 1 && e.shiftKey,
|
||||||
scrollCallback: () => true,
|
scrollCallback: () => true,
|
||||||
},
|
},
|
||||||
rotate: {
|
rotate: {
|
||||||
description: 'Middle click + drag',
|
description: 'Middle click + drag',
|
||||||
callback: (e) => e.button === 3 && noModifiersPressed(e),
|
callback: (e) => e.button === 1 && noModifiersPressed(e),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
NX: {
|
NX: {
|
||||||
pan: {
|
pan: {
|
||||||
description: 'Middle click + Shift + drag',
|
description: 'Middle click + Shift + drag',
|
||||||
callback: (e) => e.button === 3 && e.shiftKey,
|
callback: (e) => e.button === 1 && e.shiftKey,
|
||||||
},
|
},
|
||||||
zoom: {
|
zoom: {
|
||||||
description: 'Scroll wheel or Middle click + Ctrl + drag',
|
description: 'Scroll wheel or Middle click + Ctrl + drag',
|
||||||
dragCallback: (e) => e.button === 3 && e.ctrlKey,
|
dragCallback: (e) => e.button === 1 && e.ctrlKey,
|
||||||
scrollCallback: () => true,
|
scrollCallback: () => true,
|
||||||
},
|
},
|
||||||
rotate: {
|
rotate: {
|
||||||
description: 'Middle click + drag',
|
description: 'Middle click + drag',
|
||||||
callback: (e) => e.button === 3 && noModifiersPressed(e),
|
callback: (e) => e.button === 1 && noModifiersPressed(e),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Creo: {
|
Creo: {
|
||||||
pan: {
|
pan: {
|
||||||
description: 'Middle click + Shift + drag',
|
description: 'Middle click + Shift + drag',
|
||||||
callback: (e) => e.button === 3 && e.shiftKey,
|
callback: (e) => e.button === 1 && e.shiftKey,
|
||||||
},
|
},
|
||||||
zoom: {
|
zoom: {
|
||||||
description: 'Scroll wheel or Middle click + Ctrl + drag',
|
description: 'Scroll wheel or Middle click + Ctrl + drag',
|
||||||
dragCallback: (e) => e.button === 3 && e.ctrlKey,
|
dragCallback: (e) => e.button === 1 && e.ctrlKey,
|
||||||
scrollCallback: () => true,
|
scrollCallback: () => true,
|
||||||
},
|
},
|
||||||
rotate: {
|
rotate: {
|
||||||
description: 'Middle click + drag',
|
description: 'Middle click + drag',
|
||||||
callback: (e) => e.button === 3 && noModifiersPressed(e),
|
callback: (e) => e.button === 1 && noModifiersPressed(e),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
AutoCAD: {
|
AutoCAD: {
|
||||||
pan: {
|
pan: {
|
||||||
description: 'Middle click + drag',
|
description: 'Middle click + drag',
|
||||||
callback: (e) => e.button === 3 && noModifiersPressed(e),
|
callback: (e) => e.button === 1 && noModifiersPressed(e),
|
||||||
},
|
},
|
||||||
zoom: {
|
zoom: {
|
||||||
description: 'Scroll wheel',
|
description: 'Scroll wheel',
|
||||||
@ -127,7 +150,7 @@ export const cameraMouseDragGuards: Record<CADProgram, MouseGuard> = {
|
|||||||
},
|
},
|
||||||
rotate: {
|
rotate: {
|
||||||
description: 'Middle click + Shift + drag',
|
description: 'Middle click + Shift + drag',
|
||||||
callback: (e) => e.button === 3 && e.shiftKey,
|
callback: (e) => e.button === 1 && e.shiftKey,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
readDir,
|
readDir,
|
||||||
writeTextFile,
|
writeTextFile,
|
||||||
} from '@tauri-apps/api/fs'
|
} from '@tauri-apps/api/fs'
|
||||||
import { documentDir } from '@tauri-apps/api/path'
|
import { documentDir, homeDir } from '@tauri-apps/api/path'
|
||||||
import { isTauri } from './isTauri'
|
import { isTauri } from './isTauri'
|
||||||
import { ProjectWithEntryPointMetadata } from '../Router'
|
import { ProjectWithEntryPointMetadata } from '../Router'
|
||||||
import { metadata } from 'tauri-plugin-fs-extra-api'
|
import { metadata } from 'tauri-plugin-fs-extra-api'
|
||||||
@ -32,7 +32,13 @@ export async function initializeProjectDirectory(directory: string) {
|
|||||||
return directory
|
return directory
|
||||||
}
|
}
|
||||||
|
|
||||||
const docDirectory = await documentDir()
|
let docDirectory: string
|
||||||
|
try {
|
||||||
|
docDirectory = await documentDir()
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
docDirectory = await homeDir() // seems to work better on Linux
|
||||||
|
}
|
||||||
|
|
||||||
const INITIAL_DEFAULT_DIR = docDirectory + PROJECT_FOLDER
|
const INITIAL_DEFAULT_DIR = docDirectory + PROJECT_FOLDER
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class MockEngineCommandManager {
|
|||||||
|
|
||||||
export async function enginelessExecutor(
|
export async function enginelessExecutor(
|
||||||
ast: Program,
|
ast: Program,
|
||||||
pm: ProgramMemory = { root: {} }
|
pm: ProgramMemory = { root: {}, return: null }
|
||||||
): Promise<ProgramMemory> {
|
): Promise<ProgramMemory> {
|
||||||
const mockEngineCommandManager = new MockEngineCommandManager({
|
const mockEngineCommandManager = new MockEngineCommandManager({
|
||||||
setIsStreamReady: () => {},
|
setIsStreamReady: () => {},
|
||||||
@ -64,7 +64,7 @@ export async function enginelessExecutor(
|
|||||||
|
|
||||||
export async function executor(
|
export async function executor(
|
||||||
ast: Program,
|
ast: Program,
|
||||||
pm: ProgramMemory = { root: {} }
|
pm: ProgramMemory = { root: {}, return: null }
|
||||||
): Promise<ProgramMemory> {
|
): Promise<ProgramMemory> {
|
||||||
const engineCommandManager = new EngineCommandManager({
|
const engineCommandManager = new EngineCommandManager({
|
||||||
setIsStreamReady: () => {},
|
setIsStreamReady: () => {},
|
||||||
|
@ -118,16 +118,14 @@ async function getUser(context: UserContext) {
|
|||||||
if (!context.token && '__TAURI__' in window) throw 'not log in'
|
if (!context.token && '__TAURI__' in window) throw 'not log in'
|
||||||
if (context.token) headers['Authorization'] = `Bearer ${context.token}`
|
if (context.token) headers['Authorization'] = `Bearer ${context.token}`
|
||||||
if (SKIP_AUTH) return LOCAL_USER
|
if (SKIP_AUTH) return LOCAL_USER
|
||||||
try {
|
const response = await fetch(url, {
|
||||||
const response = await fetch(url, {
|
method: 'GET',
|
||||||
method: 'GET',
|
credentials: 'include',
|
||||||
credentials: 'include',
|
headers,
|
||||||
headers,
|
})
|
||||||
})
|
|
||||||
const user = await response.json()
|
const user = await response.json()
|
||||||
if ('error_code' in user) throw new Error(user.message)
|
if ('error_code' in user) throw new Error(user.message)
|
||||||
return user
|
|
||||||
} catch (e) {
|
return user
|
||||||
console.error(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { assign, createMachine } from 'xstate'
|
import { assign, createMachine } from 'xstate'
|
||||||
import { CommandBarMeta } from '../lib/commands'
|
import { CommandBarMeta } from '../lib/commands'
|
||||||
import { Themes, getSystemTheme, setThemeClass } from '../lib/theme'
|
import { Themes, getSystemTheme, setThemeClass } from '../lib/theme'
|
||||||
import { CADProgram, cadPrograms } from 'lib/cameraControls'
|
import { CameraSystem, cameraSystems } from 'lib/cameraControls'
|
||||||
|
|
||||||
export const DEFAULT_PROJECT_NAME = 'project-$nnn'
|
export const DEFAULT_PROJECT_NAME = 'project-$nnn'
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ export const settingsCommandBarMeta: CommandBarMeta = {
|
|||||||
name: 'cameraControls',
|
name: 'cameraControls',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
defaultValue: 'cameraControls',
|
defaultValue: 'cameraControls',
|
||||||
options: Object.values(cadPrograms).map((v) => ({ name: v })),
|
options: Object.values(cameraSystems).map((v) => ({ name: v })),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -109,7 +109,7 @@ export const settingsMachine = createMachine(
|
|||||||
predictableActionArguments: true,
|
predictableActionArguments: true,
|
||||||
context: {
|
context: {
|
||||||
baseUnit: 'in' as BaseUnit,
|
baseUnit: 'in' as BaseUnit,
|
||||||
cameraControls: 'KittyCAD' as CADProgram,
|
cameraControls: 'KittyCAD' as CameraSystem,
|
||||||
defaultDirectory: '',
|
defaultDirectory: '',
|
||||||
defaultProjectName: DEFAULT_PROJECT_NAME,
|
defaultProjectName: DEFAULT_PROJECT_NAME,
|
||||||
onboardingStatus: '',
|
onboardingStatus: '',
|
||||||
@ -232,7 +232,10 @@ export const settingsMachine = createMachine(
|
|||||||
schema: {
|
schema: {
|
||||||
events: {} as
|
events: {} as
|
||||||
| { type: 'Set Base Unit'; data: { baseUnit: BaseUnit } }
|
| { type: 'Set Base Unit'; data: { baseUnit: BaseUnit } }
|
||||||
| { type: 'Set Camera Controls'; data: { cameraControls: CADProgram } }
|
| {
|
||||||
|
type: 'Set Camera Controls'
|
||||||
|
data: { cameraControls: CameraSystem }
|
||||||
|
}
|
||||||
| { type: 'Set Default Directory'; data: { defaultDirectory: string } }
|
| { type: 'Set Default Directory'; data: { defaultDirectory: string } }
|
||||||
| {
|
| {
|
||||||
type: 'Set Default Project Name'
|
type: 'Set Default Project Name'
|
||||||
|
@ -18,8 +18,8 @@ import { IndexLoaderData, paths } from '../Router'
|
|||||||
import { Themes } from '../lib/theme'
|
import { Themes } from '../lib/theme'
|
||||||
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
|
||||||
import {
|
import {
|
||||||
CADProgram,
|
CameraSystem,
|
||||||
cadPrograms,
|
cameraSystems,
|
||||||
cameraMouseDragGuards,
|
cameraMouseDragGuards,
|
||||||
} from 'lib/cameraControls'
|
} from 'lib/cameraControls'
|
||||||
import { UnitSystem } from 'machines/settingsMachine'
|
import { UnitSystem } from 'machines/settingsMachine'
|
||||||
@ -103,11 +103,11 @@ export const Settings = () => {
|
|||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
send({
|
send({
|
||||||
type: 'Set Camera Controls',
|
type: 'Set Camera Controls',
|
||||||
data: { cameraControls: e.target.value as CADProgram },
|
data: { cameraControls: e.target.value as CameraSystem },
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{cadPrograms.map((program) => (
|
{cameraSystems.map((program) => (
|
||||||
<option key={program} value={program}>
|
<option key={program} value={program}>
|
||||||
{program}
|
{program}
|
||||||
</option>
|
</option>
|
||||||
|
@ -43,9 +43,12 @@ export type TooTip =
|
|||||||
| 'yLineTo'
|
| 'yLineTo'
|
||||||
| 'angledLineThatIntersects'
|
| 'angledLineThatIntersects'
|
||||||
|
|
||||||
export const toolTips: TooTip[] = [
|
export const toolTips = [
|
||||||
'lineTo',
|
'sketch_line',
|
||||||
|
'move',
|
||||||
|
// original tooltips
|
||||||
'line',
|
'line',
|
||||||
|
'lineTo',
|
||||||
'angledLine',
|
'angledLine',
|
||||||
'angledLineOfXLength',
|
'angledLineOfXLength',
|
||||||
'angledLineOfYLength',
|
'angledLineOfYLength',
|
||||||
@ -56,7 +59,7 @@ export const toolTips: TooTip[] = [
|
|||||||
'xLineTo',
|
'xLineTo',
|
||||||
'yLineTo',
|
'yLineTo',
|
||||||
'angledLineThatIntersects',
|
'angledLineThatIntersects',
|
||||||
]
|
] as any as TooTip[]
|
||||||
|
|
||||||
export type GuiModes =
|
export type GuiModes =
|
||||||
| {
|
| {
|
||||||
@ -66,6 +69,7 @@ export type GuiModes =
|
|||||||
mode: 'sketch'
|
mode: 'sketch'
|
||||||
sketchMode: TooTip
|
sketchMode: TooTip
|
||||||
isTooltip: true
|
isTooltip: true
|
||||||
|
waitingFirstClick: boolean
|
||||||
rotation: Rotation
|
rotation: Rotation
|
||||||
position: Position
|
position: Position
|
||||||
id?: string
|
id?: string
|
||||||
@ -84,6 +88,7 @@ export type GuiModes =
|
|||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
mode: 'canEditSketch'
|
mode: 'canEditSketch'
|
||||||
|
pathId: string
|
||||||
pathToNode: PathToNode
|
pathToNode: PathToNode
|
||||||
rotation: Rotation
|
rotation: Rotation
|
||||||
position: Position
|
position: Position
|
||||||
@ -122,8 +127,8 @@ export interface StoreState {
|
|||||||
kclErrors: KCLError[]
|
kclErrors: KCLError[]
|
||||||
addKCLError: (err: KCLError) => void
|
addKCLError: (err: KCLError) => void
|
||||||
resetKCLErrors: () => void
|
resetKCLErrors: () => void
|
||||||
ast: Program | null
|
ast: Program
|
||||||
setAst: (ast: Program | null) => void
|
setAst: (ast: Program) => void
|
||||||
updateAst: (
|
updateAst: (
|
||||||
ast: Program,
|
ast: Program,
|
||||||
optionalParams?: {
|
optionalParams?: {
|
||||||
@ -160,8 +165,8 @@ export interface StoreState {
|
|||||||
setIsStreamReady: (isStreamReady: boolean) => void
|
setIsStreamReady: (isStreamReady: boolean) => void
|
||||||
isLSPServerReady: boolean
|
isLSPServerReady: boolean
|
||||||
setIsLSPServerReady: (isLSPServerReady: boolean) => void
|
setIsLSPServerReady: (isLSPServerReady: boolean) => void
|
||||||
buttonDownInStream: number
|
buttonDownInStream: number | undefined
|
||||||
setButtonDownInStream: (buttonDownInStream: number) => void
|
setButtonDownInStream: (buttonDownInStream: number | undefined) => void
|
||||||
didDragInStream: boolean
|
didDragInStream: boolean
|
||||||
setDidDragInStream: (didDragInStream: boolean) => void
|
setDidDragInStream: (didDragInStream: boolean) => void
|
||||||
fileId: string
|
fileId: string
|
||||||
@ -222,12 +227,13 @@ export const useStore = create<StoreState>()(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
editorView.dispatch({
|
ranges.length &&
|
||||||
selection: EditorSelection.create(
|
editorView.dispatch({
|
||||||
ranges,
|
selection: EditorSelection.create(
|
||||||
selections.codeBasedSelections.length - 1
|
ranges,
|
||||||
),
|
selections.codeBasedSelections.length - 1
|
||||||
})
|
),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setCursor2: (codeSelections) => {
|
setCursor2: (codeSelections) => {
|
||||||
@ -281,7 +287,15 @@ export const useStore = create<StoreState>()(
|
|||||||
resetKCLErrors: () => {
|
resetKCLErrors: () => {
|
||||||
set({ kclErrors: [] })
|
set({ kclErrors: [] })
|
||||||
},
|
},
|
||||||
ast: null,
|
ast: {
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
body: [],
|
||||||
|
nonCodeMeta: {
|
||||||
|
noneCodeNodes: {},
|
||||||
|
start: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
setAst: (ast) => {
|
setAst: (ast) => {
|
||||||
set({ ast })
|
set({ ast })
|
||||||
},
|
},
|
||||||
@ -290,7 +304,11 @@ export const useStore = create<StoreState>()(
|
|||||||
const astWithUpdatedSource = parser_wasm(newCode)
|
const astWithUpdatedSource = parser_wasm(newCode)
|
||||||
callBack(astWithUpdatedSource)
|
callBack(astWithUpdatedSource)
|
||||||
|
|
||||||
set({ ast: astWithUpdatedSource, code: newCode })
|
set({
|
||||||
|
ast: astWithUpdatedSource,
|
||||||
|
code: newCode,
|
||||||
|
defferedCode: newCode,
|
||||||
|
})
|
||||||
if (focusPath) {
|
if (focusPath) {
|
||||||
const { node } = getNodeFromPath<any>(
|
const { node } = getNodeFromPath<any>(
|
||||||
astWithUpdatedSource,
|
astWithUpdatedSource,
|
||||||
@ -342,7 +360,7 @@ export const useStore = create<StoreState>()(
|
|||||||
setError: (error = '') => {
|
setError: (error = '') => {
|
||||||
set({ errorState: { isError: !!error, error } })
|
set({ errorState: { isError: !!error, error } })
|
||||||
},
|
},
|
||||||
programMemory: { root: {}, pendingMemory: {} },
|
programMemory: { root: {}, return: null },
|
||||||
setProgramMemory: (programMemory) => set({ programMemory }),
|
setProgramMemory: (programMemory) => set({ programMemory }),
|
||||||
isShiftDown: false,
|
isShiftDown: false,
|
||||||
setIsShiftDown: (isShiftDown) => set({ isShiftDown }),
|
setIsShiftDown: (isShiftDown) => set({ isShiftDown }),
|
||||||
@ -356,7 +374,7 @@ export const useStore = create<StoreState>()(
|
|||||||
setIsStreamReady: (isStreamReady) => set({ isStreamReady }),
|
setIsStreamReady: (isStreamReady) => set({ isStreamReady }),
|
||||||
isLSPServerReady: false,
|
isLSPServerReady: false,
|
||||||
setIsLSPServerReady: (isLSPServerReady) => set({ isLSPServerReady }),
|
setIsLSPServerReady: (isLSPServerReady) => set({ isLSPServerReady }),
|
||||||
buttonDownInStream: 0,
|
buttonDownInStream: undefined,
|
||||||
setButtonDownInStream: (buttonDownInStream) => {
|
setButtonDownInStream: (buttonDownInStream) => {
|
||||||
set({ buttonDownInStream })
|
set({ buttonDownInStream })
|
||||||
},
|
},
|
||||||
|
652
src/wasm-lib/Cargo.lock
generated
652
src/wasm-lib/Cargo.lock
generated
@ -229,6 +229,32 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bindgen"
|
||||||
|
version = "0.64.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"cexpr",
|
||||||
|
"clang-sys",
|
||||||
|
"lazy_static",
|
||||||
|
"lazycell",
|
||||||
|
"peeking_take_while",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"rustc-hash",
|
||||||
|
"shlex",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit_field"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@ -290,6 +316,12 @@ version = "3.13.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
|
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
@ -314,6 +346,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cexpr"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||||
|
dependencies = [
|
||||||
|
"nom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -336,6 +377,17 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clang-sys"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
|
||||||
|
dependencies = [
|
||||||
|
"glob",
|
||||||
|
"libc",
|
||||||
|
"libloading",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "3.2.25"
|
version = "3.2.25"
|
||||||
@ -418,6 +470,12 @@ version = "0.5.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color_quant"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -482,6 +540,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.8"
|
version = "0.5.8"
|
||||||
@ -492,6 +559,30 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.16"
|
version = "0.8.16"
|
||||||
@ -501,6 +592,12 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crunchy"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@ -521,7 +618,7 @@ dependencies = [
|
|||||||
"hashbrown 0.14.0",
|
"hashbrown 0.14.0",
|
||||||
"lock_api",
|
"lock_api",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot_core",
|
"parking_lot_core 0.9.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -667,12 +764,85 @@ dependencies = [
|
|||||||
"similar",
|
"similar",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "exr"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d1e481eb11a482815d3e9d618db8c42a93207134662873809335a92327440c18"
|
||||||
|
dependencies = [
|
||||||
|
"bit_field",
|
||||||
|
"flume",
|
||||||
|
"half",
|
||||||
|
"lebe",
|
||||||
|
"miniz_oxide",
|
||||||
|
"rayon-core",
|
||||||
|
"smallvec",
|
||||||
|
"zune-inflate",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
|
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fdeflate"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10"
|
||||||
|
dependencies = [
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ffmpeg-next"
|
||||||
|
version = "6.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8af03c47ad26832ab3aabc4cdbf210af3d3b878783edd5a7ba044ba33aab7a60"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"ffmpeg-sys-next",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ffmpeg-sys-next"
|
||||||
|
version = "6.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf650f461ccf130f4eef4927affed703cc387b183bfc4a7dfee86a076c131127"
|
||||||
|
dependencies = [
|
||||||
|
"bindgen",
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"num_cpus",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flate2"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flume"
|
||||||
|
version = "0.10.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"nanorand",
|
||||||
|
"pin-project",
|
||||||
|
"spin 0.9.8",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@ -819,12 +989,28 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gif"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
|
||||||
|
dependencies = [
|
||||||
|
"color_quant",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glob"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gloo-utils"
|
name = "gloo-utils"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -857,6 +1043,15 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "half"
|
||||||
|
version = "2.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0"
|
||||||
|
dependencies = [
|
||||||
|
"crunchy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@ -1010,6 +1205,37 @@ dependencies = [
|
|||||||
"unicode-normalization",
|
"unicode-normalization",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "image"
|
||||||
|
version = "0.24.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"byteorder",
|
||||||
|
"color_quant",
|
||||||
|
"exr",
|
||||||
|
"gif",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"png",
|
||||||
|
"qoi",
|
||||||
|
"tiff",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "image-compare"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "419d59423b7202f6a2a95d3b9cf11a8cc9bf83a29cf7dda4d617a90e8c5ccfcf"
|
||||||
|
dependencies = [
|
||||||
|
"image",
|
||||||
|
"itertools 0.10.5",
|
||||||
|
"rayon",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.9.3"
|
version = "1.9.3"
|
||||||
@ -1031,6 +1257,18 @@ dependencies = [
|
|||||||
"hashbrown 0.14.0",
|
"hashbrown 0.14.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.8.0"
|
version = "2.8.0"
|
||||||
@ -1072,6 +1310,15 @@ version = "1.0.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jpeg-decoder"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
|
||||||
|
dependencies = [
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.64"
|
version = "0.3.64"
|
||||||
@ -1131,18 +1378,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d9cf962b1e81a0b4eb923a727e761b40672cbacc7f5f0b75e13579d346352bc7"
|
checksum = "d9cf962b1e81a0b4eb923a727e761b40672cbacc7f5f0b75e13579d346352bc7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"async-trait",
|
||||||
"base64 0.21.2",
|
"base64 0.21.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
"data-encoding",
|
"data-encoding",
|
||||||
|
"format_serde_error",
|
||||||
|
"futures",
|
||||||
|
"http",
|
||||||
"itertools 0.10.5",
|
"itertools 0.10.5",
|
||||||
|
"log",
|
||||||
"parse-display",
|
"parse-display",
|
||||||
"phonenumber",
|
"phonenumber",
|
||||||
|
"rand",
|
||||||
|
"reqwest",
|
||||||
|
"reqwest-conditional-middleware",
|
||||||
|
"reqwest-middleware 0.2.3",
|
||||||
|
"reqwest-retry",
|
||||||
|
"reqwest-tracing",
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_bytes",
|
"serde_bytes",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"serde_urlencoded",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
@ -1153,12 +1413,34 @@ version = "1.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazycell"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lebe"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.147"
|
version = "0.2.147"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libloading"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked-hash-map"
|
name = "linked-hash-map"
|
||||||
version = "0.5.6"
|
version = "0.5.6"
|
||||||
@ -1212,12 +1494,27 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchit"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
version = "0.3.17"
|
version = "0.3.17"
|
||||||
@ -1247,6 +1544,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"adler",
|
"adler",
|
||||||
|
"simd-adler32",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1260,6 +1558,15 @@ dependencies = [
|
|||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nanorand"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "newline-converter"
|
name = "newline-converter"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -1300,6 +1607,17 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@ -1380,7 +1698,7 @@ dependencies = [
|
|||||||
"rand",
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"reqwest-middleware",
|
"reqwest-middleware 0.1.6",
|
||||||
"rustfmt-wrapper",
|
"rustfmt-wrapper",
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
@ -1415,12 +1733,42 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opentelemetry"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6105e89802af13fdf48c49d7646d3b533a70e536d818aae7e78ba0433d01acb8"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"crossbeam-channel",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-executor",
|
||||||
|
"futures-util",
|
||||||
|
"js-sys",
|
||||||
|
"lazy_static",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project",
|
||||||
|
"rand",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_str_bytes"
|
name = "os_str_bytes"
|
||||||
version = "6.5.1"
|
version = "6.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac"
|
checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core 0.8.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@ -1428,7 +1776,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lock_api",
|
"lock_api",
|
||||||
"parking_lot_core",
|
"parking_lot_core 0.9.8",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"instant",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall 0.2.16",
|
||||||
|
"smallvec",
|
||||||
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1470,6 +1832,12 @@ dependencies = [
|
|||||||
"syn 2.0.29",
|
"syn 2.0.29",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "peeking_take_while"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
@ -1538,6 +1906,25 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.17.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"crc32fast",
|
||||||
|
"fdeflate",
|
||||||
|
"flate2",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
@ -1587,6 +1974,15 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "qoi"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-xml"
|
name = "quick-xml"
|
||||||
version = "0.28.2"
|
version = "0.28.2"
|
||||||
@ -1641,6 +2037,28 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@ -1757,6 +2175,18 @@ dependencies = [
|
|||||||
"winreg",
|
"winreg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reqwest-conditional-middleware"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59e50a2e70970896c99d1b8f20ddc30a70b30d3ac6e619a03a8353b64a49b277"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"reqwest",
|
||||||
|
"reqwest-middleware 0.2.3",
|
||||||
|
"task-local-extensions",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest-middleware"
|
name = "reqwest-middleware"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
@ -1773,6 +2203,73 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reqwest-middleware"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff44108c7925d082f2861e683a88618b68235ad9cdc60d64d9d1188efc951cdb"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"async-trait",
|
||||||
|
"http",
|
||||||
|
"reqwest",
|
||||||
|
"serde",
|
||||||
|
"task-local-extensions",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reqwest-retry"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c6a11c05102e5bec712c0619b8c7b7eda8b21a558a0bd981ceee15c38df8be4"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"async-trait",
|
||||||
|
"chrono",
|
||||||
|
"futures",
|
||||||
|
"getrandom",
|
||||||
|
"http",
|
||||||
|
"hyper",
|
||||||
|
"parking_lot 0.11.2",
|
||||||
|
"reqwest",
|
||||||
|
"reqwest-middleware 0.2.3",
|
||||||
|
"retry-policies",
|
||||||
|
"task-local-extensions",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"wasm-timer",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reqwest-tracing"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14b1e66540e0cac90acadaf7109bf99c90d95abcc94b4c096bfa16a2d7aa7a71"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"async-trait",
|
||||||
|
"getrandom",
|
||||||
|
"matchit",
|
||||||
|
"opentelemetry",
|
||||||
|
"reqwest",
|
||||||
|
"reqwest-middleware 0.2.3",
|
||||||
|
"task-local-extensions",
|
||||||
|
"tracing",
|
||||||
|
"tracing-opentelemetry",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "retry-policies"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e09bbcb5003282bcb688f0bae741b278e9c7e8f378f561522c9806c58e075d9b"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"chrono",
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.16.20"
|
version = "0.16.20"
|
||||||
@ -1782,7 +2279,7 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"spin",
|
"spin 0.5.2",
|
||||||
"untrusted",
|
"untrusted",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"winapi",
|
"winapi",
|
||||||
@ -1794,6 +2291,12 @@ version = "0.1.23"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustfmt-wrapper"
|
name = "rustfmt-wrapper"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -2102,6 +2605,21 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sharded-slab"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
@ -2111,6 +2629,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simd-adler32"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "similar"
|
name = "similar"
|
||||||
version = "2.2.1"
|
version = "2.2.1"
|
||||||
@ -2223,6 +2747,15 @@ version = "0.5.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@ -2367,6 +2900,17 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiff"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211"
|
||||||
|
dependencies = [
|
||||||
|
"flate2",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.45"
|
version = "0.1.45"
|
||||||
@ -2434,7 +2978,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"parking_lot",
|
"parking_lot 0.12.1",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2 0.5.3",
|
"socket2 0.5.3",
|
||||||
@ -2605,6 +3149,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
|
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"valuable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-log"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-opentelemetry"
|
||||||
|
version = "0.17.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fbbe89715c1dbbb790059e2565353978564924ee85017b5fff365c872ff6721f"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"opentelemetry",
|
||||||
|
"tracing",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-subscriber"
|
||||||
|
version = "0.3.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
|
||||||
|
dependencies = [
|
||||||
|
"sharded-slab",
|
||||||
|
"thread_local",
|
||||||
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2668,6 +3249,19 @@ dependencies = [
|
|||||||
"utf-8",
|
"utf-8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "twenty-twenty"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c77f4c2039b998d194da9717843bb8c634609b5ccacac513be56985569f6e732"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"ffmpeg-next",
|
||||||
|
"image",
|
||||||
|
"image-compare",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
@ -2769,6 +3363,18 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "valuable"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vcpkg"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
@ -2877,14 +3483,20 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
|
|||||||
name = "wasm-lib"
|
name = "wasm-lib"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"bson",
|
"bson",
|
||||||
"futures",
|
"futures",
|
||||||
"gloo-utils",
|
"gloo-utils",
|
||||||
|
"image",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"kcl-lib",
|
"kcl-lib",
|
||||||
"kittycad",
|
"kittycad",
|
||||||
|
"reqwest",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"tokio",
|
||||||
"tower-lsp",
|
"tower-lsp",
|
||||||
|
"twenty-twenty",
|
||||||
|
"uuid",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"wasm-streams",
|
"wasm-streams",
|
||||||
@ -2904,6 +3516,21 @@ dependencies = [
|
|||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-timer"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f"
|
||||||
|
dependencies = [
|
||||||
|
"futures",
|
||||||
|
"js-sys",
|
||||||
|
"parking_lot 0.11.2",
|
||||||
|
"pin-utils",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.64"
|
version = "0.3.64"
|
||||||
@ -2920,6 +3547,12 @@ version = "0.25.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "weezl"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@ -3125,3 +3758,12 @@ name = "yansi"
|
|||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zune-inflate"
|
||||||
|
version = "0.2.54"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
|
||||||
|
dependencies = [
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
@ -16,6 +16,15 @@ serde_json = "1.0.93"
|
|||||||
wasm-bindgen = "0.2.87"
|
wasm-bindgen = "0.2.87"
|
||||||
wasm-bindgen-futures = "0.4.37"
|
wasm-bindgen-futures = "0.4.37"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
anyhow = "1"
|
||||||
|
image = "0.24.7"
|
||||||
|
kittycad = "0.2.25"
|
||||||
|
reqwest = { version = "0.11.20", default-features = false }
|
||||||
|
tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros", "time"] }
|
||||||
|
twenty-twenty = "0.6.1"
|
||||||
|
uuid = { version = "1.4.1", features = ["v4", "js", "serde"] }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
futures = "0.3.28"
|
futures = "0.3.28"
|
||||||
js-sys = "0.3.64"
|
js-sys = "0.3.64"
|
||||||
|
@ -12,7 +12,7 @@ use tower_lsp::lsp_types::{CompletionItem, CompletionItemKind, DocumentSymbol, R
|
|||||||
use crate::{
|
use crate::{
|
||||||
engine::EngineConnection,
|
engine::EngineConnection,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{MemoryItem, Metadata, PipeInfo, ProgramMemory, SourceRange},
|
executor::{MemoryItem, Metadata, PipeInfo, ProgramMemory, SourceRange, UserVal},
|
||||||
parser::PIPE_OPERATOR,
|
parser::PIPE_OPERATOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -500,15 +500,22 @@ impl BinaryPart {
|
|||||||
pipe_info: &mut PipeInfo,
|
pipe_info: &mut PipeInfo,
|
||||||
engine: &mut EngineConnection,
|
engine: &mut EngineConnection,
|
||||||
) -> Result<MemoryItem, KclError> {
|
) -> Result<MemoryItem, KclError> {
|
||||||
pipe_info.is_in_pipe = false;
|
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
||||||
|
// stop the execution of the pipe.
|
||||||
|
// THIS IS IMPORTANT.
|
||||||
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
|
new_pipe_info.is_in_pipe = false;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
BinaryPart::Literal(literal) => Ok(literal.into()),
|
BinaryPart::Literal(literal) => Ok(literal.into()),
|
||||||
BinaryPart::Identifier(identifier) => {
|
BinaryPart::Identifier(identifier) => {
|
||||||
let value = memory.get(&identifier.name, identifier.into())?;
|
let value = memory.get(&identifier.name, identifier.into())?;
|
||||||
Ok(value.clone())
|
Ok(value.clone())
|
||||||
}
|
}
|
||||||
BinaryPart::BinaryExpression(binary_expression) => binary_expression.get_result(memory, pipe_info, engine),
|
BinaryPart::BinaryExpression(binary_expression) => {
|
||||||
BinaryPart::CallExpression(call_expression) => call_expression.execute(memory, pipe_info, engine),
|
binary_expression.get_result(memory, &mut new_pipe_info, engine)
|
||||||
|
}
|
||||||
|
BinaryPart::CallExpression(call_expression) => call_expression.execute(memory, &mut new_pipe_info, engine),
|
||||||
BinaryPart::UnaryExpression(unary_expression) => {
|
BinaryPart::UnaryExpression(unary_expression) => {
|
||||||
// Return an error this should not happen.
|
// Return an error this should not happen.
|
||||||
Err(KclError::Semantic(KclErrorDetails {
|
Err(KclError::Semantic(KclErrorDetails {
|
||||||
@ -718,8 +725,12 @@ impl CallExpression {
|
|||||||
binary_expression.get_result(memory, pipe_info, engine)?
|
binary_expression.get_result(memory, pipe_info, engine)?
|
||||||
}
|
}
|
||||||
Value::CallExpression(call_expression) => {
|
Value::CallExpression(call_expression) => {
|
||||||
pipe_info.is_in_pipe = false;
|
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
||||||
call_expression.execute(memory, pipe_info, engine)?
|
// stop the execution of the pipe.
|
||||||
|
// THIS IS IMPORTANT.
|
||||||
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
|
new_pipe_info.is_in_pipe = false;
|
||||||
|
call_expression.execute(memory, &mut new_pipe_info, engine)?
|
||||||
}
|
}
|
||||||
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, engine)?,
|
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, engine)?,
|
||||||
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, engine)?,
|
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, engine)?,
|
||||||
@ -773,7 +784,7 @@ impl CallExpression {
|
|||||||
Function::InMemory => {
|
Function::InMemory => {
|
||||||
let mem = memory.clone();
|
let mem = memory.clone();
|
||||||
let func = mem.get(&fn_name, self.into())?;
|
let func = mem.get(&fn_name, self.into())?;
|
||||||
let result = func.call_fn(&fn_args, memory, engine)?.ok_or_else(|| {
|
let result = func.call_fn(&fn_args, &mem, engine)?.ok_or_else(|| {
|
||||||
KclError::UndefinedValue(KclErrorDetails {
|
KclError::UndefinedValue(KclErrorDetails {
|
||||||
message: format!("Result of function {} is undefined", fn_name),
|
message: format!("Result of function {} is undefined", fn_name),
|
||||||
source_ranges: vec![self.into()],
|
source_ranges: vec![self.into()],
|
||||||
@ -1071,23 +1082,23 @@ impl Literal {
|
|||||||
|
|
||||||
impl From<Literal> for MemoryItem {
|
impl From<Literal> for MemoryItem {
|
||||||
fn from(literal: Literal) -> Self {
|
fn from(literal: Literal) -> Self {
|
||||||
MemoryItem::UserVal {
|
MemoryItem::UserVal(UserVal {
|
||||||
value: literal.value.clone(),
|
value: literal.value.clone(),
|
||||||
meta: vec![Metadata {
|
meta: vec![Metadata {
|
||||||
source_range: literal.into(),
|
source_range: literal.into(),
|
||||||
}],
|
}],
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Box<Literal>> for MemoryItem {
|
impl From<&Box<Literal>> for MemoryItem {
|
||||||
fn from(literal: &Box<Literal>) -> Self {
|
fn from(literal: &Box<Literal>) -> Self {
|
||||||
MemoryItem::UserVal {
|
MemoryItem::UserVal(UserVal {
|
||||||
value: literal.value.clone(),
|
value: literal.value.clone(),
|
||||||
meta: vec![Metadata {
|
meta: vec![Metadata {
|
||||||
source_range: literal.into(),
|
source_range: literal.into(),
|
||||||
}],
|
}],
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1199,8 +1210,12 @@ impl ArrayExpression {
|
|||||||
binary_expression.get_result(memory, pipe_info, engine)?
|
binary_expression.get_result(memory, pipe_info, engine)?
|
||||||
}
|
}
|
||||||
Value::CallExpression(call_expression) => {
|
Value::CallExpression(call_expression) => {
|
||||||
pipe_info.is_in_pipe = false;
|
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
||||||
call_expression.execute(memory, pipe_info, engine)?
|
// stop the execution of the pipe.
|
||||||
|
// THIS IS IMPORTANT.
|
||||||
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
|
new_pipe_info.is_in_pipe = false;
|
||||||
|
call_expression.execute(memory, &mut new_pipe_info, engine)?
|
||||||
}
|
}
|
||||||
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, engine)?,
|
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, engine)?,
|
||||||
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, engine)?,
|
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, engine)?,
|
||||||
@ -1230,12 +1245,12 @@ impl ArrayExpression {
|
|||||||
results.push(result);
|
results.push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(MemoryItem::UserVal {
|
Ok(MemoryItem::UserVal(UserVal {
|
||||||
value: results.into(),
|
value: results.into(),
|
||||||
meta: vec![Metadata {
|
meta: vec![Metadata {
|
||||||
source_range: self.into(),
|
source_range: self.into(),
|
||||||
}],
|
}],
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rename all identifiers that have the old name to the new given name.
|
/// Rename all identifiers that have the old name to the new given name.
|
||||||
@ -1321,8 +1336,12 @@ impl ObjectExpression {
|
|||||||
binary_expression.get_result(memory, pipe_info, engine)?
|
binary_expression.get_result(memory, pipe_info, engine)?
|
||||||
}
|
}
|
||||||
Value::CallExpression(call_expression) => {
|
Value::CallExpression(call_expression) => {
|
||||||
pipe_info.is_in_pipe = false;
|
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
||||||
call_expression.execute(memory, pipe_info, engine)?
|
// stop the execution of the pipe.
|
||||||
|
// THIS IS IMPORTANT.
|
||||||
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
|
new_pipe_info.is_in_pipe = false;
|
||||||
|
call_expression.execute(memory, &mut new_pipe_info, engine)?
|
||||||
}
|
}
|
||||||
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, engine)?,
|
Value::UnaryExpression(unary_expression) => unary_expression.get_result(memory, pipe_info, engine)?,
|
||||||
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, engine)?,
|
Value::ObjectExpression(object_expression) => object_expression.execute(memory, pipe_info, engine)?,
|
||||||
@ -1351,12 +1370,12 @@ impl ObjectExpression {
|
|||||||
object.insert(property.key.name.clone(), result.get_json_value()?);
|
object.insert(property.key.name.clone(), result.get_json_value()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(MemoryItem::UserVal {
|
Ok(MemoryItem::UserVal(UserVal {
|
||||||
value: object.into(),
|
value: object.into(),
|
||||||
meta: vec![Metadata {
|
meta: vec![Metadata {
|
||||||
source_range: self.into(),
|
source_range: self.into(),
|
||||||
}],
|
}],
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rename all identifiers that have the old name to the new given name.
|
/// Rename all identifiers that have the old name to the new given name.
|
||||||
@ -1563,12 +1582,12 @@ impl MemberExpression {
|
|||||||
|
|
||||||
if let serde_json::Value::Object(map) = object {
|
if let serde_json::Value::Object(map) = object {
|
||||||
if let Some(value) = map.get(&property_name) {
|
if let Some(value) = map.get(&property_name) {
|
||||||
Ok(MemoryItem::UserVal {
|
Ok(MemoryItem::UserVal(UserVal {
|
||||||
value: value.clone(),
|
value: value.clone(),
|
||||||
meta: vec![Metadata {
|
meta: vec![Metadata {
|
||||||
source_range: self.into(),
|
source_range: self.into(),
|
||||||
}],
|
}],
|
||||||
})
|
}))
|
||||||
} else {
|
} else {
|
||||||
Err(KclError::UndefinedValue(KclErrorDetails {
|
Err(KclError::UndefinedValue(KclErrorDetails {
|
||||||
message: format!("Property {} not found in object", property_name),
|
message: format!("Property {} not found in object", property_name),
|
||||||
@ -1674,10 +1693,20 @@ impl BinaryExpression {
|
|||||||
pipe_info: &mut PipeInfo,
|
pipe_info: &mut PipeInfo,
|
||||||
engine: &mut EngineConnection,
|
engine: &mut EngineConnection,
|
||||||
) -> Result<MemoryItem, KclError> {
|
) -> Result<MemoryItem, KclError> {
|
||||||
pipe_info.is_in_pipe = false;
|
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
||||||
|
// stop the execution of the pipe.
|
||||||
|
// THIS IS IMPORTANT.
|
||||||
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
|
new_pipe_info.is_in_pipe = false;
|
||||||
|
|
||||||
let left_json_value = self.left.get_result(memory, pipe_info, engine)?.get_json_value()?;
|
let left_json_value = self
|
||||||
let right_json_value = self.right.get_result(memory, pipe_info, engine)?.get_json_value()?;
|
.left
|
||||||
|
.get_result(memory, &mut new_pipe_info, engine)?
|
||||||
|
.get_json_value()?;
|
||||||
|
let right_json_value = self
|
||||||
|
.right
|
||||||
|
.get_result(memory, &mut new_pipe_info, engine)?
|
||||||
|
.get_json_value()?;
|
||||||
|
|
||||||
// First check if we are doing string concatenation.
|
// First check if we are doing string concatenation.
|
||||||
if self.operator == BinaryOperator::Add {
|
if self.operator == BinaryOperator::Add {
|
||||||
@ -1686,12 +1715,12 @@ impl BinaryExpression {
|
|||||||
parse_json_value_as_string(&right_json_value),
|
parse_json_value_as_string(&right_json_value),
|
||||||
) {
|
) {
|
||||||
let value = serde_json::Value::String(format!("{}{}", left, right));
|
let value = serde_json::Value::String(format!("{}{}", left, right));
|
||||||
return Ok(MemoryItem::UserVal {
|
return Ok(MemoryItem::UserVal(UserVal {
|
||||||
value,
|
value,
|
||||||
meta: vec![Metadata {
|
meta: vec![Metadata {
|
||||||
source_range: self.into(),
|
source_range: self.into(),
|
||||||
}],
|
}],
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1706,12 +1735,12 @@ impl BinaryExpression {
|
|||||||
BinaryOperator::Mod => (left % right).into(),
|
BinaryOperator::Mod => (left % right).into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(MemoryItem::UserVal {
|
Ok(MemoryItem::UserVal(UserVal {
|
||||||
value,
|
value,
|
||||||
meta: vec![Metadata {
|
meta: vec![Metadata {
|
||||||
source_range: self.into(),
|
source_range: self.into(),
|
||||||
}],
|
}],
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rename all identifiers that have the old name to the new given name.
|
/// Rename all identifiers that have the old name to the new given name.
|
||||||
@ -1803,18 +1832,25 @@ impl UnaryExpression {
|
|||||||
pipe_info: &mut PipeInfo,
|
pipe_info: &mut PipeInfo,
|
||||||
engine: &mut EngineConnection,
|
engine: &mut EngineConnection,
|
||||||
) -> Result<MemoryItem, KclError> {
|
) -> Result<MemoryItem, KclError> {
|
||||||
pipe_info.is_in_pipe = false;
|
// We DO NOT set this gloablly because if we did and this was called inside a pipe it would
|
||||||
|
// stop the execution of the pipe.
|
||||||
|
// THIS IS IMPORTANT.
|
||||||
|
let mut new_pipe_info = pipe_info.clone();
|
||||||
|
new_pipe_info.is_in_pipe = false;
|
||||||
|
|
||||||
let num = parse_json_number_as_f64(
|
let num = parse_json_number_as_f64(
|
||||||
&self.argument.get_result(memory, pipe_info, engine)?.get_json_value()?,
|
&self
|
||||||
|
.argument
|
||||||
|
.get_result(memory, &mut new_pipe_info, engine)?
|
||||||
|
.get_json_value()?,
|
||||||
self.into(),
|
self.into(),
|
||||||
)?;
|
)?;
|
||||||
Ok(MemoryItem::UserVal {
|
Ok(MemoryItem::UserVal(UserVal {
|
||||||
value: (-(num)).into(),
|
value: (-(num)).into(),
|
||||||
meta: vec![Metadata {
|
meta: vec![Metadata {
|
||||||
source_range: self.into(),
|
source_range: self.into(),
|
||||||
}],
|
}],
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a hover value that includes the given character position.
|
/// Returns a hover value that includes the given character position.
|
||||||
@ -1980,6 +2016,9 @@ impl_value_meta!(FunctionExpression);
|
|||||||
|
|
||||||
impl FunctionExpression {
|
impl FunctionExpression {
|
||||||
pub fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String {
|
pub fn recast(&self, options: &FormatOptions, indentation_level: usize) -> String {
|
||||||
|
// We don't want to end with a new line inside nested functions.
|
||||||
|
let mut new_options = options.clone();
|
||||||
|
new_options.insert_final_newline = false;
|
||||||
format!(
|
format!(
|
||||||
"({}) => {{\n{}{}\n}}",
|
"({}) => {{\n{}{}\n}}",
|
||||||
self.params
|
self.params
|
||||||
@ -1988,7 +2027,7 @@ impl FunctionExpression {
|
|||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", "),
|
.join(", "),
|
||||||
options.get_indentation(indentation_level + 1),
|
options.get_indentation(indentation_level + 1),
|
||||||
self.body.recast(options, indentation_level + 1)
|
self.body.recast(&new_options, indentation_level + 1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2056,7 +2095,7 @@ impl FormatOptions {
|
|||||||
Self {
|
Self {
|
||||||
tab_size: 2,
|
tab_size: 2,
|
||||||
use_tabs: false,
|
use_tabs: false,
|
||||||
insert_final_newline: false,
|
insert_final_newline: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2127,7 +2166,8 @@ show(part001)"#;
|
|||||||
r#"const part001 = startSketchAt('default')
|
r#"const part001 = startSketchAt('default')
|
||||||
|> ry(90, %)
|
|> ry(90, %)
|
||||||
|> line('default', %)
|
|> line('default', %)
|
||||||
show(part001)"#
|
show(part001)
|
||||||
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2145,7 +2185,8 @@ show(part001)"#
|
|||||||
recasted,
|
recasted,
|
||||||
r#"const part001 = startSketchAt([0.0, 5.0])
|
r#"const part001 = startSketchAt([0.0, 5.0])
|
||||||
|> line([0.4900857016, -0.0240763666], %)
|
|> line([0.4900857016, -0.0240763666], %)
|
||||||
|> line([0.6804562304, 0.9087880491], %)"#
|
|> line([0.6804562304, 0.9087880491], %)
|
||||||
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2163,7 +2204,8 @@ show(part001)"#
|
|||||||
recasted,
|
recasted,
|
||||||
r#"const part001 = startSketchAt([0.0, 5.0])
|
r#"const part001 = startSketchAt([0.0, 5.0])
|
||||||
|> line([0.4900857016, -0.0240763666], %) // hello world
|
|> line([0.4900857016, -0.0240763666], %) // hello world
|
||||||
|> line([0.6804562304, 0.9087880491], %)"#
|
|> line([0.6804562304, 0.9087880491], %)
|
||||||
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
@ -2182,7 +2224,8 @@ show(part001)"#
|
|||||||
r#"const part001 = startSketchAt([0.0, 5.0])
|
r#"const part001 = startSketchAt([0.0, 5.0])
|
||||||
|> line([0.4900857016, -0.0240763666], %)
|
|> line([0.4900857016, -0.0240763666], %)
|
||||||
// hello world
|
// hello world
|
||||||
|> line([0.6804562304, 0.9087880491], %)"#
|
|> line([0.6804562304, 0.9087880491], %)
|
||||||
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2212,7 +2255,8 @@ show(part001)"#
|
|||||||
const key = 'c'
|
const key = 'c'
|
||||||
// this is also a comment
|
// this is also a comment
|
||||||
return things
|
return things
|
||||||
}"#
|
}
|
||||||
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2254,7 +2298,8 @@ a comment between pipe expression statements */
|
|||||||
// and another with just white space between others below
|
// and another with just white space between others below
|
||||||
|> ry(45, %)
|
|> ry(45, %)
|
||||||
|> rx(45, %)
|
|> rx(45, %)
|
||||||
// one more for good measure"#
|
// one more for good measure
|
||||||
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2276,7 +2321,7 @@ show(part001)"#;
|
|||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast(&Default::default(), 0);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(recasted, some_program_string);
|
assert_eq!(recasted.trim(), some_program_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2295,7 +2340,8 @@ const yo = [
|
|||||||
"three",
|
"three",
|
||||||
4 + 5,
|
4 + 5,
|
||||||
" hey oooooo really long long long"
|
" hey oooooo really long long long"
|
||||||
]"#;
|
]
|
||||||
|
"#;
|
||||||
let tokens = crate::tokeniser::lexer(some_program_string);
|
let tokens = crate::tokeniser::lexer(some_program_string);
|
||||||
let parser = crate::parser::Parser::new(tokens);
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
@ -2319,7 +2365,7 @@ const things = "things"
|
|||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast(&Default::default(), 0);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(recasted, some_program_string.trim());
|
assert_eq!(recasted.trim(), some_program_string.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2337,7 +2383,7 @@ const things = "things"
|
|||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast(&Default::default(), 0);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(recasted, some_program_string.trim());
|
assert_eq!(recasted.trim(), some_program_string.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2362,7 +2408,7 @@ const part001 = startSketchAt([0, 0])
|
|||||||
let program = parser.ast().unwrap();
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
let recasted = program.recast(&Default::default(), 0);
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
assert_eq!(recasted, some_program_string);
|
assert_eq!(recasted.trim(), some_program_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2435,7 +2481,8 @@ fn ghi = (part001) => {
|
|||||||
return part001
|
return part001
|
||||||
}
|
}
|
||||||
|
|
||||||
show(mySuperCoolPart)"#
|
show(mySuperCoolPart)
|
||||||
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2454,7 +2501,45 @@ show(mySuperCoolPart)"#
|
|||||||
recasted,
|
recasted,
|
||||||
r#"fn ghi = (newName, y, z) => {
|
r#"fn ghi = (newName, y, z) => {
|
||||||
return newName
|
return newName
|
||||||
}"#
|
}
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_recast_negative_var() {
|
||||||
|
let some_program_string = r#"const w = 20
|
||||||
|
const l = 8
|
||||||
|
const h = 10
|
||||||
|
|
||||||
|
const firstExtrude = startSketchAt([0,0])
|
||||||
|
|> line([0, l], %)
|
||||||
|
|> line([w, 0], %)
|
||||||
|
|> line([0, -l], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(h, %)
|
||||||
|
|
||||||
|
show(firstExtrude)"#;
|
||||||
|
let tokens = crate::tokeniser::lexer(some_program_string);
|
||||||
|
let parser = crate::parser::Parser::new(tokens);
|
||||||
|
let program = parser.ast().unwrap();
|
||||||
|
|
||||||
|
let recasted = program.recast(&Default::default(), 0);
|
||||||
|
assert_eq!(
|
||||||
|
recasted,
|
||||||
|
r#"const w = 20
|
||||||
|
const l = 8
|
||||||
|
const h = 10
|
||||||
|
|
||||||
|
const firstExtrude = startSketchAt([0, 0])
|
||||||
|
|> line([0, l], %)
|
||||||
|
|> line([w, 0], %)
|
||||||
|
|> line([0, -l], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(h, %)
|
||||||
|
|
||||||
|
show(firstExtrude)
|
||||||
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,16 +98,14 @@ impl ProgramReturn {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(tag = "type", rename_all = "camelCase")]
|
#[serde(tag = "type")]
|
||||||
pub enum MemoryItem {
|
pub enum MemoryItem {
|
||||||
UserVal {
|
UserVal(UserVal),
|
||||||
value: serde_json::Value,
|
|
||||||
#[serde(rename = "__meta")]
|
|
||||||
meta: Vec<Metadata>,
|
|
||||||
},
|
|
||||||
SketchGroup(SketchGroup),
|
SketchGroup(SketchGroup),
|
||||||
ExtrudeGroup(ExtrudeGroup),
|
ExtrudeGroup(ExtrudeGroup),
|
||||||
|
#[ts(skip)]
|
||||||
ExtrudeTransform(ExtrudeTransform),
|
ExtrudeTransform(ExtrudeTransform),
|
||||||
|
#[ts(skip)]
|
||||||
Function {
|
Function {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
func: Option<MemoryFunction>,
|
func: Option<MemoryFunction>,
|
||||||
@ -119,7 +117,16 @@ pub enum MemoryItem {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
|
pub struct UserVal {
|
||||||
|
pub value: serde_json::Value,
|
||||||
|
#[serde(rename = "__meta")]
|
||||||
|
pub meta: Vec<Metadata>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
|
#[ts(export)]
|
||||||
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
pub struct ExtrudeTransform {
|
pub struct ExtrudeTransform {
|
||||||
pub position: Position,
|
pub position: Position,
|
||||||
pub rotation: Rotation,
|
pub rotation: Rotation,
|
||||||
@ -138,7 +145,7 @@ pub type MemoryFunction = fn(
|
|||||||
impl From<MemoryItem> for Vec<SourceRange> {
|
impl From<MemoryItem> for Vec<SourceRange> {
|
||||||
fn from(item: MemoryItem) -> Self {
|
fn from(item: MemoryItem) -> Self {
|
||||||
match item {
|
match item {
|
||||||
MemoryItem::UserVal { meta, .. } => meta.iter().map(|m| m.source_range).collect(),
|
MemoryItem::UserVal(u) => u.meta.iter().map(|m| m.source_range).collect(),
|
||||||
MemoryItem::SketchGroup(s) => s.meta.iter().map(|m| m.source_range).collect(),
|
MemoryItem::SketchGroup(s) => s.meta.iter().map(|m| m.source_range).collect(),
|
||||||
MemoryItem::ExtrudeGroup(e) => e.meta.iter().map(|m| m.source_range).collect(),
|
MemoryItem::ExtrudeGroup(e) => e.meta.iter().map(|m| m.source_range).collect(),
|
||||||
MemoryItem::ExtrudeTransform(e) => e.meta.iter().map(|m| m.source_range).collect(),
|
MemoryItem::ExtrudeTransform(e) => e.meta.iter().map(|m| m.source_range).collect(),
|
||||||
@ -149,8 +156,8 @@ impl From<MemoryItem> for Vec<SourceRange> {
|
|||||||
|
|
||||||
impl MemoryItem {
|
impl MemoryItem {
|
||||||
pub fn get_json_value(&self) -> Result<serde_json::Value, KclError> {
|
pub fn get_json_value(&self) -> Result<serde_json::Value, KclError> {
|
||||||
if let MemoryItem::UserVal { value, .. } = self {
|
if let MemoryItem::UserVal(user_val) = self {
|
||||||
Ok(value.clone())
|
Ok(user_val.value.clone())
|
||||||
} else {
|
} else {
|
||||||
Err(KclError::Semantic(KclErrorDetails {
|
Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!("Not a user value: {:?}", self),
|
message: format!("Not a user value: {:?}", self),
|
||||||
@ -186,7 +193,7 @@ impl MemoryItem {
|
|||||||
/// A sketch group is a collection of paths.
|
/// A sketch group is a collection of paths.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
pub struct SketchGroup {
|
pub struct SketchGroup {
|
||||||
/// The id of the sketch group.
|
/// The id of the sketch group.
|
||||||
pub id: uuid::Uuid,
|
pub id: uuid::Uuid,
|
||||||
@ -238,7 +245,7 @@ impl SketchGroup {
|
|||||||
/// An extrude group is a collection of extrude surfaces.
|
/// An extrude group is a collection of extrude surfaces.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(tag = "type", rename_all = "camelCase")]
|
||||||
pub struct ExtrudeGroup {
|
pub struct ExtrudeGroup {
|
||||||
/// The id of the extrude group.
|
/// The id of the extrude group.
|
||||||
pub id: uuid::Uuid,
|
pub id: uuid::Uuid,
|
||||||
@ -276,15 +283,15 @@ pub enum BodyType {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Copy, Clone, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Deserialize, Serialize, PartialEq, Copy, Clone, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub struct Position(pub [f64; 3]);
|
pub struct Position(#[ts(type = "[number, number, number]")] pub [f64; 3]);
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Copy, Clone, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Deserialize, Serialize, PartialEq, Copy, Clone, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub struct Rotation(pub [f64; 4]);
|
pub struct Rotation(#[ts(type = "[number, number, number, number]")] pub [f64; 4]);
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, PartialEq, Copy, Clone, ts_rs::TS, JsonSchema, Hash, Eq)]
|
#[derive(Debug, Default, Deserialize, Serialize, PartialEq, Copy, Clone, ts_rs::TS, JsonSchema, Hash, Eq)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
pub struct SourceRange(pub [usize; 2]);
|
pub struct SourceRange(#[ts(type = "[number, number]")] pub [usize; 2]);
|
||||||
|
|
||||||
impl SourceRange {
|
impl SourceRange {
|
||||||
/// Create a new source range.
|
/// Create a new source range.
|
||||||
@ -401,8 +408,10 @@ impl From<SourceRange> for Metadata {
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct BasePath {
|
pub struct BasePath {
|
||||||
/// The from point.
|
/// The from point.
|
||||||
|
#[ts(type = "[number, number]")]
|
||||||
pub from: [f64; 2],
|
pub from: [f64; 2],
|
||||||
/// The to point.
|
/// The to point.
|
||||||
|
#[ts(type = "[number, number]")]
|
||||||
pub to: [f64; 2],
|
pub to: [f64; 2],
|
||||||
/// The name of the path.
|
/// The name of the path.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -595,7 +604,9 @@ pub fn execute(
|
|||||||
|
|
||||||
memory.return_ = Some(ProgramReturn::Arguments(call_expr.arguments.clone()));
|
memory.return_ = Some(ProgramReturn::Arguments(call_expr.arguments.clone()));
|
||||||
} else if let Some(func) = memory.clone().root.get(&fn_name) {
|
} else if let Some(func) = memory.clone().root.get(&fn_name) {
|
||||||
func.call_fn(&args, memory, engine)?;
|
let result = func.call_fn(&args, memory, engine)?;
|
||||||
|
|
||||||
|
memory.return_ = result;
|
||||||
} else {
|
} else {
|
||||||
return Err(KclError::Semantic(KclErrorDetails {
|
return Err(KclError::Semantic(KclErrorDetails {
|
||||||
message: format!("No such name {} defined", fn_name),
|
message: format!("No such name {} defined", fn_name),
|
||||||
@ -696,11 +707,39 @@ pub fn execute(
|
|||||||
let result = bin_expr.get_result(memory, &mut pipe_info, engine)?;
|
let result = bin_expr.get_result(memory, &mut pipe_info, engine)?;
|
||||||
memory.return_ = Some(ProgramReturn::Value(result));
|
memory.return_ = Some(ProgramReturn::Value(result));
|
||||||
}
|
}
|
||||||
|
Value::UnaryExpression(unary_expr) => {
|
||||||
|
let result = unary_expr.get_result(memory, &mut pipe_info, engine)?;
|
||||||
|
memory.return_ = Some(ProgramReturn::Value(result));
|
||||||
|
}
|
||||||
Value::Identifier(identifier) => {
|
Value::Identifier(identifier) => {
|
||||||
let value = memory.get(&identifier.name, identifier.into())?.clone();
|
let value = memory.get(&identifier.name, identifier.into())?.clone();
|
||||||
memory.return_ = Some(ProgramReturn::Value(value));
|
memory.return_ = Some(ProgramReturn::Value(value));
|
||||||
}
|
}
|
||||||
_ => (),
|
Value::Literal(literal) => {
|
||||||
|
memory.return_ = Some(ProgramReturn::Value(literal.into()));
|
||||||
|
}
|
||||||
|
Value::ArrayExpression(array_expr) => {
|
||||||
|
let result = array_expr.execute(memory, &mut pipe_info, engine)?;
|
||||||
|
memory.return_ = Some(ProgramReturn::Value(result));
|
||||||
|
}
|
||||||
|
Value::ObjectExpression(obj_expr) => {
|
||||||
|
let result = obj_expr.execute(memory, &mut pipe_info, engine)?;
|
||||||
|
memory.return_ = Some(ProgramReturn::Value(result));
|
||||||
|
}
|
||||||
|
Value::CallExpression(call_expr) => {
|
||||||
|
let result = call_expr.execute(memory, &mut pipe_info, engine)?;
|
||||||
|
memory.return_ = Some(ProgramReturn::Value(result));
|
||||||
|
}
|
||||||
|
Value::MemberExpression(member_expr) => {
|
||||||
|
let result = member_expr.get_result(memory)?;
|
||||||
|
memory.return_ = Some(ProgramReturn::Value(result));
|
||||||
|
}
|
||||||
|
Value::PipeExpression(pipe_expr) => {
|
||||||
|
let result = pipe_expr.get_result(memory, &mut pipe_info, engine)?;
|
||||||
|
memory.return_ = Some(ProgramReturn::Value(result));
|
||||||
|
}
|
||||||
|
Value::PipeSubstitution(_) => {}
|
||||||
|
Value::FunctionExpression(_) => {}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -856,4 +895,116 @@ show(part001)"#;
|
|||||||
|
|
||||||
parse_execute(ast).await.unwrap();
|
parse_execute(ast).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_execute_with_function_literal_in_pipe() {
|
||||||
|
let ast = r#"const w = 20
|
||||||
|
const l = 8
|
||||||
|
const h = 10
|
||||||
|
|
||||||
|
fn thing = () => {
|
||||||
|
return -8
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstExtrude = startSketchAt([0,0])
|
||||||
|
|> line([0, l], %)
|
||||||
|
|> line([w, 0], %)
|
||||||
|
|> line([0, thing()], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(h, %)
|
||||||
|
|
||||||
|
show(firstExtrude)"#;
|
||||||
|
|
||||||
|
parse_execute(ast).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_execute_with_function_unary_in_pipe() {
|
||||||
|
let ast = r#"const w = 20
|
||||||
|
const l = 8
|
||||||
|
const h = 10
|
||||||
|
|
||||||
|
fn thing = (x) => {
|
||||||
|
return -x
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstExtrude = startSketchAt([0,0])
|
||||||
|
|> line([0, l], %)
|
||||||
|
|> line([w, 0], %)
|
||||||
|
|> line([0, thing(8)], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(h, %)
|
||||||
|
|
||||||
|
show(firstExtrude)"#;
|
||||||
|
|
||||||
|
parse_execute(ast).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_execute_with_function_array_in_pipe() {
|
||||||
|
let ast = r#"const w = 20
|
||||||
|
const l = 8
|
||||||
|
const h = 10
|
||||||
|
|
||||||
|
fn thing = (x) => {
|
||||||
|
return [0, -x]
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstExtrude = startSketchAt([0,0])
|
||||||
|
|> line([0, l], %)
|
||||||
|
|> line([w, 0], %)
|
||||||
|
|> line(thing(8), %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(h, %)
|
||||||
|
|
||||||
|
show(firstExtrude)"#;
|
||||||
|
|
||||||
|
parse_execute(ast).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_execute_with_function_call_in_pipe() {
|
||||||
|
let ast = r#"const w = 20
|
||||||
|
const l = 8
|
||||||
|
const h = 10
|
||||||
|
|
||||||
|
fn other_thing = (y) => {
|
||||||
|
return -y
|
||||||
|
}
|
||||||
|
|
||||||
|
fn thing = (x) => {
|
||||||
|
return other_thing(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstExtrude = startSketchAt([0,0])
|
||||||
|
|> line([0, l], %)
|
||||||
|
|> line([w, 0], %)
|
||||||
|
|> line([0, thing(8)], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(h, %)
|
||||||
|
|
||||||
|
show(firstExtrude)"#;
|
||||||
|
|
||||||
|
parse_execute(ast).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_execute_with_function_sketch() {
|
||||||
|
let ast = r#"const box = (h, l, w) => {
|
||||||
|
const myBox = startSketchAt([0,0])
|
||||||
|
|> line([0, l], %)
|
||||||
|
|> line([w, 0], %)
|
||||||
|
|> line([0, -l], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(h, %)
|
||||||
|
|
||||||
|
return myBox
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnBox = box(3, 6, 10)
|
||||||
|
|
||||||
|
show(fnBox)"#;
|
||||||
|
|
||||||
|
parse_execute(ast).await.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,12 +103,12 @@ impl<'a> Args<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn make_user_val_from_json(&self, j: serde_json::Value) -> Result<MemoryItem, KclError> {
|
fn make_user_val_from_json(&self, j: serde_json::Value) -> Result<MemoryItem, KclError> {
|
||||||
Ok(MemoryItem::UserVal {
|
Ok(MemoryItem::UserVal(crate::executor::UserVal {
|
||||||
value: j,
|
value: j,
|
||||||
meta: vec![Metadata {
|
meta: vec![Metadata {
|
||||||
source_range: self.source_range,
|
source_range: self.source_range,
|
||||||
}],
|
}],
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_user_val_from_f64(&self, f: f64) -> Result<MemoryItem, KclError> {
|
fn make_user_val_from_f64(&self, f: f64) -> Result<MemoryItem, KclError> {
|
||||||
|
@ -382,6 +382,20 @@ fn inner_angled_line(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
args.send_modeling_cmd(
|
||||||
|
id,
|
||||||
|
ModelingCmd::ExtendPath {
|
||||||
|
path: sketch_group.id,
|
||||||
|
segment: kittycad::types::PathSegment::Line {
|
||||||
|
end: Point3D {
|
||||||
|
x: to[0],
|
||||||
|
y: to[1],
|
||||||
|
z: 0.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut new_sketch_group = sketch_group.clone();
|
let mut new_sketch_group = sketch_group.clone();
|
||||||
new_sketch_group.value.push(current_path);
|
new_sketch_group.value.push(current_path);
|
||||||
Ok(new_sketch_group)
|
Ok(new_sketch_group)
|
||||||
|
98
src/wasm-lib/tests/executor/main.rs
Normal file
98
src/wasm-lib/tests/executor/main.rs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
/// Executes a kcl program and takes a snapshot of the result.
|
||||||
|
/// This returns the bytes of the snapshot.
|
||||||
|
async fn execute_and_snapshot(code: &str) -> Result<image::DynamicImage> {
|
||||||
|
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
|
||||||
|
let http_client = reqwest::Client::builder()
|
||||||
|
.user_agent(user_agent)
|
||||||
|
// For file conversions we need this to be long.
|
||||||
|
.timeout(std::time::Duration::from_secs(600))
|
||||||
|
.connect_timeout(std::time::Duration::from_secs(60));
|
||||||
|
let ws_client = reqwest::Client::builder()
|
||||||
|
.user_agent(user_agent)
|
||||||
|
// For file conversions we need this to be long.
|
||||||
|
.timeout(std::time::Duration::from_secs(600))
|
||||||
|
.connect_timeout(std::time::Duration::from_secs(60))
|
||||||
|
.tcp_keepalive(std::time::Duration::from_secs(600))
|
||||||
|
.http1_only();
|
||||||
|
|
||||||
|
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
|
||||||
|
|
||||||
|
// Create the client.
|
||||||
|
let client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
|
||||||
|
|
||||||
|
let ws = client
|
||||||
|
.modeling()
|
||||||
|
.commands_ws(None, None, None, None, Some(false))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// Create a temporary file to write the output to.
|
||||||
|
let output_file = std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
|
||||||
|
|
||||||
|
let tokens = kcl_lib::tokeniser::lexer(code);
|
||||||
|
let parser = kcl_lib::parser::Parser::new(tokens);
|
||||||
|
let program = parser.ast()?;
|
||||||
|
let mut mem: kcl_lib::executor::ProgramMemory = Default::default();
|
||||||
|
let mut engine = kcl_lib::engine::EngineConnection::new(
|
||||||
|
ws,
|
||||||
|
std::env::temp_dir().display().to_string().as_str(),
|
||||||
|
output_file.display().to_string().as_str(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let _ = kcl_lib::executor::execute(program, &mut mem, kcl_lib::executor::BodyType::Root, &mut engine)?;
|
||||||
|
|
||||||
|
// Send a snapshot request to the engine.
|
||||||
|
engine.send_modeling_cmd(
|
||||||
|
uuid::Uuid::new_v4(),
|
||||||
|
kcl_lib::executor::SourceRange::default(),
|
||||||
|
kittycad::types::ModelingCmd::TakeSnapshot {
|
||||||
|
format: kittycad::types::ImageFormat::Png,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Wait for the snapshot to be taken.
|
||||||
|
engine.wait_for_snapshot().await;
|
||||||
|
|
||||||
|
// Read the output file.
|
||||||
|
let actual = image::io::Reader::open(output_file).unwrap().decode().unwrap();
|
||||||
|
Ok(actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_execute_with_function_sketch() {
|
||||||
|
let code = r#"const box = (h, l, w) => {
|
||||||
|
const myBox = startSketchAt([0,0])
|
||||||
|
|> line([0, l], %)
|
||||||
|
|> line([w, 0], %)
|
||||||
|
|> line([0, -l], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(h, %)
|
||||||
|
|
||||||
|
return myBox
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnBox = box(3, 6, 10)
|
||||||
|
|
||||||
|
show(fnBox)"#;
|
||||||
|
|
||||||
|
let result = execute_and_snapshot(code).await.unwrap();
|
||||||
|
twenty_twenty::assert_image("tests/executor/outputs/function_sketch.png", &result, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_execute_with_angled_line() {
|
||||||
|
let code = r#"const part001 = startSketchAt([4.83, 12.56])
|
||||||
|
|> line([15.1, 2.48], %)
|
||||||
|
|> line({ to: [3.15, -9.85], tag: 'seg01' }, %)
|
||||||
|
|> line([-15.17, -4.1], %)
|
||||||
|
|> angledLine([segAng('seg01', %), 12.35], %)
|
||||||
|
|> line([-13.02, 10.03], %)
|
||||||
|
|> close(%)
|
||||||
|
|> extrude(4, %)
|
||||||
|
|
||||||
|
show(part001)"#;
|
||||||
|
|
||||||
|
let result = execute_and_snapshot(code).await.unwrap();
|
||||||
|
twenty_twenty::assert_image("tests/executor/outputs/angled_line.png", &result, 1.0);
|
||||||
|
}
|
BIN
src/wasm-lib/tests/executor/outputs/angled_line.png
Normal file
BIN
src/wasm-lib/tests/executor/outputs/angled_line.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
BIN
src/wasm-lib/tests/executor/outputs/function_sketch.png
Normal file
BIN
src/wasm-lib/tests/executor/outputs/function_sketch.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
Reference in New Issue
Block a user