Compare commits
9 Commits
v0.23.1
...
callbacks-
Author | SHA1 | Date | |
---|---|---|---|
cf068f325e | |||
d60d2292f3 | |||
7d564cc2ac | |||
05a84213dd | |||
a85c1a9375 | |||
5701616f3e | |||
846acaba2f | |||
0a524d42f6 | |||
fe28527ef9 |
@ -121,6 +121,9 @@ const extrusion = extrude(5, sketch001)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -282,6 +285,9 @@ const extrusion = extrude(5, sketch001)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -125,6 +125,9 @@ const extrusion = extrude(5, sketch001)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -286,6 +289,9 @@ const extrusion = extrude(5, sketch001)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -126,6 +126,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -287,6 +290,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -476,6 +482,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -637,6 +646,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -125,6 +125,9 @@ const extrusion = extrude(10, sketch001)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -286,6 +289,9 @@ const extrusion = extrude(10, sketch001)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -475,6 +481,9 @@ const extrusion = extrude(10, sketch001)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -636,6 +645,9 @@ const extrusion = extrude(10, sketch001)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -133,6 +133,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -294,6 +297,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -483,6 +489,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -644,6 +653,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -124,6 +124,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -285,6 +288,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -474,6 +480,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -635,6 +644,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -124,6 +124,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -285,6 +288,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -474,6 +480,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -635,6 +644,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -135,6 +135,9 @@ const exampleSketch = startSketchOn('XZ')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -296,6 +299,9 @@ const exampleSketch = startSketchOn('XZ')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -485,6 +491,9 @@ const exampleSketch = startSketchOn('XZ')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -646,6 +655,9 @@ const exampleSketch = startSketchOn('XZ')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -130,6 +130,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -291,6 +294,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -480,6 +486,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -641,6 +650,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -225,6 +225,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -532,6 +535,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -123,6 +123,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -410,6 +413,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -599,6 +605,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -760,6 +769,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -125,6 +125,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -286,6 +289,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -475,6 +481,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -636,6 +645,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -150,6 +150,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -311,6 +314,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
type: "sketchGroup",
|
||||
// The paths in the sketch group.
|
||||
@ -580,6 +586,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -225,6 +225,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -524,6 +527,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -215,6 +215,9 @@ const revolution = startSketchOn(box, "revolveAxis")
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -211,6 +211,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -211,6 +211,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -213,6 +213,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -213,6 +213,9 @@ const part001 = startSketchOn('XY')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -512,6 +515,9 @@ const part001 = startSketchOn('XY')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -136,6 +136,9 @@ const example = extrude(1, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -297,6 +300,9 @@ const example = extrude(1, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
type: "sketchGroup",
|
||||
// The paths in the sketch group.
|
||||
@ -479,6 +485,9 @@ const example = extrude(1, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -640,6 +649,9 @@ const example = extrude(1, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -821,6 +833,9 @@ const example = extrude(1, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -982,6 +997,9 @@ const example = extrude(1, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -116,6 +116,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -277,6 +280,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -116,6 +116,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -277,6 +280,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -129,6 +129,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -290,6 +293,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -479,6 +485,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -640,6 +649,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -116,6 +116,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -277,6 +280,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -466,6 +472,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -627,6 +636,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -134,6 +134,9 @@ const example = extrude(1, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -295,6 +298,9 @@ const example = extrude(1, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
type: "sketchGroup",
|
||||
// The paths in the sketch group.
|
||||
|
@ -217,6 +217,9 @@ const example = extrude(-5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -127,6 +127,9 @@ const example = extrude(1, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -288,6 +291,9 @@ const example = extrude(1, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
type: "sketchGroup",
|
||||
// The paths in the sketch group.
|
||||
|
@ -215,6 +215,9 @@ const example = extrude(1, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -217,6 +217,9 @@ let vase = layer()
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -117,6 +117,9 @@ const sketch001 = startSketchOn('XY')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -278,6 +281,9 @@ const sketch001 = startSketchOn('XY')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -112,6 +112,9 @@ const sketch001 = startSketchOn('XY')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -273,6 +276,9 @@ const sketch001 = startSketchOn('XY')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -111,6 +111,9 @@ const sketch001 = startSketchOn('XY')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -272,6 +275,9 @@ const sketch001 = startSketchOn('XY')
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -247,6 +247,9 @@ uuid |
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -408,6 +411,9 @@ uuid |
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -673,6 +679,9 @@ uuid |
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -124,6 +124,9 @@ const example = extrude(4, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -285,6 +288,9 @@ const example = extrude(4, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -122,6 +122,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -283,6 +286,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -123,6 +123,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -284,6 +287,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -121,6 +121,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -282,6 +285,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -213,6 +213,9 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -512,6 +515,9 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -195,6 +195,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -442,6 +445,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -603,6 +609,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -142,6 +142,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -303,6 +306,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -264,6 +264,9 @@ const a1 = startSketchOn({
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -539,6 +542,9 @@ const a1 = startSketchOn({
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
5655
docs/kcl/std.json
@ -125,6 +125,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -286,6 +289,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -475,6 +481,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -636,6 +645,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -116,6 +116,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -277,6 +280,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -466,6 +472,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -627,6 +636,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -74,6 +74,107 @@ You can nest expressions in parenthesis as well:
|
||||
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
|
||||
repo](https://github.com/KittyCAD/modeling-app/issues/new).
|
||||
|
@ -119,6 +119,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -280,6 +283,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -469,6 +475,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -630,6 +639,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -119,6 +119,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -280,6 +283,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -469,6 +475,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -630,6 +639,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -117,6 +117,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -278,6 +281,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -467,6 +473,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -628,6 +637,9 @@ const example = extrude(10, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -115,6 +115,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -276,6 +279,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -465,6 +471,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
@ -626,6 +635,9 @@ const example = extrude(5, exampleSketch)
|
||||
},
|
||||
// The to point.
|
||||
to: [number, number],
|
||||
},
|
||||
// Tag identifiers that have been declared in this sketch group.
|
||||
tags: {
|
||||
},
|
||||
// The paths in the sketch group.
|
||||
value: [{
|
||||
|
@ -7134,6 +7134,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 }) => {
|
||||
// FYI this test doesn't work with only engine running locally
|
||||
// And you will need to have the KittyCAD CLI installed
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 29 KiB |
6
src-tauri/Cargo.lock
generated
@ -2571,7 +2571,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.1.69"
|
||||
version = "0.1.70"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx",
|
||||
@ -2628,9 +2628,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kittycad"
|
||||
version = "0.3.6"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af3de9bb4b1441f198689a9f64a8163a518377e30b348a784680e738985b95eb"
|
||||
checksum = "e1777b503442fa4666564cc3ab237d456df853a09648a4b2bb09622d25d021a5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -16,7 +16,7 @@ tauri-build = { version = "2.0.0-beta.18", features = [] }
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
kcl-lib = { version = "0.1.53", path = "../src/wasm-lib/kcl" }
|
||||
kittycad = "0.3.5"
|
||||
kittycad = "0.3.7"
|
||||
log = "0.4.21"
|
||||
oauth2 = "4.4.2"
|
||||
serde_json = "1.0"
|
||||
|
@ -25,6 +25,7 @@ import ModalContainer from 'react-modal-promise'
|
||||
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
||||
import Gizmo from 'components/Gizmo'
|
||||
import { CoreDumpManager } from 'lib/coredump'
|
||||
import { UnitsMenu } from 'components/UnitsMenu'
|
||||
|
||||
export function App() {
|
||||
useRefreshSettings(paths.FILE + 'SETTINGS')
|
||||
@ -127,6 +128,7 @@ export function App() {
|
||||
<Stream />
|
||||
{/* <CamToggle /> */}
|
||||
<LowerRightControls coreDumpManager={coreDumpManager}>
|
||||
<UnitsMenu />
|
||||
<Gizmo />
|
||||
</LowerRightControls>
|
||||
</div>
|
||||
|
@ -19,7 +19,10 @@ import {
|
||||
PROFILE_START,
|
||||
getParentGroup,
|
||||
} from './sceneEntities'
|
||||
import { SegmentOverlay, SketchDetails } from 'machines/modelingMachine'
|
||||
import {
|
||||
SegmentOverlay,
|
||||
ModelingMachineContext as ModelingContextType,
|
||||
} from 'machines/modelingMachine'
|
||||
import { findUsesOfTagInPipe, getNodeFromPath } from 'lang/queryAst'
|
||||
import {
|
||||
CallExpression,
|
||||
@ -353,11 +356,12 @@ export const confirmModal = create<ConfirmModalProps, boolean, boolean>(
|
||||
|
||||
export async function deleteSegment({
|
||||
pathToNode,
|
||||
sketchDetails,
|
||||
context,
|
||||
}: {
|
||||
pathToNode: PathToNode
|
||||
sketchDetails: SketchDetails | null
|
||||
context: ModelingContextType
|
||||
}) {
|
||||
const { sketchDetails } = context
|
||||
let modifiedAst: Program | Error = kclManager.ast
|
||||
const dependentRanges = findUsesOfTagInPipe(modifiedAst, pathToNode)
|
||||
|
||||
@ -394,13 +398,7 @@ export async function deleteSegment({
|
||||
}
|
||||
|
||||
if (!sketchDetails) return
|
||||
await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
pathToNode,
|
||||
modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
)
|
||||
await sceneEntitiesManager.updateAstAndRejigSketch(modifiedAst, context)
|
||||
|
||||
// Now 'Set sketchDetails' is called with the modified pathToNode
|
||||
}
|
||||
|
362
src/clientSideScene/sceneCallbacks.ts
Normal file
@ -0,0 +1,362 @@
|
||||
import { getEventForSegmentSelection } from 'lib/selections'
|
||||
import {
|
||||
editorManager,
|
||||
kclManager,
|
||||
sceneEntitiesManager,
|
||||
sceneInfra,
|
||||
} from 'lib/singletons'
|
||||
import {
|
||||
Intersection,
|
||||
Mesh,
|
||||
MeshBasicMaterial,
|
||||
Object3D,
|
||||
Object3DEventMap,
|
||||
OrthographicCamera,
|
||||
Points,
|
||||
Vector2,
|
||||
Vector3,
|
||||
} from 'three'
|
||||
import {
|
||||
EXTRA_SEGMENT_HANDLE,
|
||||
PROFILE_START,
|
||||
STRAIGHT_SEGMENT,
|
||||
TANGENTIAL_ARC_TO_SEGMENT,
|
||||
getParentGroup,
|
||||
sketchGroupFromPathToNode,
|
||||
} from './sceneEntities'
|
||||
import { trap } from 'lib/trap'
|
||||
import { addNewSketchLn } from 'lang/std/sketch'
|
||||
import { CallExpression, PathToNode, parse, recast } from 'lang/wasm'
|
||||
import { ARROWHEAD, X_AXIS, Y_AXIS } from './sceneInfra'
|
||||
import { getNodeFromPath } from 'lang/queryAst'
|
||||
import { getThemeColorForThreeJs } from 'lib/theme'
|
||||
import { orthoScale, perspScale, quaternionFromUpNForward } from './helpers'
|
||||
import { ModelingMachineContext } from 'machines/modelingMachine'
|
||||
import { addStartProfileAt } from 'lang/modifyAst'
|
||||
|
||||
export interface OnMouseEnterLeaveArgs {
|
||||
selected: Object3D<Object3DEventMap>
|
||||
dragSelected?: Object3D<Object3DEventMap>
|
||||
mouseEvent: MouseEvent
|
||||
}
|
||||
|
||||
export interface OnDragCallbackArgs extends OnMouseEnterLeaveArgs {
|
||||
intersectionPoint: {
|
||||
twoD: Vector2
|
||||
threeD: Vector3
|
||||
}
|
||||
intersects: Intersection<Object3D<Object3DEventMap>>[]
|
||||
}
|
||||
export interface OnClickCallbackArgs {
|
||||
mouseEvent: MouseEvent
|
||||
intersectionPoint?: {
|
||||
twoD: Vector2
|
||||
threeD: Vector3
|
||||
}
|
||||
intersects: Intersection<Object3D<Object3DEventMap>>[]
|
||||
selected?: Object3D<Object3DEventMap>
|
||||
}
|
||||
|
||||
export interface OnMoveCallbackArgs {
|
||||
mouseEvent: MouseEvent
|
||||
intersectionPoint: {
|
||||
twoD: Vector2
|
||||
threeD: Vector3
|
||||
}
|
||||
intersects: Intersection<Object3D<Object3DEventMap>>[]
|
||||
selected?: Object3D<Object3DEventMap>
|
||||
}
|
||||
|
||||
interface Callbacks {
|
||||
onDragStart: (arg: OnDragCallbackArgs) => void
|
||||
onDragEnd: (arg: OnDragCallbackArgs) => void
|
||||
onDrag: (arg: OnDragCallbackArgs) => void
|
||||
onMove: (arg: OnMoveCallbackArgs) => void
|
||||
onClick: (arg: OnClickCallbackArgs) => void
|
||||
onMouseEnter: (arg: OnMouseEnterLeaveArgs) => void
|
||||
onMouseLeave: (arg: OnMouseEnterLeaveArgs) => void
|
||||
}
|
||||
|
||||
type SetCallbacksWithCtx = (context: ModelingMachineContext) => Callbacks
|
||||
|
||||
const dummyListenersAll: Callbacks = {
|
||||
onDragStart: () => {},
|
||||
onDragEnd: () => {},
|
||||
onDrag: () => {},
|
||||
onMove: () => {},
|
||||
onClick: () => {},
|
||||
onMouseEnter: () => {},
|
||||
onMouseLeave: () => {},
|
||||
}
|
||||
|
||||
const onMousEnterLeaveCallbacks = {
|
||||
onMouseEnter: ({ selected, dragSelected }: OnMouseEnterLeaveArgs) => {
|
||||
if ([X_AXIS, Y_AXIS].includes(selected?.userData?.type)) {
|
||||
const obj = selected as Mesh
|
||||
const mat = obj.material as MeshBasicMaterial
|
||||
mat.color.set(obj.userData.baseColor)
|
||||
mat.color.offsetHSL(0, 0, 0.5)
|
||||
}
|
||||
const parent = getParentGroup(selected, [
|
||||
STRAIGHT_SEGMENT,
|
||||
TANGENTIAL_ARC_TO_SEGMENT,
|
||||
PROFILE_START,
|
||||
])
|
||||
if (parent?.userData?.pathToNode) {
|
||||
const updatedAst = parse(recast(kclManager.ast))
|
||||
if (trap(updatedAst)) return
|
||||
const _node = getNodeFromPath<CallExpression>(
|
||||
updatedAst,
|
||||
parent.userData.pathToNode,
|
||||
'CallExpression'
|
||||
)
|
||||
if (trap(_node, { suppress: true })) return
|
||||
const node = _node.node
|
||||
editorManager.setHighlightRange([node.start, node.end])
|
||||
const yellow = 0xffff00
|
||||
colorSegment(selected, yellow)
|
||||
const extraSegmentGroup = parent.getObjectByName(EXTRA_SEGMENT_HANDLE)
|
||||
if (extraSegmentGroup) {
|
||||
extraSegmentGroup.traverse((child) => {
|
||||
if (child instanceof Points || child instanceof Mesh) {
|
||||
child.material.opacity = dragSelected ? 0 : 1
|
||||
}
|
||||
})
|
||||
}
|
||||
const orthoFactor = orthoScale(sceneInfra.camControls.camera)
|
||||
|
||||
const factor =
|
||||
(sceneInfra.camControls.camera instanceof OrthographicCamera
|
||||
? orthoFactor
|
||||
: perspScale(sceneInfra.camControls.camera, parent)) /
|
||||
sceneInfra._baseUnitMultiplier
|
||||
if (parent.name === STRAIGHT_SEGMENT) {
|
||||
sceneEntitiesManager.updateStraightSegment({
|
||||
from: parent.userData.from,
|
||||
to: parent.userData.to,
|
||||
group: parent,
|
||||
scale: factor,
|
||||
})
|
||||
} else if (parent.name === TANGENTIAL_ARC_TO_SEGMENT) {
|
||||
sceneEntitiesManager.updateTangentialArcToSegment({
|
||||
prevSegment: parent.userData.prevSegment,
|
||||
from: parent.userData.from,
|
||||
to: parent.userData.to,
|
||||
group: parent,
|
||||
scale: factor,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
editorManager.setHighlightRange([0, 0])
|
||||
},
|
||||
onMouseLeave: ({ selected, ...rest }: OnMouseEnterLeaveArgs) => {
|
||||
editorManager.setHighlightRange([0, 0])
|
||||
const parent = getParentGroup(selected, [
|
||||
STRAIGHT_SEGMENT,
|
||||
TANGENTIAL_ARC_TO_SEGMENT,
|
||||
PROFILE_START,
|
||||
])
|
||||
if (parent) {
|
||||
const orthoFactor = orthoScale(sceneInfra.camControls.camera)
|
||||
|
||||
const factor =
|
||||
(sceneInfra.camControls.camera instanceof OrthographicCamera
|
||||
? orthoFactor
|
||||
: perspScale(sceneInfra.camControls.camera, parent)) /
|
||||
sceneInfra._baseUnitMultiplier
|
||||
if (parent.name === STRAIGHT_SEGMENT) {
|
||||
sceneEntitiesManager.updateStraightSegment({
|
||||
from: parent.userData.from,
|
||||
to: parent.userData.to,
|
||||
group: parent,
|
||||
scale: factor,
|
||||
})
|
||||
} else if (parent.name === TANGENTIAL_ARC_TO_SEGMENT) {
|
||||
sceneEntitiesManager.updateTangentialArcToSegment({
|
||||
prevSegment: parent.userData.prevSegment,
|
||||
from: parent.userData.from,
|
||||
to: parent.userData.to,
|
||||
group: parent,
|
||||
scale: factor,
|
||||
})
|
||||
}
|
||||
}
|
||||
const isSelected = parent?.userData?.isSelected
|
||||
colorSegment(
|
||||
selected,
|
||||
isSelected
|
||||
? 0x0000ff
|
||||
: parent?.userData?.baseColor ||
|
||||
getThemeColorForThreeJs(sceneInfra._theme)
|
||||
)
|
||||
const extraSegmentGroup = parent?.getObjectByName(EXTRA_SEGMENT_HANDLE)
|
||||
if (extraSegmentGroup) {
|
||||
extraSegmentGroup.traverse((child) => {
|
||||
if (child instanceof Points || child instanceof Mesh) {
|
||||
child.material.opacity = 0
|
||||
}
|
||||
})
|
||||
}
|
||||
if ([X_AXIS, Y_AXIS].includes(selected?.userData?.type)) {
|
||||
const obj = selected as Mesh
|
||||
const mat = obj.material as MeshBasicMaterial
|
||||
mat.color.set(obj.userData.baseColor)
|
||||
if (obj.userData.isSelected) mat.color.offsetHSL(0, 0, 0.2)
|
||||
}
|
||||
},
|
||||
} as const
|
||||
|
||||
export const idleCallbacks: SetCallbacksWithCtx = (context) => {
|
||||
let addingNewSegmentStatus: 'nothing' | 'pending' | 'added' = 'nothing'
|
||||
return {
|
||||
onDragStart: () => {},
|
||||
onDragEnd: () => {},
|
||||
onMove: () => {},
|
||||
...onMousEnterLeaveCallbacks,
|
||||
onClick: (args) => {
|
||||
if (args?.mouseEvent.which !== 1) return
|
||||
if (!args || !args.selected) {
|
||||
sceneInfra.modelingSend({
|
||||
type: 'Set selection',
|
||||
data: {
|
||||
selectionType: 'singleCodeCursor',
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
const { selected } = args
|
||||
const event = getEventForSegmentSelection(selected)
|
||||
if (!event) return
|
||||
sceneInfra.modelingSend(event)
|
||||
},
|
||||
onDrag: async ({ selected, intersectionPoint, mouseEvent, intersects }) => {
|
||||
if (mouseEvent.which !== 1) return
|
||||
|
||||
const group = getParentGroup(selected, [EXTRA_SEGMENT_HANDLE])
|
||||
if (group?.name === EXTRA_SEGMENT_HANDLE) {
|
||||
const segGroup = getParentGroup(selected)
|
||||
const pathToNode: PathToNode = segGroup?.userData?.pathToNode
|
||||
const pathToNodeIndex = pathToNode.findIndex(
|
||||
(x) => x[1] === 'PipeExpression'
|
||||
)
|
||||
|
||||
const sketchGroup = sketchGroupFromPathToNode({
|
||||
pathToNode,
|
||||
ast: kclManager.ast,
|
||||
programMemory: kclManager.programMemory,
|
||||
})
|
||||
if (trap(sketchGroup)) return
|
||||
|
||||
const pipeIndex = pathToNode[pathToNodeIndex + 1][0] as number
|
||||
if (addingNewSegmentStatus === 'nothing') {
|
||||
const prevSegment = sketchGroup.value[pipeIndex - 2]
|
||||
const mod = addNewSketchLn({
|
||||
node: kclManager.ast,
|
||||
programMemory: kclManager.programMemory,
|
||||
to: [intersectionPoint.twoD.x, intersectionPoint.twoD.y],
|
||||
from: [prevSegment.from[0], prevSegment.from[1]],
|
||||
// TODO assuming it's always a straight segments being added
|
||||
// as this is easiest, and we'll need to add "tabbing" behavior
|
||||
// to support other segment types
|
||||
fnName: 'line',
|
||||
pathToNode: pathToNode,
|
||||
spliceBetween: true,
|
||||
})
|
||||
addingNewSegmentStatus = 'pending'
|
||||
if (trap(mod)) return
|
||||
|
||||
await kclManager.executeAstMock(mod.modifiedAst)
|
||||
await sceneEntitiesManager.tearDownSketch({ removeAxis: false })
|
||||
sceneEntitiesManager.setupSketch({
|
||||
sketchPathToNode: pathToNode,
|
||||
maybeModdedAst: kclManager.ast,
|
||||
up: context.sketchDetails?.yAxis || [0, 1, 0],
|
||||
forward: context.sketchDetails?.zAxis || [0, 0, 1],
|
||||
position: context.sketchDetails?.origin || [0, 0, 0],
|
||||
})
|
||||
addingNewSegmentStatus = 'added'
|
||||
} else if (addingNewSegmentStatus === 'added') {
|
||||
const pathToNodeForNewSegment = pathToNode.slice(0, pathToNodeIndex)
|
||||
pathToNodeForNewSegment.push([pipeIndex - 2, 'index'])
|
||||
sceneEntitiesManager.onDragSegment({
|
||||
sketchPathToNode: pathToNodeForNewSegment,
|
||||
object: selected,
|
||||
intersection2d: intersectionPoint.twoD,
|
||||
intersects,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
sceneEntitiesManager.onDragSegment({
|
||||
object: selected,
|
||||
intersection2d: intersectionPoint.twoD,
|
||||
intersects,
|
||||
sketchPathToNode: context.sketchDetails?.sketchPathToNode || [],
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export const Sketch_LineTool_NoPoints: SetCallbacksWithCtx = ({
|
||||
sketchDetails,
|
||||
}) => {
|
||||
if (!sketchDetails) return dummyListenersAll
|
||||
sceneEntitiesManager.createIntersectionPlane()
|
||||
const quaternion = quaternionFromUpNForward(
|
||||
new Vector3(...sketchDetails.yAxis),
|
||||
new Vector3(...sketchDetails.zAxis)
|
||||
)
|
||||
sceneEntitiesManager.intersectionPlane &&
|
||||
sceneEntitiesManager.intersectionPlane.setRotationFromQuaternion(quaternion)
|
||||
sceneEntitiesManager.intersectionPlane &&
|
||||
sceneEntitiesManager.intersectionPlane.position.copy(
|
||||
new Vector3(...(sketchDetails?.origin || [0, 0, 0]))
|
||||
)
|
||||
return {
|
||||
...dummyListenersAll,
|
||||
onClick: async (args) => {
|
||||
if (!args) return
|
||||
if (args.mouseEvent.which !== 1) return
|
||||
const { intersectionPoint } = args
|
||||
if (!intersectionPoint?.twoD || !sketchDetails?.sketchPathToNode) return
|
||||
const addStartProfileAtRes = addStartProfileAt(
|
||||
kclManager.ast,
|
||||
sketchDetails.sketchPathToNode,
|
||||
[intersectionPoint.twoD.x, intersectionPoint.twoD.y]
|
||||
)
|
||||
|
||||
if (trap(addStartProfileAtRes)) return
|
||||
const { modifiedAst } = addStartProfileAtRes
|
||||
|
||||
await kclManager.updateAst(modifiedAst, false)
|
||||
sceneEntitiesManager.removeIntersectionPlane()
|
||||
sceneInfra.modelingSend('Add start point')
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function colorSegment(object: any, color: number) {
|
||||
const segmentHead = getParentGroup(object, [ARROWHEAD, PROFILE_START])
|
||||
if (segmentHead) {
|
||||
segmentHead.traverse((child) => {
|
||||
if (child instanceof Mesh) {
|
||||
child.material.color.set(color)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
const straightSegmentBody = getParentGroup(object, [
|
||||
STRAIGHT_SEGMENT,
|
||||
TANGENTIAL_ARC_TO_SEGMENT,
|
||||
])
|
||||
if (straightSegmentBody) {
|
||||
straightSegmentBody.traverse((child) => {
|
||||
if (child instanceof Mesh && !child.userData.ignoreColorChange) {
|
||||
child.material.color.set(color)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
@ -22,12 +22,8 @@ import {
|
||||
import {
|
||||
ARROWHEAD,
|
||||
AXIS_GROUP,
|
||||
DEFAULT_PLANES,
|
||||
DefaultPlane,
|
||||
defaultPlaneColor,
|
||||
getSceneScale,
|
||||
INTERSECTION_PLANE_LAYER,
|
||||
OnMouseEnterLeaveArgs,
|
||||
RAYCASTABLE_PLANE,
|
||||
SKETCH_GROUP_SEGMENTS,
|
||||
SKETCH_LAYER,
|
||||
@ -82,16 +78,16 @@ import {
|
||||
createPipeSubstitution,
|
||||
findUniqueName,
|
||||
} from 'lang/modifyAst'
|
||||
import {
|
||||
Selections,
|
||||
getEventForSegmentSelection,
|
||||
sendSelectEventToEngine,
|
||||
} from 'lib/selections'
|
||||
import { Selections, sendSelectEventToEngine } from 'lib/selections'
|
||||
import { getTangentPointFromPreviousArc } from 'lib/utils2d'
|
||||
import { createGridHelper, orthoScale, perspScale } from './helpers'
|
||||
import { Models } from '@kittycad/lib'
|
||||
import { uuidv4 } from 'lib/utils'
|
||||
import { SegmentOverlayPayload, SketchDetails } from 'machines/modelingMachine'
|
||||
import {
|
||||
SegmentOverlayPayload,
|
||||
SketchDetails,
|
||||
ModelingMachineContext,
|
||||
} from 'machines/modelingMachine'
|
||||
import {
|
||||
ArtifactMapCommand,
|
||||
EngineCommandManager,
|
||||
@ -102,6 +98,7 @@ import {
|
||||
} from 'lib/rectangleTool'
|
||||
import { getThemeColorForThreeJs } from 'lib/theme'
|
||||
import { err, trap } from 'lib/trap'
|
||||
import { OnMouseEnterLeaveArgs, idleCallbacks } from './sceneCallbacks'
|
||||
|
||||
type DraftSegment = 'line' | 'tangentialArcTo'
|
||||
|
||||
@ -499,31 +496,23 @@ export class SceneEntities {
|
||||
variableDeclarationName,
|
||||
}
|
||||
}
|
||||
updateAstAndRejigSketch = async (
|
||||
sketchPathToNode: PathToNode,
|
||||
updateAstAndRejigSketch: (
|
||||
modifiedAst: Program | Error,
|
||||
forward: [number, number, number],
|
||||
up: [number, number, number],
|
||||
origin: [number, number, number]
|
||||
) => {
|
||||
context: ModelingMachineContext
|
||||
) => Promise<any> = async (modifiedAst, context) => {
|
||||
if (err(modifiedAst)) return modifiedAst
|
||||
|
||||
const nextAst = await kclManager.updateAst(modifiedAst, false)
|
||||
await this.tearDownSketch({ removeAxis: false })
|
||||
sceneInfra.resetMouseListeners()
|
||||
await this.setupSketch({
|
||||
sketchPathToNode,
|
||||
forward,
|
||||
up,
|
||||
position: origin,
|
||||
sketchPathToNode: context.sketchDetails?.sketchPathToNode || [],
|
||||
forward: context.sketchDetails?.zAxis || [0, 0, 1],
|
||||
up: context.sketchDetails?.yAxis || [0, 1, 0],
|
||||
position: context.sketchDetails?.origin || [0, 0, 0],
|
||||
maybeModdedAst: nextAst.newAst,
|
||||
})
|
||||
this.setupSketchIdleCallbacks({
|
||||
forward,
|
||||
up,
|
||||
position: origin,
|
||||
pathToNode: sketchPathToNode,
|
||||
})
|
||||
this.setupSketchIdleCallbacks(context)
|
||||
return nextAst
|
||||
}
|
||||
setUpDraftSegment = async (
|
||||
@ -838,128 +827,8 @@ export class SceneEntities {
|
||||
},
|
||||
})
|
||||
}
|
||||
setupSketchIdleCallbacks = ({
|
||||
pathToNode,
|
||||
up,
|
||||
forward,
|
||||
position,
|
||||
}: {
|
||||
pathToNode: PathToNode
|
||||
forward: [number, number, number]
|
||||
up: [number, number, number]
|
||||
position?: [number, number, number]
|
||||
}) => {
|
||||
let addingNewSegmentStatus: 'nothing' | 'pending' | 'added' = 'nothing'
|
||||
sceneInfra.setCallbacks({
|
||||
onDragEnd: async () => {
|
||||
if (addingNewSegmentStatus !== 'nothing') {
|
||||
await this.tearDownSketch({ removeAxis: false })
|
||||
this.setupSketch({
|
||||
sketchPathToNode: pathToNode,
|
||||
maybeModdedAst: kclManager.ast,
|
||||
up,
|
||||
forward,
|
||||
position,
|
||||
})
|
||||
// setting up the callbacks again resets value in closures
|
||||
this.setupSketchIdleCallbacks({
|
||||
pathToNode,
|
||||
up,
|
||||
forward,
|
||||
position,
|
||||
})
|
||||
}
|
||||
},
|
||||
onDrag: async ({
|
||||
selected,
|
||||
intersectionPoint,
|
||||
mouseEvent,
|
||||
intersects,
|
||||
}) => {
|
||||
if (mouseEvent.which !== 1) return
|
||||
|
||||
const group = getParentGroup(selected, [EXTRA_SEGMENT_HANDLE])
|
||||
if (group?.name === EXTRA_SEGMENT_HANDLE) {
|
||||
const segGroup = getParentGroup(selected)
|
||||
const pathToNode: PathToNode = segGroup?.userData?.pathToNode
|
||||
const pathToNodeIndex = pathToNode.findIndex(
|
||||
(x) => x[1] === 'PipeExpression'
|
||||
)
|
||||
|
||||
const sketchGroup = sketchGroupFromPathToNode({
|
||||
pathToNode,
|
||||
ast: kclManager.ast,
|
||||
programMemory: kclManager.programMemory,
|
||||
})
|
||||
if (trap(sketchGroup)) return
|
||||
|
||||
const pipeIndex = pathToNode[pathToNodeIndex + 1][0] as number
|
||||
if (addingNewSegmentStatus === 'nothing') {
|
||||
const prevSegment = sketchGroup.value[pipeIndex - 2]
|
||||
const mod = addNewSketchLn({
|
||||
node: kclManager.ast,
|
||||
programMemory: kclManager.programMemory,
|
||||
to: [intersectionPoint.twoD.x, intersectionPoint.twoD.y],
|
||||
from: [prevSegment.from[0], prevSegment.from[1]],
|
||||
// TODO assuming it's always a straight segments being added
|
||||
// as this is easiest, and we'll need to add "tabbing" behavior
|
||||
// to support other segment types
|
||||
fnName: 'line',
|
||||
pathToNode: pathToNode,
|
||||
spliceBetween: true,
|
||||
})
|
||||
addingNewSegmentStatus = 'pending'
|
||||
if (trap(mod)) return
|
||||
|
||||
await kclManager.executeAstMock(mod.modifiedAst)
|
||||
await this.tearDownSketch({ removeAxis: false })
|
||||
this.setupSketch({
|
||||
sketchPathToNode: pathToNode,
|
||||
maybeModdedAst: kclManager.ast,
|
||||
up,
|
||||
forward,
|
||||
position,
|
||||
})
|
||||
addingNewSegmentStatus = 'added'
|
||||
} else if (addingNewSegmentStatus === 'added') {
|
||||
const pathToNodeForNewSegment = pathToNode.slice(0, pathToNodeIndex)
|
||||
pathToNodeForNewSegment.push([pipeIndex - 2, 'index'])
|
||||
this.onDragSegment({
|
||||
sketchPathToNode: pathToNodeForNewSegment,
|
||||
object: selected,
|
||||
intersection2d: intersectionPoint.twoD,
|
||||
intersects,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
this.onDragSegment({
|
||||
object: selected,
|
||||
intersection2d: intersectionPoint.twoD,
|
||||
intersects,
|
||||
sketchPathToNode: pathToNode,
|
||||
})
|
||||
},
|
||||
onMove: () => {},
|
||||
onClick: (args) => {
|
||||
if (args?.mouseEvent.which !== 1) return
|
||||
if (!args || !args.selected) {
|
||||
sceneInfra.modelingSend({
|
||||
type: 'Set selection',
|
||||
data: {
|
||||
selectionType: 'singleCodeCursor',
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
const { selected } = args
|
||||
const event = getEventForSegmentSelection(selected)
|
||||
if (!event) return
|
||||
sceneInfra.modelingSend(event)
|
||||
},
|
||||
...this.mouseEnterLeaveCallbacks(),
|
||||
})
|
||||
setupSketchIdleCallbacks = (context: ModelingMachineContext) => {
|
||||
sceneInfra.setCallbacks(idleCallbacks(context))
|
||||
}
|
||||
prepareTruncatedMemoryAndAst = (
|
||||
sketchPathToNode: PathToNode,
|
||||
@ -1429,150 +1298,6 @@ export class SceneEntities {
|
||||
this._tearDownSketch(0, resolve, reject, { removeAxis })
|
||||
})
|
||||
}
|
||||
setupDefaultPlaneHover() {
|
||||
sceneInfra.setCallbacks({
|
||||
onMouseEnter: ({ selected }) => {
|
||||
if (!(selected instanceof Mesh && selected.parent)) return
|
||||
if (selected.parent.userData.type !== DEFAULT_PLANES) return
|
||||
const type: DefaultPlane = selected.userData.type
|
||||
selected.material.color = defaultPlaneColor(type, 0.5, 1)
|
||||
},
|
||||
onMouseLeave: ({ selected }) => {
|
||||
if (!(selected instanceof Mesh && selected.parent)) return
|
||||
if (selected.parent.userData.type !== DEFAULT_PLANES) return
|
||||
const type: DefaultPlane = selected.userData.type
|
||||
selected.material.color = defaultPlaneColor(type)
|
||||
},
|
||||
onClick: async (args) => {
|
||||
const { entity_id } = await sendSelectEventToEngine(
|
||||
args?.mouseEvent,
|
||||
document.getElementById('video-stream') as HTMLVideoElement,
|
||||
sceneInfra._streamDimensions
|
||||
)
|
||||
|
||||
let _entity_id = entity_id
|
||||
if (!_entity_id) return
|
||||
if (
|
||||
engineCommandManager.defaultPlanes?.xy === _entity_id ||
|
||||
engineCommandManager.defaultPlanes?.xz === _entity_id ||
|
||||
engineCommandManager.defaultPlanes?.yz === _entity_id ||
|
||||
engineCommandManager.defaultPlanes?.negXy === _entity_id ||
|
||||
engineCommandManager.defaultPlanes?.negXz === _entity_id ||
|
||||
engineCommandManager.defaultPlanes?.negYz === _entity_id
|
||||
) {
|
||||
const defaultPlaneStrMap: Record<string, DefaultPlaneStr> = {
|
||||
[engineCommandManager.defaultPlanes.xy]: 'XY',
|
||||
[engineCommandManager.defaultPlanes.xz]: 'XZ',
|
||||
[engineCommandManager.defaultPlanes.yz]: 'YZ',
|
||||
[engineCommandManager.defaultPlanes.negXy]: '-XY',
|
||||
[engineCommandManager.defaultPlanes.negXz]: '-XZ',
|
||||
[engineCommandManager.defaultPlanes.negYz]: '-YZ',
|
||||
}
|
||||
// TODO can we get this information from rust land when it creates the default planes?
|
||||
// maybe returned from make_default_planes (src/wasm-lib/src/wasm.rs)
|
||||
let zAxis: [number, number, number] = [0, 0, 1]
|
||||
let yAxis: [number, number, number] = [0, 1, 0]
|
||||
|
||||
// get unit vector from camera position to target
|
||||
const camVector = sceneInfra.camControls.camera.position
|
||||
.clone()
|
||||
.sub(sceneInfra.camControls.target)
|
||||
|
||||
if (engineCommandManager.defaultPlanes?.xy === _entity_id) {
|
||||
zAxis = [0, 0, 1]
|
||||
yAxis = [0, 1, 0]
|
||||
if (camVector.z < 0) {
|
||||
zAxis = [0, 0, -1]
|
||||
_entity_id = engineCommandManager.defaultPlanes?.negXy || ''
|
||||
}
|
||||
} else if (engineCommandManager.defaultPlanes?.yz === _entity_id) {
|
||||
zAxis = [1, 0, 0]
|
||||
yAxis = [0, 0, 1]
|
||||
if (camVector.x < 0) {
|
||||
zAxis = [-1, 0, 0]
|
||||
_entity_id = engineCommandManager.defaultPlanes?.negYz || ''
|
||||
}
|
||||
} else if (engineCommandManager.defaultPlanes?.xz === _entity_id) {
|
||||
zAxis = [0, 1, 0]
|
||||
yAxis = [0, 0, 1]
|
||||
_entity_id = engineCommandManager.defaultPlanes?.negXz || ''
|
||||
if (camVector.y < 0) {
|
||||
zAxis = [0, -1, 0]
|
||||
_entity_id = engineCommandManager.defaultPlanes?.xz || ''
|
||||
}
|
||||
}
|
||||
|
||||
sceneInfra.modelingSend({
|
||||
type: 'Select default plane',
|
||||
data: {
|
||||
type: 'defaultPlane',
|
||||
planeId: _entity_id,
|
||||
plane: defaultPlaneStrMap[_entity_id],
|
||||
zAxis,
|
||||
yAxis,
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
const artifact = this.engineCommandManager.artifactMap[_entity_id]
|
||||
// If we clicked on an extrude wall, we climb up the parent Id
|
||||
// to get the sketch profile's face ID. If we clicked on an endcap,
|
||||
// we already have it.
|
||||
const targetId =
|
||||
'additionalData' in artifact &&
|
||||
artifact.additionalData?.type === 'cap'
|
||||
? _entity_id
|
||||
: artifact.parentId
|
||||
|
||||
// tsc cannot infer that target can have extrusions
|
||||
// from the commandType (why?) so we need to cast it
|
||||
const target = this.engineCommandManager.artifactMap?.[
|
||||
targetId || ''
|
||||
] as ArtifactMapCommand & { extrusions?: string[] }
|
||||
|
||||
// TODO: We get the first extrusion command ID,
|
||||
// which is fine while backend systems only support one extrusion.
|
||||
// but we need to more robustly handle resolving to the correct extrusion
|
||||
// if there are multiple.
|
||||
const extrusions =
|
||||
this.engineCommandManager.artifactMap?.[target?.extrusions?.[0] || '']
|
||||
|
||||
if (artifact?.commandType !== 'solid3d_get_extrusion_face_info') return
|
||||
|
||||
const faceInfo = await getFaceDetails(_entity_id)
|
||||
if (!faceInfo?.origin || !faceInfo?.z_axis || !faceInfo?.y_axis) return
|
||||
const { z_axis, y_axis, origin } = faceInfo
|
||||
const sketchPathToNode = getNodePathFromSourceRange(
|
||||
kclManager.ast,
|
||||
artifact.range
|
||||
)
|
||||
|
||||
const extrudePathToNode = extrusions?.range
|
||||
? getNodePathFromSourceRange(kclManager.ast, extrusions.range)
|
||||
: []
|
||||
|
||||
sceneInfra.modelingSend({
|
||||
type: 'Select default plane',
|
||||
data: {
|
||||
type: 'extrudeFace',
|
||||
zAxis: [z_axis.x, z_axis.y, z_axis.z],
|
||||
yAxis: [y_axis.x, y_axis.y, y_axis.z],
|
||||
position: [origin.x, origin.y, origin.z].map(
|
||||
(num) => num / sceneInfra._baseUnitMultiplier
|
||||
) as [number, number, number],
|
||||
sketchPathToNode,
|
||||
extrudePathToNode,
|
||||
cap:
|
||||
artifact?.additionalData?.type === 'cap'
|
||||
? artifact.additionalData.info
|
||||
: 'none',
|
||||
faceId: _entity_id,
|
||||
},
|
||||
})
|
||||
return
|
||||
},
|
||||
})
|
||||
}
|
||||
mouseEnterLeaveCallbacks() {
|
||||
return {
|
||||
onMouseEnter: ({ selected, dragSelected }: OnMouseEnterLeaveArgs) => {
|
||||
@ -1863,6 +1588,7 @@ export function sketchGroupFromPathToNode({
|
||||
return result as SketchGroup
|
||||
}
|
||||
|
||||
// TODO delete
|
||||
function colorSegment(object: any, color: number) {
|
||||
const segmentHead = getParentGroup(object, [ARROWHEAD, PROFILE_START])
|
||||
if (segmentHead) {
|
||||
|
@ -1,25 +1,25 @@
|
||||
import {
|
||||
AmbientLight,
|
||||
Color,
|
||||
GridHelper,
|
||||
LineBasicMaterial,
|
||||
OrthographicCamera,
|
||||
PerspectiveCamera,
|
||||
Scene,
|
||||
Vector3,
|
||||
WebGLRenderer,
|
||||
Raycaster,
|
||||
Vector2,
|
||||
Group,
|
||||
PlaneGeometry,
|
||||
MeshBasicMaterial,
|
||||
Mesh,
|
||||
DoubleSide,
|
||||
GridHelper,
|
||||
Group,
|
||||
Intersection,
|
||||
LineBasicMaterial,
|
||||
Mesh,
|
||||
MeshBasicMaterial,
|
||||
Object3D,
|
||||
Object3DEventMap,
|
||||
TextureLoader,
|
||||
OrthographicCamera,
|
||||
PerspectiveCamera,
|
||||
PlaneGeometry,
|
||||
Raycaster,
|
||||
Scene,
|
||||
Texture,
|
||||
TextureLoader,
|
||||
Vector2,
|
||||
Vector3,
|
||||
WebGLRenderer,
|
||||
} from 'three'
|
||||
import { Coords2d, compareVec2Epsilon2 } from 'lang/std/sketch'
|
||||
import { useModelingContext } from 'hooks/useModelingContext'
|
||||
@ -31,6 +31,12 @@ import { EngineCommandManager } from 'lang/std/engineConnection'
|
||||
import { MouseState, SegmentOverlayPayload } from 'machines/modelingMachine'
|
||||
import { getAngle, throttle } from 'lib/utils'
|
||||
import { Themes } from 'lib/theme'
|
||||
import {
|
||||
OnClickCallbackArgs,
|
||||
OnDragCallbackArgs,
|
||||
OnMouseEnterLeaveArgs,
|
||||
OnMoveCallbackArgs,
|
||||
} from './sceneCallbacks'
|
||||
|
||||
type SendType = ReturnType<typeof useModelingContext>['send']
|
||||
|
||||
@ -55,39 +61,6 @@ export const AXIS_GROUP = 'axisGroup'
|
||||
export const SKETCH_GROUP_SEGMENTS = 'sketch-group-segments'
|
||||
export const ARROWHEAD = 'arrowhead'
|
||||
|
||||
export interface OnMouseEnterLeaveArgs {
|
||||
selected: Object3D<Object3DEventMap>
|
||||
dragSelected?: Object3D<Object3DEventMap>
|
||||
mouseEvent: MouseEvent
|
||||
}
|
||||
|
||||
interface OnDragCallbackArgs extends OnMouseEnterLeaveArgs {
|
||||
intersectionPoint: {
|
||||
twoD: Vector2
|
||||
threeD: Vector3
|
||||
}
|
||||
intersects: Intersection<Object3D<Object3DEventMap>>[]
|
||||
}
|
||||
interface OnClickCallbackArgs {
|
||||
mouseEvent: MouseEvent
|
||||
intersectionPoint?: {
|
||||
twoD: Vector2
|
||||
threeD: Vector3
|
||||
}
|
||||
intersects: Intersection<Object3D<Object3DEventMap>>[]
|
||||
selected?: Object3D<Object3DEventMap>
|
||||
}
|
||||
|
||||
interface OnMoveCallbackArgs {
|
||||
mouseEvent: MouseEvent
|
||||
intersectionPoint: {
|
||||
twoD: Vector2
|
||||
threeD: Vector3
|
||||
}
|
||||
intersects: Intersection<Object3D<Object3DEventMap>>[]
|
||||
selected?: Object3D<Object3DEventMap>
|
||||
}
|
||||
|
||||
// This singleton class is responsible for all of the under the hood setup for the client side scene.
|
||||
// That is the cameras and switching between them, raycasters for click mouse events and their abstractions (onClick etc), setting up controls.
|
||||
// Anything that added the the scene for the user to interact with is probably in SceneEntities.ts
|
||||
@ -618,59 +591,6 @@ export class SceneInfra {
|
||||
this.onClickCallback({ mouseEvent, intersects })
|
||||
}
|
||||
}
|
||||
showDefaultPlanes() {
|
||||
const addPlane = (
|
||||
rotation: { x: number; y: number; z: number }, //
|
||||
type: DefaultPlane
|
||||
): Mesh => {
|
||||
const planeGeometry = new PlaneGeometry(100, 100)
|
||||
const planeMaterial = new MeshBasicMaterial({
|
||||
color: defaultPlaneColor(type),
|
||||
transparent: true,
|
||||
opacity: 0.0,
|
||||
side: DoubleSide,
|
||||
depthTest: false, // needed to avoid transparency issues
|
||||
})
|
||||
const plane = new Mesh(planeGeometry, planeMaterial)
|
||||
plane.rotation.x = rotation.x
|
||||
plane.rotation.y = rotation.y
|
||||
plane.rotation.z = rotation.z
|
||||
plane.userData.type = type
|
||||
plane.name = type
|
||||
return plane
|
||||
}
|
||||
const planes = [
|
||||
addPlane({ x: 0, y: Math.PI / 2, z: 0 }, YZ_PLANE),
|
||||
addPlane({ x: 0, y: 0, z: 0 }, XY_PLANE),
|
||||
addPlane({ x: -Math.PI / 2, y: 0, z: 0 }, XZ_PLANE),
|
||||
]
|
||||
const planesGroup = new Group()
|
||||
planesGroup.userData.type = DEFAULT_PLANES
|
||||
planesGroup.name = DEFAULT_PLANES
|
||||
planesGroup.add(...planes)
|
||||
planesGroup.traverse((child) => {
|
||||
if (child instanceof Mesh) {
|
||||
child.layers.enable(SKETCH_LAYER)
|
||||
}
|
||||
})
|
||||
planesGroup.layers.enable(SKETCH_LAYER)
|
||||
const sceneScale = getSceneScale(
|
||||
this.camControls.camera,
|
||||
this.camControls.target
|
||||
)
|
||||
planesGroup.scale.set(
|
||||
sceneScale / this._baseUnitMultiplier,
|
||||
sceneScale / this._baseUnitMultiplier,
|
||||
sceneScale / this._baseUnitMultiplier
|
||||
)
|
||||
this.scene.add(planesGroup)
|
||||
}
|
||||
removeDefaultPlanes() {
|
||||
const planesGroup = this.scene.children.find(
|
||||
({ userData }) => userData.type === DEFAULT_PLANES
|
||||
)
|
||||
if (planesGroup) this.scene.remove(planesGroup)
|
||||
}
|
||||
updateOtherSelectionColors = (otherSelections: Axis[]) => {
|
||||
const axisGroup = this.scene.children.find(
|
||||
({ userData }) => userData?.type === AXIS_GROUP
|
||||
@ -728,28 +648,3 @@ function baseUnitTomm(baseUnit: BaseUnit) {
|
||||
return 914.4
|
||||
}
|
||||
}
|
||||
|
||||
export type DefaultPlane =
|
||||
| 'xy-default-plane'
|
||||
| 'xz-default-plane'
|
||||
| 'yz-default-plane'
|
||||
|
||||
export const XY_PLANE: DefaultPlane = 'xy-default-plane'
|
||||
export const XZ_PLANE: DefaultPlane = 'xz-default-plane'
|
||||
export const YZ_PLANE: DefaultPlane = 'yz-default-plane'
|
||||
|
||||
export function defaultPlaneColor(
|
||||
plane: DefaultPlane,
|
||||
lowCh = 0.1,
|
||||
highCh = 0.7
|
||||
): Color {
|
||||
switch (plane) {
|
||||
case XY_PLANE:
|
||||
return new Color(highCh, lowCh, lowCh)
|
||||
case XZ_PLANE:
|
||||
return new Color(lowCh, lowCh, highCh)
|
||||
case YZ_PLANE:
|
||||
return new Color(lowCh, highCh, lowCh)
|
||||
}
|
||||
return new Color(lowCh, lowCh, lowCh)
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ export default function Gizmo() {
|
||||
<div
|
||||
ref={wrapperRef}
|
||||
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} />
|
||||
<ContextMenu
|
||||
|
@ -53,9 +53,8 @@ import {
|
||||
sketchOnExtrudedFace,
|
||||
startSketchOnDefault,
|
||||
} from 'lang/modifyAst'
|
||||
import { Program, VariableDeclaration, parse, recast } from 'lang/wasm'
|
||||
import { Program, parse, recast } from 'lang/wasm'
|
||||
import {
|
||||
getNodeFromPath,
|
||||
getNodePathFromSourceRange,
|
||||
hasExtrudableGeometry,
|
||||
isSingleCursorInPipe,
|
||||
@ -550,10 +549,8 @@ export const ModelingMachineProvider = ({
|
||||
) as [number, number, number],
|
||||
}
|
||||
},
|
||||
'Get horizontal info': async ({
|
||||
selectionRanges,
|
||||
sketchDetails,
|
||||
}): Promise<SetSelections> => {
|
||||
'Get horizontal info': async (context): Promise<SetSelections> => {
|
||||
const { selectionRanges, sketchDetails } = context
|
||||
const { modifiedAst, pathToNodeMap } =
|
||||
await applyConstraintHorzVertDistance({
|
||||
constraint: 'setHorzDistance',
|
||||
@ -567,11 +564,8 @@ export const ModelingMachineProvider = ({
|
||||
pathToNodeMap
|
||||
)
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
context
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
@ -586,10 +580,8 @@ export const ModelingMachineProvider = ({
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
'Get vertical info': async ({
|
||||
selectionRanges,
|
||||
sketchDetails,
|
||||
}): Promise<SetSelections> => {
|
||||
'Get vertical info': async (context): Promise<SetSelections> => {
|
||||
const { selectionRanges, sketchDetails } = context
|
||||
const { modifiedAst, pathToNodeMap } =
|
||||
await applyConstraintHorzVertDistance({
|
||||
constraint: 'setVertDistance',
|
||||
@ -603,11 +595,8 @@ export const ModelingMachineProvider = ({
|
||||
pathToNodeMap
|
||||
)
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
context
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
@ -622,10 +611,8 @@ export const ModelingMachineProvider = ({
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
'Get angle info': async ({
|
||||
selectionRanges,
|
||||
sketchDetails,
|
||||
}): Promise<SetSelections> => {
|
||||
'Get angle info': async (context): Promise<SetSelections> => {
|
||||
const { selectionRanges, sketchDetails } = context
|
||||
const info = angleBetweenInfo({
|
||||
selectionRanges,
|
||||
})
|
||||
@ -648,11 +635,8 @@ export const ModelingMachineProvider = ({
|
||||
pathToNodeMap
|
||||
)
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
context
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
@ -667,10 +651,8 @@ export const ModelingMachineProvider = ({
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
'Get length info': async ({
|
||||
selectionRanges,
|
||||
sketchDetails,
|
||||
}): Promise<SetSelections> => {
|
||||
'Get length info': async (context): Promise<SetSelections> => {
|
||||
const { selectionRanges, sketchDetails } = context
|
||||
const { modifiedAst, pathToNodeMap } =
|
||||
await applyConstraintAngleLength({ selectionRanges })
|
||||
const _modifiedAst = parse(recast(modifiedAst))
|
||||
@ -681,11 +663,8 @@ export const ModelingMachineProvider = ({
|
||||
pathToNodeMap
|
||||
)
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
context
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
@ -700,10 +679,10 @@ export const ModelingMachineProvider = ({
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
'Get perpendicular distance info': async ({
|
||||
selectionRanges,
|
||||
sketchDetails,
|
||||
}): Promise<SetSelections> => {
|
||||
'Get perpendicular distance info': async (
|
||||
context
|
||||
): Promise<SetSelections> => {
|
||||
const { selectionRanges, sketchDetails } = context
|
||||
const { modifiedAst, pathToNodeMap } = await applyConstraintIntersect(
|
||||
{
|
||||
selectionRanges,
|
||||
@ -717,11 +696,8 @@ export const ModelingMachineProvider = ({
|
||||
pathToNodeMap
|
||||
)
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
context
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
@ -736,10 +712,8 @@ export const ModelingMachineProvider = ({
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
'Get ABS X info': async ({
|
||||
selectionRanges,
|
||||
sketchDetails,
|
||||
}): Promise<SetSelections> => {
|
||||
'Get ABS X info': async (context): Promise<SetSelections> => {
|
||||
const { selectionRanges, sketchDetails } = context
|
||||
const { modifiedAst, pathToNodeMap } =
|
||||
await applyConstraintAbsDistance({
|
||||
constraint: 'xAbs',
|
||||
@ -753,11 +727,8 @@ export const ModelingMachineProvider = ({
|
||||
pathToNodeMap
|
||||
)
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
context
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
@ -772,10 +743,8 @@ export const ModelingMachineProvider = ({
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
'Get ABS Y info': async ({
|
||||
selectionRanges,
|
||||
sketchDetails,
|
||||
}): Promise<SetSelections> => {
|
||||
'Get ABS Y info': async (context): Promise<SetSelections> => {
|
||||
const { selectionRanges, sketchDetails } = context
|
||||
const { modifiedAst, pathToNodeMap } =
|
||||
await applyConstraintAbsDistance({
|
||||
constraint: 'yAbs',
|
||||
@ -789,11 +758,8 @@ export const ModelingMachineProvider = ({
|
||||
pathToNodeMap
|
||||
)
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
context
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
@ -809,9 +775,10 @@ export const ModelingMachineProvider = ({
|
||||
}
|
||||
},
|
||||
'Get convert to variable info': async (
|
||||
{ sketchDetails, selectionRanges },
|
||||
context,
|
||||
{ data }
|
||||
): Promise<SetSelections> => {
|
||||
const { selectionRanges, sketchDetails } = context
|
||||
if (!sketchDetails)
|
||||
return Promise.reject(new Error('No sketch details'))
|
||||
const { variableName } = await getVarNameModal({
|
||||
@ -835,11 +802,8 @@ export const ModelingMachineProvider = ({
|
||||
return Promise.reject(new Error('No path to replaced node'))
|
||||
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
pathToReplacedNode || [],
|
||||
parsed,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
context
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
|
@ -109,7 +109,6 @@ export const Stream = () => {
|
||||
},
|
||||
})
|
||||
if (state.matches('Sketch')) return
|
||||
if (state.matches('Sketch no face')) return
|
||||
|
||||
if (!context.store?.didDragInStream && butName(e).left) {
|
||||
sendSelectEventToEngine(
|
||||
|
54
src/components/UnitsMenu.tsx
Normal 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: </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>
|
||||
)
|
||||
}
|
@ -4,7 +4,7 @@ import { useModelingContext } from './useModelingContext'
|
||||
import { getEventForSelectWithPoint } from 'lib/selections'
|
||||
|
||||
export function useEngineConnectionSubscriptions() {
|
||||
const { send, context } = useModelingContext()
|
||||
const { send, state } = useModelingContext()
|
||||
|
||||
useEffect(() => {
|
||||
if (!engineCommandManager) return
|
||||
@ -29,9 +29,7 @@ export function useEngineConnectionSubscriptions() {
|
||||
const unSubClick = engineCommandManager.subscribeTo({
|
||||
event: 'select_with_point',
|
||||
callback: async (engineEvent) => {
|
||||
const event = await getEventForSelectWithPoint(engineEvent, {
|
||||
sketchEnginePathId: context.sketchEnginePathId,
|
||||
})
|
||||
const event = await getEventForSelectWithPoint(engineEvent, state)
|
||||
event && send(event)
|
||||
},
|
||||
})
|
||||
@ -39,5 +37,5 @@ export function useEngineConnectionSubscriptions() {
|
||||
unSubHover()
|
||||
unSubClick()
|
||||
}
|
||||
}, [engineCommandManager, context?.sketchEnginePathId])
|
||||
}, [engineCommandManager, state])
|
||||
}
|
||||
|
@ -185,6 +185,17 @@ const sk2 = startSketchOn('XY')
|
||||
on: expect.any(Object),
|
||||
start: expect.any(Object),
|
||||
type: 'SketchGroup',
|
||||
tags: {
|
||||
p: {
|
||||
__meta: [
|
||||
{
|
||||
sourceRange: [114, 116],
|
||||
},
|
||||
],
|
||||
type: 'TagIdentifier',
|
||||
value: 'p',
|
||||
},
|
||||
},
|
||||
value: [
|
||||
{
|
||||
type: 'ToPoint',
|
||||
@ -265,6 +276,17 @@ const sk2 = startSketchOn('XY')
|
||||
on: expect.any(Object),
|
||||
start: expect.any(Object),
|
||||
type: 'SketchGroup',
|
||||
tags: {
|
||||
o: {
|
||||
__meta: [
|
||||
{
|
||||
sourceRange: [417, 419],
|
||||
},
|
||||
],
|
||||
type: 'TagIdentifier',
|
||||
value: 'o',
|
||||
},
|
||||
},
|
||||
value: [
|
||||
{
|
||||
type: 'ToPoint',
|
||||
|
@ -155,6 +155,17 @@ const newVar = myVar + 1`
|
||||
sourceRange: [39, 63],
|
||||
},
|
||||
},
|
||||
tags: {
|
||||
myPath: {
|
||||
__meta: [
|
||||
{
|
||||
sourceRange: [109, 117],
|
||||
},
|
||||
],
|
||||
type: 'TagIdentifier',
|
||||
value: 'myPath',
|
||||
},
|
||||
},
|
||||
value: [
|
||||
{
|
||||
type: 'ToPoint',
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
engineCommandManager,
|
||||
kclManager,
|
||||
sceneEntitiesManager,
|
||||
sceneInfra,
|
||||
} from 'lib/singletons'
|
||||
import { CallExpression, SourceRange, Value, parse, recast } from 'lang/wasm'
|
||||
import { ModelingMachineEvent } from 'machines/modelingMachine'
|
||||
@ -15,6 +16,7 @@ import { Program } from 'lang/wasm'
|
||||
import {
|
||||
doesPipeHaveCallExp,
|
||||
getNodeFromPath,
|
||||
getNodePathFromSourceRange,
|
||||
hasSketchPipeBeenExtruded,
|
||||
isSingleCursorInPipe,
|
||||
} from 'lang/queryAst'
|
||||
@ -24,11 +26,15 @@ import {
|
||||
TANGENTIAL_ARC_TO_SEGMENT,
|
||||
getParentGroup,
|
||||
PROFILE_START,
|
||||
getFaceDetails,
|
||||
DefaultPlaneStr,
|
||||
} from 'clientSideScene/sceneEntities'
|
||||
import { Mesh, Object3D, Object3DEventMap } from 'three'
|
||||
import { AXIS_GROUP, X_AXIS } from 'clientSideScene/sceneInfra'
|
||||
import { PathToNodeMap } from 'lang/std/sketchcombos'
|
||||
import { err } from 'lib/trap'
|
||||
import { useModelingContext } from 'hooks/useModelingContext'
|
||||
import { ArtifactMapCommand } from 'lang/std/engineConnection'
|
||||
|
||||
export const X_AXIS_UUID = 'ad792545-7fd3-482a-a602-a93924e3055b'
|
||||
export const Y_AXIS_UUID = '680fd157-266f-4b8a-984f-cdf46b8bdf01'
|
||||
@ -62,8 +68,12 @@ export async function getEventForSelectWithPoint(
|
||||
Models['OkModelingCmdResponse_type'],
|
||||
{ type: 'select_with_point' }
|
||||
>,
|
||||
{ sketchEnginePathId }: { sketchEnginePathId?: string }
|
||||
state: ReturnType<typeof useModelingContext>['state']
|
||||
): Promise<ModelingMachineEvent | null> {
|
||||
if (state.matches('Sketch no face'))
|
||||
return handleSelectionInSketchNoFace(data?.entity_id || '')
|
||||
|
||||
// assumes XState state is `idle` from this point
|
||||
if (!data?.entity_id) {
|
||||
return {
|
||||
type: 'Set selection',
|
||||
@ -143,6 +153,128 @@ export async function getEventForSelectWithPoint(
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSelectionInSketchNoFace(
|
||||
entity_id: string
|
||||
): Promise<ModelingMachineEvent | null> {
|
||||
let _entity_id = entity_id
|
||||
if (!_entity_id) return Promise.resolve(null)
|
||||
if (
|
||||
engineCommandManager.defaultPlanes?.xy === _entity_id ||
|
||||
engineCommandManager.defaultPlanes?.xz === _entity_id ||
|
||||
engineCommandManager.defaultPlanes?.yz === _entity_id ||
|
||||
engineCommandManager.defaultPlanes?.negXy === _entity_id ||
|
||||
engineCommandManager.defaultPlanes?.negXz === _entity_id ||
|
||||
engineCommandManager.defaultPlanes?.negYz === _entity_id
|
||||
) {
|
||||
const defaultPlaneStrMap: Record<string, DefaultPlaneStr> = {
|
||||
[engineCommandManager.defaultPlanes.xy]: 'XY',
|
||||
[engineCommandManager.defaultPlanes.xz]: 'XZ',
|
||||
[engineCommandManager.defaultPlanes.yz]: 'YZ',
|
||||
[engineCommandManager.defaultPlanes.negXy]: '-XY',
|
||||
[engineCommandManager.defaultPlanes.negXz]: '-XZ',
|
||||
[engineCommandManager.defaultPlanes.negYz]: '-YZ',
|
||||
}
|
||||
// TODO can we get this information from rust land when it creates the default planes?
|
||||
// maybe returned from make_default_planes (src/wasm-lib/src/wasm.rs)
|
||||
let zAxis: [number, number, number] = [0, 0, 1]
|
||||
let yAxis: [number, number, number] = [0, 1, 0]
|
||||
|
||||
// get unit vector from camera position to target
|
||||
const camVector = sceneInfra.camControls.camera.position
|
||||
.clone()
|
||||
.sub(sceneInfra.camControls.target)
|
||||
|
||||
if (engineCommandManager.defaultPlanes?.xy === _entity_id) {
|
||||
zAxis = [0, 0, 1]
|
||||
yAxis = [0, 1, 0]
|
||||
if (camVector.z < 0) {
|
||||
zAxis = [0, 0, -1]
|
||||
_entity_id = engineCommandManager.defaultPlanes?.negXy || ''
|
||||
}
|
||||
} else if (engineCommandManager.defaultPlanes?.yz === _entity_id) {
|
||||
zAxis = [1, 0, 0]
|
||||
yAxis = [0, 0, 1]
|
||||
if (camVector.x < 0) {
|
||||
zAxis = [-1, 0, 0]
|
||||
_entity_id = engineCommandManager.defaultPlanes?.negYz || ''
|
||||
}
|
||||
} else if (engineCommandManager.defaultPlanes?.xz === _entity_id) {
|
||||
zAxis = [0, 1, 0]
|
||||
yAxis = [0, 0, 1]
|
||||
_entity_id = engineCommandManager.defaultPlanes?.negXz || ''
|
||||
if (camVector.y < 0) {
|
||||
zAxis = [0, -1, 0]
|
||||
_entity_id = engineCommandManager.defaultPlanes?.xz || ''
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'Select default plane',
|
||||
data: {
|
||||
type: 'defaultPlane',
|
||||
planeId: _entity_id,
|
||||
plane: defaultPlaneStrMap[_entity_id],
|
||||
zAxis,
|
||||
yAxis,
|
||||
},
|
||||
}
|
||||
}
|
||||
const artifact = engineCommandManager.artifactMap[_entity_id]
|
||||
// If we clicked on an extrude wall, we climb up the parent Id
|
||||
// to get the sketch profile's face ID. If we clicked on an endcap,
|
||||
// we already have it.
|
||||
const targetId =
|
||||
'additionalData' in artifact && artifact.additionalData?.type === 'cap'
|
||||
? _entity_id
|
||||
: artifact.parentId
|
||||
|
||||
// tsc cannot infer that target can have extrusions
|
||||
// from the commandType (why?) so we need to cast it
|
||||
const target = engineCommandManager.artifactMap?.[
|
||||
targetId || ''
|
||||
] as ArtifactMapCommand & { extrusions?: string[] }
|
||||
|
||||
// TODO: We get the first extrusion command ID,
|
||||
// which is fine while backend systems only support one extrusion.
|
||||
// but we need to more robustly handle resolving to the correct extrusion
|
||||
// if there are multiple.
|
||||
const extrusions =
|
||||
engineCommandManager.artifactMap?.[target?.extrusions?.[0] || '']
|
||||
|
||||
if (artifact?.commandType !== 'solid3d_get_extrusion_face_info') return null
|
||||
|
||||
const faceInfo = await getFaceDetails(_entity_id)
|
||||
if (!faceInfo?.origin || !faceInfo?.z_axis || !faceInfo?.y_axis) return null
|
||||
const { z_axis, y_axis, origin } = faceInfo
|
||||
const sketchPathToNode = getNodePathFromSourceRange(
|
||||
kclManager.ast,
|
||||
artifact.range
|
||||
)
|
||||
|
||||
const extrudePathToNode = extrusions?.range
|
||||
? getNodePathFromSourceRange(kclManager.ast, extrusions.range)
|
||||
: []
|
||||
|
||||
return {
|
||||
type: 'Select default plane',
|
||||
data: {
|
||||
type: 'extrudeFace',
|
||||
zAxis: [z_axis.x, z_axis.y, z_axis.z],
|
||||
yAxis: [y_axis.x, y_axis.y, y_axis.z],
|
||||
position: [origin.x, origin.y, origin.z].map(
|
||||
(num) => num / sceneInfra._baseUnitMultiplier
|
||||
) as [number, number, number],
|
||||
sketchPathToNode,
|
||||
extrudePathToNode,
|
||||
cap:
|
||||
artifact?.additionalData?.type === 'cap'
|
||||
? artifact.additionalData.info
|
||||
: 'none',
|
||||
faceId: _entity_id,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export function getEventForSegmentSelection(
|
||||
obj: Object3D<Object3DEventMap>
|
||||
): ModelingMachineEvent | null {
|
||||
|
@ -16,6 +16,14 @@ export const baseUnits = {
|
||||
export type BaseUnit = Models['UnitLength_type']
|
||||
|
||||
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 const toggleAsArray = ['On', 'Off'] as const
|
||||
|
8
src/wasm-lib/Cargo.lock
generated
@ -1385,7 +1385,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.1.69"
|
||||
version = "0.1.71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx",
|
||||
@ -1453,7 +1453,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-test-server"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hyper",
|
||||
@ -1466,9 +1466,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kittycad"
|
||||
version = "0.3.6"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af3de9bb4b1441f198689a9f64a8163a518377e30b348a784680e738985b95eb"
|
||||
checksum = "e1777b503442fa4666564cc3ab237d456df853a09648a4b2bb09622d25d021a5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
|
@ -69,7 +69,7 @@ members = [
|
||||
]
|
||||
|
||||
[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"
|
||||
|
||||
[[test]]
|
||||
|
@ -1,14 +1,14 @@
|
||||
[package]
|
||||
name = "kcl-test-server"
|
||||
description = "A test server for KCL"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.86"
|
||||
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"
|
||||
serde = { version = "1.0.203", features = ["derive"] }
|
||||
serde_json = "1.0.120"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-lib"
|
||||
description = "KittyCAD Language implementation and tools"
|
||||
version = "0.1.69"
|
||||
version = "0.1.71"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -1238,11 +1238,10 @@ impl CallExpression {
|
||||
}
|
||||
FunctionKind::UserDefined => {
|
||||
let func = memory.get(&fn_name, self.into())?;
|
||||
let (result, global_memory_items) =
|
||||
func.call_fn(fn_args, memory.clone(), ctx.clone()).await.map_err(|e| {
|
||||
// Add the call expression to the source ranges.
|
||||
e.add_source_ranges(vec![self.into()])
|
||||
})?;
|
||||
let result = func.call_fn(fn_args, memory.clone(), ctx.clone()).await.map_err(|e| {
|
||||
// Add the call expression to the source ranges.
|
||||
e.add_source_ranges(vec![self.into()])
|
||||
})?;
|
||||
|
||||
let result = result.ok_or_else(|| {
|
||||
KclError::UndefinedValue(KclErrorDetails {
|
||||
@ -1252,14 +1251,6 @@ impl CallExpression {
|
||||
})?;
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -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 {
|
||||
fn from(tag: &TagDeclarator) -> Self {
|
||||
CompletionItem {
|
||||
|
@ -537,17 +537,14 @@ impl std::hash::Hash for TagIdentifier {
|
||||
}
|
||||
}
|
||||
|
||||
pub type MemoryFunction = fn(
|
||||
s: Vec<MemoryItem>,
|
||||
memory: ProgramMemory,
|
||||
expression: Box<FunctionExpression>,
|
||||
metadata: Vec<Metadata>,
|
||||
ctx: ExecutorContext,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn std::future::Future<Output = Result<(Option<ProgramReturn>, HashMap<String, MemoryItem>), KclError>> + Send,
|
||||
>,
|
||||
>;
|
||||
pub type MemoryFunction =
|
||||
fn(
|
||||
s: Vec<MemoryItem>,
|
||||
memory: ProgramMemory,
|
||||
expression: Box<FunctionExpression>,
|
||||
metadata: Vec<Metadata>,
|
||||
ctx: ExecutorContext,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>> + Send>>;
|
||||
|
||||
fn force_memory_function<
|
||||
F: Fn(
|
||||
@ -556,12 +553,7 @@ fn force_memory_function<
|
||||
Box<FunctionExpression>,
|
||||
Vec<Metadata>,
|
||||
ExecutorContext,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn std::future::Future<Output = Result<(Option<ProgramReturn>, HashMap<String, MemoryItem>), KclError>>
|
||||
+ Send,
|
||||
>,
|
||||
>,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Option<ProgramReturn>, KclError>> + Send>>,
|
||||
>(
|
||||
f: F,
|
||||
) -> F {
|
||||
@ -691,11 +683,15 @@ impl MemoryItem {
|
||||
match self {
|
||||
MemoryItem::TagIdentifier(t) => Ok(*t.clone()),
|
||||
MemoryItem::UserVal(u) => {
|
||||
let name: String = self.get_json()?;
|
||||
Ok(TagIdentifier {
|
||||
value: name,
|
||||
meta: u.meta.clone(),
|
||||
})
|
||||
if let Some(identifier) = self.get_json_opt::<TagIdentifier>()? {
|
||||
Ok(identifier)
|
||||
} else {
|
||||
let name: String = self.get_json()?;
|
||||
Ok(TagIdentifier {
|
||||
value: name,
|
||||
meta: u.meta.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => Err(KclError::Semantic(KclErrorDetails {
|
||||
message: format!("Not a tag identifier: {:?}", self),
|
||||
@ -752,7 +748,7 @@ impl MemoryItem {
|
||||
args: Vec<MemoryItem>,
|
||||
memory: ProgramMemory,
|
||||
ctx: ExecutorContext,
|
||||
) -> Result<(Option<ProgramReturn>, HashMap<String, MemoryItem>), KclError> {
|
||||
) -> Result<Option<ProgramReturn>, KclError> {
|
||||
let MemoryItem::Function { func, expression, meta } = &self else {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: "not a in memory function".to_string(),
|
||||
@ -782,6 +778,9 @@ pub struct SketchGroup {
|
||||
pub on: SketchSurface,
|
||||
/// The starting path.
|
||||
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.
|
||||
#[serde(rename = "__meta")]
|
||||
pub meta: Vec<Metadata>,
|
||||
@ -1359,6 +1358,8 @@ pub struct ExecutorSettings {
|
||||
pub highlight_edges: bool,
|
||||
/// Whether or not Screen Space Ambient Occlusion (SSAO) is enabled.
|
||||
pub enable_ssao: bool,
|
||||
// Show grid?
|
||||
pub show_grid: bool,
|
||||
}
|
||||
|
||||
impl Default for ExecutorSettings {
|
||||
@ -1367,6 +1368,7 @@ impl Default for ExecutorSettings {
|
||||
units: Default::default(),
|
||||
highlight_edges: true,
|
||||
enable_ssao: false,
|
||||
show_grid: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1377,6 +1379,7 @@ impl From<crate::settings::types::Configuration> for ExecutorSettings {
|
||||
units: config.settings.modeling.base_unit,
|
||||
highlight_edges: config.settings.modeling.highlight_edges.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,
|
||||
highlight_edges: config.settings.modeling.highlight_edges.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,
|
||||
highlight_edges: modeling.highlight_edges.into(),
|
||||
enable_ssao: modeling.enable_ssao.into(),
|
||||
show_grid: modeling.show_scale_grid,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1415,6 +1420,7 @@ impl ExecutorContext {
|
||||
} else {
|
||||
None
|
||||
},
|
||||
if settings.show_grid { Some(true) } else { None },
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
@ -1478,6 +1484,7 @@ impl ExecutorContext {
|
||||
units,
|
||||
highlight_edges: true,
|
||||
enable_ssao: false,
|
||||
show_grid: false,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
@ -1564,16 +1571,7 @@ impl ExecutorContext {
|
||||
}
|
||||
FunctionKind::UserDefined => {
|
||||
if let Some(func) = memory.clone().root.get(&fn_name) {
|
||||
let (result, global_memory_items) =
|
||||
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();
|
||||
}
|
||||
let result = func.call_fn(args.clone(), memory.clone(), self.clone()).await?;
|
||||
|
||||
memory.return_ = result;
|
||||
} else {
|
||||
@ -1698,7 +1696,7 @@ impl ExecutorContext {
|
||||
.inner_execute(&function_expression.body, &mut fn_memory, BodyType::Block)
|
||||
.await?;
|
||||
|
||||
Ok((result.return_, fn_memory.get_tags()))
|
||||
Ok(result.return_)
|
||||
})
|
||||
},
|
||||
);
|
||||
|
@ -1,5 +1,3 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use schemars::JsonSchema;
|
||||
|
||||
use crate::{
|
||||
@ -18,10 +16,7 @@ pub struct FunctionParam<'a> {
|
||||
}
|
||||
|
||||
impl<'a> FunctionParam<'a> {
|
||||
pub async fn call(
|
||||
&self,
|
||||
args: Vec<MemoryItem>,
|
||||
) -> Result<(Option<ProgramReturn>, HashMap<String, MemoryItem>), KclError> {
|
||||
pub async fn call(&self, args: Vec<MemoryItem>) -> Result<Option<ProgramReturn>, KclError> {
|
||||
(self.inner)(
|
||||
args,
|
||||
self.memory.clone(),
|
||||
|
@ -1542,6 +1542,7 @@ fn fn_call(i: TokenSlice) -> PResult<CallExpression> {
|
||||
// Replace the literal with the tag.
|
||||
args[i] = Value::Identifier(Box::new(tag));
|
||||
}
|
||||
Value::MemberExpression(_) => {}
|
||||
e => {
|
||||
return Err(ErrMode::Cut(
|
||||
KclError::Syntax(KclErrorDetails {
|
||||
|
@ -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 mut extrude_groups = Vec::new();
|
||||
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(
|
||||
id,
|
||||
kittycad::types::ModelingCmd::Extrude {
|
||||
|
@ -207,7 +207,7 @@ async fn make_transform<'a>(
|
||||
meta: vec![source_range.into()],
|
||||
});
|
||||
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.
|
||||
let source_ranges = vec![source_range];
|
||||
|
@ -1,5 +1,7 @@
|
||||
//! Functions related to sketching.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::Result;
|
||||
use derive_docs::stdlib;
|
||||
use kittycad::types::{Angle, ModelingCmd, Point3D};
|
||||
@ -127,6 +129,11 @@ async fn inner_line_to(
|
||||
)
|
||||
.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 {
|
||||
base: BasePath {
|
||||
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);
|
||||
|
||||
Ok(new_sketch_group)
|
||||
@ -291,6 +297,11 @@ async fn inner_line(
|
||||
)
|
||||
.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 {
|
||||
base: BasePath {
|
||||
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);
|
||||
|
||||
Ok(new_sketch_group)
|
||||
@ -455,18 +465,6 @@ async fn inner_angled_line(
|
||||
|
||||
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(
|
||||
id,
|
||||
ModelingCmd::ExtendPath {
|
||||
@ -484,6 +482,22 @@ async fn inner_angled_line(
|
||||
.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 {
|
||||
base: BasePath {
|
||||
from: from.into(),
|
||||
to,
|
||||
tag,
|
||||
geo_meta: GeoMeta {
|
||||
id,
|
||||
metadata: args.source_range.into(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
new_sketch_group.value.push(current_path);
|
||||
Ok(new_sketch_group)
|
||||
}
|
||||
@ -1206,7 +1220,7 @@ pub(crate) async fn inner_start_profile_at(
|
||||
let current_path = BasePath {
|
||||
from: to,
|
||||
to,
|
||||
tag,
|
||||
tag: tag.clone(),
|
||||
geo_meta: GeoMeta {
|
||||
id,
|
||||
metadata: args.source_range.into(),
|
||||
@ -1219,6 +1233,11 @@ pub(crate) async fn inner_start_profile_at(
|
||||
value: vec![],
|
||||
start: current_path,
|
||||
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))
|
||||
}
|
||||
@ -1353,6 +1372,9 @@ pub(crate) async fn inner_close(
|
||||
}
|
||||
|
||||
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 {
|
||||
base: BasePath {
|
||||
from: from.into(),
|
||||
@ -1461,6 +1483,11 @@ pub(crate) async fn inner_arc(
|
||||
)
|
||||
.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 {
|
||||
base: BasePath {
|
||||
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);
|
||||
|
||||
Ok(new_sketch_group)
|
||||
@ -1567,6 +1593,11 @@ async fn inner_tangential_arc(
|
||||
|
||||
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 {
|
||||
base: BasePath {
|
||||
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);
|
||||
|
||||
Ok(new_sketch_group)
|
||||
@ -1671,6 +1701,11 @@ async fn inner_tangential_arc_to(
|
||||
let id = uuid::Uuid::new_v4();
|
||||
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 {
|
||||
base: BasePath {
|
||||
from: from.into(),
|
||||
@ -1685,7 +1720,6 @@ async fn inner_tangential_arc_to(
|
||||
ccw: result.ccw > 0,
|
||||
};
|
||||
|
||||
let mut new_sketch_group = sketch_group.clone();
|
||||
new_sketch_group.value.push(current_path);
|
||||
|
||||
Ok(new_sketch_group)
|
||||
@ -1772,6 +1806,11 @@ async fn inner_bezier_curve(
|
||||
)
|
||||
.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 {
|
||||
base: BasePath {
|
||||
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);
|
||||
|
||||
Ok(new_sketch_group)
|
||||
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 114 KiB |
@ -1,6 +1,7 @@
|
||||
// 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
|
||||
|
||||
|
||||
// define constants in mm
|
||||
const radius = 6.0
|
||||
const width = 144.0
|
||||
@ -16,10 +17,10 @@ const tabThk = 4
|
||||
fn rectShape = (pos, w, l) => {
|
||||
const rr = startSketchOn('xy')
|
||||
|> 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], %, "edge02")
|
||||
|> lineTo([pos[0] - (w / 2), pos[1] + l / 2], %, "edge03")
|
||||
|> close(%, "edge04")
|
||||
|> 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], %, $edge03)
|
||||
|> close(%, $edge04)
|
||||
return rr
|
||||
}
|
||||
|
||||
@ -37,27 +38,28 @@ const bracketPlane = {
|
||||
fn bracketSketch = (w, d, t) => {
|
||||
const s = startSketchOn(bracketPlane)
|
||||
|> startProfileAt([-w / 2 - t, d + t], %)
|
||||
|> lineTo([-w / 2 - t, -t], %, "edge1")
|
||||
|> lineTo([w / 2 + t, -t], %, "edge2")
|
||||
|> lineTo([w / 2 + t, d + t], %, "edge3")
|
||||
|> lineTo([w / 2, d + t], %, "edge4")
|
||||
|> lineTo([w / 2, 0], %, "edge5")
|
||||
|> lineTo([-w / 2, 0], %, "edge6")
|
||||
|> lineTo([-w / 2, d + t], %, "edge7")
|
||||
|> close(%, "edge8")
|
||||
|> lineTo([-w / 2 - t, -t], %, $edge1)
|
||||
|> lineTo([w / 2 + t, -t], %, $edge2)
|
||||
|> lineTo([w / 2 + t, d + t], %, $edge3)
|
||||
|> lineTo([w / 2, d + t], %, $edge4)
|
||||
|> lineTo([w / 2, 0], %, $edge5)
|
||||
|> lineTo([-w / 2, 0], %, $edge6)
|
||||
|> lineTo([-w / 2, d + t], %, $edge7)
|
||||
|> close(%, $edge8)
|
||||
return s
|
||||
}
|
||||
|
||||
// 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, %)
|
||||
|> fillet({
|
||||
radius: radius,
|
||||
tags: [
|
||||
getNextAdjacentEdge("edge7", %),
|
||||
getNextAdjacentEdge("edge2", %),
|
||||
getNextAdjacentEdge("edge3", %),
|
||||
getNextAdjacentEdge("edge6", %)
|
||||
getNextAdjacentEdge(bs.tags.edge7, %),
|
||||
getNextAdjacentEdge(bs.tags.edge2, %),
|
||||
getNextAdjacentEdge(bs.tags.edge3, %),
|
||||
getNextAdjacentEdge(bs.tags.edge6, %)
|
||||
]
|
||||
}, %)
|
||||
|
||||
@ -74,10 +76,10 @@ const tabPlane = {
|
||||
// build the tabs of the mounting bracket (right side)
|
||||
const tabsR = startSketchOn(tabPlane)
|
||||
|> startProfileAt([width / 2 + thk, length / 2 + thk], %)
|
||||
|> line([tabWidth, -tabLength / 3], %, "edge11")
|
||||
|> line([0, -tabLength / 3 * 2], %, "edge12")
|
||||
|> line([-tabWidth, -tabLength / 3], %, "edge13")
|
||||
|> close(%, "edge14")
|
||||
|> line([tabWidth, -tabLength / 3], %, $edge11)
|
||||
|> line([0, -tabLength / 3 * 2], %, $edge12)
|
||||
|> line([-tabWidth, -tabLength / 3], %, $edge13)
|
||||
|> close(%, $edge14)
|
||||
|> hole(circle([
|
||||
width / 2 + thk + tabWidth / 2,
|
||||
length / 2 + thk - (tabLength / (3 / 2))
|
||||
@ -86,8 +88,8 @@ const tabsR = startSketchOn(tabPlane)
|
||||
|> fillet({
|
||||
radius: holeDiam / 2,
|
||||
tags: [
|
||||
getNextAdjacentEdge("edge12", %),
|
||||
getNextAdjacentEdge("edge13", %)
|
||||
getNextAdjacentEdge(edge12, %),
|
||||
getNextAdjacentEdge(edge13, %)
|
||||
]
|
||||
}, %)
|
||||
|> patternLinear3d({
|
||||
@ -99,10 +101,10 @@ const tabsR = startSketchOn(tabPlane)
|
||||
// build the tabs of the mounting bracket (left side)
|
||||
const tabsL = startSketchOn(tabPlane)
|
||||
|> startProfileAt([-width / 2 - thk, length / 2 + thk], %)
|
||||
|> line([-tabWidth, -tabLength / 3], %, "edge21")
|
||||
|> line([0, -tabLength / 3 * 2], %, "edge22")
|
||||
|> line([tabWidth, -tabLength / 3], %, "edge23")
|
||||
|> close(%, "edge24")
|
||||
|> line([-tabWidth, -tabLength / 3], %, $edge21)
|
||||
|> line([0, -tabLength / 3 * 2], %, $edge22)
|
||||
|> line([tabWidth, -tabLength / 3], %, $edge23)
|
||||
|> close(%, $edge24)
|
||||
|> hole(circle([
|
||||
-width / 2 - thk - (tabWidth / 2),
|
||||
length / 2 + thk - (tabLength / (3 / 2))
|
||||
@ -111,8 +113,8 @@ const tabsL = startSketchOn(tabPlane)
|
||||
|> fillet({
|
||||
radius: holeDiam / 2,
|
||||
tags: [
|
||||
getNextAdjacentEdge("edge21", %),
|
||||
getNextAdjacentEdge("edge22", %)
|
||||
getNextAdjacentEdge(edge21, %),
|
||||
getNextAdjacentEdge(edge22, %)
|
||||
]
|
||||
}, %)
|
||||
|> patternLinear3d({
|
||||
|
@ -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)
|