Merge remote-tracking branch 'origin' into kurt-sketch-on-chamfer
@ -618,19 +618,19 @@ test.describe('Sketch tests', () => {
|
|||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
await click00r(30, 0)
|
await click00r(30, 0)
|
||||||
codeStr += ` |> startProfileAt([1.53, 0], %)`
|
codeStr += ` |> startProfileAt([2.03, 0], %)`
|
||||||
await expect(u.codeLocator).toHaveText(codeStr)
|
await expect(u.codeLocator).toHaveText(codeStr)
|
||||||
|
|
||||||
await click00r(30, 0)
|
await click00r(30, 0)
|
||||||
codeStr += ` |> line([1.53, 0], %)`
|
codeStr += ` |> line([2.04, 0], %)`
|
||||||
await expect(u.codeLocator).toHaveText(codeStr)
|
await expect(u.codeLocator).toHaveText(codeStr)
|
||||||
|
|
||||||
await click00r(0, 30)
|
await click00r(0, 30)
|
||||||
codeStr += ` |> line([0, -1.53], %)`
|
codeStr += ` |> line([0, -2.03], %)`
|
||||||
await expect(u.codeLocator).toHaveText(codeStr)
|
await expect(u.codeLocator).toHaveText(codeStr)
|
||||||
|
|
||||||
await click00r(-30, 0)
|
await click00r(-30, 0)
|
||||||
codeStr += ` |> line([-1.53, 0], %)`
|
codeStr += ` |> line([-2.04, 0], %)`
|
||||||
await expect(u.codeLocator).toHaveText(codeStr)
|
await expect(u.codeLocator).toHaveText(codeStr)
|
||||||
|
|
||||||
await click00r(undefined, undefined)
|
await click00r(undefined, undefined)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 43 KiB |
@ -31,6 +31,8 @@ test.describe('Testing selections', () => {
|
|||||||
|
|
||||||
const xAxisClick = () =>
|
const xAxisClick = () =>
|
||||||
page.mouse.click(700, 253).then(() => page.waitForTimeout(100))
|
page.mouse.click(700, 253).then(() => page.waitForTimeout(100))
|
||||||
|
const xAxisClickAfterExitingSketch = () =>
|
||||||
|
page.mouse.click(639, 278).then(() => page.waitForTimeout(100))
|
||||||
const emptySpaceHover = () =>
|
const emptySpaceHover = () =>
|
||||||
test.step('Hover over empty space', async () => {
|
test.step('Hover over empty space', async () => {
|
||||||
await page.mouse.move(700, 143, { steps: 5 })
|
await page.mouse.move(700, 143, { steps: 5 })
|
||||||
@ -44,9 +46,13 @@ test.describe('Testing selections', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
const topHorzSegmentClick = () =>
|
const topHorzSegmentClick = () =>
|
||||||
page.mouse.click(709, 290).then(() => page.waitForTimeout(100))
|
page.mouse
|
||||||
|
.click(startXPx, 500 - PUR * 20)
|
||||||
|
.then(() => page.waitForTimeout(100))
|
||||||
const bottomHorzSegmentClick = () =>
|
const bottomHorzSegmentClick = () =>
|
||||||
page.mouse.click(767, 396).then(() => page.waitForTimeout(100))
|
page.mouse
|
||||||
|
.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||||
|
.then(() => page.waitForTimeout(100))
|
||||||
|
|
||||||
await u.clearCommandLogs()
|
await u.clearCommandLogs()
|
||||||
await expect(
|
await expect(
|
||||||
@ -196,6 +202,8 @@ test.describe('Testing selections', () => {
|
|||||||
|
|
||||||
// select a line, this verifies that sketches in the scene can be selected outside of sketch mode
|
// select a line, this verifies that sketches in the scene can be selected outside of sketch mode
|
||||||
await topHorzSegmentClick()
|
await topHorzSegmentClick()
|
||||||
|
await xAxisClickAfterExitingSketch()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
await emptySpaceHover()
|
await emptySpaceHover()
|
||||||
|
|
||||||
// enter sketch again
|
// enter sketch again
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import { reportRejection } from 'lib/trap'
|
|||||||
|
|
||||||
const ORTHOGRAPHIC_CAMERA_SIZE = 20
|
const ORTHOGRAPHIC_CAMERA_SIZE = 20
|
||||||
const FRAMES_TO_ANIMATE_IN = 30
|
const FRAMES_TO_ANIMATE_IN = 30
|
||||||
|
const ORTHOGRAPHIC_MAGIC_FOV = 4
|
||||||
|
|
||||||
const tempQuaternion = new Quaternion() // just used for maths
|
const tempQuaternion = new Quaternion() // just used for maths
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ export class CameraControls {
|
|||||||
pendingPan: Vector2 | null = null
|
pendingPan: Vector2 | null = null
|
||||||
interactionGuards: MouseGuard = cameraMouseDragGuards.KittyCAD
|
interactionGuards: MouseGuard = cameraMouseDragGuards.KittyCAD
|
||||||
isFovAnimationInProgress = false
|
isFovAnimationInProgress = false
|
||||||
fovBeforeOrtho = 45
|
perspectiveFovBeforeOrtho = 45
|
||||||
get isPerspective() {
|
get isPerspective() {
|
||||||
return this.camera instanceof PerspectiveCamera
|
return this.camera instanceof PerspectiveCamera
|
||||||
}
|
}
|
||||||
@ -398,7 +399,7 @@ export class CameraControls {
|
|||||||
const zoomFudgeFactor = 2280
|
const zoomFudgeFactor = 2280
|
||||||
distance = zoomFudgeFactor / (this.camera.zoom * 45)
|
distance = zoomFudgeFactor / (this.camera.zoom * 45)
|
||||||
}
|
}
|
||||||
const panSpeed = (distance / 1000 / 45) * this.fovBeforeOrtho
|
const panSpeed = (distance / 1000 / 45) * this.perspectiveFovBeforeOrtho
|
||||||
this.pendingPan.x += -deltaMove.x * panSpeed
|
this.pendingPan.x += -deltaMove.x * panSpeed
|
||||||
this.pendingPan.y += deltaMove.y * panSpeed
|
this.pendingPan.y += deltaMove.y * panSpeed
|
||||||
}
|
}
|
||||||
@ -443,8 +444,19 @@ export class CameraControls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMouseWheel = (event: WheelEvent) => {
|
onMouseWheel = (event: WheelEvent) => {
|
||||||
|
const interaction = this.getInteractionType(event)
|
||||||
|
if (interaction === 'none') return
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
if (this.syncDirection === 'engineToClient') {
|
if (this.syncDirection === 'engineToClient') {
|
||||||
this.zoomDataFromLastFrame = event.deltaY
|
if (interaction === 'zoom') {
|
||||||
|
this.zoomDataFromLastFrame = event.deltaY
|
||||||
|
} else {
|
||||||
|
// This case will get handled when we add pan and rotate using Apple trackpad.
|
||||||
|
console.error(
|
||||||
|
`Unexpected interaction type for engineToClient wheel event: ${interaction}`
|
||||||
|
)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,8 +466,16 @@ export class CameraControls {
|
|||||||
// zoom commands to engine. This means dropping some zoom
|
// zoom commands to engine. This means dropping some zoom
|
||||||
// commands too.
|
// commands too.
|
||||||
// From onMouseMove zoom handling which seems to be really smooth
|
// From onMouseMove zoom handling which seems to be really smooth
|
||||||
|
|
||||||
this.handleStart()
|
this.handleStart()
|
||||||
this.pendingZoom = 1 + (event.deltaY / window.devicePixelRatio) * 0.001
|
if (interaction === 'zoom') {
|
||||||
|
this.pendingZoom = 1 + (event.deltaY / window.devicePixelRatio) * 0.001
|
||||||
|
} else {
|
||||||
|
// This case will get handled when we add pan and rotate using Apple trackpad.
|
||||||
|
console.error(
|
||||||
|
`Unexpected interaction type for wheel event: ${interaction}`
|
||||||
|
)
|
||||||
|
}
|
||||||
this.handleEnd()
|
this.handleEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,19 +536,15 @@ export class CameraControls {
|
|||||||
_usePerspectiveCamera = () => {
|
_usePerspectiveCamera = () => {
|
||||||
const { x: px, y: py, z: pz } = this.camera.position
|
const { x: px, y: py, z: pz } = this.camera.position
|
||||||
const { x: qx, y: qy, z: qz, w: qw } = this.camera.quaternion
|
const { x: qx, y: qy, z: qz, w: qw } = this.camera.quaternion
|
||||||
const zoom = this.camera.zoom
|
|
||||||
this.camera = this.createPerspectiveCamera()
|
this.camera = this.createPerspectiveCamera()
|
||||||
|
|
||||||
this.camera.position.set(px, py, pz)
|
this.camera.position.set(px, py, pz)
|
||||||
this.camera.quaternion.set(qx, qy, qz, qw)
|
this.camera.quaternion.set(qx, qy, qz, qw)
|
||||||
const zoomFudgeFactor = 2280
|
|
||||||
const distance = zoomFudgeFactor / (zoom * this.lastPerspectiveFov)
|
|
||||||
const direction = new Vector3().subVectors(
|
const direction = new Vector3().subVectors(
|
||||||
this.camera.position,
|
this.camera.position,
|
||||||
this.target
|
this.target
|
||||||
)
|
)
|
||||||
direction.normalize()
|
direction.normalize()
|
||||||
this.camera.position.copy(this.target).addScaledVector(direction, distance)
|
|
||||||
}
|
}
|
||||||
usePerspectiveCamera = async (forceSend = false) => {
|
usePerspectiveCamera = async (forceSend = false) => {
|
||||||
this._usePerspectiveCamera()
|
this._usePerspectiveCamera()
|
||||||
@ -980,9 +996,9 @@ export class CameraControls {
|
|||||||
)
|
)
|
||||||
this.isFovAnimationInProgress = true
|
this.isFovAnimationInProgress = true
|
||||||
let currentFov = this.lastPerspectiveFov
|
let currentFov = this.lastPerspectiveFov
|
||||||
this.fovBeforeOrtho = currentFov
|
this.perspectiveFovBeforeOrtho = currentFov
|
||||||
|
|
||||||
const targetFov = 4
|
const targetFov = ORTHOGRAPHIC_MAGIC_FOV
|
||||||
const fovAnimationStep = (currentFov - targetFov) / FRAMES_TO_ANIMATE_IN
|
const fovAnimationStep = (currentFov - targetFov) / FRAMES_TO_ANIMATE_IN
|
||||||
let frameWaitOnFinish = 10
|
let frameWaitOnFinish = 10
|
||||||
|
|
||||||
@ -1018,9 +1034,9 @@ export class CameraControls {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
this.isFovAnimationInProgress = true
|
this.isFovAnimationInProgress = true
|
||||||
const targetFov = this.fovBeforeOrtho // Target FOV for perspective
|
const targetFov = this.perspectiveFovBeforeOrtho // Target FOV for perspective
|
||||||
this.lastPerspectiveFov = 4
|
this.lastPerspectiveFov = ORTHOGRAPHIC_MAGIC_FOV
|
||||||
let currentFov = 4
|
let currentFov = ORTHOGRAPHIC_MAGIC_FOV
|
||||||
const initialCameraUp = this.camera.up.clone()
|
const initialCameraUp = this.camera.up.clone()
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.usePerspectiveCamera()
|
this.usePerspectiveCamera()
|
||||||
@ -1056,9 +1072,8 @@ export class CameraControls {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
this.isFovAnimationInProgress = true
|
this.isFovAnimationInProgress = true
|
||||||
const targetFov = this.fovBeforeOrtho // Target FOV for perspective
|
const targetFov = this.perspectiveFovBeforeOrtho // Target FOV for perspective
|
||||||
this.lastPerspectiveFov = 4
|
let currentFov = ORTHOGRAPHIC_MAGIC_FOV
|
||||||
let currentFov = 4
|
|
||||||
const initialCameraUp = this.camera.up.clone()
|
const initialCameraUp = this.camera.up.clone()
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.usePerspectiveCamera()
|
this.usePerspectiveCamera()
|
||||||
@ -1127,7 +1142,7 @@ export class CameraControls {
|
|||||||
this.deferReactUpdate(this.reactCameraProperties)
|
this.deferReactUpdate(this.reactCameraProperties)
|
||||||
Object.values(this._camChangeCallbacks).forEach((cb) => cb())
|
Object.values(this._camChangeCallbacks).forEach((cb) => cb())
|
||||||
}
|
}
|
||||||
getInteractionType = (event: any) =>
|
getInteractionType = (event: MouseEvent) =>
|
||||||
_getInteractionType(
|
_getInteractionType(
|
||||||
this.interactionGuards,
|
this.interactionGuards,
|
||||||
event,
|
event,
|
||||||
@ -1235,16 +1250,21 @@ function _lookAt(position: Vector3, target: Vector3, up: Vector3): Quaternion {
|
|||||||
|
|
||||||
function _getInteractionType(
|
function _getInteractionType(
|
||||||
interactionGuards: MouseGuard,
|
interactionGuards: MouseGuard,
|
||||||
event: any,
|
event: MouseEvent | WheelEvent,
|
||||||
enablePan: boolean,
|
enablePan: boolean,
|
||||||
enableRotate: boolean,
|
enableRotate: boolean,
|
||||||
enableZoom: boolean
|
enableZoom: boolean
|
||||||
): interactionType | 'none' {
|
): interactionType | 'none' {
|
||||||
let state: interactionType | 'none' = 'none'
|
if (event instanceof WheelEvent) {
|
||||||
if (enablePan && interactionGuards.pan.callback(event)) return 'pan'
|
if (enableZoom && interactionGuards.zoom.scrollCallback(event))
|
||||||
if (enableRotate && interactionGuards.rotate.callback(event)) return 'rotate'
|
return 'zoom'
|
||||||
if (enableZoom && interactionGuards.zoom.dragCallback(event)) return 'zoom'
|
} else {
|
||||||
return state
|
if (enablePan && interactionGuards.pan.callback(event)) return 'pan'
|
||||||
|
if (enableRotate && interactionGuards.rotate.callback(event))
|
||||||
|
return 'rotate'
|
||||||
|
if (enableZoom && interactionGuards.zoom.dragCallback(event)) return 'zoom'
|
||||||
|
}
|
||||||
|
return 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -260,7 +260,7 @@ export const Stream = () => {
|
|||||||
if (state.matches('Sketch')) return
|
if (state.matches('Sketch')) return
|
||||||
if (state.matches({ idle: 'showPlanes' })) return
|
if (state.matches({ idle: 'showPlanes' })) return
|
||||||
|
|
||||||
if (btnName(e).left) {
|
if (btnName(e.nativeEvent).left) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
sendSelectEventToEngine(e, videoRef.current)
|
sendSelectEventToEngine(e, videoRef.current)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -410,6 +410,11 @@ describe('testing math operators', () => {
|
|||||||
const mem = await exe(code)
|
const mem = await exe(code)
|
||||||
expect(mem.get('myVar')?.value).toBe(5)
|
expect(mem.get('myVar')?.value).toBe(5)
|
||||||
})
|
})
|
||||||
|
it('can do power of math', async () => {
|
||||||
|
const code = 'const myNeg2 = 4 ^ 2 - 3 ^ 2 * 2'
|
||||||
|
const mem = await exe(code)
|
||||||
|
expect(mem.get('myNeg2')?.value).toBe(-2)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Testing Errors', () => {
|
describe('Testing Errors', () => {
|
||||||
|
|||||||
@ -6,7 +6,7 @@ const META =
|
|||||||
PLATFORM === 'macos' ? 'Cmd' : PLATFORM === 'windows' ? 'Win' : 'Super'
|
PLATFORM === 'macos' ? 'Cmd' : PLATFORM === 'windows' ? 'Win' : 'Super'
|
||||||
const ALT = PLATFORM === 'macos' ? 'Option' : 'Alt'
|
const ALT = PLATFORM === 'macos' ? 'Option' : 'Alt'
|
||||||
|
|
||||||
const noModifiersPressed = (e: React.MouseEvent) =>
|
const noModifiersPressed = (e: MouseEvent) =>
|
||||||
!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey
|
!e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey
|
||||||
|
|
||||||
export type CameraSystem =
|
export type CameraSystem =
|
||||||
@ -53,14 +53,14 @@ export function mouseControlsToCameraSystem(
|
|||||||
|
|
||||||
interface MouseGuardHandler {
|
interface MouseGuardHandler {
|
||||||
description: string
|
description: string
|
||||||
callback: (e: React.MouseEvent) => boolean
|
callback: (e: MouseEvent) => boolean
|
||||||
lenientDragStartButton?: number
|
lenientDragStartButton?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MouseGuardZoomHandler {
|
interface MouseGuardZoomHandler {
|
||||||
description: string
|
description: string
|
||||||
dragCallback: (e: React.MouseEvent) => boolean
|
dragCallback: (e: MouseEvent) => boolean
|
||||||
scrollCallback: (e: React.MouseEvent) => boolean
|
scrollCallback: (e: WheelEvent) => boolean
|
||||||
lenientDragStartButton?: number
|
lenientDragStartButton?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ export interface MouseGuard {
|
|||||||
rotate: MouseGuardHandler
|
rotate: MouseGuardHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
export const btnName = (e: React.MouseEvent) => ({
|
export const btnName = (e: MouseEvent) => ({
|
||||||
middle: !!(e.buttons & 4) || e.button === 1,
|
middle: !!(e.buttons & 4) || e.button === 1,
|
||||||
right: !!(e.buttons & 2) || e.button === 2,
|
right: !!(e.buttons & 2) || e.button === 2,
|
||||||
left: !!(e.buttons & 1) || e.button === 0,
|
left: !!(e.buttons & 1) || e.button === 0,
|
||||||
|
|||||||
22
src/wasm-lib/Cargo.lock
generated
@ -264,7 +264,7 @@ dependencies = [
|
|||||||
"bitvec",
|
"bitvec",
|
||||||
"chrono",
|
"chrono",
|
||||||
"hex",
|
"hex",
|
||||||
"indexmap 2.2.5",
|
"indexmap 2.5.0",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
@ -690,7 +690,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive-docs"
|
name = "derive-docs"
|
||||||
version = "0.1.26"
|
version = "0.1.27"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -1067,7 +1067,7 @@ dependencies = [
|
|||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
"indexmap 2.2.5",
|
"indexmap 2.5.0",
|
||||||
"slab",
|
"slab",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
@ -1293,12 +1293,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.2.5"
|
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 = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
|
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.14.3",
|
"hashbrown 0.14.3",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1399,7 +1400,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.2.14"
|
version = "0.2.15"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"approx 0.5.1",
|
"approx 0.5.1",
|
||||||
@ -1422,6 +1423,7 @@ dependencies = [
|
|||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
"iai",
|
"iai",
|
||||||
"image",
|
"image",
|
||||||
|
"indexmap 2.5.0",
|
||||||
"insta",
|
"insta",
|
||||||
"itertools 0.13.0",
|
"itertools 0.13.0",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@ -1472,7 +1474,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-test-server"
|
name = "kcl-test-server"
|
||||||
version = "0.1.10"
|
version = "0.1.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"hyper",
|
"hyper",
|
||||||
@ -2740,7 +2742,7 @@ version = "1.0.128"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.2.5",
|
"indexmap 2.5.0",
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
"ryu",
|
"ryu",
|
||||||
@ -3268,7 +3270,7 @@ version = "0.22.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
|
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.2.5",
|
"indexmap 2.5.0",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
@ -4035,6 +4037,6 @@ dependencies = [
|
|||||||
"crc32fast",
|
"crc32fast",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
"indexmap 2.2.5",
|
"indexmap 2.5.0",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "derive-docs"
|
name = "derive-docs"
|
||||||
description = "A tool for generating documentation from Rust derive macros"
|
description = "A tool for generating documentation from Rust derive macros"
|
||||||
version = "0.1.26"
|
version = "0.1.27"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-test-server"
|
name = "kcl-test-server"
|
||||||
description = "A test server for KCL"
|
description = "A test server for KCL"
|
||||||
version = "0.1.10"
|
version = "0.1.11"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
description = "KittyCAD Language implementation and tools"
|
description = "KittyCAD Language implementation and tools"
|
||||||
version = "0.2.14"
|
version = "0.2.15"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
@ -20,13 +20,14 @@ clap = { version = "4.5.17", default-features = false, optional = true, features
|
|||||||
convert_case = "0.6.0"
|
convert_case = "0.6.0"
|
||||||
dashmap = "6.1.0"
|
dashmap = "6.1.0"
|
||||||
databake = { version = "0.1.8", features = ["derive"] }
|
databake = { version = "0.1.8", features = ["derive"] }
|
||||||
derive-docs = { version = "0.1.26", path = "../derive-docs" }
|
derive-docs = { version = "0.1.27", path = "../derive-docs" }
|
||||||
form_urlencoded = "1.2.1"
|
form_urlencoded = "1.2.1"
|
||||||
futures = { version = "0.3.30" }
|
futures = { version = "0.3.30" }
|
||||||
git_rev = "0.1.0"
|
git_rev = "0.1.0"
|
||||||
gltf-json = "1.4.1"
|
gltf-json = "1.4.1"
|
||||||
http = { workspace = true }
|
http = { workspace = true }
|
||||||
image = { version = "0.25.1", default-features = false, features = ["png"] }
|
image = { version = "0.25.1", default-features = false, features = ["png"] }
|
||||||
|
indexmap = { version = "2.5.0", features = ["serde"] }
|
||||||
kittycad = { workspace = true }
|
kittycad = { workspace = true }
|
||||||
kittycad-modeling-cmds = { workspace = true }
|
kittycad-modeling-cmds = { workspace = true }
|
||||||
lazy_static = "1.5.0"
|
lazy_static = "1.5.0"
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use kcmc::each_cmd as mcmd;
|
use kcmc::{
|
||||||
use kcmc::ok_response::OkModelingCmdResponse;
|
each_cmd as mcmd, ok_response::OkModelingCmdResponse, shared::PathCommand, websocket::OkWebSocketResponseData,
|
||||||
use kcmc::shared::PathCommand;
|
ModelingCmd,
|
||||||
use kcmc::websocket::OkWebSocketResponseData;
|
};
|
||||||
use kcmc::ModelingCmd;
|
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|||||||
@ -2875,7 +2875,7 @@ impl BinaryOperator {
|
|||||||
match &self {
|
match &self {
|
||||||
BinaryOperator::Add | BinaryOperator::Sub => 11,
|
BinaryOperator::Add | BinaryOperator::Sub => 11,
|
||||||
BinaryOperator::Mul | BinaryOperator::Div | BinaryOperator::Mod => 12,
|
BinaryOperator::Mul | BinaryOperator::Div | BinaryOperator::Mod => 12,
|
||||||
BinaryOperator::Pow => 6,
|
BinaryOperator::Pow => 13,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,19 +1,19 @@
|
|||||||
//! Functions for setting up our WebSocket and WebRTC connections for communications with the
|
//! Functions for setting up our WebSocket and WebRTC connections for communications with the
|
||||||
//! engine.
|
//! engine.
|
||||||
|
|
||||||
use std::{
|
use std::sync::{Arc, Mutex};
|
||||||
collections::HashMap,
|
|
||||||
sync::{Arc, Mutex},
|
|
||||||
};
|
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use kcmc::websocket::{
|
use indexmap::IndexMap;
|
||||||
BatchResponse, FailureWebSocketResponse, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData,
|
use kcmc::{
|
||||||
SuccessWebSocketResponse, WebSocketRequest, WebSocketResponse,
|
websocket::{
|
||||||
|
BatchResponse, FailureWebSocketResponse, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData,
|
||||||
|
SuccessWebSocketResponse, WebSocketRequest, WebSocketResponse,
|
||||||
|
},
|
||||||
|
ModelingCmd,
|
||||||
};
|
};
|
||||||
use kcmc::ModelingCmd;
|
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use tokio::sync::{mpsc, oneshot, RwLock};
|
use tokio::sync::{mpsc, oneshot, RwLock};
|
||||||
use tokio_tungstenite::tungstenite::Message as WsMsg;
|
use tokio_tungstenite::tungstenite::Message as WsMsg;
|
||||||
@ -39,7 +39,7 @@ pub struct EngineConnection {
|
|||||||
tcp_read_handle: Arc<TcpReadHandle>,
|
tcp_read_handle: Arc<TcpReadHandle>,
|
||||||
socket_health: Arc<Mutex<SocketHealth>>,
|
socket_health: Arc<Mutex<SocketHealth>>,
|
||||||
batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>,
|
batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>,
|
||||||
batch_end: Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>,
|
batch_end: Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>,
|
||||||
|
|
||||||
/// The default planes for the scene.
|
/// The default planes for the scene.
|
||||||
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
||||||
@ -269,7 +269,7 @@ impl EngineConnection {
|
|||||||
responses,
|
responses,
|
||||||
socket_health,
|
socket_health,
|
||||||
batch: Arc::new(Mutex::new(Vec::new())),
|
batch: Arc::new(Mutex::new(Vec::new())),
|
||||||
batch_end: Arc::new(Mutex::new(HashMap::new())),
|
batch_end: Arc::new(Mutex::new(IndexMap::new())),
|
||||||
default_planes: Default::default(),
|
default_planes: Default::default(),
|
||||||
session_data,
|
session_data,
|
||||||
})
|
})
|
||||||
@ -282,7 +282,7 @@ impl EngineManager for EngineConnection {
|
|||||||
self.batch.clone()
|
self.batch.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn batch_end(&self) -> Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>> {
|
fn batch_end(&self) -> Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>> {
|
||||||
self.batch_end.clone()
|
self.batch_end.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,10 +7,13 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::ok_response::OkModelingCmdResponse;
|
use indexmap::IndexMap;
|
||||||
use kcmc::websocket::{
|
use kcmc::{
|
||||||
BatchResponse, ModelingBatch, OkWebSocketResponseData, SuccessWebSocketResponse, WebSocketRequest,
|
ok_response::OkModelingCmdResponse,
|
||||||
WebSocketResponse,
|
websocket::{
|
||||||
|
BatchResponse, ModelingBatch, OkWebSocketResponseData, SuccessWebSocketResponse, WebSocketRequest,
|
||||||
|
WebSocketResponse,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds::{self as kcmc};
|
use kittycad_modeling_cmds::{self as kcmc};
|
||||||
|
|
||||||
@ -19,14 +22,14 @@ use crate::{errors::KclError, executor::DefaultPlanes};
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct EngineConnection {
|
pub struct EngineConnection {
|
||||||
batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>,
|
batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>,
|
||||||
batch_end: Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>,
|
batch_end: Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EngineConnection {
|
impl EngineConnection {
|
||||||
pub async fn new() -> Result<EngineConnection> {
|
pub async fn new() -> Result<EngineConnection> {
|
||||||
Ok(EngineConnection {
|
Ok(EngineConnection {
|
||||||
batch: Arc::new(Mutex::new(Vec::new())),
|
batch: Arc::new(Mutex::new(Vec::new())),
|
||||||
batch_end: Arc::new(Mutex::new(HashMap::new())),
|
batch_end: Arc::new(Mutex::new(IndexMap::new())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,7 +40,7 @@ impl crate::engine::EngineManager for EngineConnection {
|
|||||||
self.batch.clone()
|
self.batch.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn batch_end(&self) -> Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>> {
|
fn batch_end(&self) -> Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>> {
|
||||||
self.batch_end.clone()
|
self.batch_end.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use indexmap::IndexMap;
|
||||||
use kcmc::websocket::{WebSocketRequest, WebSocketResponse};
|
use kcmc::websocket::{WebSocketRequest, WebSocketResponse};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
@ -43,7 +44,7 @@ extern "C" {
|
|||||||
pub struct EngineConnection {
|
pub struct EngineConnection {
|
||||||
manager: Arc<EngineCommandManager>,
|
manager: Arc<EngineCommandManager>,
|
||||||
batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>,
|
batch: Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>,
|
||||||
batch_end: Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>,
|
batch_end: Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safety: WebAssembly will only ever run in a single-threaded context.
|
// Safety: WebAssembly will only ever run in a single-threaded context.
|
||||||
@ -55,7 +56,7 @@ impl EngineConnection {
|
|||||||
Ok(EngineConnection {
|
Ok(EngineConnection {
|
||||||
manager: Arc::new(manager),
|
manager: Arc::new(manager),
|
||||||
batch: Arc::new(Mutex::new(Vec::new())),
|
batch: Arc::new(Mutex::new(Vec::new())),
|
||||||
batch_end: Arc::new(Mutex::new(HashMap::new())),
|
batch_end: Arc::new(Mutex::new(IndexMap::new())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +67,7 @@ impl crate::engine::EngineManager for EngineConnection {
|
|||||||
self.batch.clone()
|
self.batch.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn batch_end(&self) -> Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>> {
|
fn batch_end(&self) -> Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>> {
|
||||||
self.batch_end.clone()
|
self.batch_end.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,15 +13,18 @@ use std::{
|
|||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use kcmc::each_cmd as mcmd;
|
use indexmap::IndexMap;
|
||||||
use kcmc::length_unit::LengthUnit;
|
use kcmc::{
|
||||||
use kcmc::ok_response::OkModelingCmdResponse;
|
each_cmd as mcmd,
|
||||||
use kcmc::shared::Color;
|
length_unit::LengthUnit,
|
||||||
use kcmc::websocket::ModelingBatch;
|
ok_response::OkModelingCmdResponse,
|
||||||
use kcmc::websocket::{
|
shared::Color,
|
||||||
BatchResponse, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData, WebSocketRequest, WebSocketResponse,
|
websocket::{
|
||||||
|
BatchResponse, ModelingBatch, ModelingCmdReq, ModelingSessionData, OkWebSocketResponseData, WebSocketRequest,
|
||||||
|
WebSocketResponse,
|
||||||
|
},
|
||||||
|
ModelingCmd,
|
||||||
};
|
};
|
||||||
use kcmc::ModelingCmd;
|
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -44,7 +47,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
|||||||
fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>;
|
fn batch(&self) -> Arc<Mutex<Vec<(WebSocketRequest, crate::executor::SourceRange)>>>;
|
||||||
|
|
||||||
/// Get the batch of end commands to be sent to the engine.
|
/// Get the batch of end commands to be sent to the engine.
|
||||||
fn batch_end(&self) -> Arc<Mutex<HashMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>;
|
fn batch_end(&self) -> Arc<Mutex<IndexMap<uuid::Uuid, (WebSocketRequest, crate::executor::SourceRange)>>>;
|
||||||
|
|
||||||
/// Get the default planes.
|
/// Get the default planes.
|
||||||
async fn default_planes(
|
async fn default_planes(
|
||||||
|
|||||||
@ -4,10 +4,12 @@ use std::{collections::HashMap, sync::Arc};
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
use kcmc::each_cmd as mcmd;
|
use kcmc::{
|
||||||
use kcmc::ok_response::{output::TakeSnapshot, OkModelingCmdResponse};
|
each_cmd as mcmd,
|
||||||
use kcmc::websocket::{ModelingSessionData, OkWebSocketResponseData};
|
ok_response::{output::TakeSnapshot, OkModelingCmdResponse},
|
||||||
use kcmc::{ImageFormat, ModelingCmd};
|
websocket::{ModelingSessionData, OkWebSocketResponseData},
|
||||||
|
ImageFormat, ModelingCmd,
|
||||||
|
};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use kittycad_modeling_cmds::length_unit::LengthUnit;
|
use kittycad_modeling_cmds::length_unit::LengthUnit;
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
|
|||||||
@ -3465,6 +3465,12 @@ const sketch001 = startSketchOn('XY')
|
|||||||
// angleStart: 450,
|
// angleStart: 450,
|
||||||
// }, %)
|
// }, %)
|
||||||
|> startProfileAt(%)
|
|> startProfileAt(%)
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
snapshot_test!(
|
||||||
|
bb,
|
||||||
|
r#"
|
||||||
|
const my14 = 4 ^ 2 - 3 ^ 2 * 2
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,117 @@
|
|||||||
|
---
|
||||||
|
source: kcl/src/parser/parser_impl.rs
|
||||||
|
assertion_line: 3470
|
||||||
|
expression: actual
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"start": 0,
|
||||||
|
"end": 32,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start": 1,
|
||||||
|
"end": 31,
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start": 7,
|
||||||
|
"end": 31,
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 7,
|
||||||
|
"end": 11,
|
||||||
|
"name": "my14",
|
||||||
|
"digest": null
|
||||||
|
},
|
||||||
|
"init": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 14,
|
||||||
|
"end": 31,
|
||||||
|
"operator": "-",
|
||||||
|
"left": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 14,
|
||||||
|
"end": 19,
|
||||||
|
"operator": "^",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 14,
|
||||||
|
"end": 15,
|
||||||
|
"value": 4,
|
||||||
|
"raw": "4",
|
||||||
|
"digest": null
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 18,
|
||||||
|
"end": 19,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2",
|
||||||
|
"digest": null
|
||||||
|
},
|
||||||
|
"digest": null
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 22,
|
||||||
|
"end": 31,
|
||||||
|
"operator": "*",
|
||||||
|
"left": {
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"type": "BinaryExpression",
|
||||||
|
"start": 22,
|
||||||
|
"end": 27,
|
||||||
|
"operator": "^",
|
||||||
|
"left": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 22,
|
||||||
|
"end": 23,
|
||||||
|
"value": 3,
|
||||||
|
"raw": "3",
|
||||||
|
"digest": null
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 26,
|
||||||
|
"end": 27,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2",
|
||||||
|
"digest": null
|
||||||
|
},
|
||||||
|
"digest": null
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"start": 30,
|
||||||
|
"end": 31,
|
||||||
|
"value": 2,
|
||||||
|
"raw": "2",
|
||||||
|
"digest": null
|
||||||
|
},
|
||||||
|
"digest": null
|
||||||
|
},
|
||||||
|
"digest": null
|
||||||
|
},
|
||||||
|
"digest": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "const",
|
||||||
|
"digest": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nonCodeMeta": {
|
||||||
|
"nonCodeNodes": {},
|
||||||
|
"start": [],
|
||||||
|
"digest": null
|
||||||
|
},
|
||||||
|
"digest": null
|
||||||
|
}
|
||||||
@ -1,8 +1,7 @@
|
|||||||
use std::any::type_name;
|
use std::any::type_name;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::websocket::OkWebSocketResponseData;
|
use kcmc::{websocket::OkWebSocketResponseData, ModelingCmd};
|
||||||
use kcmc::ModelingCmd;
|
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
@ -166,7 +165,7 @@ impl Args {
|
|||||||
// before what ever we call next.
|
// before what ever we call next.
|
||||||
for id in ids {
|
for id in ids {
|
||||||
// Pop it off the batch_end and add it to the batch.
|
// Pop it off the batch_end and add it to the batch.
|
||||||
let Some(item) = self.ctx.engine.batch_end().lock().unwrap().remove(&id) else {
|
let Some(item) = self.ctx.engine.batch_end().lock().unwrap().shift_remove(&id) else {
|
||||||
// It might be in the batch already.
|
// It might be in the batch already.
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
|
|
||||||
|
use super::{args::FromArgs, Args, FnAsArg};
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{ExecState, KclValue, SketchGroup, SourceRange, UserVal},
|
executor::{ExecState, KclValue, SketchGroup, SourceRange, UserVal},
|
||||||
function_param::FunctionParam,
|
function_param::FunctionParam,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{args::FromArgs, Args, FnAsArg};
|
|
||||||
|
|
||||||
/// For each item in an array, update a value.
|
/// For each item in an array, update a value.
|
||||||
pub async fn array_reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
pub async fn array_reduce(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (array, start, f): (Vec<u64>, SketchGroup, FnAsArg<'_>) = FromArgs::from_args(&args, 0)?;
|
let (array, start, f): (Vec<u64>, SketchGroup, FnAsArg<'_>) = FromArgs::from_args(&args, 0)?;
|
||||||
|
|||||||
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kcmc::each_cmd as mcmd;
|
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::CutType, ModelingCmd};
|
||||||
use kcmc::length_unit::LengthUnit;
|
|
||||||
use kcmc::{shared::CutType, ModelingCmd};
|
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -130,7 +128,6 @@ async fn inner_chamfer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut extrude_group = extrude_group.clone();
|
let mut extrude_group = extrude_group.clone();
|
||||||
let mut edge_cuts = Vec::new();
|
|
||||||
for edge_tag in data.tags {
|
for edge_tag in data.tags {
|
||||||
let edge_id = match edge_tag {
|
let edge_id = match edge_tag {
|
||||||
EdgeReference::Uuid(uuid) => uuid,
|
EdgeReference::Uuid(uuid) => uuid,
|
||||||
@ -146,12 +143,15 @@ async fn inner_chamfer(
|
|||||||
radius: LengthUnit(data.length),
|
radius: LengthUnit(data.length),
|
||||||
tolerance: LengthUnit(DEFAULT_TOLERANCE), // We can let the user set this in the future.
|
tolerance: LengthUnit(DEFAULT_TOLERANCE), // We can let the user set this in the future.
|
||||||
cut_type: CutType::Chamfer,
|
cut_type: CutType::Chamfer,
|
||||||
|
// We pass in the command id as the face id.
|
||||||
|
// So the resulting face of the fillet will be the same.
|
||||||
|
// This is because that's how most other endpoints work.
|
||||||
face_id: Some(id),
|
face_id: Some(id),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
edge_cuts.push(EdgeCut::Chamfer {
|
extrude_group.edge_cuts.push(EdgeCut::Chamfer {
|
||||||
id,
|
id,
|
||||||
edge_id,
|
edge_id,
|
||||||
length: data.length,
|
length: data.length,
|
||||||
@ -170,7 +170,5 @@ async fn inner_chamfer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extrude_group.edge_cuts = edge_cuts;
|
|
||||||
|
|
||||||
Ok(extrude_group)
|
Ok(extrude_group)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,11 +4,10 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kcmc::each_cmd as mcmd;
|
use kcmc::{
|
||||||
use kcmc::length_unit::LengthUnit;
|
each_cmd as mcmd, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, output::ExtrusionFaceInfo,
|
||||||
use kcmc::ok_response::OkModelingCmdResponse;
|
shared::ExtrusionFaceCapType, websocket::OkWebSocketResponseData, ModelingCmd,
|
||||||
use kcmc::websocket::OkWebSocketResponseData;
|
};
|
||||||
use kcmc::{output::ExtrusionFaceInfo, shared::ExtrusionFaceCapType, ModelingCmd};
|
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|||||||
@ -2,11 +2,10 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kcmc::each_cmd as mcmd;
|
use kcmc::{
|
||||||
use kcmc::length_unit::LengthUnit;
|
each_cmd as mcmd, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, shared::CutType,
|
||||||
use kcmc::ok_response::OkModelingCmdResponse;
|
websocket::OkWebSocketResponseData, ModelingCmd,
|
||||||
use kcmc::websocket::OkWebSocketResponseData;
|
};
|
||||||
use kcmc::{shared::CutType, ModelingCmd};
|
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -134,7 +133,6 @@ async fn inner_fillet(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut extrude_group = extrude_group.clone();
|
let mut extrude_group = extrude_group.clone();
|
||||||
let mut edge_cuts = Vec::new();
|
|
||||||
for edge_tag in data.tags {
|
for edge_tag in data.tags {
|
||||||
let edge_id = match edge_tag {
|
let edge_id = match edge_tag {
|
||||||
EdgeReference::Uuid(uuid) => uuid,
|
EdgeReference::Uuid(uuid) => uuid,
|
||||||
@ -150,12 +148,15 @@ async fn inner_fillet(
|
|||||||
radius: LengthUnit(data.radius),
|
radius: LengthUnit(data.radius),
|
||||||
tolerance: LengthUnit(data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
|
tolerance: LengthUnit(data.tolerance.unwrap_or(default_tolerance(&args.ctx.settings.units))),
|
||||||
cut_type: CutType::Fillet,
|
cut_type: CutType::Fillet,
|
||||||
face_id: None,
|
// We pass in the command id as the face id.
|
||||||
|
// So the resulting face of the fillet will be the same.
|
||||||
|
// This is because that's how most other endpoints work.
|
||||||
|
face_id: Some(id),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
edge_cuts.push(EdgeCut::Fillet {
|
extrude_group.edge_cuts.push(EdgeCut::Fillet {
|
||||||
id,
|
id,
|
||||||
edge_id,
|
edge_id,
|
||||||
radius: data.radius,
|
radius: data.radius,
|
||||||
@ -164,7 +165,7 @@ async fn inner_fillet(
|
|||||||
|
|
||||||
if let Some(ref tag) = tag {
|
if let Some(ref tag) = tag {
|
||||||
extrude_group.value.push(ExtrudeSurface::Fillet(FilletSurface {
|
extrude_group.value.push(ExtrudeSurface::Fillet(FilletSurface {
|
||||||
face_id: edge_id,
|
face_id: id,
|
||||||
tag: Some(tag.clone()),
|
tag: Some(tag.clone()),
|
||||||
geo_meta: GeoMeta {
|
geo_meta: GeoMeta {
|
||||||
id,
|
id,
|
||||||
@ -174,8 +175,6 @@ async fn inner_fillet(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extrude_group.edge_cuts = edge_cuts;
|
|
||||||
|
|
||||||
Ok(extrude_group)
|
Ok(extrude_group)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,7 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kcmc::each_cmd as mcmd;
|
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
|
||||||
use kcmc::length_unit::LengthUnit;
|
|
||||||
use kcmc::shared::Angle;
|
|
||||||
use kcmc::ModelingCmd;
|
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|||||||
@ -4,14 +4,16 @@ use std::str::FromStr;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kcmc::coord::{Axis, AxisDirectionPair, Direction, System};
|
use kcmc::{
|
||||||
use kcmc::each_cmd as mcmd;
|
coord::{Axis, AxisDirectionPair, Direction, System},
|
||||||
use kcmc::format::InputFormat;
|
each_cmd as mcmd,
|
||||||
use kcmc::ok_response::OkModelingCmdResponse;
|
format::InputFormat,
|
||||||
use kcmc::shared::FileImportFormat;
|
ok_response::OkModelingCmdResponse,
|
||||||
use kcmc::units::UnitLength;
|
shared::FileImportFormat,
|
||||||
use kcmc::websocket::OkWebSocketResponseData;
|
units::UnitLength,
|
||||||
use kcmc::{ImportFile, ModelingCmd};
|
websocket::OkWebSocketResponseData,
|
||||||
|
ImportFile, ModelingCmd,
|
||||||
|
};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
|
|
||||||
|
|||||||
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kcmc::each_cmd as mcmd;
|
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
|
||||||
use kcmc::length_unit::LengthUnit;
|
|
||||||
use kcmc::ModelingCmd;
|
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|||||||
@ -2,12 +2,10 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kcmc::each_cmd as mcmd;
|
use kcmc::{
|
||||||
use kcmc::length_unit::LengthUnit;
|
each_cmd as mcmd, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, shared::Transform,
|
||||||
use kcmc::ok_response::OkModelingCmdResponse;
|
websocket::OkWebSocketResponseData, ModelingCmd,
|
||||||
use kcmc::shared::Transform;
|
};
|
||||||
use kcmc::websocket::OkWebSocketResponseData;
|
|
||||||
use kcmc::ModelingCmd;
|
|
||||||
use kittycad_modeling_cmds::{self as kcmc};
|
use kittycad_modeling_cmds::{self as kcmc};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|||||||
@ -2,10 +2,7 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kcmc::each_cmd as mcmd;
|
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
|
||||||
use kcmc::length_unit::LengthUnit;
|
|
||||||
use kcmc::shared::Angle;
|
|
||||||
use kcmc::ModelingCmd;
|
|
||||||
use kittycad_modeling_cmds::{self as kcmc};
|
use kittycad_modeling_cmds::{self as kcmc};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|||||||
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kcmc::each_cmd as mcmd;
|
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
|
||||||
use kcmc::length_unit::LengthUnit;
|
|
||||||
use kcmc::ModelingCmd;
|
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|||||||
@ -4,11 +4,8 @@ use std::collections::HashMap;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_docs::stdlib;
|
use derive_docs::stdlib;
|
||||||
use kcmc::each_cmd as mcmd;
|
|
||||||
use kcmc::length_unit::LengthUnit;
|
|
||||||
use kcmc::shared::Angle;
|
|
||||||
use kcmc::shared::Point2d as KPoint2d; // Point2d is already defined in this pkg, to impl ts_rs traits.
|
use kcmc::shared::Point2d as KPoint2d; // Point2d is already defined in this pkg, to impl ts_rs traits.
|
||||||
use kcmc::ModelingCmd;
|
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
use kittycad_modeling_cmds::shared::PathSegment;
|
use kittycad_modeling_cmds::shared::PathSegment;
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 57 KiB |
@ -0,0 +1,48 @@
|
|||||||
|
const sketch001 = startSketchOn('XZ')
|
||||||
|
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
||||||
|
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001) - 90,
|
||||||
|
217.26
|
||||||
|
], %, $seg01)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001),
|
||||||
|
-segLen(rectangleSegmentA001)
|
||||||
|
], %)
|
||||||
|
|> lineTo([profileStartX(%), profileStartY(%)], %, $seg02)
|
||||||
|
|> close(%)
|
||||||
|
const extrude001 = extrude(100, sketch001)
|
||||||
|
|> fillet({ radius: 20, tags: [seg01] }, %)
|
||||||
|
|> chamfer({
|
||||||
|
length: 50,
|
||||||
|
tags: [getOppositeEdge(seg01)]
|
||||||
|
}, %, $seg03)
|
||||||
|
|> chamfer({ length: 50, tags: [seg02] }, %, $seg04)
|
||||||
|
|
||||||
|
const sketch003 = startSketchOn(extrude001, seg04)
|
||||||
|
|> startProfileAt([-69.1, 277.34], %)
|
||||||
|
|> angledLine([0, 41.48], %, $rectangleSegmentA003)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA003) - 90,
|
||||||
|
104.8
|
||||||
|
], %, $rectangleSegmentB002)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA003),
|
||||||
|
-segLen(rectangleSegmentA003)
|
||||||
|
], %, $rectangleSegmentC002)
|
||||||
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|
|> close(%)
|
||||||
|
const sketch002 = startSketchOn(extrude001, seg03)
|
||||||
|
|> startProfileAt([159.25, 278.35], %)
|
||||||
|
|> angledLine([0, 40.82], %, $rectangleSegmentA002)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA002) - 90,
|
||||||
|
132.27
|
||||||
|
], %, $rectangleSegmentB001)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA002),
|
||||||
|
-segLen(rectangleSegmentA002)
|
||||||
|
], %, $rectangleSegmentC001)
|
||||||
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|
|> close(%)
|
||||||
|
const extrude002 = extrude(50, sketch002)
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
const sketch001 = startSketchOn('XZ')
|
||||||
|
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|
||||||
|
|> angledLine([0, 268.43], %, $rectangleSegmentA001)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001) - 90,
|
||||||
|
217.26
|
||||||
|
], %, $seg01)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001),
|
||||||
|
-segLen(rectangleSegmentA001)
|
||||||
|
], %)
|
||||||
|
|> lineTo([profileStartX(%), profileStartY(%)], %, $seg02)
|
||||||
|
|> close(%)
|
||||||
|
const extrude001 = extrude(100, sketch001)
|
||||||
|
|> fillet({ radius: 20, tags: [seg01] }, %)
|
||||||
|
|> chamfer({ length: 50, tags: [seg02] }, %, $seg04)
|
||||||
|
|> chamfer({
|
||||||
|
length: 50,
|
||||||
|
tags: [getOppositeEdge(seg01)]
|
||||||
|
}, %, $seg03)
|
||||||
|
|
||||||
|
const sketch003 = startSketchOn(extrude001, seg04)
|
||||||
|
|> startProfileAt([-69.1, 277.34], %)
|
||||||
|
|> angledLine([0, 41.48], %, $rectangleSegmentA003)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA003) - 90,
|
||||||
|
104.8
|
||||||
|
], %, $rectangleSegmentB002)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA003),
|
||||||
|
-segLen(rectangleSegmentA003)
|
||||||
|
], %, $rectangleSegmentC002)
|
||||||
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|
|> close(%)
|
||||||
|
const sketch002 = startSketchOn(extrude001, seg03)
|
||||||
|
|> startProfileAt([159.25, 278.35], %)
|
||||||
|
|> angledLine([0, 40.82], %, $rectangleSegmentA002)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA002) - 90,
|
||||||
|
132.27
|
||||||
|
], %, $rectangleSegmentB001)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA002),
|
||||||
|
-segLen(rectangleSegmentA002)
|
||||||
|
], %, $rectangleSegmentC001)
|
||||||
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|
|> close(%)
|
||||||
|
const extrude002 = extrude(50, sketch002)
|
||||||
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 74 KiB |
@ -57,3 +57,8 @@ kcl_test!("lego", kcl_test_lego);
|
|||||||
kcl_test!("riddle_small", kcl_test_riddle_small);
|
kcl_test!("riddle_small", kcl_test_riddle_small);
|
||||||
kcl_test!("tan_arc_x_line", kcl_test_tan_arc_x_line);
|
kcl_test!("tan_arc_x_line", kcl_test_tan_arc_x_line);
|
||||||
kcl_test!("fillet-and-shell", kcl_test_fillet_and_shell);
|
kcl_test!("fillet-and-shell", kcl_test_fillet_and_shell);
|
||||||
|
kcl_test!("sketch-on-chamfer-two-times", kcl_test_sketch_on_chamfer_two_times);
|
||||||
|
kcl_test!(
|
||||||
|
"sketch-on-chamfer-two-times-different-order",
|
||||||
|
kcl_test_sketch_on_chamfer_two_times_different_order
|
||||||
|
);
|
||||||
|
|||||||
@ -3,9 +3,7 @@ use kcl_lib::{
|
|||||||
ast::{modify::modify_ast_for_sketch, types::Program},
|
ast::{modify::modify_ast_for_sketch, types::Program},
|
||||||
executor::{ExecutorContext, KclValue, PlaneType, SketchGroup, SourceRange},
|
executor::{ExecutorContext, KclValue, PlaneType, SketchGroup, SourceRange},
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds::shared::Point3d;
|
use kittycad_modeling_cmds::{each_cmd as mcmd, length_unit::LengthUnit, shared::Point3d, ModelingCmd};
|
||||||
use kittycad_modeling_cmds::ModelingCmd;
|
|
||||||
use kittycad_modeling_cmds::{each_cmd as mcmd, length_unit::LengthUnit};
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
/// Setup the engine and parse code for an ast.
|
/// Setup the engine and parse code for an ast.
|
||||||
|
|||||||