Merge remote-tracking branch 'origin' into kurt-sketch-on-chamfer

This commit is contained in:
Kurt Hutten Irev-Dev
2024-09-20 10:23:28 +10:00
43 changed files with 403 additions and 156 deletions

File diff suppressed because one or more lines are too long

View File

@ -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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -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

View File

@ -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'
} }
/** /**

View File

@ -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)
} }

View File

@ -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', () => {

View File

@ -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,

View File

@ -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",
] ]

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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::{

View File

@ -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,
} }
} }

View File

@ -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()
} }

View File

@ -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()
} }

View File

@ -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()
} }

View File

@ -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(

View File

@ -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};

View File

@ -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
"# "#
); );
} }

View File

@ -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
}

View File

@ -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;
}; };

View File

@ -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)?;

View File

@ -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)
} }

View File

@ -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;

View File

@ -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)
} }

View File

@ -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};

View File

@ -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;

View File

@ -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};

View File

@ -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};

View File

@ -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};

View File

@ -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};

View File

@ -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};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

@ -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)

View File

@ -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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View File

@ -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
);

View File

@ -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.