Compare commits

...

7 Commits

Author SHA1 Message Date
0d7049d90f skip network tests mac 2024-07-08 21:28:07 +10:00
8ebe78c664 Lf94/eco mode save the planet (#2940)
* Trigger shutdown operations after each test

* Idle mode states

* Don't show the reconnect when coming back from tab
2024-07-07 10:10:52 -07:00
a85c1a9375 Scoped tags (#2941)
* start of scoped tags

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

* add the tags to the sketch group context

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

* scoped tags

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

* update docs

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

* fix tests

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

* updates

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

* updates

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

* scoped

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

* updates

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

* fix;

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-07-05 16:53:13 -07:00
5701616f3e Add a current default unit indicator with menu to switch (#2937)
* Add a units indicator with a menu to switch default units

* Add a playwright test, add a SR label

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Re-run CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Re-run CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-05 18:40:43 -04:00
846acaba2f fix bug with order of operations (#2938)
* fix bug with order of operations

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

* fix

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-07-05 15:37:30 -07:00
0a524d42f6 Bump kittycad.rs (#2936)
* update kittycad.rs

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

* tauri bump

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-07-05 12:39:58 -07:00
fe28527ef9 update docs (#2933)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-07-05 10:44:29 -07:00
103 changed files with 6704 additions and 143 deletions

View File

@ -121,6 +121,9 @@ const extrusion = extrude(5, sketch001)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -282,6 +285,9 @@ const extrusion = extrude(5, sketch001)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -125,6 +125,9 @@ const extrusion = extrude(5, sketch001)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -286,6 +289,9 @@ const extrusion = extrude(5, sketch001)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -126,6 +126,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -287,6 +290,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -476,6 +482,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -637,6 +646,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -125,6 +125,9 @@ const extrusion = extrude(10, sketch001)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -286,6 +289,9 @@ const extrusion = extrude(10, sketch001)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -475,6 +481,9 @@ const extrusion = extrude(10, sketch001)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -636,6 +645,9 @@ const extrusion = extrude(10, sketch001)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

File diff suppressed because one or more lines are too long

View File

@ -133,6 +133,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -294,6 +297,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -483,6 +489,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -644,6 +653,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -124,6 +124,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -285,6 +288,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -474,6 +480,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -635,6 +644,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -124,6 +124,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -285,6 +288,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -474,6 +480,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -635,6 +644,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -135,6 +135,9 @@ const exampleSketch = startSketchOn('XZ')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -296,6 +299,9 @@ const exampleSketch = startSketchOn('XZ')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -485,6 +491,9 @@ const exampleSketch = startSketchOn('XZ')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -646,6 +655,9 @@ const exampleSketch = startSketchOn('XZ')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -130,6 +130,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -291,6 +294,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -480,6 +486,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -641,6 +650,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -225,6 +225,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -532,6 +535,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -123,6 +123,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -410,6 +413,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -599,6 +605,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -760,6 +769,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -125,6 +125,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -286,6 +289,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -475,6 +481,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -636,6 +645,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -150,6 +150,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -311,6 +314,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
type: "sketchGroup", type: "sketchGroup",
// The paths in the sketch group. // The paths in the sketch group.
@ -580,6 +586,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -225,6 +225,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -524,6 +527,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -215,6 +215,9 @@ const revolution = startSketchOn(box, "revolveAxis")
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -211,6 +211,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -211,6 +211,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -213,6 +213,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -213,6 +213,9 @@ const part001 = startSketchOn('XY')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -512,6 +515,9 @@ const part001 = startSketchOn('XY')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -136,6 +136,9 @@ const example = extrude(1, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -297,6 +300,9 @@ const example = extrude(1, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
type: "sketchGroup", type: "sketchGroup",
// The paths in the sketch group. // The paths in the sketch group.
@ -479,6 +485,9 @@ const example = extrude(1, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -640,6 +649,9 @@ const example = extrude(1, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -821,6 +833,9 @@ const example = extrude(1, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -982,6 +997,9 @@ const example = extrude(1, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -116,6 +116,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -277,6 +280,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -116,6 +116,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -277,6 +280,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -129,6 +129,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -290,6 +293,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -479,6 +485,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -640,6 +649,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -116,6 +116,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -277,6 +280,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -466,6 +472,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -627,6 +636,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -134,6 +134,9 @@ const example = extrude(1, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -295,6 +298,9 @@ const example = extrude(1, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
type: "sketchGroup", type: "sketchGroup",
// The paths in the sketch group. // The paths in the sketch group.

View File

@ -217,6 +217,9 @@ const example = extrude(-5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -127,6 +127,9 @@ const example = extrude(1, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -288,6 +291,9 @@ const example = extrude(1, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
type: "sketchGroup", type: "sketchGroup",
// The paths in the sketch group. // The paths in the sketch group.

View File

@ -215,6 +215,9 @@ const example = extrude(1, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -217,6 +217,9 @@ let vase = layer()
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -117,6 +117,9 @@ const sketch001 = startSketchOn('XY')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -278,6 +281,9 @@ const sketch001 = startSketchOn('XY')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -112,6 +112,9 @@ const sketch001 = startSketchOn('XY')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -273,6 +276,9 @@ const sketch001 = startSketchOn('XY')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -111,6 +111,9 @@ const sketch001 = startSketchOn('XY')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -272,6 +275,9 @@ const sketch001 = startSketchOn('XY')
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -247,6 +247,9 @@ uuid |
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -408,6 +411,9 @@ uuid |
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -673,6 +679,9 @@ uuid |
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -124,6 +124,9 @@ const example = extrude(4, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -285,6 +288,9 @@ const example = extrude(4, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -122,6 +122,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -283,6 +286,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -123,6 +123,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -284,6 +287,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -121,6 +121,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -282,6 +285,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -213,6 +213,9 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -512,6 +515,9 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -195,6 +195,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -442,6 +445,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -603,6 +609,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -142,6 +142,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -303,6 +306,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -264,6 +264,9 @@ const a1 = startSketchOn({
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -539,6 +542,9 @@ const a1 = startSketchOn({
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

File diff suppressed because it is too large Load Diff

View File

@ -125,6 +125,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -286,6 +289,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -475,6 +481,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -636,6 +645,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -116,6 +116,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -277,6 +280,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -466,6 +472,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -627,6 +636,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -74,6 +74,107 @@ You can nest expressions in parenthesis as well:
let myMathExpression = 3 + (1 * 2 / (3 - 7)) let myMathExpression = 3 + (1 * 2 / (3 - 7))
``` ```
Please if you find any issues using any of the above expressions or syntax ## Tags
Tags are used to give a name (tag) to a specific path.
### Tag Declaration
The syntax for declaring a tag is `$myTag` you would use it in the following
way:
```
startSketchOn('XZ')
|> startProfileAt(origin, %)
|> angledLine([0, 191.26], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001, %) - 90,
196.99
], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001, %),
-segLen(rectangleSegmentA001, %)
], %, $rectangleSegmentC001)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
```
### Tag Identifier
As per the example above you can use the tag identifier to get a reference to the
tagged object. The syntax for this is `myTag`.
In the example above we use the tag identifier to get the angle of the segment
`segAng(rectangleSegmentA001, %)`.
### Tag Scope
Tags are scoped globally if in the root context meaning in this example you can
use the tag `rectangleSegmentA001` in any function or expression in the file.
However if the code was written like this:
```
fn rect = (origin) => {
return startSketchOn('XZ')
|> startProfileAt(origin, %)
|> angledLine([0, 191.26], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001, %) - 90,
196.99
], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001, %),
-segLen(rectangleSegmentA001, %)
], %, $rectangleSegmentC001)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
}
rect([0, 0])
rect([20, 0])
```
Those tags would only be available in the `rect` function and not globally.
However you likely want to use those tags somewhere outside the `rect` function.
Tags are accessible through the sketch group they are declared in.
For example the following code works.
```
fn rect = (origin) => {
return startSketchOn('XZ')
|> startProfileAt(origin, %)
|> angledLine([0, 191.26], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001, %) - 90,
196.99
], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001, %),
-segLen(rectangleSegmentA001, %)
], %, $rectangleSegmentC001)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
}
rect([0, 0])
const myRect = rect([20, 0])
myRect
|> extrude(10, %)
|> fillet({radius: 0.5, tags: [myRect.tags.rectangleSegmentA001]}, %)
```
See how we use the tag `rectangleSegmentA001` in the `fillet` function outside
the `rect` function. This is because the `rect` function is returning the
sketch group that contains the tags.
---
If you find any issues using any of the above expressions or syntax,
please file an issue with the `ast` label on the [modeling-app please file an issue with the `ast` label on the [modeling-app
repo](https://github.com/KittyCAD/modeling-app/issues/new). repo](https://github.com/KittyCAD/modeling-app/issues/new).

View File

@ -119,6 +119,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -280,6 +283,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -469,6 +475,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -630,6 +639,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -119,6 +119,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -280,6 +283,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -469,6 +475,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -630,6 +639,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -117,6 +117,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -278,6 +281,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -467,6 +473,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -628,6 +637,9 @@ const example = extrude(10, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -115,6 +115,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -276,6 +279,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -465,6 +471,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{
@ -626,6 +635,9 @@ const example = extrude(5, exampleSketch)
}, },
// The to point. // The to point.
to: [number, number], to: [number, number],
},
// Tag identifiers that have been declared in this sketch group.
tags: {
}, },
// The paths in the sketch group. // The paths in the sketch group.
value: [{ value: [{

View File

@ -52,7 +52,24 @@ const commonPoints = {
// num2: 19.19, // num2: 19.19,
} }
// Utilities for writing tests that depend on test values test.afterEach(async ({ context, page }, testInfo) => {
if (testInfo.status === 'skipped') return
if (testInfo.status === 'failed') return
const u = await getUtils(page)
// Kill the network so shutdown happens properly
await u.emulateNetworkConditions({
offline: true,
// values of 0 remove any active throttling. crbug.com/456324#c9
latency: 0,
downloadThroughput: -1,
uploadThroughput: -1,
})
// It seems it's best to give the browser about 3s to close things
// It's not super reliable but we have no real other choice for now
await page.waitForTimeout(3000)
})
test.beforeEach(async ({ context, page }) => { test.beforeEach(async ({ context, page }) => {
// wait for Vite preview server to be up // wait for Vite preview server to be up
@ -78,7 +95,7 @@ test.beforeEach(async ({ context, page }) => {
await page.emulateMedia({ reducedMotion: 'reduce' }) await page.emulateMedia({ reducedMotion: 'reduce' })
}) })
test.setTimeout(60000) test.setTimeout(120000)
async function doBasicSketch(page: Page, openPanes: string[]) { async function doBasicSketch(page: Page, openPanes: string[]) {
const u = await getUtils(page) const u = await getUtils(page)
@ -6705,6 +6722,11 @@ ${extraLine ? 'const myVar = segLen(seg01, part001)' : ''}`
test.describe('Test network and connection issues', () => { test.describe('Test network and connection issues', () => {
test('simulate network down and network little widget', async ({ page }) => { test('simulate network down and network little widget', async ({ page }) => {
const browserType = page.context().browser()?.browserType().name()
test.skip(
browserType !== 'chromium',
'emulateNetworkConditions only works in chromium'
)
const u = await getUtils(page) const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 }) await page.setViewportSize({ width: 1200, height: 500 })
@ -6775,6 +6797,11 @@ test.describe('Test network and connection issues', () => {
}) })
test('Engine disconnect & reconnect in sketch mode', async ({ page }) => { test('Engine disconnect & reconnect in sketch mode', async ({ page }) => {
const browserType = page.context().browser()?.browserType().name()
test.skip(
browserType !== 'chromium',
'emulateNetworkConditions only works in chromium'
)
const u = await getUtils(page) const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 }) await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio const PUR = 400 / 37.5 //pixeltoUnitRatio
@ -7134,6 +7161,40 @@ test.describe('Testing Gizmo', () => {
}) })
}) })
test('Units menu', async ({ page }) => {
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('/')
await page.waitForURL('**/file/**', { waitUntil: 'domcontentloaded' })
await u.waitForAuthSkipAppStart()
const unitsMenuButton = page.getByRole('button', {
name: 'Current Units',
exact: false,
})
await expect(unitsMenuButton).toBeVisible()
await expect(unitsMenuButton).toContainText('in')
await unitsMenuButton.click()
const millimetersButton = page.getByRole('button', { name: 'Millimeters' })
await expect(millimetersButton).toBeVisible()
await millimetersButton.click()
// Look out for the toast message
const toastMessage = page.getByText(
`Set default unit to "mm" for this project`
)
await expect(toastMessage).toBeVisible()
// Verify that the popover has closed
await expect(millimetersButton).not.toBeAttached()
// Verify that the button label has updated
await expect(unitsMenuButton).toContainText('mm')
})
test('Successful export shows a success toast', async ({ page }) => { test('Successful export shows a success toast', async ({ page }) => {
// FYI this test doesn't work with only engine running locally // FYI this test doesn't work with only engine running locally
// And you will need to have the KittyCAD CLI installed // And you will need to have the KittyCAD CLI installed

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -312,9 +312,9 @@ export async function getUtils(page: Page) {
fullPage: true, fullPage: true,
}) })
const screenshot = await PNG.sync.read(buffer) const screenshot = await PNG.sync.read(buffer)
// most likely related to pixel density but the screenshots for webkit are 2x the size const pixMultiplier: number = await page.evaluate(
// there might be a more robust way of doing this. 'window.devicePixelRatio'
const pixMultiplier = browserType === 'webkit' ? 2 : 1 )
const index = const index =
(screenshot.width * coords.y * pixMultiplier + (screenshot.width * coords.y * pixMultiplier +
coords.x * pixMultiplier) * coords.x * pixMultiplier) *
@ -377,11 +377,13 @@ export async function getUtils(page: Page) {
emulateNetworkConditions: async ( emulateNetworkConditions: async (
networkOptions: Protocol.Network.emulateNetworkConditionsParameters networkOptions: Protocol.Network.emulateNetworkConditionsParameters
) => { ) => {
// Skip on non-Chromium browsers, since we need to use the CDP. if (browserType !== 'chromium') {
test.skip( console.warn('emulateNetworkConditions will not work on this browser')
cdpSession === null, }
'Network emulation is only supported in Chromium' if (cdpSession === null) {
) // Use a fail safe if we can't simulate disconnect (on Safari)
return page.evaluate('window.tearDown()')
}
cdpSession?.send('Network.emulateNetworkConditions', networkOptions) cdpSession?.send('Network.emulateNetworkConditions', networkOptions)
}, },

6
src-tauri/Cargo.lock generated
View File

@ -2571,7 +2571,7 @@ dependencies = [
[[package]] [[package]]
name = "kcl-lib" name = "kcl-lib"
version = "0.1.69" version = "0.1.70"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"approx", "approx",
@ -2628,9 +2628,9 @@ dependencies = [
[[package]] [[package]]
name = "kittycad" name = "kittycad"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af3de9bb4b1441f198689a9f64a8163a518377e30b348a784680e738985b95eb" checksum = "e1777b503442fa4666564cc3ab237d456df853a09648a4b2bb09622d25d021a5"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",

View File

@ -16,7 +16,7 @@ tauri-build = { version = "2.0.0-beta.18", features = [] }
[dependencies] [dependencies]
anyhow = "1" anyhow = "1"
kcl-lib = { version = "0.1.53", path = "../src/wasm-lib/kcl" } kcl-lib = { version = "0.1.53", path = "../src/wasm-lib/kcl" }
kittycad = "0.3.5" kittycad = "0.3.7"
log = "0.4.21" log = "0.4.21"
oauth2 = "4.4.2" oauth2 = "4.4.2"
serde_json = "1.0" serde_json = "1.0"

View File

@ -25,6 +25,7 @@ import ModalContainer from 'react-modal-promise'
import useHotkeyWrapper from 'lib/hotkeyWrapper' import useHotkeyWrapper from 'lib/hotkeyWrapper'
import Gizmo from 'components/Gizmo' import Gizmo from 'components/Gizmo'
import { CoreDumpManager } from 'lib/coredump' import { CoreDumpManager } from 'lib/coredump'
import { UnitsMenu } from 'components/UnitsMenu'
export function App() { export function App() {
useRefreshSettings(paths.FILE + 'SETTINGS') useRefreshSettings(paths.FILE + 'SETTINGS')
@ -127,6 +128,7 @@ export function App() {
<Stream /> <Stream />
{/* <CamToggle /> */} {/* <CamToggle /> */}
<LowerRightControls coreDumpManager={coreDumpManager}> <LowerRightControls coreDumpManager={coreDumpManager}>
<UnitsMenu />
<Gizmo /> <Gizmo />
</LowerRightControls> </LowerRightControls>
</div> </div>

View File

@ -119,7 +119,7 @@ export default function Gizmo() {
<div <div
ref={wrapperRef} ref={wrapperRef}
aria-label="View orientation gizmo" aria-label="View orientation gizmo"
className="grid place-content-center rounded-full overflow-hidden border border-solid border-primary/50 pointer-events-auto" className="grid place-content-center rounded-full overflow-hidden border border-solid border-primary/50 pointer-events-auto bg-chalkboard-10/70 dark:bg-chalkboard-100/80 backdrop-blur-sm"
> >
<canvas ref={canvasRef} /> <canvas ref={canvasRef} />
<ContextMenu <ContextMenu

View File

@ -53,9 +53,8 @@ import {
sketchOnExtrudedFace, sketchOnExtrudedFace,
startSketchOnDefault, startSketchOnDefault,
} from 'lang/modifyAst' } from 'lang/modifyAst'
import { Program, VariableDeclaration, parse, recast } from 'lang/wasm' import { Program, parse, recast } from 'lang/wasm'
import { import {
getNodeFromPath,
getNodePathFromSourceRange, getNodePathFromSourceRange,
hasExtrudableGeometry, hasExtrudableGeometry,
isSingleCursorInPipe, isSingleCursorInPipe,
@ -164,6 +163,8 @@ export const ModelingMachineProvider = ({
store.videoElement?.pause() store.videoElement?.pause()
kclManager.executeCode(true).then(() => { kclManager.executeCode(true).then(() => {
if (engineCommandManager.engineConnection?.freezeFrame) return
store.videoElement?.play() store.videoElement?.play()
}) })
})() })()

View File

@ -8,7 +8,7 @@ import { NetworkHealthState } from 'hooks/useNetworkStatus'
import { ClientSideScene } from 'clientSideScene/ClientSideSceneComp' import { ClientSideScene } from 'clientSideScene/ClientSideSceneComp'
import { butName } from 'lib/cameraControls' import { butName } from 'lib/cameraControls'
import { sendSelectEventToEngine } from 'lib/selections' import { sendSelectEventToEngine } from 'lib/selections'
import { kclManager } from 'lib/singletons' import { kclManager, engineCommandManager } from 'lib/singletons'
export const Stream = () => { export const Stream = () => {
const [isLoading, setIsLoading] = useState(true) const [isLoading, setIsLoading] = useState(true)
@ -18,6 +18,7 @@ export const Stream = () => {
const { settings } = useSettingsAuthContext() const { settings } = useSettingsAuthContext()
const { state, send, context } = useModelingContext() const { state, send, context } = useModelingContext()
const { overallState } = useNetworkContext() const { overallState } = useNetworkContext()
const [isFreezeFrame, setIsFreezeFrame] = useState(false)
const isNetworkOkay = const isNetworkOkay =
overallState === NetworkHealthState.Ok || overallState === NetworkHealthState.Ok ||
@ -49,14 +50,69 @@ export const Stream = () => {
globalThis?.window?.document?.addEventListener('paste', handlePaste, { globalThis?.window?.document?.addEventListener('paste', handlePaste, {
capture: true, capture: true,
}) })
return () =>
// Teardown everything if we go hidden or reconnect
if (globalThis?.window?.document) {
globalThis.window.document.onvisibilitychange = () => {
if (globalThis.window.document.visibilityState === 'hidden') {
videoRef.current?.pause()
setIsFreezeFrame(true)
window.requestAnimationFrame(() => {
engineCommandManager.engineConnection?.tearDown({ freeze: true })
})
} else {
engineCommandManager.engineConnection?.connect(true)
}
}
}
const IDLE_TIME_MS = 1000 * 20
let timeoutIdIdle: ReturnType<typeof setTimeout> | undefined = undefined
const onIdle = () => {
videoRef.current?.pause()
setIsFreezeFrame(true)
kclManager.isFirstRender = true
setIsFirstRender(true)
// Give video time to pause
window.requestAnimationFrame(() => {
engineCommandManager.engineConnection?.tearDown({ freeze: true })
})
}
const onAnyInput = () => {
if (!engineCommandManager.engineConnection?.isReady()) {
engineCommandManager.engineConnection?.connect(true)
}
clearTimeout(timeoutIdIdle)
timeoutIdIdle = setTimeout(onIdle, IDLE_TIME_MS)
}
globalThis?.window?.document?.addEventListener('keydown', onAnyInput)
globalThis?.window?.document?.addEventListener('mousemove', onAnyInput)
globalThis?.window?.document?.addEventListener('mousedown', onAnyInput)
globalThis?.window?.document?.addEventListener('scroll', onAnyInput)
globalThis?.window?.document?.addEventListener('touchstart', onAnyInput)
timeoutIdIdle = setTimeout(onIdle, IDLE_TIME_MS)
return () => {
globalThis?.window?.document?.removeEventListener('paste', handlePaste, { globalThis?.window?.document?.removeEventListener('paste', handlePaste, {
capture: true, capture: true,
}) })
globalThis?.window?.document?.removeEventListener('keydown', onAnyInput)
globalThis?.window?.document?.removeEventListener('mousemove', onAnyInput)
globalThis?.window?.document?.removeEventListener('mousedown', onAnyInput)
globalThis?.window?.document?.removeEventListener('scroll', onAnyInput)
globalThis?.window?.document?.removeEventListener(
'touchstart',
onAnyInput
)
}
}, []) }, [])
useEffect(() => { useEffect(() => {
setIsFirstRender(kclManager.isFirstRender) setIsFirstRender(kclManager.isFirstRender)
if (!kclManager.isFirstRender) videoRef.current?.play()
}, [kclManager.isFirstRender]) }, [kclManager.isFirstRender])
useEffect(() => { useEffect(() => {
@ -67,7 +123,10 @@ export const Stream = () => {
return return
if (!videoRef.current) return if (!videoRef.current) return
if (!context.store?.mediaStream) return if (!context.store?.mediaStream) return
// Do not immediately play the stream!
videoRef.current.srcObject = context.store.mediaStream videoRef.current.srcObject = context.store.mediaStream
videoRef.current.pause()
send({ send({
type: 'Set context', type: 'Set context',
@ -172,17 +231,12 @@ export const Stream = () => {
<ClientSideScene <ClientSideScene
cameraControls={settings.context.modeling.mouseControls.current} cameraControls={settings.context.modeling.mouseControls.current}
/> />
{!isNetworkOkay && !isLoading && ( {(!isNetworkOkay || isLoading || isFirstRender) && !isFreezeFrame && (
<div className="text-center absolute inset-0"> <div className="text-center absolute inset-0">
<Loading> <Loading>
<span data-testid="loading-stream">Stream disconnected...</span> {!isNetworkOkay && !isLoading ? (
</Loading> <span data-testid="loading-stream">Stream disconnected...</span>
</div> ) : !isLoading && isFirstRender ? (
)}
{(isLoading || isFirstRender) && (
<div className="text-center absolute inset-0">
<Loading>
{!isLoading && isFirstRender ? (
<span data-testid="loading-stream">Building scene...</span> <span data-testid="loading-stream">Building scene...</span>
) : ( ) : (
<span data-testid="loading-stream">Loading stream...</span> <span data-testid="loading-stream">Loading stream...</span>

View File

@ -0,0 +1,54 @@
import { Popover } from '@headlessui/react'
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
import { baseUnitLabels, baseUnitsUnion } from 'lib/settings/settingsTypes'
export function UnitsMenu() {
const { settings } = useSettingsAuthContext()
return (
<Popover className="relative pointer-events-auto">
{({ close }) => (
<>
<Popover.Button
className={`flex items-center gap-2 px-3 py-1
text-xs text-primary bg-chalkboard-10/70 dark:bg-chalkboard-100/80 backdrop-blur-sm
border !border-primary/50 rounded-full`}
>
<div className="w-4 h-[1px] bg-primary relative">
<div className="absolute w-[1px] h-[1em] bg-primary left-0 top-1/2 -translate-y-1/2"></div>
<div className="absolute w-[1px] h-[1em] bg-primary right-0 top-1/2 -translate-y-1/2"></div>
</div>
<span className="sr-only">Current units are:&nbsp;</span>
{settings.context.modeling.defaultUnit.current}
</Popover.Button>
<Popover.Panel
className={`absolute bottom-full right-0 mb-2 w-48 bg-chalkboard-10 dark:bg-chalkboard-90
border border-solid border-chalkboard-10 dark:border-chalkboard-90 rounded
shadow-lg`}
>
<ul className="relative flex flex-col gap-0.5 items-stretch content-stretch">
{baseUnitsUnion.map((unit) => (
<li key={unit} className="contents">
<button
className="flex items-center gap-2 py-1 px-2 cursor-pointer hover:bg-chalkboard-20 dark:hover:bg-chalkboard-80 border-none text-left"
onClick={() => {
settings.send({
type: 'set.modeling.defaultUnit',
data: {
level: 'project',
value: unit,
},
})
close()
}}
>
{baseUnitLabels[unit]}
</button>
</li>
))}
</ul>
</Popover.Panel>
</>
)}
</Popover>
)
}

View File

@ -185,6 +185,17 @@ const sk2 = startSketchOn('XY')
on: expect.any(Object), on: expect.any(Object),
start: expect.any(Object), start: expect.any(Object),
type: 'SketchGroup', type: 'SketchGroup',
tags: {
p: {
__meta: [
{
sourceRange: [114, 116],
},
],
type: 'TagIdentifier',
value: 'p',
},
},
value: [ value: [
{ {
type: 'ToPoint', type: 'ToPoint',
@ -265,6 +276,17 @@ const sk2 = startSketchOn('XY')
on: expect.any(Object), on: expect.any(Object),
start: expect.any(Object), start: expect.any(Object),
type: 'SketchGroup', type: 'SketchGroup',
tags: {
o: {
__meta: [
{
sourceRange: [417, 419],
},
],
type: 'TagIdentifier',
value: 'o',
},
},
value: [ value: [
{ {
type: 'ToPoint', type: 'ToPoint',

View File

@ -155,6 +155,17 @@ const newVar = myVar + 1`
sourceRange: [39, 63], sourceRange: [39, 63],
}, },
}, },
tags: {
myPath: {
__meta: [
{
sourceRange: [109, 117],
},
],
type: 'TagIdentifier',
value: 'myPath',
},
},
value: [ value: [
{ {
type: 'ToPoint', type: 'ToPoint',

View File

@ -300,6 +300,7 @@ class EngineConnection extends EventTarget {
pc?: RTCPeerConnection pc?: RTCPeerConnection
unreliableDataChannel?: RTCDataChannel unreliableDataChannel?: RTCDataChannel
mediaStream?: MediaStream mediaStream?: MediaStream
freezeFrame: boolean = false
private _state: EngineConnectionState = { private _state: EngineConnectionState = {
type: EngineConnectionStateType.Fresh, type: EngineConnectionStateType.Fresh,
@ -365,7 +366,11 @@ class EngineConnection extends EventTarget {
this.pingPongSpan = { ping: undefined, pong: undefined } this.pingPongSpan = { ping: undefined, pong: undefined }
// Without an interval ping, our connection will timeout. // Without an interval ping, our connection will timeout.
// If this.freezeFrame is true we skip this logic so only reconnect
// happens on mouse move
setInterval(() => { setInterval(() => {
if (this.freezeFrame) return
switch (this.state.type as EngineConnectionStateType) { switch (this.state.type as EngineConnectionStateType) {
case EngineConnectionStateType.ConnectionEstablished: case EngineConnectionStateType.ConnectionEstablished:
// If there was no reply to the last ping, report a timeout. // If there was no reply to the last ping, report a timeout.
@ -426,7 +431,8 @@ class EngineConnection extends EventTarget {
return this.state.type === EngineConnectionStateType.ConnectionEstablished return this.state.type === EngineConnectionStateType.ConnectionEstablished
} }
tearDown() { tearDown(opts?: { freeze: boolean }) {
this.freezeFrame = opts?.freeze ?? false
this.disconnectAll() this.disconnectAll()
this.state = { this.state = {
type: EngineConnectionStateType.Disconnecting, type: EngineConnectionStateType.Disconnecting,
@ -996,6 +1002,9 @@ class EngineConnection extends EventTarget {
this.pc?.connectionState === 'closed' && this.pc?.connectionState === 'closed' &&
this.unreliableDataChannel?.readyState === 'closed' this.unreliableDataChannel?.readyState === 'closed'
if (allClosed) { if (allClosed) {
// Do not notify the rest of the program that we have cut off anything.
if (this.freezeFrame) return
this.state = { type: EngineConnectionStateType.Disconnected } this.state = { type: EngineConnectionStateType.Disconnected }
} }
} }
@ -1619,7 +1628,15 @@ export class EngineCommandManager extends EventTarget {
} }
} }
tearDown() { tearDown() {
this.engineConnection?.tearDown() if (this.engineConnection) {
this.engineConnection?.tearDown()
// Our window.tearDown assignment causes this case to happen which is
// only really for tests.
// @ts-ignore
} else if (this.engineCommandManager?.engineConnection) {
// @ts-ignore
this.engineCommandManager?.engineConnection?.tearDown()
}
} }
async startNewSession() { async startNewSession() {
this.lastArtifactMap = this.artifactMap this.lastArtifactMap = this.artifactMap

View File

@ -16,6 +16,14 @@ export const baseUnits = {
export type BaseUnit = Models['UnitLength_type'] export type BaseUnit = Models['UnitLength_type']
export const baseUnitsUnion = Object.values(baseUnits).flatMap((v) => v) export const baseUnitsUnion = Object.values(baseUnits).flatMap((v) => v)
export const baseUnitLabels = {
in: 'Inches',
ft: 'Feet',
yd: 'Yards',
mm: 'Millimeters',
cm: 'Centimeters',
m: 'Meters',
} as const
export type Toggle = 'On' | 'Off' export type Toggle = 'On' | 'Off'
export const toggleAsArray = ['On', 'Off'] as const export const toggleAsArray = ['On', 'Off'] as const

View File

@ -9,6 +9,10 @@ export const codeManager = new CodeManager()
export const engineCommandManager = new EngineCommandManager() export const engineCommandManager = new EngineCommandManager()
// Accessible for tests mostly
// @ts-ignore
window.tearDown = engineCommandManager.tearDown
// This needs to be after codeManager is created. // This needs to be after codeManager is created.
export const kclManager = new KclManager(engineCommandManager) export const kclManager = new KclManager(engineCommandManager)
kclManager.isFirstRender = true kclManager.isFirstRender = true

View File

@ -1051,7 +1051,9 @@ export const modelingMachine = createMachine(
type: 'start_path', type: 'start_path',
}, },
}) })
store.videoElement?.play() if (!engineCommandManager.engineConnection?.freezeFrame) {
store.videoElement?.play()
}
if (updatedAst?.selections) { if (updatedAst?.selections) {
editorManager.selectRange(updatedAst?.selections) editorManager.selectRange(updatedAst?.selections)
} }

View File

@ -1385,7 +1385,7 @@ dependencies = [
[[package]] [[package]]
name = "kcl-lib" name = "kcl-lib"
version = "0.1.69" version = "0.1.71"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"approx", "approx",
@ -1453,7 +1453,7 @@ dependencies = [
[[package]] [[package]]
name = "kcl-test-server" name = "kcl-test-server"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"hyper", "hyper",
@ -1466,9 +1466,9 @@ dependencies = [
[[package]] [[package]]
name = "kittycad" name = "kittycad"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af3de9bb4b1441f198689a9f64a8163a518377e30b348a784680e738985b95eb" checksum = "e1777b503442fa4666564cc3ab237d456df853a09648a4b2bb09622d25d021a5"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",

View File

@ -69,7 +69,7 @@ members = [
] ]
[workspace.dependencies] [workspace.dependencies]
kittycad = { version = "0.3.6", default-features = false, features = ["js", "requests"] } kittycad = { version = "0.3.7", default-features = false, features = ["js", "requests"] }
kittycad-modeling-session = "0.1.4" kittycad-modeling-session = "0.1.4"
[[test]] [[test]]

View File

@ -1,14 +1,14 @@
[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.1" version = "0.1.2"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
[dependencies] [dependencies]
anyhow = "1.0.86" anyhow = "1.0.86"
hyper = { version = "0.14.29", features = ["server"] } hyper = { version = "0.14.29", features = ["server"] }
kcl-lib = { version = "0.1.62", path = "../kcl" } kcl-lib = { version = "0.1.70", path = "../kcl" }
pico-args = "0.5.0" pico-args = "0.5.0"
serde = { version = "1.0.203", features = ["derive"] } serde = { version = "1.0.203", features = ["derive"] }
serde_json = "1.0.120" serde_json = "1.0.120"

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.1.69" version = "0.1.71"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app" repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -1238,11 +1238,10 @@ impl CallExpression {
} }
FunctionKind::UserDefined => { FunctionKind::UserDefined => {
let func = memory.get(&fn_name, self.into())?; let func = memory.get(&fn_name, self.into())?;
let (result, global_memory_items) = let result = func.call_fn(fn_args, memory.clone(), ctx.clone()).await.map_err(|e| {
func.call_fn(fn_args, memory.clone(), ctx.clone()).await.map_err(|e| { // Add the call expression to the source ranges.
// Add the call expression to the source ranges. e.add_source_ranges(vec![self.into()])
e.add_source_ranges(vec![self.into()]) })?;
})?;
let result = result.ok_or_else(|| { let result = result.ok_or_else(|| {
KclError::UndefinedValue(KclErrorDetails { KclError::UndefinedValue(KclErrorDetails {
@ -1252,14 +1251,6 @@ impl CallExpression {
})?; })?;
let result = result.get_value()?; let result = result.get_value()?;
// Add the global memory items to the memory.
for (key, item) in global_memory_items {
// We don't care about errors here because any collisions
// would happened in the function call itself and already
// errored out.
memory.add(&key, item, self.into()).unwrap_or_default();
}
Ok(result) Ok(result)
} }
} }
@ -1787,6 +1778,17 @@ impl From<&TagDeclarator> for MemoryItem {
} }
} }
impl From<&TagDeclarator> for TagIdentifier {
fn from(tag: &TagDeclarator) -> Self {
TagIdentifier {
value: tag.name.clone(),
meta: vec![Metadata {
source_range: tag.into(),
}],
}
}
}
impl From<&TagDeclarator> for CompletionItem { impl From<&TagDeclarator> for CompletionItem {
fn from(tag: &TagDeclarator) -> Self { fn from(tag: &TagDeclarator) -> Self {
CompletionItem { CompletionItem {

View File

@ -537,17 +537,14 @@ impl std::hash::Hash for TagIdentifier {
} }
} }
pub type MemoryFunction = fn( pub type MemoryFunction =
s: Vec<MemoryItem>, fn(
memory: ProgramMemory, s: Vec<MemoryItem>,
expression: Box<FunctionExpression>, memory: ProgramMemory,
metadata: Vec<Metadata>, expression: Box<FunctionExpression>,
ctx: ExecutorContext, metadata: Vec<Metadata>,
) -> std::pin::Pin< ctx: ExecutorContext,
Box< ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>> + Send>>;
dyn std::future::Future<Output = Result<(Option<ProgramReturn>, HashMap<String, MemoryItem>), KclError>> + Send,
>,
>;
fn force_memory_function< fn force_memory_function<
F: Fn( F: Fn(
@ -556,12 +553,7 @@ fn force_memory_function<
Box<FunctionExpression>, Box<FunctionExpression>,
Vec<Metadata>, Vec<Metadata>,
ExecutorContext, ExecutorContext,
) -> std::pin::Pin< ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>> + Send>>,
Box<
dyn std::future::Future<Output = Result<(Option<ProgramReturn>, HashMap<String, MemoryItem>), KclError>>
+ Send,
>,
>,
>( >(
f: F, f: F,
) -> F { ) -> F {
@ -691,11 +683,15 @@ impl MemoryItem {
match self { match self {
MemoryItem::TagIdentifier(t) => Ok(*t.clone()), MemoryItem::TagIdentifier(t) => Ok(*t.clone()),
MemoryItem::UserVal(u) => { MemoryItem::UserVal(u) => {
let name: String = self.get_json()?; if let Some(identifier) = self.get_json_opt::<TagIdentifier>()? {
Ok(TagIdentifier { Ok(identifier)
value: name, } else {
meta: u.meta.clone(), let name: String = self.get_json()?;
}) Ok(TagIdentifier {
value: name,
meta: u.meta.clone(),
})
}
} }
_ => Err(KclError::Semantic(KclErrorDetails { _ => Err(KclError::Semantic(KclErrorDetails {
message: format!("Not a tag identifier: {:?}", self), message: format!("Not a tag identifier: {:?}", self),
@ -752,7 +748,7 @@ impl MemoryItem {
args: Vec<MemoryItem>, args: Vec<MemoryItem>,
memory: ProgramMemory, memory: ProgramMemory,
ctx: ExecutorContext, ctx: ExecutorContext,
) -> Result<(Option<ProgramReturn>, HashMap<String, MemoryItem>), KclError> { ) -> Result<Option<ProgramReturn>, KclError> {
let MemoryItem::Function { func, expression, meta } = &self else { let MemoryItem::Function { func, expression, meta } = &self else {
return Err(KclError::Semantic(KclErrorDetails { return Err(KclError::Semantic(KclErrorDetails {
message: "not a in memory function".to_string(), message: "not a in memory function".to_string(),
@ -782,6 +778,9 @@ pub struct SketchGroup {
pub on: SketchSurface, pub on: SketchSurface,
/// The starting path. /// The starting path.
pub start: BasePath, pub start: BasePath,
/// Tag identifiers that have been declared in this sketch group.
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub tags: HashMap<String, TagIdentifier>,
/// Metadata. /// Metadata.
#[serde(rename = "__meta")] #[serde(rename = "__meta")]
pub meta: Vec<Metadata>, pub meta: Vec<Metadata>,
@ -1359,6 +1358,8 @@ pub struct ExecutorSettings {
pub highlight_edges: bool, pub highlight_edges: bool,
/// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled. /// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled.
pub enable_ssao: bool, pub enable_ssao: bool,
// Show grid?
pub show_grid: bool,
} }
impl Default for ExecutorSettings { impl Default for ExecutorSettings {
@ -1367,6 +1368,7 @@ impl Default for ExecutorSettings {
units: Default::default(), units: Default::default(),
highlight_edges: true, highlight_edges: true,
enable_ssao: false, enable_ssao: false,
show_grid: false,
} }
} }
} }
@ -1377,6 +1379,7 @@ impl From<crate::settings::types::Configuration> for ExecutorSettings {
units: config.settings.modeling.base_unit, units: config.settings.modeling.base_unit,
highlight_edges: config.settings.modeling.highlight_edges.into(), highlight_edges: config.settings.modeling.highlight_edges.into(),
enable_ssao: config.settings.modeling.enable_ssao.into(), enable_ssao: config.settings.modeling.enable_ssao.into(),
show_grid: config.settings.modeling.show_scale_grid,
} }
} }
} }
@ -1387,6 +1390,7 @@ impl From<crate::settings::types::project::ProjectConfiguration> for ExecutorSet
units: config.settings.modeling.base_unit, units: config.settings.modeling.base_unit,
highlight_edges: config.settings.modeling.highlight_edges.into(), highlight_edges: config.settings.modeling.highlight_edges.into(),
enable_ssao: config.settings.modeling.enable_ssao.into(), enable_ssao: config.settings.modeling.enable_ssao.into(),
show_grid: config.settings.modeling.show_scale_grid,
} }
} }
} }
@ -1397,6 +1401,7 @@ impl From<crate::settings::types::ModelingSettings> for ExecutorSettings {
units: modeling.base_unit, units: modeling.base_unit,
highlight_edges: modeling.highlight_edges.into(), highlight_edges: modeling.highlight_edges.into(),
enable_ssao: modeling.enable_ssao.into(), enable_ssao: modeling.enable_ssao.into(),
show_grid: modeling.show_scale_grid,
} }
} }
} }
@ -1415,6 +1420,7 @@ impl ExecutorContext {
} else { } else {
None None
}, },
if settings.show_grid { Some(true) } else { None },
None, None,
None, None,
None, None,
@ -1478,6 +1484,7 @@ impl ExecutorContext {
units, units,
highlight_edges: true, highlight_edges: true,
enable_ssao: false, enable_ssao: false,
show_grid: false,
}, },
) )
.await?; .await?;
@ -1564,16 +1571,7 @@ impl ExecutorContext {
} }
FunctionKind::UserDefined => { FunctionKind::UserDefined => {
if let Some(func) = memory.clone().root.get(&fn_name) { if let Some(func) = memory.clone().root.get(&fn_name) {
let (result, global_memory_items) = let result = func.call_fn(args.clone(), memory.clone(), self.clone()).await?;
func.call_fn(args.clone(), memory.clone(), self.clone()).await?;
// Add the global memory items to the memory.
for (key, item) in global_memory_items {
// We don't care about errors here because any collisions
// would happened in the function call itself and already
// errored out.
memory.add(&key, item, call_expr.into()).unwrap_or_default();
}
memory.return_ = result; memory.return_ = result;
} else { } else {
@ -1698,7 +1696,7 @@ impl ExecutorContext {
.inner_execute(&function_expression.body, &mut fn_memory, BodyType::Block) .inner_execute(&function_expression.body, &mut fn_memory, BodyType::Block)
.await?; .await?;
Ok((result.return_, fn_memory.get_tags())) Ok(result.return_)
}) })
}, },
); );

View File

@ -1,5 +1,3 @@
use std::collections::HashMap;
use schemars::JsonSchema; use schemars::JsonSchema;
use crate::{ use crate::{
@ -18,10 +16,7 @@ pub struct FunctionParam<'a> {
} }
impl<'a> FunctionParam<'a> { impl<'a> FunctionParam<'a> {
pub async fn call( pub async fn call(&self, args: Vec<MemoryItem>) -> Result<Option<ProgramReturn>, KclError> {
&self,
args: Vec<MemoryItem>,
) -> Result<(Option<ProgramReturn>, HashMap<String, MemoryItem>), KclError> {
(self.inner)( (self.inner)(
args, args,
self.memory.clone(), self.memory.clone(),

View File

@ -1542,6 +1542,7 @@ fn fn_call(i: TokenSlice) -> PResult<CallExpression> {
// Replace the literal with the tag. // Replace the literal with the tag.
args[i] = Value::Identifier(Box::new(tag)); args[i] = Value::Identifier(Box::new(tag));
} }
Value::MemberExpression(_) => {}
e => { e => {
return Err(ErrMode::Cut( return Err(ErrMode::Cut(
KclError::Syntax(KclErrorDetails { KclError::Syntax(KclErrorDetails {

View File

@ -77,6 +77,15 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
let sketch_groups: Vec<Box<SketchGroup>> = sketch_group_set.into(); let sketch_groups: Vec<Box<SketchGroup>> = sketch_group_set.into();
let mut extrude_groups = Vec::new(); let mut extrude_groups = Vec::new();
for sketch_group in &sketch_groups { for sketch_group in &sketch_groups {
// Make sure we exited sketch mode if sketching on a plane.
if let SketchSurface::Plane(_) = sketch_group.on {
// Disable the sketch mode.
// This is necessary for when people don't close the sketch explicitly.
// The sketch mode will mess up the extrude direction if still active.
args.batch_modeling_cmd(uuid::Uuid::new_v4(), kittycad::types::ModelingCmd::SketchModeDisable {})
.await?;
}
args.send_modeling_cmd( args.send_modeling_cmd(
id, id,
kittycad::types::ModelingCmd::Extrude { kittycad::types::ModelingCmd::Extrude {

View File

@ -207,7 +207,7 @@ async fn make_transform<'a>(
meta: vec![source_range.into()], meta: vec![source_range.into()],
}); });
let transform_fn_args = vec![repetition_num]; let transform_fn_args = vec![repetition_num];
let transform_fn_return = transform_function.call(transform_fn_args).await?.0; let transform_fn_return = transform_function.call(transform_fn_args).await?;
// Unpack the returned transform object. // Unpack the returned transform object.
let source_ranges = vec![source_range]; let source_ranges = vec![source_range];

View File

@ -1,5 +1,7 @@
//! Functions related to sketching. //! Functions related to sketching.
use std::collections::HashMap;
use anyhow::Result; use anyhow::Result;
use derive_docs::stdlib; use derive_docs::stdlib;
use kittycad::types::{Angle, ModelingCmd, Point3D}; use kittycad::types::{Angle, ModelingCmd, Point3D};
@ -127,6 +129,11 @@ async fn inner_line_to(
) )
.await?; .await?;
let mut new_sketch_group = sketch_group.clone();
if let Some(tag) = &tag {
new_sketch_group.tags.insert(tag.name.to_string(), tag.into());
}
let current_path = Path::ToPoint { let current_path = Path::ToPoint {
base: BasePath { base: BasePath {
from: from.into(), from: from.into(),
@ -139,7 +146,6 @@ async fn inner_line_to(
}, },
}; };
let mut new_sketch_group = sketch_group.clone();
new_sketch_group.value.push(current_path); new_sketch_group.value.push(current_path);
Ok(new_sketch_group) Ok(new_sketch_group)
@ -291,6 +297,11 @@ async fn inner_line(
) )
.await?; .await?;
let mut new_sketch_group = sketch_group.clone();
if let Some(tag) = &tag {
new_sketch_group.tags.insert(tag.name.to_string(), tag.into());
}
let current_path = Path::ToPoint { let current_path = Path::ToPoint {
base: BasePath { base: BasePath {
from: from.into(), from: from.into(),
@ -303,7 +314,6 @@ async fn inner_line(
}, },
}; };
let mut new_sketch_group = sketch_group.clone();
new_sketch_group.value.push(current_path); new_sketch_group.value.push(current_path);
Ok(new_sketch_group) Ok(new_sketch_group)
@ -455,18 +465,6 @@ async fn inner_angled_line(
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
let current_path = Path::ToPoint {
base: BasePath {
from: from.into(),
to,
tag,
geo_meta: GeoMeta {
id,
metadata: args.source_range.into(),
},
},
};
args.batch_modeling_cmd( args.batch_modeling_cmd(
id, id,
ModelingCmd::ExtendPath { ModelingCmd::ExtendPath {
@ -484,6 +482,22 @@ async fn inner_angled_line(
.await?; .await?;
let mut new_sketch_group = sketch_group.clone(); let mut new_sketch_group = sketch_group.clone();
if let Some(tag) = &tag {
new_sketch_group.tags.insert(tag.name.to_string(), tag.into());
}
let current_path = Path::ToPoint {
base: BasePath {
from: from.into(),
to,
tag,
geo_meta: GeoMeta {
id,
metadata: args.source_range.into(),
},
},
};
new_sketch_group.value.push(current_path); new_sketch_group.value.push(current_path);
Ok(new_sketch_group) Ok(new_sketch_group)
} }
@ -1206,7 +1220,7 @@ pub(crate) async fn inner_start_profile_at(
let current_path = BasePath { let current_path = BasePath {
from: to, from: to,
to, to,
tag, tag: tag.clone(),
geo_meta: GeoMeta { geo_meta: GeoMeta {
id, id,
metadata: args.source_range.into(), metadata: args.source_range.into(),
@ -1219,6 +1233,11 @@ pub(crate) async fn inner_start_profile_at(
value: vec![], value: vec![],
start: current_path, start: current_path,
meta: vec![args.source_range.into()], meta: vec![args.source_range.into()],
tags: if let Some(tag) = &tag {
HashMap::from([(tag.name.to_string(), tag.into())])
} else {
Default::default()
},
}; };
Ok(Box::new(sketch_group)) Ok(Box::new(sketch_group))
} }
@ -1353,6 +1372,9 @@ pub(crate) async fn inner_close(
} }
let mut new_sketch_group = sketch_group.clone(); let mut new_sketch_group = sketch_group.clone();
if let Some(ref tag) = tag {
new_sketch_group.tags.insert(tag.name.to_string(), tag.into());
}
new_sketch_group.value.push(Path::ToPoint { new_sketch_group.value.push(Path::ToPoint {
base: BasePath { base: BasePath {
from: from.into(), from: from.into(),
@ -1461,6 +1483,11 @@ pub(crate) async fn inner_arc(
) )
.await?; .await?;
let mut new_sketch_group = sketch_group.clone();
if let Some(tag) = &tag {
new_sketch_group.tags.insert(tag.name.to_string(), tag.into());
}
let current_path = Path::ToPoint { let current_path = Path::ToPoint {
base: BasePath { base: BasePath {
from: from.into(), from: from.into(),
@ -1473,7 +1500,6 @@ pub(crate) async fn inner_arc(
}, },
}; };
let mut new_sketch_group = sketch_group.clone();
new_sketch_group.value.push(current_path); new_sketch_group.value.push(current_path);
Ok(new_sketch_group) Ok(new_sketch_group)
@ -1567,6 +1593,11 @@ async fn inner_tangential_arc(
let to = [from.x + to[0], from.y + to[1]]; let to = [from.x + to[0], from.y + to[1]];
let mut new_sketch_group = sketch_group.clone();
if let Some(tag) = &tag {
new_sketch_group.tags.insert(tag.name.to_string(), tag.into());
}
let current_path = Path::TangentialArc { let current_path = Path::TangentialArc {
base: BasePath { base: BasePath {
from: from.into(), from: from.into(),
@ -1579,7 +1610,6 @@ async fn inner_tangential_arc(
}, },
}; };
let mut new_sketch_group = sketch_group.clone();
new_sketch_group.value.push(current_path); new_sketch_group.value.push(current_path);
Ok(new_sketch_group) Ok(new_sketch_group)
@ -1671,6 +1701,11 @@ async fn inner_tangential_arc_to(
let id = uuid::Uuid::new_v4(); let id = uuid::Uuid::new_v4();
args.batch_modeling_cmd(id, tan_arc_to(&sketch_group, &delta)).await?; args.batch_modeling_cmd(id, tan_arc_to(&sketch_group, &delta)).await?;
let mut new_sketch_group = sketch_group.clone();
if let Some(tag) = &tag {
new_sketch_group.tags.insert(tag.name.to_string(), tag.into());
}
let current_path = Path::TangentialArcTo { let current_path = Path::TangentialArcTo {
base: BasePath { base: BasePath {
from: from.into(), from: from.into(),
@ -1685,7 +1720,6 @@ async fn inner_tangential_arc_to(
ccw: result.ccw > 0, ccw: result.ccw > 0,
}; };
let mut new_sketch_group = sketch_group.clone();
new_sketch_group.value.push(current_path); new_sketch_group.value.push(current_path);
Ok(new_sketch_group) Ok(new_sketch_group)
@ -1772,6 +1806,11 @@ async fn inner_bezier_curve(
) )
.await?; .await?;
let mut new_sketch_group = sketch_group.clone();
if let Some(tag) = &tag {
new_sketch_group.tags.insert(tag.name.to_string(), tag.into());
}
let current_path = Path::ToPoint { let current_path = Path::ToPoint {
base: BasePath { base: BasePath {
from: from.into(), from: from.into(),
@ -1784,7 +1823,6 @@ async fn inner_bezier_curve(
}, },
}; };
let mut new_sketch_group = sketch_group.clone();
new_sketch_group.value.push(current_path); new_sketch_group.value.push(current_path);
Ok(new_sketch_group) Ok(new_sketch_group)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

@ -1,6 +1,7 @@
// A mounting bracket for the Focusrite Scarlett Solo audio interface // A mounting bracket for the Focusrite Scarlett Solo audio interface
// This is a bracket that holds an audio device underneath a desk or shelf. The audio device has dimensions of 144mm wide, 80mm length and 45mm depth with fillets of 6mm. This mounting bracket is designed to be 3D printed with PLA material // This is a bracket that holds an audio device underneath a desk or shelf. The audio device has dimensions of 144mm wide, 80mm length and 45mm depth with fillets of 6mm. This mounting bracket is designed to be 3D printed with PLA material
// define constants in mm // define constants in mm
const radius = 6.0 const radius = 6.0
const width = 144.0 const width = 144.0
@ -16,10 +17,10 @@ const tabThk = 4
fn rectShape = (pos, w, l) => { fn rectShape = (pos, w, l) => {
const rr = startSketchOn('xy') const rr = startSketchOn('xy')
|> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %) |> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
|> lineTo([pos[0] + w / 2, pos[1] - (l / 2)], %, "edge01") |> lineTo([pos[0] + w / 2, pos[1] - (l / 2)], %, $edge01)
|> lineTo([pos[0] + w / 2, pos[1] + l / 2], %, "edge02") |> lineTo([pos[0] + w / 2, pos[1] + l / 2], %, $edge02)
|> lineTo([pos[0] - (w / 2), pos[1] + l / 2], %, "edge03") |> lineTo([pos[0] - (w / 2), pos[1] + l / 2], %, $edge03)
|> close(%, "edge04") |> close(%, $edge04)
return rr return rr
} }
@ -37,27 +38,28 @@ const bracketPlane = {
fn bracketSketch = (w, d, t) => { fn bracketSketch = (w, d, t) => {
const s = startSketchOn(bracketPlane) const s = startSketchOn(bracketPlane)
|> startProfileAt([-w / 2 - t, d + t], %) |> startProfileAt([-w / 2 - t, d + t], %)
|> lineTo([-w / 2 - t, -t], %, "edge1") |> lineTo([-w / 2 - t, -t], %, $edge1)
|> lineTo([w / 2 + t, -t], %, "edge2") |> lineTo([w / 2 + t, -t], %, $edge2)
|> lineTo([w / 2 + t, d + t], %, "edge3") |> lineTo([w / 2 + t, d + t], %, $edge3)
|> lineTo([w / 2, d + t], %, "edge4") |> lineTo([w / 2, d + t], %, $edge4)
|> lineTo([w / 2, 0], %, "edge5") |> lineTo([w / 2, 0], %, $edge5)
|> lineTo([-w / 2, 0], %, "edge6") |> lineTo([-w / 2, 0], %, $edge6)
|> lineTo([-w / 2, d + t], %, "edge7") |> lineTo([-w / 2, d + t], %, $edge7)
|> close(%, "edge8") |> close(%, $edge8)
return s return s
} }
// build the body of the bracket // build the body of the bracket
const bracketBody = bracketSketch(width, depth, thk) const bs = bracketSketch(width, depth, thk)
const bracketBody = bs
|> extrude(length + 2 * thk, %) |> extrude(length + 2 * thk, %)
|> fillet({ |> fillet({
radius: radius, radius: radius,
tags: [ tags: [
getNextAdjacentEdge("edge7", %), getNextAdjacentEdge(bs.tags.edge7, %),
getNextAdjacentEdge("edge2", %), getNextAdjacentEdge(bs.tags.edge2, %),
getNextAdjacentEdge("edge3", %), getNextAdjacentEdge(bs.tags.edge3, %),
getNextAdjacentEdge("edge6", %) getNextAdjacentEdge(bs.tags.edge6, %)
] ]
}, %) }, %)
@ -74,10 +76,10 @@ const tabPlane = {
// build the tabs of the mounting bracket (right side) // build the tabs of the mounting bracket (right side)
const tabsR = startSketchOn(tabPlane) const tabsR = startSketchOn(tabPlane)
|> startProfileAt([width / 2 + thk, length / 2 + thk], %) |> startProfileAt([width / 2 + thk, length / 2 + thk], %)
|> line([tabWidth, -tabLength / 3], %, "edge11") |> line([tabWidth, -tabLength / 3], %, $edge11)
|> line([0, -tabLength / 3 * 2], %, "edge12") |> line([0, -tabLength / 3 * 2], %, $edge12)
|> line([-tabWidth, -tabLength / 3], %, "edge13") |> line([-tabWidth, -tabLength / 3], %, $edge13)
|> close(%, "edge14") |> close(%, $edge14)
|> hole(circle([ |> hole(circle([
width / 2 + thk + tabWidth / 2, width / 2 + thk + tabWidth / 2,
length / 2 + thk - (tabLength / (3 / 2)) length / 2 + thk - (tabLength / (3 / 2))
@ -86,8 +88,8 @@ const tabsR = startSketchOn(tabPlane)
|> fillet({ |> fillet({
radius: holeDiam / 2, radius: holeDiam / 2,
tags: [ tags: [
getNextAdjacentEdge("edge12", %), getNextAdjacentEdge(edge12, %),
getNextAdjacentEdge("edge13", %) getNextAdjacentEdge(edge13, %)
] ]
}, %) }, %)
|> patternLinear3d({ |> patternLinear3d({
@ -99,10 +101,10 @@ const tabsR = startSketchOn(tabPlane)
// build the tabs of the mounting bracket (left side) // build the tabs of the mounting bracket (left side)
const tabsL = startSketchOn(tabPlane) const tabsL = startSketchOn(tabPlane)
|> startProfileAt([-width / 2 - thk, length / 2 + thk], %) |> startProfileAt([-width / 2 - thk, length / 2 + thk], %)
|> line([-tabWidth, -tabLength / 3], %, "edge21") |> line([-tabWidth, -tabLength / 3], %, $edge21)
|> line([0, -tabLength / 3 * 2], %, "edge22") |> line([0, -tabLength / 3 * 2], %, $edge22)
|> line([tabWidth, -tabLength / 3], %, "edge23") |> line([tabWidth, -tabLength / 3], %, $edge23)
|> close(%, "edge24") |> close(%, $edge24)
|> hole(circle([ |> hole(circle([
-width / 2 - thk - (tabWidth / 2), -width / 2 - thk - (tabWidth / 2),
length / 2 + thk - (tabLength / (3 / 2)) length / 2 + thk - (tabLength / (3 / 2))
@ -111,8 +113,8 @@ const tabsL = startSketchOn(tabPlane)
|> fillet({ |> fillet({
radius: holeDiam / 2, radius: holeDiam / 2,
tags: [ tags: [
getNextAdjacentEdge("edge21", %), getNextAdjacentEdge(edge21, %),
getNextAdjacentEdge("edge22", %) getNextAdjacentEdge(edge22, %)
] ]
}, %) }, %)
|> patternLinear3d({ |> patternLinear3d({

View File

@ -0,0 +1,39 @@
// define a plane with UID 94894440791888
const plane94894440791888 = {
plane: {
origin: [0.005000000000000001, 0.01, -0.005],
x_axis: [
0.9285064634886234,
0.37131623619207604,
0.0
],
y_axis: [-0.0, 0.0, 1.0],
z_axis: [
0.37131623619207604,
-0.9285064634886234,
0.0
]
}
}
// create a sketch with UID 94894440902176
const sketch94894440902176 = startSketchOn('-XZ')
|> startProfileAt([-0.005, -0.005], %)
|> line([0.01, 0.0], %, $line94894439494384)
|> line([0.0, 0.01], %, $line94894439429616)
|> line([-0.01, 0.0], %, $line94894439638160)
|> line([0.0, -0.01], %, $line94894439971808)
// create an extrusion with UID 94894439487136
const extrude94894439487136 = extrude(0.01, sketch94894440902176)
// create a sketch with UID 94894439448464
const sketch94894439448464 = startSketchOn(plane94894440791888)
|> startProfileAt([
0.00074557205559017,
0.00306415853984399
], %)
|> line([0.004999999999999999, 0.0], %, $line94894440230336)
|> line([0.0, -0.005], %, $line94894439497168)
|> line([-0.004999999999999999, 0.0], %, $line94894439496768)
|> line([0.0, 0.005], %, $line94894440231952)

View File

@ -0,0 +1,39 @@
// define a plane with UID 94894440791888
const plane94894440791888 = {
plane: {
origin: [0.005000000000000001, 0.01, -0.005],
x_axis: [
0.9285064634886234,
0.37131623619207604,
0.0
],
y_axis: [-0.0, 0.0, 1.0],
z_axis: [
0.37131623619207604,
-0.9285064634886234,
0.0
]
}
}
// create a sketch with UID 94894440902176
const sketch94894440902176 = startSketchOn('-XZ')
|> startProfileAt([-0.005, -0.005], %)
|> line([0.01, 0.0], %, $line94894439494384)
|> line([0.0, 0.01], %, $line94894439429616)
|> line([-0.01, 0.0], %, $line94894439638160)
|> line([0.0, -0.01], %, $line94894439971808)
// create a sketch with UID 94894439448464
const sketch94894439448464 = startSketchOn(plane94894440791888)
|> startProfileAt([
0.00074557205559017,
0.00306415853984399
], %)
|> line([0.004999999999999999, 0.0], %, $line94894440230336)
|> line([0.0, -0.005], %, $line94894439497168)
|> line([-0.004999999999999999, 0.0], %, $line94894439496768)
|> line([0.0, 0.005], %, $line94894440231952)
// create an extrusion with UID 94894439487136
const extrude94894439487136 = extrude(0.01, sketch94894440902176)

View File

@ -0,0 +1,18 @@
fn rect = (origin) => {
return startSketchOn('XZ')
|> startProfileAt(origin, %)
|> angledLine([0, 191.26], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001, %) - 90,
196.99
], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001, %),
-segLen(rectangleSegmentA001, %)
], %, $rectangleSegmentC001)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
}
rect([0, 0])
rect([20, 0])

View File

@ -37,6 +37,7 @@ async fn new_context(units: UnitLength) -> Result<ExecutorContext> {
units, units,
highlight_edges: true, highlight_edges: true,
enable_ssao: false, enable_ssao: false,
show_grid: false,
}, },
) )
.await?; .await?;
@ -2471,3 +2472,32 @@ async fn serial_test_pattern_vase() {
let result = execute_and_snapshot(code, UnitLength::Mm).await.unwrap(); let result = execute_and_snapshot(code, UnitLength::Mm).await.unwrap();
twenty_twenty::assert_image("tests/executor/outputs/pattern_vase.png", &result, 0.999); twenty_twenty::assert_image("tests/executor/outputs/pattern_vase.png", &result, 0.999);
} }
#[tokio::test(flavor = "multi_thread")]
async fn serial_test_scoped_tags() {
let code = include_str!("inputs/scoped-tags.kcl");
let result = execute_and_snapshot(code, UnitLength::Mm).await.unwrap();
twenty_twenty::assert_image("tests/executor/outputs/scoped_tags.png", &result, 0.999);
}
#[tokio::test(flavor = "multi_thread")]
async fn serial_test_order_sketch_extrude_in_order() {
let code = include_str!("inputs/order-sketch-extrude-in-order.kcl");
let result = execute_and_snapshot(code, UnitLength::Mm).await.unwrap();
twenty_twenty::assert_image(
"tests/executor/outputs/order-sketch-extrude-in-order.png",
&result,
0.999,
);
}
#[tokio::test(flavor = "multi_thread")]
async fn serial_test_order_sketch_extrude_out_of_order() {
let code = include_str!("inputs/order-sketch-extrude-out-of-order.kcl");
let result = execute_and_snapshot(code, UnitLength::Mm).await.unwrap();
twenty_twenty::assert_image(
"tests/executor/outputs/order-sketch-extrude-out-of-order.png",
&result,
0.999,
);
}

Some files were not shown because too many files have changed in this diff Show More