Compare commits
29 Commits
franknoiro
...
achalmers/
| Author | SHA1 | Date | |
|---|---|---|---|
| 921bf2aa47 | |||
| 925d8df3d5 | |||
| 0568663ff4 | |||
| 2a85ea26ad | |||
| 94b6ad2e68 | |||
| 5274ae80db | |||
| d5475eab81 | |||
| 38c1278948 | |||
| 6595fca000 | |||
| 8b0b5a0215 | |||
| 2263958fd0 | |||
| 66e60f2ddb | |||
| 5f51a0f569 | |||
| aee1d66e56 | |||
| 1d1bb8cee0 | |||
| c7dd89e720 | |||
| 9860294eb1 | |||
| 1c393bfa84 | |||
| 95ea1427bc | |||
| f1b0e40388 | |||
| 7848d63177 | |||
| 619b059ae1 | |||
| 429fc3eb1b | |||
| 615f661cbb | |||
| 6e0675cfda | |||
| 3e79b90884 | |||
| 5a0a635995 | |||
| 93d9b10e11 | |||
| 166487433c |
2
.github/workflows/playwright.yml
vendored
2
.github/workflows/playwright.yml
vendored
@ -263,7 +263,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, windows-latest, macos-14]
|
os: [ubuntu-latest, windows-latest, macos-14]
|
||||||
timeout-minutes: 40
|
timeout-minutes: 60
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
needs: check-rust-changes
|
needs: check-rust-changes
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@ -270,6 +270,26 @@ const extrusion = extrude(5, sketch001)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -479,6 +499,26 @@ const extrusion = extrude(5, sketch001)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -274,6 +274,26 @@ const extrusion = extrude(5, sketch001)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -483,6 +503,26 @@ const extrusion = extrude(5, sketch001)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -189,6 +189,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -398,6 +418,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -609,6 +649,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -818,6 +878,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -188,6 +188,26 @@ const extrusion = extrude(10, sketch001)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -397,6 +417,26 @@ const extrusion = extrude(10, sketch001)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -608,6 +648,26 @@ const extrusion = extrude(10, sketch001)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -817,6 +877,26 @@ const extrusion = extrude(10, sketch001)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -190,6 +190,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -399,6 +419,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -610,6 +650,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -819,6 +879,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -282,6 +282,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -491,6 +511,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -702,6 +742,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -911,6 +971,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -187,6 +187,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -396,6 +416,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -607,6 +647,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -816,6 +876,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -187,6 +187,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -396,6 +416,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -607,6 +647,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -816,6 +876,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -200,6 +200,26 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -409,6 +429,26 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -620,6 +660,26 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -829,6 +889,26 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -182,6 +182,26 @@ decagon(5.0)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -391,6 +411,26 @@ decagon(5.0)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -594,6 +634,26 @@ decagon(5.0)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -803,6 +863,26 @@ decagon(5.0)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -193,6 +193,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -402,6 +422,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -613,6 +653,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -822,6 +882,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -448,6 +448,26 @@ const sketch001 = startSketchOn(part001, chamfer1)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -852,6 +872,26 @@ const sketch001 = startSketchOn(part001, chamfer1)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -9,14 +9,14 @@ Construct a 2-dimensional circle, of the specified radius, centered at
|
|||||||
the provided (x, y) origin point.
|
the provided (x, y) origin point.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
circle(center: [number], radius: number, sketch_surface_or_group: SketchSurfaceOrGroup, tag?: TagDeclarator) -> SketchGroup
|
circle(data: CircleData, sketch_surface_or_group: SketchSurfaceOrGroup, tag?: TagDeclarator) -> SketchGroup
|
||||||
```
|
```
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const exampleSketch = startSketchOn("-XZ")
|
const exampleSketch = startSketchOn("-XZ")
|
||||||
|> circle([0, 0], 10, %)
|
|> circle({ center: [0, 0], radius: 10 }, %)
|
||||||
|
|
||||||
const example = extrude(5, exampleSketch)
|
const example = extrude(5, exampleSketch)
|
||||||
```
|
```
|
||||||
@ -30,7 +30,7 @@ const exampleSketch = startSketchOn("XZ")
|
|||||||
|> line([0, 30], %)
|
|> line([0, 30], %)
|
||||||
|> line([-30, 0], %)
|
|> line([-30, 0], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> hole(circle([0, 15], 5, %), %)
|
|> hole(circle({ center: [0, 15], radius: 5 }, %), %)
|
||||||
|
|
||||||
const example = extrude(5, exampleSketch)
|
const example = extrude(5, exampleSketch)
|
||||||
```
|
```
|
||||||
@ -39,8 +39,15 @@ const example = extrude(5, exampleSketch)
|
|||||||
|
|
||||||
### Arguments
|
### Arguments
|
||||||
|
|
||||||
* `center`: `[number]` (REQUIRED)
|
* `data`: `CircleData` - Data for drawing an circle (REQUIRED)
|
||||||
* `radius`: `number` (REQUIRED)
|
```js
|
||||||
|
{
|
||||||
|
// The center of the circle.
|
||||||
|
center: [number, number],
|
||||||
|
// The circle radius
|
||||||
|
radius: number,
|
||||||
|
}
|
||||||
|
```
|
||||||
* `sketch_surface_or_group`: `SketchSurfaceOrGroup` - A sketch surface or a sketch group. (REQUIRED)
|
* `sketch_surface_or_group`: `SketchSurfaceOrGroup` - A sketch surface or a sketch group. (REQUIRED)
|
||||||
```js
|
```js
|
||||||
{
|
{
|
||||||
@ -186,6 +193,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -562,6 +589,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -773,6 +820,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -982,6 +1049,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -188,6 +188,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -397,6 +417,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -608,6 +648,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -817,6 +877,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -213,6 +213,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -423,6 +443,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -753,6 +793,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -445,6 +445,26 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -849,6 +869,26 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -16,7 +16,7 @@ helix(data: HelixData, extrude_group: ExtrudeGroup) -> ExtrudeGroup
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const part001 = startSketchOn('XY')
|
const part001 = startSketchOn('XY')
|
||||||
|> circle([5, 5], 10, %)
|
|> circle({ center: [5, 5], radius: 10 }, %)
|
||||||
|> extrude(10, %)
|
|> extrude(10, %)
|
||||||
|> helix({
|
|> helix({
|
||||||
angleStart: 0,
|
angleStart: 0,
|
||||||
@ -316,6 +316,26 @@ const part001 = startSketchOn('XY')
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -711,6 +731,26 @@ const part001 = startSketchOn('XY')
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
126
docs/kcl/hole.md
126
docs/kcl/hole.md
@ -21,8 +21,8 @@ const exampleSketch = startSketchOn('XY')
|
|||||||
|> line([5, 0], %)
|
|> line([5, 0], %)
|
||||||
|> line([0, -5], %)
|
|> line([0, -5], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> hole(circle([1, 1], .25, %), %)
|
|> hole(circle({ center: [1, 1], radius: .25 }, %), %)
|
||||||
|> hole(circle([1, 4], .25, %), %)
|
|> hole(circle({ center: [1, 4], radius: .25 }, %), %)
|
||||||
|
|
||||||
const example = extrude(1, exampleSketch)
|
const example = extrude(1, exampleSketch)
|
||||||
```
|
```
|
||||||
@ -41,7 +41,7 @@ fn squareHoleSketch = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const exampleSketch = startSketchOn('-XZ')
|
const exampleSketch = startSketchOn('-XZ')
|
||||||
|> circle([0, 0], 3, %)
|
|> circle({ center: [0, 0], radius: 3 }, %)
|
||||||
|> hole(squareHoleSketch(), %)
|
|> hole(squareHoleSketch(), %)
|
||||||
const example = extrude(1, exampleSketch)
|
const example = extrude(1, exampleSketch)
|
||||||
```
|
```
|
||||||
@ -199,6 +199,26 @@ const example = extrude(1, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -409,6 +429,26 @@ const example = extrude(1, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -611,6 +651,26 @@ const example = extrude(1, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -820,6 +880,26 @@ const example = extrude(1, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -1022,6 +1102,26 @@ const example = extrude(1, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -1231,6 +1331,26 @@ const example = extrude(1, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -54,11 +54,17 @@ const case = startSketchOn('-XZ')
|
|||||||
|> extrude(65, %)
|
|> extrude(65, %)
|
||||||
|
|
||||||
const thing1 = startSketchOn(case, 'end')
|
const thing1 = startSketchOn(case, 'end')
|
||||||
|> circle([-size / 2, -size / 2], 25, %)
|
|> circle({
|
||||||
|
center: [-size / 2, -size / 2],
|
||||||
|
radius: 25
|
||||||
|
}, %)
|
||||||
|> extrude(50, %)
|
|> extrude(50, %)
|
||||||
|
|
||||||
const thing2 = startSketchOn(case, 'end')
|
const thing2 = startSketchOn(case, 'end')
|
||||||
|> circle([size / 2, -size / 2], 25, %)
|
|> circle({
|
||||||
|
center: [size / 2, -size / 2],
|
||||||
|
radius: 25
|
||||||
|
}, %)
|
||||||
|> extrude(50, %)
|
|> extrude(50, %)
|
||||||
|
|
||||||
hollow(0.5, case)
|
hollow(0.5, case)
|
||||||
@ -343,6 +349,26 @@ hollow(0.5, case)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -738,6 +764,26 @@ hollow(0.5, case)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -21,7 +21,7 @@ int(num: number) -> i64
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const sketch001 = startSketchOn('XZ')
|
const sketch001 = startSketchOn('XZ')
|
||||||
|> circle([0, 0], 2, %)
|
|> circle({ center: [0, 0], radius: 2 }, %)
|
||||||
const extrude001 = extrude(5, sketch001)
|
const extrude001 = extrude(5, sketch001)
|
||||||
|
|
||||||
const pattern01 = patternTransform(int(ceil(5 / 2)), (id) => {
|
const pattern01 = patternTransform(int(ceil(5 / 2)), (id) => {
|
||||||
|
|||||||
@ -179,6 +179,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -388,6 +408,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -179,6 +179,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -388,6 +408,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -192,6 +192,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -401,6 +421,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -612,6 +652,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -821,6 +881,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -179,6 +179,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -388,6 +408,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -599,6 +639,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -808,6 +868,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -197,6 +197,26 @@ const example = extrude(1, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -407,6 +427,26 @@ const example = extrude(1, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -16,7 +16,7 @@ patternCircular3d(data: CircularPattern3dData, extrude_group_set: ExtrudeGroupSe
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const exampleSketch = startSketchOn('XZ')
|
const exampleSketch = startSketchOn('XZ')
|
||||||
|> circle([0, 0], 1, %)
|
|> circle({ center: [0, 0], radius: 1 }, %)
|
||||||
|
|
||||||
const example = extrude(-5, exampleSketch)
|
const example = extrude(-5, exampleSketch)
|
||||||
|> patternCircular3d({
|
|> patternCircular3d({
|
||||||
@ -321,6 +321,26 @@ const example = extrude(-5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -16,7 +16,7 @@ patternLinear2d(data: LinearPattern2dData, sketch_group_set: SketchGroupSet) ->
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
const exampleSketch = startSketchOn('XZ')
|
const exampleSketch = startSketchOn('XZ')
|
||||||
|> circle([0, 0], 1, %)
|
|> circle({ center: [0, 0], radius: 1 }, %)
|
||||||
|> patternLinear2d({
|
|> patternLinear2d({
|
||||||
axis: [1, 0],
|
axis: [1, 0],
|
||||||
repetitions: 6,
|
repetitions: 6,
|
||||||
@ -190,6 +190,26 @@ const example = extrude(1, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -400,6 +420,26 @@ const example = extrude(1, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -319,6 +319,26 @@ const example = extrude(1, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -32,7 +32,7 @@ fn transform = (replicaId) => {
|
|||||||
fn layer = () => {
|
fn layer = () => {
|
||||||
return startSketchOn("XY")
|
return startSketchOn("XY")
|
||||||
// or some other plane idk
|
// or some other plane idk
|
||||||
|> circle([0, 0], 1, %, $tag1)
|
|> circle({ center: [0, 0], radius: 1 }, %, $tag1)
|
||||||
|> extrude(h, %)
|
|> extrude(h, %)
|
||||||
}
|
}
|
||||||
// The vase is 100 layers tall.
|
// The vase is 100 layers tall.
|
||||||
@ -321,6 +321,26 @@ let vase = layer()
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -22,7 +22,10 @@ pi() -> number
|
|||||||
const circumference = 70
|
const circumference = 70
|
||||||
|
|
||||||
const exampleSketch = startSketchOn("XZ")
|
const exampleSketch = startSketchOn("XZ")
|
||||||
|> circle([0, 0], circumference / (2 * pi()), %)
|
|> circle({
|
||||||
|
center: [0, 0],
|
||||||
|
radius: circumference / (2 * pi())
|
||||||
|
}, %)
|
||||||
|
|
||||||
const example = extrude(5, exampleSketch)
|
const example = extrude(5, exampleSketch)
|
||||||
```
|
```
|
||||||
|
|||||||
@ -180,6 +180,26 @@ const sketch001 = startSketchOn('XY')
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -389,6 +409,26 @@ const sketch001 = startSketchOn('XY')
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -93,11 +93,17 @@ const case = startSketchOn('-XZ')
|
|||||||
|> extrude(65, %)
|
|> extrude(65, %)
|
||||||
|
|
||||||
const thing1 = startSketchOn(case, 'end')
|
const thing1 = startSketchOn(case, 'end')
|
||||||
|> circle([-size / 2, -size / 2], 25, %)
|
|> circle({
|
||||||
|
center: [-size / 2, -size / 2],
|
||||||
|
radius: 25
|
||||||
|
}, %)
|
||||||
|> extrude(50, %)
|
|> extrude(50, %)
|
||||||
|
|
||||||
const thing2 = startSketchOn(case, 'end')
|
const thing2 = startSketchOn(case, 'end')
|
||||||
|> circle([size / 2, -size / 2], 25, %)
|
|> circle({
|
||||||
|
center: [size / 2, -size / 2],
|
||||||
|
radius: 25
|
||||||
|
}, %)
|
||||||
|> extrude(50, %)
|
|> extrude(50, %)
|
||||||
|
|
||||||
// We put "case" in the shell function to shell the entire object.
|
// We put "case" in the shell function to shell the entire object.
|
||||||
@ -118,11 +124,17 @@ const case = startSketchOn('XY')
|
|||||||
|> extrude(65, %)
|
|> extrude(65, %)
|
||||||
|
|
||||||
const thing1 = startSketchOn(case, 'end')
|
const thing1 = startSketchOn(case, 'end')
|
||||||
|> circle([-size / 2, -size / 2], 25, %)
|
|> circle({
|
||||||
|
center: [-size / 2, -size / 2],
|
||||||
|
radius: 25
|
||||||
|
}, %)
|
||||||
|> extrude(50, %)
|
|> extrude(50, %)
|
||||||
|
|
||||||
const thing2 = startSketchOn(case, 'end')
|
const thing2 = startSketchOn(case, 'end')
|
||||||
|> circle([size / 2, -size / 2], 25, %)
|
|> circle({
|
||||||
|
center: [size / 2, -size / 2],
|
||||||
|
radius: 25
|
||||||
|
}, %)
|
||||||
|> extrude(50, %)
|
|> extrude(50, %)
|
||||||
|
|
||||||
// We put "thing1" in the shell function to shell the end face of the object.
|
// We put "thing1" in the shell function to shell the end face of the object.
|
||||||
@ -146,11 +158,17 @@ const case = startSketchOn('XY')
|
|||||||
|> extrude(65, %)
|
|> extrude(65, %)
|
||||||
|
|
||||||
const thing1 = startSketchOn(case, 'end')
|
const thing1 = startSketchOn(case, 'end')
|
||||||
|> circle([-size / 2, -size / 2], 25, %)
|
|> circle({
|
||||||
|
center: [-size / 2, -size / 2],
|
||||||
|
radius: 25
|
||||||
|
}, %)
|
||||||
|> extrude(50, %)
|
|> extrude(50, %)
|
||||||
|
|
||||||
const thing2 = startSketchOn(case, 'end')
|
const thing2 = startSketchOn(case, 'end')
|
||||||
|> circle([size / 2, -size / 2], 25, %)
|
|> circle({
|
||||||
|
center: [size / 2, -size / 2],
|
||||||
|
radius: 25
|
||||||
|
}, %)
|
||||||
|> extrude(50, %)
|
|> extrude(50, %)
|
||||||
|
|
||||||
// We put "thing1" and "thing2" in the shell function to shell the end face of the object.
|
// We put "thing1" and "thing2" in the shell function to shell the end face of the object.
|
||||||
@ -533,6 +551,26 @@ shell({ faces: ['end'], thickness: 5 }, [thing1, thing2])
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -932,6 +970,26 @@ shell({ faces: ['end'], thickness: 5 }, [thing1, thing2])
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -258,6 +258,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -561,6 +581,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -770,6 +810,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -205,6 +205,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -414,6 +434,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -327,6 +327,26 @@ const a1 = startSketchOn({
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -743,6 +763,26 @@ const a1 = startSketchOn({
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
18025
docs/kcl/std.json
18025
docs/kcl/std.json
File diff suppressed because it is too large
Load Diff
@ -188,6 +188,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -397,6 +417,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -608,6 +648,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -817,6 +877,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -179,6 +179,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -388,6 +408,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -599,6 +639,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -808,6 +868,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -179,6 +179,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -388,6 +408,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -599,6 +639,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -808,6 +868,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -182,6 +182,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -391,6 +411,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -602,6 +642,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -811,6 +871,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -182,6 +182,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -391,6 +411,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -602,6 +642,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -811,6 +871,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -180,6 +180,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -389,6 +409,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -600,6 +640,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -809,6 +869,26 @@ const example = extrude(10, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
@ -178,6 +178,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -387,6 +407,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -598,6 +638,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
@ -807,6 +867,26 @@ const example = extrude(5, exampleSketch)
|
|||||||
to: [number, number],
|
to: [number, number],
|
||||||
type: "TangentialArc",
|
type: "TangentialArc",
|
||||||
} |
|
} |
|
||||||
|
{
|
||||||
|
// arc's direction
|
||||||
|
ccw: bool,
|
||||||
|
// the arc's center
|
||||||
|
center: [number, number],
|
||||||
|
// The from point.
|
||||||
|
from: [number, number],
|
||||||
|
// the arc's radius
|
||||||
|
radius: number,
|
||||||
|
// The tag of the path.
|
||||||
|
tag: {
|
||||||
|
digest: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number],
|
||||||
|
end: number,
|
||||||
|
start: number,
|
||||||
|
value: string,
|
||||||
|
},
|
||||||
|
// The to point.
|
||||||
|
to: [number, number],
|
||||||
|
type: "Circle",
|
||||||
|
} |
|
||||||
{
|
{
|
||||||
// The from point.
|
// The from point.
|
||||||
from: [number, number],
|
from: [number, number],
|
||||||
|
|||||||
216
e2e/playwright/authenticatedAppFixture.ts
Normal file
216
e2e/playwright/authenticatedAppFixture.ts
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
import type { Page, Locator } from '@playwright/test'
|
||||||
|
import { expect, test as base } from '@playwright/test'
|
||||||
|
import { getUtils, setup, tearDown } from './test-utils'
|
||||||
|
import fsp from 'fs/promises'
|
||||||
|
import { join } from 'path'
|
||||||
|
|
||||||
|
type CmdBarSerilised =
|
||||||
|
| {
|
||||||
|
stage: 'commandBarClosed'
|
||||||
|
// TODO no more properties needed but needs to be implemented in _serialiseCmdBar
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
stage: 'pickCommand'
|
||||||
|
// TODO this will need more properties when implemented in _serialiseCmdBar
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
stage: 'arguments'
|
||||||
|
currentArgKey: string
|
||||||
|
currentArgValue: string
|
||||||
|
headerArguments: Record<string, string>
|
||||||
|
highlightedHeaderArg: string
|
||||||
|
commandName: string
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
stage: 'review'
|
||||||
|
headerArguments: Record<string, string>
|
||||||
|
commandName: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AuthenticatedApp {
|
||||||
|
private readonly codeContent: Locator
|
||||||
|
private readonly extrudeButton: Locator
|
||||||
|
|
||||||
|
constructor(public readonly page: Page) {
|
||||||
|
this.codeContent = page.locator('.cm-content')
|
||||||
|
this.extrudeButton = page.getByTestId('extrude')
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialise(code = '') {
|
||||||
|
const u = await getUtils(this.page)
|
||||||
|
await this.page.addInitScript(async (code) => {
|
||||||
|
localStorage.setItem('persistCode', code)
|
||||||
|
;(window as any).playwrightSkipFilePicker = true
|
||||||
|
}, code)
|
||||||
|
|
||||||
|
await this.page.setViewportSize({ width: 1000, height: 500 })
|
||||||
|
|
||||||
|
await u.waitForAuthSkipAppStart()
|
||||||
|
}
|
||||||
|
getInputFile = (fileName: string) => {
|
||||||
|
return fsp.readFile(
|
||||||
|
join('src', 'wasm-lib', 'tests', 'executor', 'inputs', fileName),
|
||||||
|
'utf-8'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
makeMouseHelpers = (x: number, y: number) => [
|
||||||
|
() => this.page.mouse.click(x, y),
|
||||||
|
() => this.page.mouse.move(x, y),
|
||||||
|
]
|
||||||
|
|
||||||
|
/** Likely no where, there's a chance it will click something in the scene, depending what you have in the scene.
|
||||||
|
*
|
||||||
|
* Expects the viewPort to be 1000x500 */
|
||||||
|
clickNoWhere = () => this.page.mouse.click(998, 60)
|
||||||
|
|
||||||
|
// Toolbars
|
||||||
|
expectExtrudeButtonToBeDisabled = async () =>
|
||||||
|
await expect(this.extrudeButton).toBeDisabled()
|
||||||
|
expectExtrudeButtonToBeEnabled = async () =>
|
||||||
|
await expect(this.extrudeButton).not.toBeDisabled()
|
||||||
|
clickExtrudeButton = async () => await this.extrudeButton.click()
|
||||||
|
|
||||||
|
private _serialiseCmdBar = async (): Promise<CmdBarSerilised> => {
|
||||||
|
const reviewForm = await this.page.locator('#review-form')
|
||||||
|
const getHeaderArgs = async () => {
|
||||||
|
const inputs = await this.page.getByTestId('cmd-bar-input-tab').all()
|
||||||
|
const entries = await Promise.all(
|
||||||
|
inputs.map((input) => {
|
||||||
|
const key = input
|
||||||
|
.locator('[data-test-name="arg-name"]')
|
||||||
|
.innerText()
|
||||||
|
.then((a) => a.trim())
|
||||||
|
const value = input
|
||||||
|
.getByTestId('header-arg-value')
|
||||||
|
.innerText()
|
||||||
|
.then((a) => a.trim())
|
||||||
|
return Promise.all([key, value])
|
||||||
|
})
|
||||||
|
)
|
||||||
|
return Object.fromEntries(entries)
|
||||||
|
}
|
||||||
|
const getCommandName = () =>
|
||||||
|
this.page.getByTestId('command-name').textContent()
|
||||||
|
if (await reviewForm.isVisible()) {
|
||||||
|
const [headerArguments, commandName] = await Promise.all([
|
||||||
|
getHeaderArgs(),
|
||||||
|
getCommandName(),
|
||||||
|
])
|
||||||
|
return {
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments,
|
||||||
|
commandName: commandName || '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const [
|
||||||
|
currentArgKey,
|
||||||
|
currentArgValue,
|
||||||
|
headerArguments,
|
||||||
|
highlightedHeaderArg,
|
||||||
|
commandName,
|
||||||
|
] = await Promise.all([
|
||||||
|
this.page.getByTestId('cmd-bar-arg-name').textContent(),
|
||||||
|
this.page.getByTestId('cmd-bar-arg-value').textContent(),
|
||||||
|
getHeaderArgs(),
|
||||||
|
this.page
|
||||||
|
.locator('[data-is-current-arg="true"]')
|
||||||
|
.locator('[data-test-name="arg-name"]')
|
||||||
|
.textContent(),
|
||||||
|
getCommandName(),
|
||||||
|
])
|
||||||
|
return {
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: currentArgKey || '',
|
||||||
|
currentArgValue: currentArgValue || '',
|
||||||
|
headerArguments,
|
||||||
|
highlightedHeaderArg: highlightedHeaderArg || '',
|
||||||
|
commandName: commandName || '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expectCmdBarToBe = async (expected: CmdBarSerilised) => {
|
||||||
|
return expect.poll(() => this._serialiseCmdBar()).toEqual(expected)
|
||||||
|
}
|
||||||
|
progressCmdBar = async () => {
|
||||||
|
if (Math.random() > 0.5) {
|
||||||
|
const arrowButton = this.page.getByRole('button', {
|
||||||
|
name: 'arrow right Continue',
|
||||||
|
})
|
||||||
|
if (await arrowButton.isVisible()) {
|
||||||
|
await arrowButton.click()
|
||||||
|
} else {
|
||||||
|
await this.page
|
||||||
|
.getByRole('button', { name: 'checkmark Submit command' })
|
||||||
|
.click()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await this.page.keyboard.press('Enter')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expectCodeHighlightedToBe = async (code: string) =>
|
||||||
|
await expect
|
||||||
|
.poll(async () => {
|
||||||
|
const texts = (
|
||||||
|
await this.page.getByTestId('hover-highlight').allInnerTexts()
|
||||||
|
).map((s) => s.replace(/\s+/g, '').trim())
|
||||||
|
return texts.join('')
|
||||||
|
})
|
||||||
|
.toBe(code.replace(/\s+/g, '').trim())
|
||||||
|
expectActiveLinesToBe = async (lines: Array<string>) => {
|
||||||
|
await expect
|
||||||
|
.poll(async () => {
|
||||||
|
return (await this.page.locator('.cm-activeLine').allInnerTexts()).map(
|
||||||
|
(l) => l.trim()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.toEqual(lines.map((l) => l.trim()))
|
||||||
|
}
|
||||||
|
private _expectEditorToContain =
|
||||||
|
(not = false) =>
|
||||||
|
(
|
||||||
|
code: string,
|
||||||
|
{
|
||||||
|
shouldNormalise = false,
|
||||||
|
timeout = 5_000,
|
||||||
|
}: { shouldNormalise?: boolean; timeout?: number } = {}
|
||||||
|
) => {
|
||||||
|
if (!shouldNormalise) {
|
||||||
|
const expectStart = expect(this.codeContent)
|
||||||
|
if (not) {
|
||||||
|
return expectStart.not.toContainText(code, { timeout })
|
||||||
|
}
|
||||||
|
return expectStart.toContainText(code, { timeout })
|
||||||
|
}
|
||||||
|
const normalisedCode = code.replaceAll(/\s+/g, ' ').trim()
|
||||||
|
const expectStart = expect.poll(() => this.codeContent.textContent(), {
|
||||||
|
timeout,
|
||||||
|
})
|
||||||
|
if (not) {
|
||||||
|
return expectStart.not.toContain(normalisedCode)
|
||||||
|
}
|
||||||
|
return expectStart.toContain(normalisedCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectEditor = {
|
||||||
|
toContain: this._expectEditorToContain(),
|
||||||
|
not: { toContain: this._expectEditorToContain(true) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const test = base.extend<{
|
||||||
|
app: AuthenticatedApp
|
||||||
|
}>({
|
||||||
|
app: async ({ page }, use) => {
|
||||||
|
const authenticatedApp = new AuthenticatedApp(page)
|
||||||
|
await use(authenticatedApp)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
test.beforeEach(async ({ context, page }, testInfo) => {
|
||||||
|
await setup(context, page, testInfo)
|
||||||
|
})
|
||||||
|
|
||||||
|
test.afterEach(async ({ page }, testInfo) => {
|
||||||
|
await tearDown(page, testInfo)
|
||||||
|
})
|
||||||
|
|
||||||
|
export { expect } from '@playwright/test'
|
||||||
@ -558,7 +558,7 @@ test.describe('Editor tests', () => {
|
|||||||
await page.keyboard.press('ArrowDown')
|
await page.keyboard.press('ArrowDown')
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
await page.keyboard.type(`const extrusion = startSketchOn('XY')
|
await page.keyboard.type(`const extrusion = startSketchOn('XY')
|
||||||
|> circle([0, 0], dia/2, %)
|
|> circle({ center: [0, 0], radius: dia/2 }, %)
|
||||||
|> hole(squareHole(length, width, height), %)
|
|> hole(squareHole(length, width, height), %)
|
||||||
|> extrude(height, %)`)
|
|> extrude(height, %)`)
|
||||||
|
|
||||||
|
|||||||
55
e2e/playwright/point-click.spec.ts
Normal file
55
e2e/playwright/point-click.spec.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { test } from './authenticatedAppFixture'
|
||||||
|
|
||||||
|
// test file is for testing point an click code gen functionality that's not sketch mode related
|
||||||
|
|
||||||
|
test('verify extruding circle works', async ({ app }) => {
|
||||||
|
test.skip(
|
||||||
|
process.platform === 'win32',
|
||||||
|
'Fails on windows in CI, can not be replicated locally on windows.'
|
||||||
|
)
|
||||||
|
const file = await app.getInputFile('test-circle-extrude.kcl')
|
||||||
|
await app.initialise(file)
|
||||||
|
const [clickCircle, moveToCircle] = app.makeMouseHelpers(582, 217)
|
||||||
|
|
||||||
|
await test.step('because there is sweepable geometry, verify extrude is enable when nothing is selected', async () => {
|
||||||
|
await app.clickNoWhere()
|
||||||
|
await app.expectExtrudeButtonToBeEnabled()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('check code model connection works and that button is still enable once circle is selected ', async () => {
|
||||||
|
await moveToCircle()
|
||||||
|
const circleSnippet =
|
||||||
|
'circle({ center: [318.33, 168.1], radius: 182.8 }, %)'
|
||||||
|
await app.expectCodeHighlightedToBe(circleSnippet)
|
||||||
|
|
||||||
|
await clickCircle()
|
||||||
|
await app.expectActiveLinesToBe([circleSnippet.slice(-5)])
|
||||||
|
await app.expectExtrudeButtonToBeEnabled()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('do extrude flow and check extrude code is added to editor', async () => {
|
||||||
|
await app.clickExtrudeButton()
|
||||||
|
|
||||||
|
await app.expectCmdBarToBe({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'distance',
|
||||||
|
currentArgValue: '5',
|
||||||
|
headerArguments: { Selection: '1 face', Distance: '' },
|
||||||
|
highlightedHeaderArg: 'distance',
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await app.progressCmdBar()
|
||||||
|
|
||||||
|
const expectString = 'const extrude001 = extrude(5, sketch001)'
|
||||||
|
await app.expectEditor.not.toContain(expectString)
|
||||||
|
|
||||||
|
await app.expectCmdBarToBe({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: { Selection: '1 face', Distance: '5' },
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await app.progressCmdBar()
|
||||||
|
|
||||||
|
await app.expectEditor.toContain(expectString)
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -537,6 +537,61 @@ const sketch001 = startSketchAt([-0, -0])
|
|||||||
await electronApp.close()
|
await electronApp.close()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
test(`View gizmo stays visible even when zoomed out all the way`, async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
|
||||||
|
// Constants and locators
|
||||||
|
const planeColor: [number, number, number] = [170, 220, 170]
|
||||||
|
const bgColor: [number, number, number] = [27, 27, 27]
|
||||||
|
const middlePixelIsColor = async (color: [number, number, number]) => {
|
||||||
|
return u.getGreatestPixDiff({ x: 600, y: 250 }, color)
|
||||||
|
}
|
||||||
|
const gizmo = page.locator('[aria-label*=gizmo]')
|
||||||
|
|
||||||
|
await test.step(`Load an empty file`, async () => {
|
||||||
|
await page.addInitScript(async () => {
|
||||||
|
localStorage.setItem('persistCode', '')
|
||||||
|
})
|
||||||
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
await u.waitForAuthSkipAppStart()
|
||||||
|
await u.closeKclCodePanel()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Zoom out until you can't see the default planes`, async () => {
|
||||||
|
await expect
|
||||||
|
.poll(async () => middlePixelIsColor(planeColor), {
|
||||||
|
timeout: 5000,
|
||||||
|
message: 'Plane color is visible',
|
||||||
|
})
|
||||||
|
.toBeLessThan(15)
|
||||||
|
|
||||||
|
let maxZoomOuts = 10
|
||||||
|
let middlePixelIsBackgroundColor =
|
||||||
|
(await middlePixelIsColor(bgColor)) < 10
|
||||||
|
while (!middlePixelIsBackgroundColor && maxZoomOuts > 0) {
|
||||||
|
await page.keyboard.down('Control')
|
||||||
|
await page.mouse.move(600, 460)
|
||||||
|
await page.mouse.down({ button: 'right' })
|
||||||
|
await page.mouse.move(600, 50, { steps: 20 })
|
||||||
|
await page.mouse.up({ button: 'right' })
|
||||||
|
await page.keyboard.up('Control')
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
maxZoomOuts--
|
||||||
|
middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 10
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(middlePixelIsBackgroundColor, {
|
||||||
|
message: 'We no longer the default planes',
|
||||||
|
}).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Check that the gizmo is still visible`, async () => {
|
||||||
|
await expect(gizmo).toBeVisible()
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
async function clickExportButton(page: Page) {
|
async function clickExportButton(page: Page) {
|
||||||
|
|||||||
@ -149,14 +149,16 @@ test.describe('Sketch tests', () => {
|
|||||||
await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await page.mouse.click(700, 200)
|
await expect(async () => {
|
||||||
|
await page.mouse.click(700, 200)
|
||||||
|
|
||||||
await expect.poll(u.normalisedEditorCode)
|
await expect.poll(u.normalisedEditorCode, { timeout: 1000 })
|
||||||
.toBe(`const sketch001 = startSketchOn('XZ')
|
.toBe(`const sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([12.34, -12.34], %)
|
|> startProfileAt([12.34, -12.34], %)
|
||||||
|> line([-12.34, 12.34], %)
|
|> line([-12.34, 12.34], %)
|
||||||
|
|
||||||
`)
|
`)
|
||||||
|
}).toPass({ timeout: 40_000, intervals: [1_000] })
|
||||||
})
|
})
|
||||||
test('Can exit selection of face', async ({ page }) => {
|
test('Can exit selection of face', async ({ page }) => {
|
||||||
// Load the app with the code panes
|
// Load the app with the code panes
|
||||||
@ -344,6 +346,92 @@ test.describe('Sketch tests', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Can edit a circle center and radius by dragging its handles', async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await page.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`const sketch001 = startSketchOn('XZ')
|
||||||
|
|> circle({ center: [4.61, -5.01], radius: 8 }, %)`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
|
||||||
|
await u.waitForAuthSkipAppStart()
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
|
).not.toBeDisabled()
|
||||||
|
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await u.openAndClearDebugPanel()
|
||||||
|
await u.sendCustomCmd({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'default_camera_look_at',
|
||||||
|
vantage: { x: 0, y: -1250, z: 580 },
|
||||||
|
center: { x: 0, y: 0, z: 0 },
|
||||||
|
up: { x: 0, y: 0, z: 1 },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await u.sendCustomCmd({
|
||||||
|
type: 'modeling_cmd_req',
|
||||||
|
cmd_id: uuidv4(),
|
||||||
|
cmd: {
|
||||||
|
type: 'default_camera_get_settings',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
|
const startPX = [667, 325]
|
||||||
|
|
||||||
|
const dragPX = 40
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByText('circle({ center: [4.61, -5.01], radius: 8 }, %)')
|
||||||
|
.click()
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', { name: 'Edit Sketch' })
|
||||||
|
).toBeVisible()
|
||||||
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
|
await page.waitForTimeout(400)
|
||||||
|
let prevContent = await page.locator('.cm-content').innerText()
|
||||||
|
|
||||||
|
await expect(page.getByTestId('segment-overlay')).toHaveCount(1)
|
||||||
|
|
||||||
|
await test.step('drag circle center handle', async () => {
|
||||||
|
await page.dragAndDrop('#stream', '#stream', {
|
||||||
|
sourcePosition: { x: startPX[0], y: startPX[1] },
|
||||||
|
targetPosition: { x: startPX[0] + dragPX, y: startPX[1] - dragPX },
|
||||||
|
})
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
prevContent = await page.locator('.cm-content').innerText()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('drag circle radius handle', async () => {
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
|
const lineEnd = await u.getBoundingBox('[data-overlay-index="0"]')
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await page.dragAndDrop('#stream', '#stream', {
|
||||||
|
sourcePosition: { x: lineEnd.x - 5, y: lineEnd.y },
|
||||||
|
targetPosition: { x: lineEnd.x + dragPX * 2, y: lineEnd.y + dragPX },
|
||||||
|
})
|
||||||
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
prevContent = await page.locator('.cm-content').innerText()
|
||||||
|
})
|
||||||
|
|
||||||
|
// expect the code to have changed
|
||||||
|
await expect(page.locator('.cm-content'))
|
||||||
|
.toHaveText(`const sketch001 = startSketchOn('XZ')
|
||||||
|
|> circle({ center: [7.26, -2.37], radius: 11.44 }, %)
|
||||||
|
`)
|
||||||
|
})
|
||||||
test('Can edit a sketch that has been extruded in the same pipe', async ({
|
test('Can edit a sketch that has been extruded in the same pipe', async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
@ -532,6 +532,64 @@ test(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
test(
|
||||||
|
'Draft circle should look right',
|
||||||
|
{ tag: '@snapshot' },
|
||||||
|
async ({ page, context }) => {
|
||||||
|
// FIXME: Skip on macos its being weird.
|
||||||
|
// test.skip(process.platform === 'darwin', 'Skip on macos')
|
||||||
|
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||||
|
|
||||||
|
await u.waitForAuthSkipAppStart()
|
||||||
|
await u.openDebugPanel()
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
|
).not.toBeDisabled()
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
|
).toBeVisible()
|
||||||
|
|
||||||
|
// click on "Start Sketch" button
|
||||||
|
await u.clearCommandLogs()
|
||||||
|
await u.doAndWaitForImageDiff(
|
||||||
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
||||||
|
200
|
||||||
|
)
|
||||||
|
|
||||||
|
// select a plane
|
||||||
|
await page.mouse.click(700, 200)
|
||||||
|
|
||||||
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
|
`const sketch001 = startSketchOn('XZ')`
|
||||||
|
)
|
||||||
|
|
||||||
|
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
|
||||||
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
|
const startXPx = 600
|
||||||
|
|
||||||
|
// Equip the rectangle tool
|
||||||
|
// await page.getByRole('button', { name: 'line Line', exact: true }).click()
|
||||||
|
await page.getByTestId('circle-center').click()
|
||||||
|
|
||||||
|
// Draw the rectangle
|
||||||
|
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
|
||||||
|
await page.mouse.move(startXPx + PUR * 10, 500 - PUR * 10, { steps: 5 })
|
||||||
|
|
||||||
|
// Ensure the draft rectangle looks the same as it usually does
|
||||||
|
await expect(page).toHaveScreenshot({
|
||||||
|
maxDiffPixels: 100,
|
||||||
|
})
|
||||||
|
await expect(page.locator('.cm-content')).toHaveText(
|
||||||
|
`const sketch001 = startSketchOn('XZ')
|
||||||
|
|> circle({ center: [14.44, -2.44], radius: 1 }, %)`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
test.describe(
|
test.describe(
|
||||||
'Client side scene scale should match engine scale',
|
'Client side scene scale should match engine scale',
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
@ -365,10 +365,10 @@ const box = startSketchOn('XY')
|
|||||||
svg(startSketchOn(keychain, 'end'), [-33, 32], -thickness)
|
svg(startSketchOn(keychain, 'end'), [-33, 32], -thickness)
|
||||||
|
|
||||||
startSketchOn(keychain, 'end')
|
startSketchOn(keychain, 'end')
|
||||||
|> circle([
|
|> circle({ center: [
|
||||||
width / 2,
|
width / 2,
|
||||||
height - (keychainHoleSize + 1.5)
|
height - (keychainHoleSize + 1.5)
|
||||||
], keychainHoleSize, %)
|
], radius: keychainHoleSize }, %)
|
||||||
|> extrude(-thickness, %)`
|
|> extrude(-thickness, %)`
|
||||||
|
|
||||||
export const TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR = `const thing = 1`
|
export const TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR = `const thing = 1`
|
||||||
|
|||||||
195
e2e/playwright/testing-samples-loading.spec.ts
Normal file
195
e2e/playwright/testing-samples-loading.spec.ts
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
import { test, expect } from '@playwright/test'
|
||||||
|
import { getUtils, setup, setupElectron, tearDown } from './test-utils'
|
||||||
|
import { bracket } from 'lib/exampleKcl'
|
||||||
|
import * as fsp from 'fs/promises'
|
||||||
|
import { join } from 'path'
|
||||||
|
import { FILE_EXT } from 'lib/constants'
|
||||||
|
|
||||||
|
test.beforeEach(async ({ context, page }, testInfo) => {
|
||||||
|
await setup(context, page, testInfo)
|
||||||
|
})
|
||||||
|
|
||||||
|
test.afterEach(async ({ page }, testInfo) => {
|
||||||
|
await tearDown(page, testInfo)
|
||||||
|
})
|
||||||
|
|
||||||
|
test.describe('Testing in-app sample loading', () => {
|
||||||
|
/**
|
||||||
|
* Note this test implicitly depends on the KCL sample "flange-with-patterns.kcl"
|
||||||
|
* and its title. https://github.com/KittyCAD/kcl-samples/blob/main/flange-with-patterns/flange-with-patterns.kcl
|
||||||
|
*/
|
||||||
|
test('Web: should overwrite current code, cannot create new file', async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
|
||||||
|
await test.step(`Test setup`, async () => {
|
||||||
|
await page.addInitScript((code) => {
|
||||||
|
window.localStorage.setItem('persistCode', code)
|
||||||
|
}, bracket)
|
||||||
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
await u.waitForAuthSkipAppStart()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Locators and constants
|
||||||
|
const newSample = {
|
||||||
|
file: 'flange-with-patterns' + FILE_EXT,
|
||||||
|
title: 'Flange',
|
||||||
|
}
|
||||||
|
const commandBarButton = page.getByRole('button', { name: 'Commands' })
|
||||||
|
const samplesCommandOption = page.getByRole('option', {
|
||||||
|
name: 'Open Sample',
|
||||||
|
})
|
||||||
|
const commandSampleOption = page.getByRole('option', {
|
||||||
|
name: newSample.title,
|
||||||
|
exact: true,
|
||||||
|
})
|
||||||
|
const commandMethodArgButton = page.getByRole('button', {
|
||||||
|
name: 'Method',
|
||||||
|
})
|
||||||
|
const commandMethodOption = (name: 'Overwrite' | 'Create new file') =>
|
||||||
|
page.getByRole('option', {
|
||||||
|
name,
|
||||||
|
})
|
||||||
|
const warningText = page.getByText('Overwrite current file?')
|
||||||
|
const confirmButton = page.getByRole('button', { name: 'Submit command' })
|
||||||
|
const codeLocator = page.locator('.cm-content')
|
||||||
|
|
||||||
|
await test.step(`Precondition: check the initial code`, async () => {
|
||||||
|
await u.openKclCodePanel()
|
||||||
|
await expect(codeLocator).toContainText(bracket.split('\n')[0])
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Load a KCL sample with the command palette`, async () => {
|
||||||
|
await commandBarButton.click()
|
||||||
|
await samplesCommandOption.click()
|
||||||
|
await commandSampleOption.click()
|
||||||
|
await commandMethodArgButton.click()
|
||||||
|
await expect(commandMethodOption('Create new file')).not.toBeVisible()
|
||||||
|
await commandMethodOption('Overwrite').click()
|
||||||
|
await expect(warningText).toBeVisible()
|
||||||
|
await confirmButton.click()
|
||||||
|
|
||||||
|
await expect(codeLocator).toContainText('// ' + newSample.title)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note this test implicitly depends on the KCL samples:
|
||||||
|
* "flange-with-patterns.kcl": https://github.com/KittyCAD/kcl-samples/blob/main/flange-with-patterns/flange-with-patterns.kcl
|
||||||
|
* "gear-rack.kcl": https://github.com/KittyCAD/kcl-samples/blob/main/gear-rack/gear-rack.kcl
|
||||||
|
*/
|
||||||
|
test(
|
||||||
|
'Desktop: should create new file by default, optionally overwrite',
|
||||||
|
{ tag: '@electron' },
|
||||||
|
async ({ browserName: _ }, testInfo) => {
|
||||||
|
const { electronApp, page, dir } = await setupElectron({
|
||||||
|
testInfo,
|
||||||
|
folderSetupFn: async (dir) => {
|
||||||
|
const bracketDir = join(dir, 'bracket')
|
||||||
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
|
await fsp.writeFile(join(bracketDir, 'main.kcl'), bracket, {
|
||||||
|
encoding: 'utf-8',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const u = await getUtils(page)
|
||||||
|
|
||||||
|
// Locators and constants
|
||||||
|
const sampleOne = {
|
||||||
|
file: 'flange-with-patterns' + FILE_EXT,
|
||||||
|
title: 'Flange',
|
||||||
|
}
|
||||||
|
const sampleTwo = {
|
||||||
|
file: 'gear-rack' + FILE_EXT,
|
||||||
|
title: '100mm Gear Rack',
|
||||||
|
}
|
||||||
|
const projectCard = page.getByRole('link', { name: 'bracket' })
|
||||||
|
const commandBarButton = page.getByRole('button', { name: 'Commands' })
|
||||||
|
const commandOption = page.getByRole('option', { name: 'Open Sample' })
|
||||||
|
const commandSampleOption = (name: string) =>
|
||||||
|
page.getByRole('option', {
|
||||||
|
name,
|
||||||
|
exact: true,
|
||||||
|
})
|
||||||
|
const commandMethodArgButton = page.getByRole('button', {
|
||||||
|
name: 'Method',
|
||||||
|
})
|
||||||
|
const commandMethodOption = page.getByRole('option', {
|
||||||
|
name: 'Overwrite',
|
||||||
|
})
|
||||||
|
const newFileWarning = page.getByText(
|
||||||
|
'Create a new file with the example code?'
|
||||||
|
)
|
||||||
|
const overwriteWarning = page.getByText('Overwrite current file?')
|
||||||
|
const confirmButton = page.getByRole('button', { name: 'Submit command' })
|
||||||
|
const projectMenuButton = page.getByTestId('project-sidebar-toggle')
|
||||||
|
const newlyCreatedFile = (name: string) =>
|
||||||
|
page.getByRole('listitem').filter({
|
||||||
|
has: page.getByRole('button', { name }),
|
||||||
|
})
|
||||||
|
const codeLocator = page.locator('.cm-content')
|
||||||
|
|
||||||
|
await test.step(`Test setup`, async () => {
|
||||||
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
await projectCard.click()
|
||||||
|
await u.waitForPageLoad()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Precondition: check the initial code`, async () => {
|
||||||
|
await u.openKclCodePanel()
|
||||||
|
await expect(codeLocator).toContainText(bracket.split('\n')[0])
|
||||||
|
await u.openFilePanel()
|
||||||
|
|
||||||
|
await expect(projectMenuButton).toContainText('main.kcl')
|
||||||
|
await expect(newlyCreatedFile(sampleOne.file)).not.toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Load a KCL sample with the command palette`, async () => {
|
||||||
|
await commandBarButton.click()
|
||||||
|
await commandOption.click()
|
||||||
|
await commandSampleOption(sampleOne.title).click()
|
||||||
|
await expect(overwriteWarning).not.toBeVisible()
|
||||||
|
await expect(newFileWarning).toBeVisible()
|
||||||
|
await confirmButton.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Ensure we made and opened a new file`, async () => {
|
||||||
|
await expect(codeLocator).toContainText('// ' + sampleOne.title)
|
||||||
|
await expect(newlyCreatedFile(sampleOne.file)).toBeVisible()
|
||||||
|
await expect(projectMenuButton).toContainText(sampleOne.file)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Now overwrite the current file`, async () => {
|
||||||
|
await commandBarButton.click()
|
||||||
|
await commandOption.click()
|
||||||
|
await commandSampleOption(sampleTwo.title).click()
|
||||||
|
await commandMethodArgButton.click()
|
||||||
|
await commandMethodOption.click()
|
||||||
|
await expect(commandMethodArgButton).toContainText('overwrite')
|
||||||
|
await expect(newFileWarning).not.toBeVisible()
|
||||||
|
await expect(overwriteWarning).toBeVisible()
|
||||||
|
await confirmButton.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Ensure we overwrote the current file without navigating`, async () => {
|
||||||
|
await expect(codeLocator).toContainText('// ' + sampleTwo.title)
|
||||||
|
await test.step(`Check actual file contents`, async () => {
|
||||||
|
await expect
|
||||||
|
.poll(async () => {
|
||||||
|
return await fsp.readFile(
|
||||||
|
join(dir, 'bracket', sampleOne.file),
|
||||||
|
'utf-8'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.toContain('// ' + sampleTwo.title)
|
||||||
|
})
|
||||||
|
await expect(newlyCreatedFile(sampleOne.file)).toBeVisible()
|
||||||
|
await expect(newlyCreatedFile(sampleTwo.file)).not.toBeVisible()
|
||||||
|
await expect(projectMenuButton).toContainText(sampleOne.file)
|
||||||
|
})
|
||||||
|
|
||||||
|
await electronApp.close()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
@ -774,6 +774,80 @@ const part001 = startSketchOn('XZ')
|
|||||||
locator: '[data-overlay-toolbar-index="12"]',
|
locator: '[data-overlay-toolbar-index="12"]',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
test('for segment [circle]', async ({ page }) => {
|
||||||
|
await page.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`const part001 = startSketchOn('XZ')
|
||||||
|
|> circle({ center: [1 + 0, 0], radius: 8 }, %)
|
||||||
|
`
|
||||||
|
)
|
||||||
|
localStorage.setItem('disableAxis', 'true')
|
||||||
|
})
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
|
||||||
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
|
// wait for execution done
|
||||||
|
await u.openDebugPanel()
|
||||||
|
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||||
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByText('circle({ center: [1 + 0, 0], radius: 8 }, %)')
|
||||||
|
.click()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
|
await expect(page.getByTestId('segment-overlay')).toHaveCount(1)
|
||||||
|
|
||||||
|
const clickUnconstrained = _clickUnconstrained(page)
|
||||||
|
const clickConstrained = _clickConstrained(page)
|
||||||
|
|
||||||
|
const hoverPos = { x: 789, y: 114 } as const
|
||||||
|
let ang = await u.getAngle('[data-overlay-index="0"]')
|
||||||
|
console.log('angl', ang)
|
||||||
|
console.log('circle center x')
|
||||||
|
await clickConstrained({
|
||||||
|
hoverPos,
|
||||||
|
constraintType: 'xAbsolute',
|
||||||
|
expectBeforeUnconstrained:
|
||||||
|
'circle({ center: [1 + 0, 0], radius: 8 }, %)',
|
||||||
|
expectAfterUnconstrained: 'circle({ center: [1, 0], radius: 8 }, %)',
|
||||||
|
expectFinal: 'circle({ center: [xAbs001, 0], radius: 8 }, %)',
|
||||||
|
ang: ang + 105,
|
||||||
|
steps: 6,
|
||||||
|
locator: '[data-overlay-toolbar-index="0"]',
|
||||||
|
})
|
||||||
|
console.log('circle center y')
|
||||||
|
await clickUnconstrained({
|
||||||
|
hoverPos,
|
||||||
|
constraintType: 'yAbsolute',
|
||||||
|
expectBeforeUnconstrained:
|
||||||
|
'circle({ center: [xAbs001, 0], radius: 8 }, %)',
|
||||||
|
expectAfterUnconstrained:
|
||||||
|
'circle({ center: [xAbs001, yAbs001], radius: 8 }, %)',
|
||||||
|
expectFinal: 'circle({ center: [xAbs001, 0], radius: 8 }, %)',
|
||||||
|
ang: ang + 105,
|
||||||
|
steps: 10,
|
||||||
|
locator: '[data-overlay-toolbar-index="0"]',
|
||||||
|
})
|
||||||
|
console.log('circle radius')
|
||||||
|
await clickUnconstrained({
|
||||||
|
hoverPos,
|
||||||
|
constraintType: 'radius',
|
||||||
|
expectBeforeUnconstrained:
|
||||||
|
'circle({ center: [xAbs001, 0], radius: 8 }, %)',
|
||||||
|
expectAfterUnconstrained:
|
||||||
|
'circle({ center: [xAbs001, 0], radius: radius001 }, %)',
|
||||||
|
expectFinal: 'circle({ center: [xAbs001, 0], radius: 8 }, %)',
|
||||||
|
ang: ang + 105,
|
||||||
|
steps: 10,
|
||||||
|
locator: '[data-overlay-toolbar-index="0"]',
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
test.describe('Testing deleting a segment', () => {
|
test.describe('Testing deleting a segment', () => {
|
||||||
const _deleteSegmentSequence =
|
const _deleteSegmentSequence =
|
||||||
|
|||||||
@ -277,8 +277,6 @@ test.describe('Testing settings', () => {
|
|||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
|
||||||
page.on('console', console.log)
|
|
||||||
|
|
||||||
// Selectors and constants
|
// Selectors and constants
|
||||||
const userThemeColor = '120'
|
const userThemeColor = '120'
|
||||||
const projectThemeColor = '50'
|
const projectThemeColor = '50'
|
||||||
@ -292,7 +290,6 @@ test.describe('Testing settings', () => {
|
|||||||
const projectLink = page.getByText('bracket')
|
const projectLink = page.getByText('bracket')
|
||||||
const logoLink = page.getByTestId('app-logo')
|
const logoLink = page.getByTestId('app-logo')
|
||||||
|
|
||||||
// Open the app and set the user theme color
|
|
||||||
await test.step('Set user theme color on home', async () => {
|
await test.step('Set user theme color on home', async () => {
|
||||||
await expect(settingsOpenButton).toBeVisible()
|
await expect(settingsOpenButton).toBeVisible()
|
||||||
await settingsOpenButton.click()
|
await settingsOpenButton.click()
|
||||||
@ -311,13 +308,15 @@ test.describe('Testing settings', () => {
|
|||||||
await expect(projectSettingsTab).toBeChecked()
|
await expect(projectSettingsTab).toBeChecked()
|
||||||
await themeColorSetting.fill(projectThemeColor)
|
await themeColorSetting.fill(projectThemeColor)
|
||||||
await expect(logoLink).toHaveCSS('--primary-hue', projectThemeColor)
|
await expect(logoLink).toHaveCSS('--primary-hue', projectThemeColor)
|
||||||
|
await settingsCloseButton.click()
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Refresh the application and see project setting applied', async () => {
|
await test.step('Refresh the application and see project setting applied', async () => {
|
||||||
|
// Make sure we're done navigating before we reload
|
||||||
|
await expect(settingsCloseButton).not.toBeVisible()
|
||||||
await page.reload({ waitUntil: 'domcontentloaded' })
|
await page.reload({ waitUntil: 'domcontentloaded' })
|
||||||
|
|
||||||
await expect(logoLink).toHaveCSS('--primary-hue', projectThemeColor)
|
await expect(logoLink).toHaveCSS('--primary-hue', projectThemeColor)
|
||||||
await settingsCloseButton.click()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Navigate back to the home view and see user setting applied`, async () => {
|
await test.step(`Navigate back to the home view and see user setting applied`, async () => {
|
||||||
|
|||||||
@ -13,9 +13,6 @@ test.afterEach(async ({ page }, testInfo) => {
|
|||||||
test('Units menu', async ({ page }) => {
|
test('Units menu', async ({ page }) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
await page.goto('/')
|
|
||||||
await page.waitForURL('**/file/**', { waitUntil: 'domcontentloaded' })
|
|
||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
const unitsMenuButton = page.getByRole('button', {
|
const unitsMenuButton = page.getByRole('button', {
|
||||||
|
|||||||
9
interface.d.ts
vendored
9
interface.d.ts
vendored
@ -10,7 +10,10 @@ export interface IElectronAPI {
|
|||||||
save: typeof dialog.showSaveDialog
|
save: typeof dialog.showSaveDialog
|
||||||
openExternal: typeof shell.openExternal
|
openExternal: typeof shell.openExternal
|
||||||
showInFolder: typeof shell.showItemInFolder
|
showInFolder: typeof shell.showItemInFolder
|
||||||
login: (host: string) => Promise<string>
|
/** Require to be called first before {@link loginWithDeviceFlow} */
|
||||||
|
startDeviceFlow: (host: string) => Promise<string>
|
||||||
|
/** Registered by first calling {@link startDeviceFlow}, which sets up the device flow handle */
|
||||||
|
loginWithDeviceFlow: () => Promise<string>
|
||||||
platform: typeof process.env.platform
|
platform: typeof process.env.platform
|
||||||
arch: typeof process.env.arch
|
arch: typeof process.env.arch
|
||||||
version: typeof process.env.version
|
version: typeof process.env.version
|
||||||
@ -60,6 +63,10 @@ export interface IElectronAPI {
|
|||||||
kittycad: (access: string, args: any) => any
|
kittycad: (access: string, args: any) => any
|
||||||
listMachines: () => Promise<MachinesListing>
|
listMachines: () => Promise<MachinesListing>
|
||||||
getMachineApiIp: () => Promise<string | null>
|
getMachineApiIp: () => Promise<string | null>
|
||||||
|
onUpdateDownloaded: (
|
||||||
|
callback: (value: string) => void
|
||||||
|
) => Electron.IpcRenderer
|
||||||
|
appRestart: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "zoo-modeling-app",
|
"name": "zoo-modeling-app",
|
||||||
"version": "0.25.2",
|
"version": "0.25.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"productName": "Zoo Modeling App",
|
"productName": "Zoo Modeling App",
|
||||||
"author": {
|
"author": {
|
||||||
@ -83,6 +83,7 @@
|
|||||||
"fmt": "prettier --write ./src *.ts *.json *.js ./e2e ./packages",
|
"fmt": "prettier --write ./src *.ts *.json *.js ./e2e ./packages",
|
||||||
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e ./packages",
|
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e ./packages",
|
||||||
"fetch:wasm": "./get-latest-wasm-bundle.sh",
|
"fetch:wasm": "./get-latest-wasm-bundle.sh",
|
||||||
|
"fetch:samples": "echo \"Fetching latest KCL samples...\" && curl -o public/kcl-samples-manifest-fallback.json https://raw.githubusercontent.com/KittyCAD/kcl-samples/main/manifest.json",
|
||||||
"isomorphic-copy-wasm": "(copy src/wasm-lib/pkg/wasm_lib_bg.wasm public || cp src/wasm-lib/pkg/wasm_lib_bg.wasm public)",
|
"isomorphic-copy-wasm": "(copy src/wasm-lib/pkg/wasm_lib_bg.wasm public || cp src/wasm-lib/pkg/wasm_lib_bg.wasm public)",
|
||||||
"build:wasm-dev": "yarn wasm-prep && (cd src/wasm-lib && wasm-pack build --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && yarn isomorphic-copy-wasm && yarn fmt",
|
"build:wasm-dev": "yarn wasm-prep && (cd src/wasm-lib && wasm-pack build --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && yarn isomorphic-copy-wasm && yarn fmt",
|
||||||
"build:wasm": "yarn wasm-prep && cd src/wasm-lib && wasm-pack build --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings && cd ../.. && yarn isomorphic-copy-wasm && yarn fmt",
|
"build:wasm": "yarn wasm-prep && cd src/wasm-lib && wasm-pack build --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings && cd ../.. && yarn isomorphic-copy-wasm && yarn fmt",
|
||||||
@ -90,7 +91,7 @@
|
|||||||
"wasm-prep": "rimraf src/wasm-lib/pkg && mkdirp src/wasm-lib/pkg && rimraf src/wasm-lib/kcl/bindings",
|
"wasm-prep": "rimraf src/wasm-lib/pkg && mkdirp src/wasm-lib/pkg && rimraf src/wasm-lib/kcl/bindings",
|
||||||
"lint": "eslint --fix src e2e packages/codemirror-lsp-client",
|
"lint": "eslint --fix src e2e packages/codemirror-lsp-client",
|
||||||
"bump-jsons": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
|
"bump-jsons": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
|
||||||
"postinstall": "yarn xstate:typegen && ./node_modules/.bin/electron-rebuild",
|
"postinstall": "yarn fetch:samples && yarn xstate:typegen && ./node_modules/.bin/electron-rebuild",
|
||||||
"xstate:typegen": "yarn xstate typegen \"src/**/*.ts?(x)\"",
|
"xstate:typegen": "yarn xstate typegen \"src/**/*.ts?(x)\"",
|
||||||
"make:dev": "make dev",
|
"make:dev": "make dev",
|
||||||
"generate:machine-api": "npx openapi-typescript ./openapi/machine-api.json -o src/lib/machine-api.d.ts",
|
"generate:machine-api": "npx openapi-typescript ./openapi/machine-api.json -o src/lib/machine-api.d.ts",
|
||||||
@ -183,7 +184,7 @@
|
|||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"ts-node": "^10.0.0",
|
"ts-node": "^10.0.0",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
"vite": "^5.4.3",
|
"vite": "^5.4.6",
|
||||||
"vite-plugin-eslint": "^1.8.1",
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
"vite-plugin-package-version": "^1.1.0",
|
"vite-plugin-package-version": "^1.1.0",
|
||||||
"vite-tsconfig-paths": "^4.3.2",
|
"vite-tsconfig-paths": "^4.3.2",
|
||||||
|
|||||||
152
public/kcl-samples-manifest-fallback.json
Normal file
152
public/kcl-samples-manifest-fallback.json
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"file": "80-20-rail.kcl",
|
||||||
|
"title": "80/20 Rail",
|
||||||
|
"description": "An 80/20 extruded aluminum linear rail. T-slot profile adjustable by profile height, rail length, and origin position"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "a-parametric-bearing-pillow-block.kcl",
|
||||||
|
"title": "A Parametric Bearing Pillow Block",
|
||||||
|
"description": "A bearing pillow block, also known as a plummer block or pillow block bearing, is a pedestal used to provide support for a rotating shaft with the help of compatible bearings and various accessories. Housing a bearing, the pillow block provides a secure and stable foundation that allows the shaft to rotate smoothly within its machinery setup. These components are essential in a wide range of mechanical systems and machinery, playing a key role in reducing friction and supporting radial and axial loads."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "ball-bearing.kcl",
|
||||||
|
"title": "Ball Bearing",
|
||||||
|
"description": "A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "bracket.kcl",
|
||||||
|
"title": "Shelf Bracket",
|
||||||
|
"description": "This is a bracket that holds a shelf. It is made of aluminum and is designed to hold a force of 300 lbs. The bracket is 6 inches wide and the force is applied at the end of the shelf, 12 inches from the wall. The bracket has a factor of safety of 1.2. The legs of the bracket are 5 inches and 2 inches long. The thickness of the bracket is calculated from the constraints provided."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "brake-caliper.kcl",
|
||||||
|
"title": "Brake Caliper",
|
||||||
|
"description": "Brake calipers are used to squeeze the brake pads against the rotor, causing larger and larger amounts of friction depending on how hard the brakes are pressed."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "car-wheel.kcl",
|
||||||
|
"title": "Car Wheel",
|
||||||
|
"description": "A sports car wheel with a circular lug pattern and spokes."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "car-wheel-assembly.kcl",
|
||||||
|
"title": "Car Wheel Assembly",
|
||||||
|
"description": "A car wheel assembly with a rotor, tire, and lug nuts."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "enclosure.kcl",
|
||||||
|
"title": "Enclosure",
|
||||||
|
"description": "An enclosure body and sealing lid for storing items"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "flange-with-patterns.kcl",
|
||||||
|
"title": "Flange",
|
||||||
|
"description": "A flange is a flat rim, collar, or rib, typically forged or cast, that is used to strengthen an object, guide it, or attach it to another object. Flanges are known for their use in various applications, including piping, plumbing, and mechanical engineering, among others."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "flange-xy.kcl",
|
||||||
|
"title": "Flange with XY coordinates",
|
||||||
|
"description": "A flange is a flat rim, collar, or rib, typically forged or cast, that is used to strengthen an object, guide it, or attach it to another object. Flanges are known for their use in various applications, including piping, plumbing, and mechanical engineering, among others."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "focusrite-scarlett-mounting-bracket.kcl",
|
||||||
|
"title": "A mounting bracket for the Focusrite Scarlett Solo audio interface",
|
||||||
|
"description": "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"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "french-press.kcl",
|
||||||
|
"title": "French Press",
|
||||||
|
"description": "A french press immersion coffee maker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "gear.kcl",
|
||||||
|
"title": "Gear",
|
||||||
|
"description": "A rotating machine part having cut teeth or, in the case of a cogwheel, inserted teeth (called cogs), which mesh with another toothed part to transmit torque. Geared devices can change the speed, torque, and direction of a power source. The two elements that define a gear are its circular shape and the teeth that are integrated into its outer edge, which are designed to fit into the teeth of another gear."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "gear-rack.kcl",
|
||||||
|
"title": "100mm Gear Rack",
|
||||||
|
"description": "A flat bar or rail that is engraved with teeth along its length. These teeth are designed to mesh with the teeth of a gear, known as a pinion. When the pinion, a small cylindrical gear, rotates, its teeth engage with the teeth on the rack, causing the rack to move linearly. Conversely, linear motion applied to the rack will cause the pinion to rotate."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "hex-nut.kcl",
|
||||||
|
"title": "Hex nut",
|
||||||
|
"description": "A hex nut is a type of fastener with a threaded hole and a hexagonal outer shape, used in a wide variety of applications to secure parts together. The hexagonal shape allows for a greater torque to be applied with wrenches or tools, making it one of the most common nut types in hardware."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "kitt.kcl",
|
||||||
|
"title": "Kitt",
|
||||||
|
"description": "The beloved KittyCAD mascot in a voxelized style."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "lego.kcl",
|
||||||
|
"title": "Lego Brick",
|
||||||
|
"description": "A standard Lego brick. This is a small, plastic construction block toy that can be interlocked with other blocks to build various structures, models, and figures. There are a lot of hacks used in this code."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "lug-nut.kcl",
|
||||||
|
"title": "Lug Nut",
|
||||||
|
"description": "lug Nuts are essential components used to create secure connections, whether for electrical purposes, like terminating wires or grounding, or for mechanical purposes, such as providing mounting points or reinforcing structural joints."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "mounting-plate.kcl",
|
||||||
|
"title": "Mounting Plate",
|
||||||
|
"description": "A flat piece of material, often metal or plastic, that serves as a support or base for attaching, securing, or mounting various types of equipment, devices, or components."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "multi-axis-robot.kcl",
|
||||||
|
"title": "Robot Arm",
|
||||||
|
"description": "A 4 axis robotic arm for industrial use. These machines can be used for assembly, packaging, organization of goods, and quality inspection processes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "pipe.kcl",
|
||||||
|
"title": "Pipe",
|
||||||
|
"description": "A tubular section or hollow cylinder, usually but not necessarily of circular cross-section, used mainly to convey substances that can flow."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "pipe-flange-assembly.kcl",
|
||||||
|
"title": "Pipe and Flange Assembly",
|
||||||
|
"description": "A crucial component in various piping systems, designed to facilitate the connection, disconnection, and access to piping for inspection, cleaning, and modifications. This assembly combines pipes (long cylindrical conduits) with flanges (plate-like fittings) to create a secure yet detachable joint."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "poopy-shoe.kcl",
|
||||||
|
"title": "Poopy Shoe",
|
||||||
|
"description": "poop shute for bambu labs printer - optimized for printing."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "router-template-cross-bar.kcl",
|
||||||
|
"title": "Router template for a cross bar",
|
||||||
|
"description": "A guide for routing a notch into a cross bar."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "router-template-slate.kcl",
|
||||||
|
"title": "Router template for a slate",
|
||||||
|
"description": "A guide for routing a slate for a cross bar."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "sheet-metal-bracket.kcl",
|
||||||
|
"title": "Sheet Metal Bracket",
|
||||||
|
"description": "A component typically made from flat sheet metal through various manufacturing processes such as bending, punching, cutting, and forming. These brackets are used to support, attach, or mount other hardware components, often providing a structural or functional base for assembly."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "socket-head-cap-screw.kcl",
|
||||||
|
"title": "Socket Head Cap Screw",
|
||||||
|
"description": "This is for a #10-24 screw that is 1.00 inches long. A socket head cap screw is a type of fastener that is widely used in a variety of applications requiring a high strength fastening solution. It is characterized by its cylindrical head and internal hexagonal drive, which allows for tightening with an Allen wrench or hex key."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "tire.kcl",
|
||||||
|
"title": "Tire",
|
||||||
|
"description": "A tire is a critical component of a vehicle that provides the necessary traction and grip between the car and the road. It supports the vehicle's weight and absorbs shocks from road irregularities."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "washer.kcl",
|
||||||
|
"title": "Washer",
|
||||||
|
"description": "A small, typically disk-shaped component with a hole in the middle, used in a wide range of applications, primarily in conjunction with fasteners like bolts and screws. Washers distribute the load of a fastener across a broader area. This is especially important when the fastening surface is soft or uneven, as it helps to prevent damage to the surface and ensures the load is evenly distributed, reducing the risk of the fastener becoming loose over time."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "wheel-rotor.kcl",
|
||||||
|
"title": "Wheel rotor",
|
||||||
|
"description": "A component of a disc brake system. It provides a surface for brake pads to press against, generating the friction needed to slow or stop the vehicle."
|
||||||
|
}
|
||||||
|
]
|
||||||
@ -96,15 +96,29 @@ export const ClientSideScene = ({
|
|||||||
canvas.appendChild(sceneInfra.renderer.domElement)
|
canvas.appendChild(sceneInfra.renderer.domElement)
|
||||||
canvas.appendChild(sceneInfra.labelRenderer.domElement)
|
canvas.appendChild(sceneInfra.labelRenderer.domElement)
|
||||||
sceneInfra.animate()
|
sceneInfra.animate()
|
||||||
canvas.addEventListener('mousemove', sceneInfra.onMouseMove, false)
|
canvas.addEventListener(
|
||||||
|
'mousemove',
|
||||||
|
toSync(sceneInfra.onMouseMove, reportRejection),
|
||||||
|
false
|
||||||
|
)
|
||||||
canvas.addEventListener('mousedown', sceneInfra.onMouseDown, false)
|
canvas.addEventListener('mousedown', sceneInfra.onMouseDown, false)
|
||||||
canvas.addEventListener('mouseup', sceneInfra.onMouseUp, false)
|
canvas.addEventListener(
|
||||||
|
'mouseup',
|
||||||
|
toSync(sceneInfra.onMouseUp, reportRejection),
|
||||||
|
false
|
||||||
|
)
|
||||||
sceneInfra.setSend(send)
|
sceneInfra.setSend(send)
|
||||||
engineCommandManager.modelingSend = send
|
engineCommandManager.modelingSend = send
|
||||||
return () => {
|
return () => {
|
||||||
canvas?.removeEventListener('mousemove', sceneInfra.onMouseMove)
|
canvas?.removeEventListener(
|
||||||
|
'mousemove',
|
||||||
|
toSync(sceneInfra.onMouseMove, reportRejection)
|
||||||
|
)
|
||||||
canvas?.removeEventListener('mousedown', sceneInfra.onMouseDown)
|
canvas?.removeEventListener('mousedown', sceneInfra.onMouseDown)
|
||||||
canvas?.removeEventListener('mouseup', sceneInfra.onMouseUp)
|
canvas?.removeEventListener(
|
||||||
|
'mouseup',
|
||||||
|
toSync(sceneInfra.onMouseUp, reportRejection)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@ -124,7 +138,8 @@ export const ClientSideScene = ({
|
|||||||
} else if (
|
} else if (
|
||||||
state.matches({ Sketch: 'Line tool' }) ||
|
state.matches({ Sketch: 'Line tool' }) ||
|
||||||
state.matches({ Sketch: 'Tangential arc to' }) ||
|
state.matches({ Sketch: 'Tangential arc to' }) ||
|
||||||
state.matches({ Sketch: 'Rectangle tool' })
|
state.matches({ Sketch: 'Rectangle tool' }) ||
|
||||||
|
state.matches({ Sketch: 'Circle tool' })
|
||||||
) {
|
) {
|
||||||
cursor = 'crosshair'
|
cursor = 'crosshair'
|
||||||
} else {
|
} else {
|
||||||
@ -269,15 +284,22 @@ const Overlay = ({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<SegmentMenu
|
{/* delete circle is complicated by the fact it's the only segment in the
|
||||||
verticalPosition={
|
pipe expression. Maybe it should delete the entire pipeExpression, however
|
||||||
overlay.windowCoords[1] > window.innerHeight / 2
|
this will likely change soon when we implement multi-profile so we'll leave it for now
|
||||||
? 'top'
|
issue: https://github.com/KittyCAD/modeling-app/issues/3910
|
||||||
: 'bottom'
|
*/}
|
||||||
}
|
{callExpression?.callee?.name !== 'circle' && (
|
||||||
pathToNode={overlay.pathToNode}
|
<SegmentMenu
|
||||||
stdLibFnName={constraints[0]?.stdLibFnName}
|
verticalPosition={
|
||||||
/>
|
overlay.windowCoords[1] > window.innerHeight / 2
|
||||||
|
? 'top'
|
||||||
|
: 'bottom'
|
||||||
|
}
|
||||||
|
pathToNode={overlay.pathToNode}
|
||||||
|
stdLibFnName={constraints[0]?.stdLibFnName}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -512,6 +534,11 @@ const ConstraintSymbol = ({
|
|||||||
displayName: 'Intersection Offset',
|
displayName: 'Intersection Offset',
|
||||||
iconName: 'intersection-offset',
|
iconName: 'intersection-offset',
|
||||||
},
|
},
|
||||||
|
radius: {
|
||||||
|
varName: 'radius',
|
||||||
|
displayName: 'Radius',
|
||||||
|
iconName: 'dimension',
|
||||||
|
},
|
||||||
|
|
||||||
// implicit constraints
|
// implicit constraints
|
||||||
vertical: {
|
vertical: {
|
||||||
|
|||||||
@ -72,6 +72,7 @@ import {
|
|||||||
createArrayExpression,
|
createArrayExpression,
|
||||||
createCallExpressionStdLib,
|
createCallExpressionStdLib,
|
||||||
createLiteral,
|
createLiteral,
|
||||||
|
createObjectExpression,
|
||||||
createPipeExpression,
|
createPipeExpression,
|
||||||
createPipeSubstitution,
|
createPipeSubstitution,
|
||||||
findUniqueName,
|
findUniqueName,
|
||||||
@ -90,6 +91,7 @@ import { getThemeColorForThreeJs, Themes } from 'lib/theme'
|
|||||||
import { err, reportRejection, trap } from 'lib/trap'
|
import { err, reportRejection, trap } from 'lib/trap'
|
||||||
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
|
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
|
||||||
import { Point3d } from 'wasm-lib/kcl/bindings/Point3d'
|
import { Point3d } from 'wasm-lib/kcl/bindings/Point3d'
|
||||||
|
import { SegmentInputs } from 'lang/std/stdTypes'
|
||||||
|
|
||||||
type DraftSegment = 'line' | 'tangentialArcTo'
|
type DraftSegment = 'line' | 'tangentialArcTo'
|
||||||
|
|
||||||
@ -103,10 +105,18 @@ export const TANGENTIAL_ARC_TO__SEGMENT_DASH =
|
|||||||
'tangential-arc-to-segment-body-dashed'
|
'tangential-arc-to-segment-body-dashed'
|
||||||
export const TANGENTIAL_ARC_TO_SEGMENT = 'tangential-arc-to-segment'
|
export const TANGENTIAL_ARC_TO_SEGMENT = 'tangential-arc-to-segment'
|
||||||
export const TANGENTIAL_ARC_TO_SEGMENT_BODY = 'tangential-arc-to-segment-body'
|
export const TANGENTIAL_ARC_TO_SEGMENT_BODY = 'tangential-arc-to-segment-body'
|
||||||
|
export const CIRCLE_SEGMENT = 'circle-segment'
|
||||||
|
export const CIRCLE_SEGMENT_BODY = 'circle-segment-body'
|
||||||
|
export const CIRCLE_SEGMENT_DASH = 'circle-segment-body-dashed'
|
||||||
|
export const CIRCLE_CENTER_HANDLE = 'circle-center-handle'
|
||||||
export const SEGMENT_WIDTH_PX = 1.6
|
export const SEGMENT_WIDTH_PX = 1.6
|
||||||
export const HIDE_SEGMENT_LENGTH = 75 // in pixels
|
export const HIDE_SEGMENT_LENGTH = 75 // in pixels
|
||||||
export const HIDE_HOVER_SEGMENT_LENGTH = 60 // in pixels
|
export const HIDE_HOVER_SEGMENT_LENGTH = 60 // in pixels
|
||||||
export const SEGMENT_BODIES = [STRAIGHT_SEGMENT, TANGENTIAL_ARC_TO_SEGMENT]
|
export const SEGMENT_BODIES = [
|
||||||
|
STRAIGHT_SEGMENT,
|
||||||
|
TANGENTIAL_ARC_TO_SEGMENT,
|
||||||
|
CIRCLE_SEGMENT,
|
||||||
|
]
|
||||||
export const SEGMENT_BODIES_PLUS_PROFILE_START = [
|
export const SEGMENT_BODIES_PLUS_PROFILE_START = [
|
||||||
...SEGMENT_BODIES,
|
...SEGMENT_BODIES,
|
||||||
PROFILE_START,
|
PROFILE_START,
|
||||||
@ -144,11 +154,11 @@ export class SceneEntities {
|
|||||||
? orthoFactor
|
? orthoFactor
|
||||||
: perspScale(sceneInfra.camControls.camera, segment)) /
|
: perspScale(sceneInfra.camControls.camera, segment)) /
|
||||||
sceneInfra._baseUnitMultiplier
|
sceneInfra._baseUnitMultiplier
|
||||||
const input = {
|
let input: SegmentInputs = {
|
||||||
type: 'straight-segment',
|
type: 'straight-segment',
|
||||||
from: segment.userData.from,
|
from: segment.userData.from,
|
||||||
to: segment.userData.to,
|
to: segment.userData.to,
|
||||||
} as const
|
}
|
||||||
let update: SegmentUtils['update'] | null = null
|
let update: SegmentUtils['update'] | null = null
|
||||||
if (
|
if (
|
||||||
segment.userData.from &&
|
segment.userData.from &&
|
||||||
@ -165,6 +175,21 @@ export class SceneEntities {
|
|||||||
) {
|
) {
|
||||||
update = segmentUtils.tangentialArcTo.update
|
update = segmentUtils.tangentialArcTo.update
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
segment.userData.from &&
|
||||||
|
segment.userData.center &&
|
||||||
|
segment.userData.radius &&
|
||||||
|
segment.userData.type === CIRCLE_SEGMENT
|
||||||
|
) {
|
||||||
|
update = segmentUtils.circle.update
|
||||||
|
input = {
|
||||||
|
type: 'arc-segment',
|
||||||
|
from: segment.userData.from,
|
||||||
|
center: segment.userData.center,
|
||||||
|
radius: segment.userData.radius,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const callBack = update?.({
|
const callBack = update?.({
|
||||||
prevSegment: segment.userData.prevSegment,
|
prevSegment: segment.userData.prevSegment,
|
||||||
input,
|
input,
|
||||||
@ -311,7 +336,6 @@ export class SceneEntities {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
sceneInfra.setCallbacks({
|
sceneInfra.setCallbacks({
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
||||||
onClick: async (args) => {
|
onClick: async (args) => {
|
||||||
if (!args) return
|
if (!args) return
|
||||||
if (args.mouseEvent.which !== 1) return
|
if (args.mouseEvent.which !== 1) return
|
||||||
@ -409,19 +433,21 @@ export class SceneEntities {
|
|||||||
maybeModdedAst,
|
maybeModdedAst,
|
||||||
sketchGroup.start.__geoMeta.sourceRange
|
sketchGroup.start.__geoMeta.sourceRange
|
||||||
)
|
)
|
||||||
const _profileStart = createProfileStartHandle({
|
if (sketchGroup?.value?.[0]?.type !== 'Circle') {
|
||||||
from: sketchGroup.start.from,
|
const _profileStart = createProfileStartHandle({
|
||||||
id: sketchGroup.start.__geoMeta.id,
|
from: sketchGroup.start.from,
|
||||||
pathToNode: segPathToNode,
|
id: sketchGroup.start.__geoMeta.id,
|
||||||
scale: factor,
|
pathToNode: segPathToNode,
|
||||||
theme: sceneInfra._theme,
|
scale: factor,
|
||||||
})
|
theme: sceneInfra._theme,
|
||||||
_profileStart.layers.set(SKETCH_LAYER)
|
})
|
||||||
_profileStart.traverse((child) => {
|
_profileStart.layers.set(SKETCH_LAYER)
|
||||||
child.layers.set(SKETCH_LAYER)
|
_profileStart.traverse((child) => {
|
||||||
})
|
child.layers.set(SKETCH_LAYER)
|
||||||
group.add(_profileStart)
|
})
|
||||||
this.activeSegments[JSON.stringify(segPathToNode)] = _profileStart
|
group.add(_profileStart)
|
||||||
|
this.activeSegments[JSON.stringify(segPathToNode)] = _profileStart
|
||||||
|
}
|
||||||
const callbacks: (() => SegmentOverlayPayload | null)[] = []
|
const callbacks: (() => SegmentOverlayPayload | null)[] = []
|
||||||
sketchGroup.value.forEach((segment, index) => {
|
sketchGroup.value.forEach((segment, index) => {
|
||||||
let segPathToNode = getNodePathFromSourceRange(
|
let segPathToNode = getNodePathFromSourceRange(
|
||||||
@ -467,15 +493,26 @@ export class SceneEntities {
|
|||||||
const initSegment =
|
const initSegment =
|
||||||
segment.type === 'TangentialArcTo'
|
segment.type === 'TangentialArcTo'
|
||||||
? segmentUtils.tangentialArcTo.init
|
? segmentUtils.tangentialArcTo.init
|
||||||
|
: segment.type === 'Circle'
|
||||||
|
? segmentUtils.circle.init
|
||||||
: segmentUtils.straight.init
|
: segmentUtils.straight.init
|
||||||
|
const input: SegmentInputs =
|
||||||
|
segment.type === 'Circle'
|
||||||
|
? {
|
||||||
|
type: 'arc-segment',
|
||||||
|
from: segment.from,
|
||||||
|
center: segment.center,
|
||||||
|
radius: segment.radius,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
type: 'straight-segment',
|
||||||
|
from: segment.from,
|
||||||
|
to: segment.to,
|
||||||
|
}
|
||||||
const result = initSegment({
|
const result = initSegment({
|
||||||
prevSegment: sketchGroup.value[index - 1],
|
prevSegment: sketchGroup.value[index - 1],
|
||||||
callExpName,
|
callExpName,
|
||||||
input: {
|
input,
|
||||||
type: 'straight-segment',
|
|
||||||
from: segment.from,
|
|
||||||
to: segment.to,
|
|
||||||
},
|
|
||||||
id: segment.__geoMeta.id,
|
id: segment.__geoMeta.id,
|
||||||
pathToNode: segPathToNode,
|
pathToNode: segPathToNode,
|
||||||
isDraftSegment,
|
isDraftSegment,
|
||||||
@ -575,7 +612,6 @@ export class SceneEntities {
|
|||||||
const lastSeg = sg?.value?.slice(-1)[0] || sg.start
|
const lastSeg = sg?.value?.slice(-1)[0] || sg.start
|
||||||
|
|
||||||
const index = sg.value.length // because we've added a new segment that's not in the memory yet, no need for `-1`
|
const index = sg.value.length // because we've added a new segment that's not in the memory yet, no need for `-1`
|
||||||
|
|
||||||
const mod = addNewSketchLn({
|
const mod = addNewSketchLn({
|
||||||
node: _ast,
|
node: _ast,
|
||||||
programMemory: kclManager.programMemory,
|
programMemory: kclManager.programMemory,
|
||||||
@ -606,7 +642,6 @@ export class SceneEntities {
|
|||||||
draftExpressionsIndices,
|
draftExpressionsIndices,
|
||||||
})
|
})
|
||||||
sceneInfra.setCallbacks({
|
sceneInfra.setCallbacks({
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
||||||
onClick: async (args) => {
|
onClick: async (args) => {
|
||||||
if (!args) return
|
if (!args) return
|
||||||
if (args.mouseEvent.which !== 1) return
|
if (args.mouseEvent.which !== 1) return
|
||||||
@ -747,7 +782,6 @@ export class SceneEntities {
|
|||||||
})
|
})
|
||||||
|
|
||||||
sceneInfra.setCallbacks({
|
sceneInfra.setCallbacks({
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
||||||
onMove: async (args) => {
|
onMove: async (args) => {
|
||||||
// Update the width and height of the draft rectangle
|
// Update the width and height of the draft rectangle
|
||||||
const pathToNodeTwo = structuredClone(sketchPathToNode)
|
const pathToNodeTwo = structuredClone(sketchPathToNode)
|
||||||
@ -779,7 +813,7 @@ export class SceneEntities {
|
|||||||
programMemory.get(variableDeclarationName),
|
programMemory.get(variableDeclarationName),
|
||||||
variableDeclarationName
|
variableDeclarationName
|
||||||
)
|
)
|
||||||
if (err(sketchGroup)) return sketchGroup
|
if (err(sketchGroup)) return Promise.reject(sketchGroup)
|
||||||
const sgPaths = sketchGroup.value
|
const sgPaths = sketchGroup.value
|
||||||
const orthoFactor = orthoScale(sceneInfra.camControls.camera)
|
const orthoFactor = orthoScale(sceneInfra.camControls.camera)
|
||||||
|
|
||||||
@ -795,7 +829,6 @@ export class SceneEntities {
|
|||||||
this.updateSegment(seg, index, 0, _ast, orthoFactor, sketchGroup)
|
this.updateSegment(seg, index, 0, _ast, orthoFactor, sketchGroup)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
||||||
onClick: async (args) => {
|
onClick: async (args) => {
|
||||||
// Commit the rectangle to the full AST/code and return to sketch.idle
|
// Commit the rectangle to the full AST/code and return to sketch.idle
|
||||||
const cornerPoint = args.intersectionPoint?.twoD
|
const cornerPoint = args.intersectionPoint?.twoD
|
||||||
@ -857,6 +890,173 @@ export class SceneEntities {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
setupDraftCircle = async (
|
||||||
|
sketchPathToNode: PathToNode,
|
||||||
|
forward: [number, number, number],
|
||||||
|
up: [number, number, number],
|
||||||
|
sketchOrigin: [number, number, number],
|
||||||
|
circleCenter: [x: number, y: number]
|
||||||
|
) => {
|
||||||
|
let _ast = structuredClone(kclManager.ast)
|
||||||
|
|
||||||
|
const _node1 = getNodeFromPath<VariableDeclaration>(
|
||||||
|
_ast,
|
||||||
|
sketchPathToNode || [],
|
||||||
|
'VariableDeclaration'
|
||||||
|
)
|
||||||
|
if (trap(_node1)) return Promise.reject(_node1)
|
||||||
|
const variableDeclarationName =
|
||||||
|
_node1.node?.declarations?.[0]?.id?.name || ''
|
||||||
|
const startSketchOn = _node1.node?.declarations
|
||||||
|
const startSketchOnInit = startSketchOn?.[0]?.init
|
||||||
|
|
||||||
|
startSketchOn[0].init = createPipeExpression([
|
||||||
|
startSketchOnInit,
|
||||||
|
createCallExpressionStdLib('circle', [
|
||||||
|
createObjectExpression({
|
||||||
|
center: createArrayExpression([
|
||||||
|
createLiteral(roundOff(circleCenter[0])),
|
||||||
|
createLiteral(roundOff(circleCenter[1])),
|
||||||
|
]),
|
||||||
|
radius: createLiteral(1),
|
||||||
|
}),
|
||||||
|
createPipeSubstitution(),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
|
||||||
|
let _recastAst = parse(recast(_ast))
|
||||||
|
if (trap(_recastAst)) return Promise.reject(_recastAst)
|
||||||
|
_ast = _recastAst
|
||||||
|
|
||||||
|
// do a quick mock execution to get the program memory up-to-date
|
||||||
|
await kclManager.executeAstMock(_ast)
|
||||||
|
|
||||||
|
const { programMemoryOverride, truncatedAst } = await this.setupSketch({
|
||||||
|
sketchPathToNode,
|
||||||
|
forward,
|
||||||
|
up,
|
||||||
|
position: sketchOrigin,
|
||||||
|
maybeModdedAst: _ast,
|
||||||
|
draftExpressionsIndices: { start: 0, end: 0 },
|
||||||
|
})
|
||||||
|
|
||||||
|
sceneInfra.setCallbacks({
|
||||||
|
onMove: async (args) => {
|
||||||
|
const pathToNodeTwo = structuredClone(sketchPathToNode)
|
||||||
|
pathToNodeTwo[1][0] = 0
|
||||||
|
|
||||||
|
const _node = getNodeFromPath<VariableDeclaration>(
|
||||||
|
truncatedAst,
|
||||||
|
pathToNodeTwo || [],
|
||||||
|
'VariableDeclaration'
|
||||||
|
)
|
||||||
|
let modded = structuredClone(truncatedAst)
|
||||||
|
if (trap(_node)) return
|
||||||
|
const sketchInit = _node.node?.declarations?.[0]?.init
|
||||||
|
|
||||||
|
const x = (args.intersectionPoint.twoD.x || 0) - circleCenter[0]
|
||||||
|
const y = (args.intersectionPoint.twoD.y || 0) - circleCenter[1]
|
||||||
|
|
||||||
|
if (sketchInit.type === 'PipeExpression') {
|
||||||
|
const moddedResult = changeSketchArguments(
|
||||||
|
modded,
|
||||||
|
kclManager.programMemory,
|
||||||
|
{
|
||||||
|
type: 'path',
|
||||||
|
pathToNode: [
|
||||||
|
..._node.deepPath,
|
||||||
|
['body', 'PipeExpression'],
|
||||||
|
[1, 'index'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'arc-segment',
|
||||||
|
center: circleCenter,
|
||||||
|
radius: Math.sqrt(x ** 2 + y ** 2),
|
||||||
|
from: circleCenter,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (err(moddedResult)) return
|
||||||
|
modded = moddedResult.modifiedAst
|
||||||
|
}
|
||||||
|
|
||||||
|
const { programMemory } = await executeAst({
|
||||||
|
ast: modded,
|
||||||
|
useFakeExecutor: true,
|
||||||
|
engineCommandManager: this.engineCommandManager,
|
||||||
|
programMemoryOverride,
|
||||||
|
})
|
||||||
|
this.sceneProgramMemory = programMemory
|
||||||
|
const sketchGroup = sketchGroupFromKclValue(
|
||||||
|
programMemory.get(variableDeclarationName),
|
||||||
|
variableDeclarationName
|
||||||
|
)
|
||||||
|
if (err(sketchGroup)) return
|
||||||
|
const sgPaths = sketchGroup.value
|
||||||
|
const orthoFactor = orthoScale(sceneInfra.camControls.camera)
|
||||||
|
|
||||||
|
this.updateSegment(
|
||||||
|
sketchGroup.start,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
_ast,
|
||||||
|
orthoFactor,
|
||||||
|
sketchGroup
|
||||||
|
)
|
||||||
|
sgPaths.forEach((seg, index) =>
|
||||||
|
this.updateSegment(seg, index, 0, _ast, orthoFactor, sketchGroup)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClick: async (args) => {
|
||||||
|
// Commit the rectangle to the full AST/code and return to sketch.idle
|
||||||
|
const cornerPoint = args.intersectionPoint?.twoD
|
||||||
|
if (!cornerPoint || args.mouseEvent.button !== 0) return
|
||||||
|
|
||||||
|
const x = roundOff((cornerPoint.x || 0) - circleCenter[0])
|
||||||
|
const y = roundOff((cornerPoint.y || 0) - circleCenter[1])
|
||||||
|
|
||||||
|
const _node = getNodeFromPath<VariableDeclaration>(
|
||||||
|
_ast,
|
||||||
|
sketchPathToNode || [],
|
||||||
|
'VariableDeclaration'
|
||||||
|
)
|
||||||
|
if (trap(_node)) return
|
||||||
|
const sketchInit = _node.node?.declarations?.[0]?.init
|
||||||
|
|
||||||
|
let modded = structuredClone(_ast)
|
||||||
|
if (sketchInit.type === 'PipeExpression') {
|
||||||
|
const moddedResult = changeSketchArguments(
|
||||||
|
modded,
|
||||||
|
kclManager.programMemory,
|
||||||
|
{
|
||||||
|
type: 'path',
|
||||||
|
pathToNode: [
|
||||||
|
..._node.deepPath,
|
||||||
|
['body', 'PipeExpression'],
|
||||||
|
[1, 'index'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'arc-segment',
|
||||||
|
center: circleCenter,
|
||||||
|
radius: Math.sqrt(x ** 2 + y ** 2),
|
||||||
|
from: circleCenter,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (err(moddedResult)) return
|
||||||
|
modded = moddedResult.modifiedAst
|
||||||
|
|
||||||
|
let _recastAst = parse(recast(modded))
|
||||||
|
if (trap(_recastAst)) return Promise.reject(_recastAst)
|
||||||
|
_ast = _recastAst
|
||||||
|
|
||||||
|
// Update the primary AST and unequip the rectangle tool
|
||||||
|
await kclManager.executeAstMock(_ast)
|
||||||
|
sceneInfra.modelingSend({ type: 'Finish circle' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
setupSketchIdleCallbacks = ({
|
setupSketchIdleCallbacks = ({
|
||||||
pathToNode,
|
pathToNode,
|
||||||
up,
|
up,
|
||||||
@ -870,7 +1070,6 @@ export class SceneEntities {
|
|||||||
}) => {
|
}) => {
|
||||||
let addingNewSegmentStatus: 'nothing' | 'pending' | 'added' = 'nothing'
|
let addingNewSegmentStatus: 'nothing' | 'pending' | 'added' = 'nothing'
|
||||||
sceneInfra.setCallbacks({
|
sceneInfra.setCallbacks({
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
||||||
onDragEnd: async () => {
|
onDragEnd: async () => {
|
||||||
if (addingNewSegmentStatus !== 'nothing') {
|
if (addingNewSegmentStatus !== 'nothing') {
|
||||||
await this.tearDownSketch({ removeAxis: false })
|
await this.tearDownSketch({ removeAxis: false })
|
||||||
@ -891,7 +1090,6 @@ export class SceneEntities {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
||||||
onDrag: async ({
|
onDrag: async ({
|
||||||
selected,
|
selected,
|
||||||
intersectionPoint,
|
intersectionPoint,
|
||||||
@ -1028,11 +1226,8 @@ export class SceneEntities {
|
|||||||
? new Vector2(profileStart.position.x, profileStart.position.y)
|
? new Vector2(profileStart.position.x, profileStart.position.y)
|
||||||
: _intersection2d
|
: _intersection2d
|
||||||
|
|
||||||
const group = getParentGroup(object, [
|
const group = getParentGroup(object, SEGMENT_BODIES_PLUS_PROFILE_START)
|
||||||
STRAIGHT_SEGMENT,
|
const subGroup = getParentGroup(object, [ARROWHEAD, CIRCLE_CENTER_HANDLE])
|
||||||
TANGENTIAL_ARC_TO_SEGMENT,
|
|
||||||
PROFILE_START,
|
|
||||||
])
|
|
||||||
if (!group) return
|
if (!group) return
|
||||||
const pathToNode: PathToNode = structuredClone(group.userData.pathToNode)
|
const pathToNode: PathToNode = structuredClone(group.userData.pathToNode)
|
||||||
const varDecIndex = pathToNode[1][0]
|
const varDecIndex = pathToNode[1][0]
|
||||||
@ -1069,6 +1264,43 @@ export class SceneEntities {
|
|||||||
pathToNode: PathToNode
|
pathToNode: PathToNode
|
||||||
}
|
}
|
||||||
| Error
|
| Error
|
||||||
|
|
||||||
|
const getChangeSketchInput = (): SegmentInputs => {
|
||||||
|
if (
|
||||||
|
group.name === CIRCLE_SEGMENT &&
|
||||||
|
// !subGroup treats grabbing the outer circumference of the circle
|
||||||
|
// as a drag of the center handle
|
||||||
|
(!subGroup || subGroup?.name === ARROWHEAD)
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
type: 'arc-segment',
|
||||||
|
from,
|
||||||
|
center: group.userData.center,
|
||||||
|
// distance between the center and the drag point
|
||||||
|
radius: Math.sqrt(
|
||||||
|
(group.userData.center[0] - dragTo[0]) ** 2 +
|
||||||
|
(group.userData.center[1] - dragTo[1]) ** 2
|
||||||
|
),
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
group.name === CIRCLE_SEGMENT &&
|
||||||
|
subGroup?.name === CIRCLE_CENTER_HANDLE
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
type: 'arc-segment',
|
||||||
|
from,
|
||||||
|
center: dragTo,
|
||||||
|
radius: group.userData.radius,
|
||||||
|
}
|
||||||
|
|
||||||
|
// straight segment is the default
|
||||||
|
return {
|
||||||
|
type: 'straight-segment',
|
||||||
|
from,
|
||||||
|
to: dragTo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (group.name === PROFILE_START) {
|
if (group.name === PROFILE_START) {
|
||||||
modded = updateStartProfileAtArgs({
|
modded = updateStartProfileAtArgs({
|
||||||
node: modifiedAst,
|
node: modifiedAst,
|
||||||
@ -1084,12 +1316,11 @@ export class SceneEntities {
|
|||||||
modded = changeSketchArguments(
|
modded = changeSketchArguments(
|
||||||
modifiedAst,
|
modifiedAst,
|
||||||
kclManager.programMemory,
|
kclManager.programMemory,
|
||||||
[node.start, node.end],
|
|
||||||
{
|
{
|
||||||
type: 'straight-segment',
|
type: 'sourceRange',
|
||||||
from,
|
sourceRange: [node.start, node.end],
|
||||||
to: dragTo,
|
},
|
||||||
}
|
getChangeSketchInput()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (trap(modded)) return
|
if (trap(modded)) return
|
||||||
@ -1192,16 +1423,28 @@ export class SceneEntities {
|
|||||||
? orthoFactor
|
? orthoFactor
|
||||||
: perspScale(sceneInfra.camControls.camera, group)) /
|
: perspScale(sceneInfra.camControls.camera, group)) /
|
||||||
sceneInfra._baseUnitMultiplier
|
sceneInfra._baseUnitMultiplier
|
||||||
const input = {
|
let input: SegmentInputs = {
|
||||||
type: 'straight-segment',
|
type: 'straight-segment',
|
||||||
from: segment.from,
|
from: segment.from,
|
||||||
to: segment.to,
|
to: segment.to,
|
||||||
} as const
|
}
|
||||||
let update: SegmentUtils['update'] | null = null
|
let update: SegmentUtils['update'] | null = null
|
||||||
if (type === TANGENTIAL_ARC_TO_SEGMENT) {
|
if (type === TANGENTIAL_ARC_TO_SEGMENT) {
|
||||||
update = segmentUtils.tangentialArcTo.update
|
update = segmentUtils.tangentialArcTo.update
|
||||||
} else if (type === STRAIGHT_SEGMENT) {
|
} else if (type === STRAIGHT_SEGMENT) {
|
||||||
update = segmentUtils.straight.update
|
update = segmentUtils.straight.update
|
||||||
|
} else if (
|
||||||
|
type === CIRCLE_SEGMENT &&
|
||||||
|
'type' in segment &&
|
||||||
|
segment.type === 'Circle'
|
||||||
|
) {
|
||||||
|
update = segmentUtils.circle.update
|
||||||
|
input = {
|
||||||
|
type: 'arc-segment',
|
||||||
|
from: segment.from,
|
||||||
|
center: segment.center,
|
||||||
|
radius: segment.radius,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const callBack =
|
const callBack =
|
||||||
update &&
|
update &&
|
||||||
@ -1276,7 +1519,7 @@ export class SceneEntities {
|
|||||||
this._tearDownSketch(callDepth + 1, resolve, reject, { removeAxis })
|
this._tearDownSketch(callDepth + 1, resolve, reject, { removeAxis })
|
||||||
}, delay)
|
}, delay)
|
||||||
} else {
|
} else {
|
||||||
reject()
|
resolve(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sceneInfra.camControls.enableRotate = true
|
sceneInfra.camControls.enableRotate = true
|
||||||
@ -1306,11 +1549,10 @@ export class SceneEntities {
|
|||||||
mat.color.set(obj.userData.baseColor)
|
mat.color.set(obj.userData.baseColor)
|
||||||
mat.color.offsetHSL(0, 0, 0.5)
|
mat.color.offsetHSL(0, 0, 0.5)
|
||||||
}
|
}
|
||||||
const parent = getParentGroup(selected, [
|
const parent = getParentGroup(
|
||||||
STRAIGHT_SEGMENT,
|
selected,
|
||||||
TANGENTIAL_ARC_TO_SEGMENT,
|
SEGMENT_BODIES_PLUS_PROFILE_START
|
||||||
PROFILE_START,
|
)
|
||||||
])
|
|
||||||
if (parent?.userData?.pathToNode) {
|
if (parent?.userData?.pathToNode) {
|
||||||
const updatedAst = parse(recast(kclManager.ast))
|
const updatedAst = parse(recast(kclManager.ast))
|
||||||
if (trap(updatedAst)) return
|
if (trap(updatedAst)) return
|
||||||
@ -1334,11 +1576,11 @@ export class SceneEntities {
|
|||||||
}
|
}
|
||||||
const orthoFactor = orthoScale(sceneInfra.camControls.camera)
|
const orthoFactor = orthoScale(sceneInfra.camControls.camera)
|
||||||
|
|
||||||
const input = {
|
let input: SegmentInputs = {
|
||||||
type: 'straight-segment',
|
type: 'straight-segment',
|
||||||
from: parent.userData.from,
|
from: parent.userData.from,
|
||||||
to: parent.userData.to,
|
to: parent.userData.to,
|
||||||
} as const
|
}
|
||||||
const factor =
|
const factor =
|
||||||
(sceneInfra.camControls.camera instanceof OrthographicCamera
|
(sceneInfra.camControls.camera instanceof OrthographicCamera
|
||||||
? orthoFactor
|
? orthoFactor
|
||||||
@ -1349,6 +1591,12 @@ export class SceneEntities {
|
|||||||
update = segmentUtils.straight.update
|
update = segmentUtils.straight.update
|
||||||
} else if (parent.name === TANGENTIAL_ARC_TO_SEGMENT) {
|
} else if (parent.name === TANGENTIAL_ARC_TO_SEGMENT) {
|
||||||
update = segmentUtils.tangentialArcTo.update
|
update = segmentUtils.tangentialArcTo.update
|
||||||
|
input = {
|
||||||
|
type: 'arc-segment',
|
||||||
|
from: parent.userData.from,
|
||||||
|
radius: parent.userData.radius,
|
||||||
|
center: parent.userData.center,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
update &&
|
update &&
|
||||||
update({
|
update({
|
||||||
@ -1364,19 +1612,18 @@ export class SceneEntities {
|
|||||||
},
|
},
|
||||||
onMouseLeave: ({ selected, ...rest }: OnMouseEnterLeaveArgs) => {
|
onMouseLeave: ({ selected, ...rest }: OnMouseEnterLeaveArgs) => {
|
||||||
editorManager.setHighlightRange([[0, 0]])
|
editorManager.setHighlightRange([[0, 0]])
|
||||||
const parent = getParentGroup(selected, [
|
const parent = getParentGroup(
|
||||||
STRAIGHT_SEGMENT,
|
selected,
|
||||||
TANGENTIAL_ARC_TO_SEGMENT,
|
SEGMENT_BODIES_PLUS_PROFILE_START
|
||||||
PROFILE_START,
|
)
|
||||||
])
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
const orthoFactor = orthoScale(sceneInfra.camControls.camera)
|
const orthoFactor = orthoScale(sceneInfra.camControls.camera)
|
||||||
|
|
||||||
const input = {
|
let input: SegmentInputs = {
|
||||||
type: 'straight-segment',
|
type: 'straight-segment',
|
||||||
from: parent.userData.from,
|
from: parent.userData.from,
|
||||||
to: parent.userData.to,
|
to: parent.userData.to,
|
||||||
} as const
|
}
|
||||||
const factor =
|
const factor =
|
||||||
(sceneInfra.camControls.camera instanceof OrthographicCamera
|
(sceneInfra.camControls.camera instanceof OrthographicCamera
|
||||||
? orthoFactor
|
? orthoFactor
|
||||||
@ -1387,6 +1634,12 @@ export class SceneEntities {
|
|||||||
update = segmentUtils.straight.update
|
update = segmentUtils.straight.update
|
||||||
} else if (parent.name === TANGENTIAL_ARC_TO_SEGMENT) {
|
} else if (parent.name === TANGENTIAL_ARC_TO_SEGMENT) {
|
||||||
update = segmentUtils.tangentialArcTo.update
|
update = segmentUtils.tangentialArcTo.update
|
||||||
|
input = {
|
||||||
|
type: 'arc-segment',
|
||||||
|
from: parent.userData.from,
|
||||||
|
radius: parent.userData.radius,
|
||||||
|
center: parent.userData.center,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
update &&
|
update &&
|
||||||
update({
|
update({
|
||||||
@ -1557,7 +1810,7 @@ function prepareTruncatedMemoryAndAst(
|
|||||||
|
|
||||||
export function getParentGroup(
|
export function getParentGroup(
|
||||||
object: any,
|
object: any,
|
||||||
stopAt: string[] = [STRAIGHT_SEGMENT, TANGENTIAL_ARC_TO_SEGMENT]
|
stopAt: string[] = SEGMENT_BODIES
|
||||||
): Group | null {
|
): Group | null {
|
||||||
if (stopAt.includes(object?.userData?.type)) {
|
if (stopAt.includes(object?.userData?.type)) {
|
||||||
return object
|
return object
|
||||||
@ -1604,10 +1857,7 @@ function colorSegment(object: any, color: number) {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const straightSegmentBody = getParentGroup(object, [
|
const straightSegmentBody = getParentGroup(object, SEGMENT_BODIES)
|
||||||
STRAIGHT_SEGMENT,
|
|
||||||
TANGENTIAL_ARC_TO_SEGMENT,
|
|
||||||
])
|
|
||||||
if (straightSegmentBody) {
|
if (straightSegmentBody) {
|
||||||
straightSegmentBody.traverse((child) => {
|
straightSegmentBody.traverse((child) => {
|
||||||
if (child instanceof Mesh && !child.userData.ignoreColorChange) {
|
if (child instanceof Mesh && !child.userData.ignoreColorChange) {
|
||||||
|
|||||||
@ -92,6 +92,8 @@ interface OnMoveCallbackArgs {
|
|||||||
// This singleton class is responsible for all of the under the hood setup for the client side scene.
|
// 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.
|
// 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
|
// Anything that added the the scene for the user to interact with is probably in SceneEntities.ts
|
||||||
|
|
||||||
|
type Voidish = void | Promise<void>
|
||||||
export class SceneInfra {
|
export class SceneInfra {
|
||||||
static instance: SceneInfra
|
static instance: SceneInfra
|
||||||
scene: Scene
|
scene: Scene
|
||||||
@ -107,21 +109,21 @@ export class SceneInfra {
|
|||||||
_theme: Themes = Themes.System
|
_theme: Themes = Themes.System
|
||||||
extraSegmentTexture: Texture
|
extraSegmentTexture: Texture
|
||||||
lastMouseState: MouseState = { type: 'idle' }
|
lastMouseState: MouseState = { type: 'idle' }
|
||||||
onDragStartCallback: (arg: OnDragCallbackArgs) => void = () => {}
|
onDragStartCallback: (arg: OnDragCallbackArgs) => Voidish = () => {}
|
||||||
onDragEndCallback: (arg: OnDragCallbackArgs) => void = () => {}
|
onDragEndCallback: (arg: OnDragCallbackArgs) => Voidish = () => {}
|
||||||
onDragCallback: (arg: OnDragCallbackArgs) => void = () => {}
|
onDragCallback: (arg: OnDragCallbackArgs) => Voidish = () => {}
|
||||||
onMoveCallback: (arg: OnMoveCallbackArgs) => void = () => {}
|
onMoveCallback: (arg: OnMoveCallbackArgs) => Voidish = () => {}
|
||||||
onClickCallback: (arg: OnClickCallbackArgs) => void = () => {}
|
onClickCallback: (arg: OnClickCallbackArgs) => Voidish = () => {}
|
||||||
onMouseEnter: (arg: OnMouseEnterLeaveArgs) => void = () => {}
|
onMouseEnter: (arg: OnMouseEnterLeaveArgs) => Voidish = () => {}
|
||||||
onMouseLeave: (arg: OnMouseEnterLeaveArgs) => void = () => {}
|
onMouseLeave: (arg: OnMouseEnterLeaveArgs) => Voidish = () => {}
|
||||||
setCallbacks = (callbacks: {
|
setCallbacks = (callbacks: {
|
||||||
onDragStart?: (arg: OnDragCallbackArgs) => void
|
onDragStart?: (arg: OnDragCallbackArgs) => Voidish
|
||||||
onDragEnd?: (arg: OnDragCallbackArgs) => void
|
onDragEnd?: (arg: OnDragCallbackArgs) => Voidish
|
||||||
onDrag?: (arg: OnDragCallbackArgs) => void
|
onDrag?: (arg: OnDragCallbackArgs) => Voidish
|
||||||
onMove?: (arg: OnMoveCallbackArgs) => void
|
onMove?: (arg: OnMoveCallbackArgs) => Voidish
|
||||||
onClick?: (arg: OnClickCallbackArgs) => void
|
onClick?: (arg: OnClickCallbackArgs) => Voidish
|
||||||
onMouseEnter?: (arg: OnMouseEnterLeaveArgs) => void
|
onMouseEnter?: (arg: OnMouseEnterLeaveArgs) => Voidish
|
||||||
onMouseLeave?: (arg: OnMouseEnterLeaveArgs) => void
|
onMouseLeave?: (arg: OnMouseEnterLeaveArgs) => Voidish
|
||||||
}) => {
|
}) => {
|
||||||
this.onDragStartCallback = callbacks.onDragStart || this.onDragStartCallback
|
this.onDragStartCallback = callbacks.onDragStart || this.onDragStartCallback
|
||||||
this.onDragEndCallback = callbacks.onDragEnd || this.onDragEndCallback
|
this.onDragEndCallback = callbacks.onDragEnd || this.onDragEndCallback
|
||||||
@ -389,7 +391,7 @@ export class SceneInfra {
|
|||||||
intersection: planeIntersects[0],
|
intersection: planeIntersects[0],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onMouseMove = (mouseEvent: MouseEvent) => {
|
onMouseMove = async (mouseEvent: MouseEvent) => {
|
||||||
this.currentMouseVector.x = (mouseEvent.clientX / window.innerWidth) * 2 - 1
|
this.currentMouseVector.x = (mouseEvent.clientX / window.innerWidth) * 2 - 1
|
||||||
this.currentMouseVector.y =
|
this.currentMouseVector.y =
|
||||||
-(mouseEvent.clientY / window.innerHeight) * 2 + 1
|
-(mouseEvent.clientY / window.innerHeight) * 2 + 1
|
||||||
@ -414,7 +416,7 @@ export class SceneInfra {
|
|||||||
planeIntersectPoint.twoD &&
|
planeIntersectPoint.twoD &&
|
||||||
planeIntersectPoint.threeD
|
planeIntersectPoint.threeD
|
||||||
) {
|
) {
|
||||||
this.onDragCallback({
|
await this.onDragCallback({
|
||||||
mouseEvent,
|
mouseEvent,
|
||||||
intersectionPoint: {
|
intersectionPoint: {
|
||||||
twoD: planeIntersectPoint.twoD,
|
twoD: planeIntersectPoint.twoD,
|
||||||
@ -433,7 +435,7 @@ export class SceneInfra {
|
|||||||
planeIntersectPoint.twoD &&
|
planeIntersectPoint.twoD &&
|
||||||
planeIntersectPoint.threeD
|
planeIntersectPoint.threeD
|
||||||
) {
|
) {
|
||||||
this.onMoveCallback({
|
await this.onMoveCallback({
|
||||||
mouseEvent,
|
mouseEvent,
|
||||||
intersectionPoint: {
|
intersectionPoint: {
|
||||||
twoD: planeIntersectPoint.twoD,
|
twoD: planeIntersectPoint.twoD,
|
||||||
@ -448,12 +450,12 @@ export class SceneInfra {
|
|||||||
if (this.hoveredObject !== firstIntersectObject) {
|
if (this.hoveredObject !== firstIntersectObject) {
|
||||||
const hoveredObj = this.hoveredObject
|
const hoveredObj = this.hoveredObject
|
||||||
this.hoveredObject = null
|
this.hoveredObject = null
|
||||||
this.onMouseLeave({
|
await this.onMouseLeave({
|
||||||
selected: hoveredObj,
|
selected: hoveredObj,
|
||||||
mouseEvent: mouseEvent,
|
mouseEvent: mouseEvent,
|
||||||
})
|
})
|
||||||
this.hoveredObject = firstIntersectObject
|
this.hoveredObject = firstIntersectObject
|
||||||
this.onMouseEnter({
|
await this.onMouseEnter({
|
||||||
selected: this.hoveredObject,
|
selected: this.hoveredObject,
|
||||||
dragSelected: this.selected?.object,
|
dragSelected: this.selected?.object,
|
||||||
mouseEvent: mouseEvent,
|
mouseEvent: mouseEvent,
|
||||||
@ -468,7 +470,7 @@ export class SceneInfra {
|
|||||||
if (this.hoveredObject) {
|
if (this.hoveredObject) {
|
||||||
const hoveredObj = this.hoveredObject
|
const hoveredObj = this.hoveredObject
|
||||||
this.hoveredObject = null
|
this.hoveredObject = null
|
||||||
this.onMouseLeave({
|
await this.onMouseLeave({
|
||||||
selected: hoveredObj,
|
selected: hoveredObj,
|
||||||
dragSelected: this.selected?.object,
|
dragSelected: this.selected?.object,
|
||||||
mouseEvent: mouseEvent,
|
mouseEvent: mouseEvent,
|
||||||
@ -555,7 +557,7 @@ export class SceneInfra {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseUp = (mouseEvent: MouseEvent) => {
|
onMouseUp = async (mouseEvent: MouseEvent) => {
|
||||||
this.currentMouseVector.x = (mouseEvent.clientX / window.innerWidth) * 2 - 1
|
this.currentMouseVector.x = (mouseEvent.clientX / window.innerWidth) * 2 - 1
|
||||||
this.currentMouseVector.y =
|
this.currentMouseVector.y =
|
||||||
-(mouseEvent.clientY / window.innerHeight) * 2 + 1
|
-(mouseEvent.clientY / window.innerHeight) * 2 + 1
|
||||||
@ -565,7 +567,7 @@ export class SceneInfra {
|
|||||||
if (this.selected) {
|
if (this.selected) {
|
||||||
if (this.selected.hasBeenDragged) {
|
if (this.selected.hasBeenDragged) {
|
||||||
// TODO do the types properly here
|
// TODO do the types properly here
|
||||||
this.onDragEndCallback({
|
await this.onDragEndCallback({
|
||||||
intersectionPoint: {
|
intersectionPoint: {
|
||||||
twoD: planeIntersectPoint?.twoD as any,
|
twoD: planeIntersectPoint?.twoD as any,
|
||||||
threeD: planeIntersectPoint?.threeD as any,
|
threeD: planeIntersectPoint?.threeD as any,
|
||||||
@ -586,7 +588,7 @@ export class SceneInfra {
|
|||||||
}
|
}
|
||||||
} else if (planeIntersectPoint?.twoD && planeIntersectPoint?.threeD) {
|
} else if (planeIntersectPoint?.twoD && planeIntersectPoint?.threeD) {
|
||||||
// fire onClick event as there was no drags
|
// fire onClick event as there was no drags
|
||||||
this.onClickCallback({
|
await this.onClickCallback({
|
||||||
mouseEvent,
|
mouseEvent,
|
||||||
intersectionPoint: {
|
intersectionPoint: {
|
||||||
twoD: planeIntersectPoint.twoD,
|
twoD: planeIntersectPoint.twoD,
|
||||||
@ -596,17 +598,17 @@ export class SceneInfra {
|
|||||||
selected: this.selected.object,
|
selected: this.selected.object,
|
||||||
})
|
})
|
||||||
} else if (planeIntersectPoint) {
|
} else if (planeIntersectPoint) {
|
||||||
this.onClickCallback({
|
await this.onClickCallback({
|
||||||
mouseEvent,
|
mouseEvent,
|
||||||
intersects,
|
intersects,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.onClickCallback({ mouseEvent, intersects })
|
await this.onClickCallback({ mouseEvent, intersects })
|
||||||
}
|
}
|
||||||
// Clear the selected state whether it was dragged or not
|
// Clear the selected state whether it was dragged or not
|
||||||
this.selected = null
|
this.selected = null
|
||||||
} else if (planeIntersectPoint?.twoD && planeIntersectPoint?.threeD) {
|
} else if (planeIntersectPoint?.twoD && planeIntersectPoint?.threeD) {
|
||||||
this.onClickCallback({
|
await this.onClickCallback({
|
||||||
mouseEvent,
|
mouseEvent,
|
||||||
intersectionPoint: {
|
intersectionPoint: {
|
||||||
twoD: planeIntersectPoint.twoD,
|
twoD: planeIntersectPoint.twoD,
|
||||||
@ -615,7 +617,7 @@ export class SceneInfra {
|
|||||||
intersects,
|
intersects,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.onClickCallback({ mouseEvent, intersects })
|
await this.onClickCallback({ mouseEvent, intersects })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateOtherSelectionColors = (otherSelections: Axis[]) => {
|
updateOtherSelectionColors = (otherSelections: Axis[]) => {
|
||||||
|
|||||||
@ -24,6 +24,10 @@ import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js
|
|||||||
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
|
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
|
||||||
import { PathToNode, SketchGroup, getTangentialArcToInfo } from 'lang/wasm'
|
import { PathToNode, SketchGroup, getTangentialArcToInfo } from 'lang/wasm'
|
||||||
import {
|
import {
|
||||||
|
CIRCLE_CENTER_HANDLE,
|
||||||
|
CIRCLE_SEGMENT,
|
||||||
|
CIRCLE_SEGMENT_BODY,
|
||||||
|
CIRCLE_SEGMENT_DASH,
|
||||||
EXTRA_SEGMENT_HANDLE,
|
EXTRA_SEGMENT_HANDLE,
|
||||||
EXTRA_SEGMENT_OFFSET_PX,
|
EXTRA_SEGMENT_OFFSET_PX,
|
||||||
HIDE_HOVER_SEGMENT_LENGTH,
|
HIDE_HOVER_SEGMENT_LENGTH,
|
||||||
@ -477,6 +481,169 @@ class TangentialArcToSegment implements SegmentUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CircleSegment implements SegmentUtils {
|
||||||
|
init: SegmentUtils['init'] = ({
|
||||||
|
prevSegment,
|
||||||
|
input,
|
||||||
|
id,
|
||||||
|
pathToNode,
|
||||||
|
isDraftSegment,
|
||||||
|
scale = 1,
|
||||||
|
theme,
|
||||||
|
isSelected,
|
||||||
|
sceneInfra,
|
||||||
|
}) => {
|
||||||
|
if (input.type !== 'arc-segment') {
|
||||||
|
return new Error('Invalid segment type')
|
||||||
|
}
|
||||||
|
const { from, center, radius } = input
|
||||||
|
const baseColor = getThemeColorForThreeJs(theme)
|
||||||
|
const color = isSelected ? 0x0000ff : baseColor
|
||||||
|
|
||||||
|
const group = new Group()
|
||||||
|
const geometry = createArcGeometry({
|
||||||
|
center,
|
||||||
|
radius,
|
||||||
|
startAngle: 0,
|
||||||
|
endAngle: Math.PI * 2,
|
||||||
|
ccw: true,
|
||||||
|
isDashed: isDraftSegment,
|
||||||
|
scale,
|
||||||
|
})
|
||||||
|
const mat = new MeshBasicMaterial({ color })
|
||||||
|
const arcMesh = new Mesh(geometry, mat)
|
||||||
|
const meshType = isDraftSegment ? CIRCLE_SEGMENT_DASH : CIRCLE_SEGMENT_BODY
|
||||||
|
const arrowGroup = createArrowhead(scale, theme, color)
|
||||||
|
const circleCenterGroup = createCircleCenterHandle(scale, theme, color)
|
||||||
|
|
||||||
|
arcMesh.userData.type = meshType
|
||||||
|
arcMesh.name = meshType
|
||||||
|
group.userData = {
|
||||||
|
type: CIRCLE_SEGMENT,
|
||||||
|
id,
|
||||||
|
from,
|
||||||
|
radius,
|
||||||
|
center,
|
||||||
|
ccw: true,
|
||||||
|
prevSegment,
|
||||||
|
pathToNode,
|
||||||
|
isSelected,
|
||||||
|
baseColor,
|
||||||
|
}
|
||||||
|
group.name = CIRCLE_SEGMENT
|
||||||
|
|
||||||
|
group.add(arcMesh, arrowGroup, circleCenterGroup)
|
||||||
|
const updateOverlaysCallback = this.update({
|
||||||
|
prevSegment,
|
||||||
|
input,
|
||||||
|
group,
|
||||||
|
scale,
|
||||||
|
sceneInfra,
|
||||||
|
})
|
||||||
|
if (err(updateOverlaysCallback)) return updateOverlaysCallback
|
||||||
|
|
||||||
|
return {
|
||||||
|
group,
|
||||||
|
updateOverlaysCallback,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update: SegmentUtils['update'] = ({
|
||||||
|
prevSegment,
|
||||||
|
input,
|
||||||
|
group,
|
||||||
|
scale = 1,
|
||||||
|
sceneInfra,
|
||||||
|
}) => {
|
||||||
|
if (input.type !== 'arc-segment') {
|
||||||
|
return new Error('Invalid segment type')
|
||||||
|
}
|
||||||
|
const { from, center, radius } = input
|
||||||
|
group.userData.from = from
|
||||||
|
// group.userData.to = to
|
||||||
|
group.userData.center = center
|
||||||
|
group.userData.radius = radius
|
||||||
|
group.userData.prevSegment = prevSegment
|
||||||
|
const arrowGroup = group.getObjectByName(ARROWHEAD) as Group
|
||||||
|
const circleCenterHandle = group.getObjectByName(
|
||||||
|
CIRCLE_CENTER_HANDLE
|
||||||
|
) as Group
|
||||||
|
|
||||||
|
const pxLength = (2 * radius * Math.PI) / scale
|
||||||
|
const shouldHideIdle = pxLength < HIDE_SEGMENT_LENGTH
|
||||||
|
const shouldHideHover = pxLength < HIDE_HOVER_SEGMENT_LENGTH
|
||||||
|
|
||||||
|
const hoveredParent =
|
||||||
|
sceneInfra.hoveredObject &&
|
||||||
|
getParentGroup(sceneInfra.hoveredObject, [CIRCLE_SEGMENT])
|
||||||
|
let isHandlesVisible = !shouldHideIdle
|
||||||
|
if (hoveredParent && hoveredParent?.uuid === group?.uuid) {
|
||||||
|
isHandlesVisible = !shouldHideHover
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arrowGroup) {
|
||||||
|
arrowGroup.position.set(
|
||||||
|
center[0] + Math.cos(Math.PI / 4) * radius,
|
||||||
|
center[1] + Math.sin(Math.PI / 4) * radius,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
|
const arrowheadAngle = Math.PI / 4
|
||||||
|
arrowGroup.quaternion.setFromUnitVectors(
|
||||||
|
new Vector3(0, 1, 0),
|
||||||
|
new Vector3(Math.cos(arrowheadAngle), Math.sin(arrowheadAngle), 0)
|
||||||
|
)
|
||||||
|
arrowGroup.scale.set(scale, scale, scale)
|
||||||
|
arrowGroup.visible = isHandlesVisible
|
||||||
|
}
|
||||||
|
|
||||||
|
if (circleCenterHandle) {
|
||||||
|
circleCenterHandle.position.set(center[0], center[1], 0)
|
||||||
|
circleCenterHandle.scale.set(scale, scale, scale)
|
||||||
|
circleCenterHandle.visible = isHandlesVisible
|
||||||
|
}
|
||||||
|
|
||||||
|
const circleSegmentBody = group.children.find(
|
||||||
|
(child) => child.userData.type === CIRCLE_SEGMENT_BODY
|
||||||
|
) as Mesh
|
||||||
|
|
||||||
|
if (circleSegmentBody) {
|
||||||
|
const newGeo = createArcGeometry({
|
||||||
|
radius,
|
||||||
|
center,
|
||||||
|
startAngle: 0,
|
||||||
|
endAngle: Math.PI * 2,
|
||||||
|
ccw: true,
|
||||||
|
scale,
|
||||||
|
})
|
||||||
|
circleSegmentBody.geometry = newGeo
|
||||||
|
}
|
||||||
|
const circleSegmentBodyDashed = group.getObjectByName(CIRCLE_SEGMENT_DASH)
|
||||||
|
if (circleSegmentBodyDashed instanceof Mesh) {
|
||||||
|
// consider throttling the whole updateTangentialArcToSegment
|
||||||
|
// if there are more perf considerations going forward
|
||||||
|
circleSegmentBodyDashed.geometry = createArcGeometry({
|
||||||
|
center,
|
||||||
|
radius,
|
||||||
|
ccw: true,
|
||||||
|
// make the start end where the handle is
|
||||||
|
startAngle: Math.PI * 0.25,
|
||||||
|
endAngle: Math.PI * 2.25,
|
||||||
|
isDashed: true,
|
||||||
|
scale,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return () =>
|
||||||
|
sceneInfra.updateOverlayDetails({
|
||||||
|
arrowGroup,
|
||||||
|
group,
|
||||||
|
isHandlesVisible,
|
||||||
|
from: from,
|
||||||
|
to: [center[0], center[1]],
|
||||||
|
angle: Math.PI / 4,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function createProfileStartHandle({
|
export function createProfileStartHandle({
|
||||||
from,
|
from,
|
||||||
id,
|
id,
|
||||||
@ -535,6 +702,28 @@ function createArrowhead(scale = 1, theme: Themes, color?: number): Group {
|
|||||||
arrowGroup.scale.set(scale, scale, scale)
|
arrowGroup.scale.set(scale, scale, scale)
|
||||||
return arrowGroup
|
return arrowGroup
|
||||||
}
|
}
|
||||||
|
function createCircleCenterHandle(
|
||||||
|
scale = 1,
|
||||||
|
theme: Themes,
|
||||||
|
color?: number
|
||||||
|
): Group {
|
||||||
|
const circleCenterGroup = new Group()
|
||||||
|
|
||||||
|
const geometry = new BoxGeometry(12, 12, 12) // in pixels scaled later
|
||||||
|
const baseColor = getThemeColorForThreeJs(theme)
|
||||||
|
const body = new MeshBasicMaterial({ color })
|
||||||
|
const mesh = new Mesh(geometry, body)
|
||||||
|
|
||||||
|
circleCenterGroup.add(mesh)
|
||||||
|
|
||||||
|
circleCenterGroup.userData = {
|
||||||
|
type: CIRCLE_CENTER_HANDLE,
|
||||||
|
baseColor,
|
||||||
|
}
|
||||||
|
circleCenterGroup.name = CIRCLE_CENTER_HANDLE
|
||||||
|
circleCenterGroup.scale.set(scale, scale, scale)
|
||||||
|
return circleCenterGroup
|
||||||
|
}
|
||||||
|
|
||||||
function createExtraSegmentHandle(
|
function createExtraSegmentHandle(
|
||||||
scale: number,
|
scale: number,
|
||||||
@ -788,4 +977,5 @@ export function dashedStraight(
|
|||||||
export const segmentUtils = {
|
export const segmentUtils = {
|
||||||
straight: new StraightSegment(),
|
straight: new StraightSegment(),
|
||||||
tangentialArcTo: new TangentialArcToSegment(),
|
tangentialArcTo: new TangentialArcToSegment(),
|
||||||
|
circle: new CircleSegment(),
|
||||||
} as const
|
} as const
|
||||||
|
|||||||
42
src/components/ActionButton.test.tsx
Normal file
42
src/components/ActionButton.test.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { render, screen } from '@testing-library/react'
|
||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
import { ActionButton } from './ActionButton'
|
||||||
|
|
||||||
|
describe('ActionButton tests', () => {
|
||||||
|
it('ActionButton with no iconStart or iconEnd should have even left and right padding', () => {
|
||||||
|
render(<ActionButton Element="button">No icons</ActionButton>)
|
||||||
|
expect(screen.getByRole('button')).toHaveClass('px-2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('ActionButton with iconStart should have no padding on the left', () => {
|
||||||
|
render(
|
||||||
|
<ActionButton Element="button" iconStart={{ icon: 'trash' }}>
|
||||||
|
Start icon only
|
||||||
|
</ActionButton>
|
||||||
|
)
|
||||||
|
expect(screen.getByRole('button')).toHaveClass('pr-2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('ActionButton with iconEnd should have no padding on the right', () => {
|
||||||
|
render(
|
||||||
|
<ActionButton Element="button" iconEnd={{ icon: 'trash' }}>
|
||||||
|
End icon only
|
||||||
|
</ActionButton>
|
||||||
|
)
|
||||||
|
expect(screen.getByRole('button')).toHaveClass('pl-2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('ActionButton with both icons should have no padding on either side', () => {
|
||||||
|
render(
|
||||||
|
<ActionButton
|
||||||
|
Element="button"
|
||||||
|
iconStart={{ icon: 'trash' }}
|
||||||
|
iconEnd={{ icon: 'trash' }}
|
||||||
|
>
|
||||||
|
Both icons
|
||||||
|
</ActionButton>
|
||||||
|
)
|
||||||
|
expect(screen.getByRole('button')).not.toHaveClass('px-2')
|
||||||
|
expect(screen.getByRole('button')).toHaveClass('px-0')
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -44,11 +44,11 @@ export const ActionButton = forwardRef((props: ActionButtonProps, ref) => {
|
|||||||
const classNames = `action-button p-0 m-0 group mono text-xs leading-none flex items-center gap-2 rounded-sm border-solid border border-chalkboard-30 hover:border-chalkboard-40 enabled:dark:border-chalkboard-70 dark:hover:border-chalkboard-60 dark:bg-chalkboard-90/50 text-chalkboard-100 dark:text-chalkboard-10 ${
|
const classNames = `action-button p-0 m-0 group mono text-xs leading-none flex items-center gap-2 rounded-sm border-solid border border-chalkboard-30 hover:border-chalkboard-40 enabled:dark:border-chalkboard-70 dark:hover:border-chalkboard-60 dark:bg-chalkboard-90/50 text-chalkboard-100 dark:text-chalkboard-10 ${
|
||||||
props.iconStart
|
props.iconStart
|
||||||
? props.iconEnd
|
? props.iconEnd
|
||||||
? 'px-0'
|
? 'px-0' // No padding if both icons are present
|
||||||
: 'pr-2'
|
: 'pr-2' // Padding on the right if only the start icon is present
|
||||||
: props.iconEnd
|
: props.iconEnd
|
||||||
? 'px-2'
|
? 'pl-2' // Padding on the left if only the end icon is present
|
||||||
: 'pl-2'
|
: 'px-2' // Padding on both sides if no icons are present
|
||||||
} ${props.className ? props.className : ''}`
|
} ${props.className ? props.className : ''}`
|
||||||
|
|
||||||
switch (props.Element) {
|
switch (props.Element) {
|
||||||
|
|||||||
@ -6,8 +6,8 @@ import { CommandArgument, CommandArgumentOption } from 'lib/commandTypes'
|
|||||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { AnyStateMachine, StateFrom } from 'xstate'
|
import { AnyStateMachine, StateFrom } from 'xstate'
|
||||||
|
|
||||||
const contextSelector = (snapshot: StateFrom<AnyStateMachine>) =>
|
const contextSelector = (snapshot: StateFrom<AnyStateMachine> | undefined) =>
|
||||||
snapshot.context
|
snapshot?.context
|
||||||
|
|
||||||
function CommandArgOptionInput({
|
function CommandArgOptionInput({
|
||||||
arg,
|
arg,
|
||||||
|
|||||||
@ -33,11 +33,15 @@ function CommandBarBasicInput({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form id="arg-form" onSubmit={handleSubmit}>
|
<form id="arg-form" onSubmit={handleSubmit}>
|
||||||
<label className="flex items-center mx-4 my-4">
|
<label
|
||||||
|
data-testid="cmd-bar-arg-name"
|
||||||
|
className="flex items-center mx-4 my-4"
|
||||||
|
>
|
||||||
<span className="capitalize px-2 py-1 rounded-l bg-chalkboard-100 dark:bg-chalkboard-80 text-chalkboard-10 border-b border-b-chalkboard-100 dark:border-b-chalkboard-80">
|
<span className="capitalize px-2 py-1 rounded-l bg-chalkboard-100 dark:bg-chalkboard-80 text-chalkboard-10 border-b border-b-chalkboard-100 dark:border-b-chalkboard-80">
|
||||||
{arg.name}
|
{arg.name}
|
||||||
</span>
|
</span>
|
||||||
<input
|
<input
|
||||||
|
data-testid="cmd-bar-arg-value"
|
||||||
id="arg-form"
|
id="arg-form"
|
||||||
name={arg.inputType}
|
name={arg.inputType}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
|||||||
@ -74,7 +74,9 @@ function CommandBarHeader({ children }: React.PropsWithChildren<{}>) {
|
|||||||
selectedCommand.icon && (
|
selectedCommand.icon && (
|
||||||
<CustomIcon name={selectedCommand.icon} className="w-5 h-5" />
|
<CustomIcon name={selectedCommand.icon} className="w-5 h-5" />
|
||||||
)}
|
)}
|
||||||
{selectedCommand.displayName || selectedCommand.name}
|
<span data-testid="command-name">
|
||||||
|
{selectedCommand.displayName || selectedCommand.name}
|
||||||
|
</span>
|
||||||
</p>
|
</p>
|
||||||
{Object.entries(selectedCommand?.args || {})
|
{Object.entries(selectedCommand?.args || {})
|
||||||
.filter(([_, argConfig]) =>
|
.filter(([_, argConfig]) =>
|
||||||
@ -92,6 +94,10 @@ function CommandBarHeader({ children }: React.PropsWithChildren<{}>) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
|
data-testid="cmd-bar-input-tab"
|
||||||
|
data-is-current-arg={
|
||||||
|
argName === currentArgument?.name ? 'true' : 'false'
|
||||||
|
}
|
||||||
disabled={!isReviewing && currentArgument?.name === argName}
|
disabled={!isReviewing && currentArgument?.name === argName}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
commandBarSend({
|
commandBarSend({
|
||||||
@ -110,29 +116,38 @@ function CommandBarHeader({ children }: React.PropsWithChildren<{}>) {
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
data-testid={`arg-name-${argName.toLowerCase()}`}
|
data-testid={`arg-name-${argName.toLowerCase()}`}
|
||||||
|
data-test-name="arg-name"
|
||||||
className="capitalize"
|
className="capitalize"
|
||||||
>
|
>
|
||||||
{argName}
|
{argName}
|
||||||
</span>
|
</span>
|
||||||
<span className="sr-only">: </span>
|
<span className="sr-only">: </span>
|
||||||
{argValue ? (
|
<span data-testid="header-arg-value">
|
||||||
arg.inputType === 'selection' ? (
|
{argValue ? (
|
||||||
getSelectionTypeDisplayText(argValue as Selections)
|
arg.inputType === 'selection' ? (
|
||||||
) : arg.inputType === 'kcl' ? (
|
getSelectionTypeDisplayText(argValue as Selections)
|
||||||
roundOff(
|
) : arg.inputType === 'kcl' ? (
|
||||||
Number((argValue as KclCommandValue).valueCalculated),
|
roundOff(
|
||||||
4
|
Number(
|
||||||
)
|
(argValue as KclCommandValue).valueCalculated
|
||||||
) : typeof argValue === 'object' ? (
|
),
|
||||||
arg.valueSummary ? (
|
4
|
||||||
arg.valueSummary(argValue)
|
)
|
||||||
|
) : typeof argValue === 'object' ? (
|
||||||
|
arg.valueSummary ? (
|
||||||
|
arg.valueSummary(argValue)
|
||||||
|
) : (
|
||||||
|
JSON.stringify(argValue)
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
JSON.stringify(argValue)
|
<em>
|
||||||
|
{arg.valueSummary
|
||||||
|
? arg.valueSummary(argValue)
|
||||||
|
: argValue}
|
||||||
|
</em>
|
||||||
)
|
)
|
||||||
) : (
|
) : null}
|
||||||
<em>{argValue}</em>
|
</span>
|
||||||
)
|
|
||||||
) : null}
|
|
||||||
{showShortcuts && (
|
{showShortcuts && (
|
||||||
<small className="absolute -top-[1px] right-full translate-x-1/2 px-0.5 rounded-sm bg-chalkboard-80 text-chalkboard-10 dark:bg-primary dark:text-chalkboard-100">
|
<small className="absolute -top-[1px] right-full translate-x-1/2 px-0.5 rounded-sm bg-chalkboard-80 text-chalkboard-10 dark:bg-primary dark:text-chalkboard-100">
|
||||||
<span className="sr-only">Hotkey: </span>
|
<span className="sr-only">Hotkey: </span>
|
||||||
|
|||||||
@ -139,10 +139,17 @@ function CommandBarKclInput({
|
|||||||
return (
|
return (
|
||||||
<form id="arg-form" onSubmit={handleSubmit} data-can-submit={canSubmit}>
|
<form id="arg-form" onSubmit={handleSubmit} data-can-submit={canSubmit}>
|
||||||
<label className="flex gap-4 items-center mx-4 my-4 border-solid border-b border-chalkboard-50">
|
<label className="flex gap-4 items-center mx-4 my-4 border-solid border-b border-chalkboard-50">
|
||||||
<span className="capitalize text-chalkboard-80 dark:text-chalkboard-20">
|
<span
|
||||||
|
data-testid="cmd-bar-arg-name"
|
||||||
|
className="capitalize text-chalkboard-80 dark:text-chalkboard-20"
|
||||||
|
>
|
||||||
{arg.name}
|
{arg.name}
|
||||||
</span>
|
</span>
|
||||||
<div ref={editorRef} className={styles.editor} />
|
<div
|
||||||
|
data-testid="cmd-bar-arg-value"
|
||||||
|
ref={editorRef}
|
||||||
|
className={styles.editor}
|
||||||
|
/>
|
||||||
<CustomIcon
|
<CustomIcon
|
||||||
name="equal"
|
name="equal"
|
||||||
className="w-5 h-5 text-chalkboard-70 dark:text-chalkboard-40"
|
className="w-5 h-5 text-chalkboard-70 dark:text-chalkboard-40"
|
||||||
|
|||||||
@ -58,7 +58,17 @@ function CommandBarReview({ stepBack }: { stepBack: () => void }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<CommandBarHeader>
|
<CommandBarHeader>
|
||||||
<p className="px-4">Confirm {selectedCommand?.name}</p>
|
<p className="px-4">
|
||||||
|
{selectedCommand?.reviewMessage ? (
|
||||||
|
selectedCommand.reviewMessage instanceof Function ? (
|
||||||
|
selectedCommand.reviewMessage(commandBarState.context)
|
||||||
|
) : (
|
||||||
|
selectedCommand.reviewMessage
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<>Confirm {selectedCommand?.name}</>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
<form
|
<form
|
||||||
id="review-form"
|
id="review-form"
|
||||||
className="absolute opacity-0 inset-0 pointer-events-none"
|
className="absolute opacity-0 inset-0 pointer-events-none"
|
||||||
|
|||||||
@ -31,8 +31,8 @@ function getSemanticSelectionType(selectionType: Array<Selection['type']>) {
|
|||||||
return Array.from(semanticSelectionType)
|
return Array.from(semanticSelectionType)
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectionSelector = (snapshot: StateFrom<typeof modelingMachine>) =>
|
const selectionSelector = (snapshot?: StateFrom<typeof modelingMachine>) =>
|
||||||
snapshot.context.selectionRanges
|
snapshot?.context.selectionRanges
|
||||||
|
|
||||||
function CommandBarSelectionInput({
|
function CommandBarSelectionInput({
|
||||||
arg,
|
arg,
|
||||||
@ -49,7 +49,7 @@ function CommandBarSelectionInput({
|
|||||||
const [hasSubmitted, setHasSubmitted] = useState(false)
|
const [hasSubmitted, setHasSubmitted] = useState(false)
|
||||||
const selection = useSelector(arg.machineActor, selectionSelector)
|
const selection = useSelector(arg.machineActor, selectionSelector)
|
||||||
const selectionsByType = useMemo(() => {
|
const selectionsByType = useMemo(() => {
|
||||||
const selectionRangeEnd = selection.codeBasedSelections[0]?.range[1]
|
const selectionRangeEnd = selection?.codeBasedSelections[0]?.range[1]
|
||||||
return !selectionRangeEnd || selectionRangeEnd === code.length
|
return !selectionRangeEnd || selectionRangeEnd === code.length
|
||||||
? 'none'
|
? 'none'
|
||||||
: getSelectionType(selection)
|
: getSelectionType(selection)
|
||||||
|
|||||||
@ -36,10 +36,14 @@ function CommandBarTextareaInput({
|
|||||||
return (
|
return (
|
||||||
<form id="arg-form" onSubmit={handleSubmit} ref={formRef}>
|
<form id="arg-form" onSubmit={handleSubmit} ref={formRef}>
|
||||||
<label className="flex items-start rounded mx-4 my-4 border border-chalkboard-100 dark:border-chalkboard-80">
|
<label className="flex items-start rounded mx-4 my-4 border border-chalkboard-100 dark:border-chalkboard-80">
|
||||||
<span className="capitalize px-2 py-1 rounded-br bg-chalkboard-100 dark:bg-chalkboard-80 text-chalkboard-10 border-b border-b-chalkboard-100 dark:border-b-chalkboard-80">
|
<span
|
||||||
|
data-testid="cmd-bar-arg-name"
|
||||||
|
className="capitalize px-2 py-1 rounded-br bg-chalkboard-100 dark:bg-chalkboard-80 text-chalkboard-10 border-b border-b-chalkboard-100 dark:border-b-chalkboard-80"
|
||||||
|
>
|
||||||
{arg.name}
|
{arg.name}
|
||||||
</span>
|
</span>
|
||||||
<textarea
|
<textarea
|
||||||
|
data-testid="cmd-bar-arg-value"
|
||||||
id="arg-form"
|
id="arg-form"
|
||||||
name={arg.inputType}
|
name={arg.inputType}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
|||||||
16
src/components/CommandBarOverwriteWarning.tsx
Normal file
16
src/components/CommandBarOverwriteWarning.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
interface CommandBarOverwriteWarningProps {
|
||||||
|
heading?: string
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CommandBarOverwriteWarning({
|
||||||
|
heading = 'Overwrite current file?',
|
||||||
|
message = 'This will permanently replace the current code in the editor.',
|
||||||
|
}: CommandBarOverwriteWarningProps) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p className="font-bold text-destroy-60">{heading}</p>
|
||||||
|
<p>{message}</p>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@ import { useMachine } from '@xstate/react'
|
|||||||
import { useNavigate, useRouteLoaderData } from 'react-router-dom'
|
import { useNavigate, useRouteLoaderData } from 'react-router-dom'
|
||||||
import { type IndexLoaderData } from 'lib/types'
|
import { type IndexLoaderData } from 'lib/types'
|
||||||
import { PATHS } from 'lib/paths'
|
import { PATHS } from 'lib/paths'
|
||||||
import React, { createContext } from 'react'
|
import React, { createContext, useEffect, useMemo } from 'react'
|
||||||
import { toast } from 'react-hot-toast'
|
import { toast } from 'react-hot-toast'
|
||||||
import {
|
import {
|
||||||
Actor,
|
Actor,
|
||||||
@ -22,6 +22,12 @@ import {
|
|||||||
} from 'lib/constants'
|
} from 'lib/constants'
|
||||||
import { getProjectInfo } from 'lib/desktop'
|
import { getProjectInfo } from 'lib/desktop'
|
||||||
import { getNextDirName, getNextFileName } from 'lib/desktopFS'
|
import { getNextDirName, getNextFileName } from 'lib/desktopFS'
|
||||||
|
import { kclCommands } from 'lib/kclCommands'
|
||||||
|
import { codeManager, kclManager } from 'lib/singletons'
|
||||||
|
import {
|
||||||
|
getKclSamplesManifest,
|
||||||
|
KclSamplesManifestItem,
|
||||||
|
} from 'lib/getKclSamplesManifest'
|
||||||
|
|
||||||
type MachineContext<T extends AnyStateMachine> = {
|
type MachineContext<T extends AnyStateMachine> = {
|
||||||
state: StateFrom<T>
|
state: StateFrom<T>
|
||||||
@ -41,6 +47,16 @@ export const FileMachineProvider = ({
|
|||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { commandBarSend } = useCommandsContext()
|
const { commandBarSend } = useCommandsContext()
|
||||||
const { project, file } = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
|
const { project, file } = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
|
||||||
|
const [kclSamples, setKclSamples] = React.useState<KclSamplesManifestItem[]>(
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchKclSamples() {
|
||||||
|
setKclSamples(await getKclSamplesManifest())
|
||||||
|
}
|
||||||
|
fetchKclSamples().catch(reportError)
|
||||||
|
}, [])
|
||||||
|
|
||||||
const [state, send] = useMachine(
|
const [state, send] = useMachine(
|
||||||
fileMachine.provide({
|
fileMachine.provide({
|
||||||
@ -121,6 +137,7 @@ export const FileMachineProvider = ({
|
|||||||
return {
|
return {
|
||||||
message: `Successfully created "${createdName}"`,
|
message: `Successfully created "${createdName}"`,
|
||||||
path: createdPath,
|
path: createdPath,
|
||||||
|
shouldSetToRename: input.shouldSetToRename,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
createFile: fromPromise(async ({ input }) => {
|
createFile: fromPromise(async ({ input }) => {
|
||||||
@ -271,6 +288,46 @@ export const FileMachineProvider = ({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const kclCommandMemo = useMemo(
|
||||||
|
() =>
|
||||||
|
kclCommands(
|
||||||
|
async (data) => {
|
||||||
|
if (data.method === 'overwrite') {
|
||||||
|
codeManager.updateCodeStateEditor(data.code)
|
||||||
|
await kclManager.executeCode(true)
|
||||||
|
await codeManager.writeToFile()
|
||||||
|
} else if (data.method === 'newFile' && isDesktop()) {
|
||||||
|
send({
|
||||||
|
type: 'Create file',
|
||||||
|
data: {
|
||||||
|
name: data.sampleName,
|
||||||
|
content: data.code,
|
||||||
|
makeDir: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
kclSamples.map((sample) => ({
|
||||||
|
value: sample.file,
|
||||||
|
name: sample.title,
|
||||||
|
}))
|
||||||
|
).filter(
|
||||||
|
(command) => kclSamples.length || command.name !== 'open-kcl-example'
|
||||||
|
),
|
||||||
|
[codeManager, kclManager, send, kclSamples]
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
commandBarSend({ type: 'Add commands', data: { commands: kclCommandMemo } })
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
commandBarSend({
|
||||||
|
type: 'Remove commands',
|
||||||
|
data: { commands: kclCommandMemo },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [commandBarSend, kclCommandMemo])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FileContext.Provider
|
<FileContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
|||||||
@ -393,14 +393,14 @@ export const FileTreeMenu = () => {
|
|||||||
function createFile() {
|
function createFile() {
|
||||||
send({
|
send({
|
||||||
type: 'Create file',
|
type: 'Create file',
|
||||||
data: { name: '', makeDir: false },
|
data: { name: '', makeDir: false, shouldSetToRename: true },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function createFolder() {
|
function createFolder() {
|
||||||
send({
|
send({
|
||||||
type: 'Create file',
|
type: 'Create file',
|
||||||
data: { name: '', makeDir: true },
|
data: { name: '', makeDir: true, shouldSetToRename: true },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,7 @@ import {
|
|||||||
canSweepSelection,
|
canSweepSelection,
|
||||||
handleSelectionBatch,
|
handleSelectionBatch,
|
||||||
isSelectionLastLine,
|
isSelectionLastLine,
|
||||||
isRangeInbetweenCharacters,
|
isRangeBetweenCharacters,
|
||||||
isSketchPipe,
|
isSketchPipe,
|
||||||
updateSelections,
|
updateSelections,
|
||||||
} from 'lib/selections'
|
} from 'lib/selections'
|
||||||
@ -50,8 +50,7 @@ import { applyConstraintAbsDistance } from './Toolbar/SetAbsDistance'
|
|||||||
import useStateMachineCommands from 'hooks/useStateMachineCommands'
|
import useStateMachineCommands from 'hooks/useStateMachineCommands'
|
||||||
import { modelingMachineCommandConfig } from 'lib/commandBarConfigs/modelingCommandConfig'
|
import { modelingMachineCommandConfig } from 'lib/commandBarConfigs/modelingCommandConfig'
|
||||||
import {
|
import {
|
||||||
STRAIGHT_SEGMENT,
|
SEGMENT_BODIES,
|
||||||
TANGENTIAL_ARC_TO_SEGMENT,
|
|
||||||
getParentGroup,
|
getParentGroup,
|
||||||
getSketchOrientationDetails,
|
getSketchOrientationDetails,
|
||||||
} from 'clientSideScene/sceneEntities'
|
} from 'clientSideScene/sceneEntities'
|
||||||
@ -168,10 +167,7 @@ export const ModelingMachineProvider = ({
|
|||||||
if (event.type !== 'Set mouse state') return {}
|
if (event.type !== 'Set mouse state') return {}
|
||||||
const nextSegmentHoverMap = () => {
|
const nextSegmentHoverMap = () => {
|
||||||
if (event.data.type === 'isHovering') {
|
if (event.data.type === 'isHovering') {
|
||||||
const parent = getParentGroup(event.data.on, [
|
const parent = getParentGroup(event.data.on, SEGMENT_BODIES)
|
||||||
STRAIGHT_SEGMENT,
|
|
||||||
TANGENTIAL_ARC_TO_SEGMENT,
|
|
||||||
])
|
|
||||||
const pathToNode = parent?.userData?.pathToNode
|
const pathToNode = parent?.userData?.pathToNode
|
||||||
const pathToNodeString = JSON.stringify(pathToNode)
|
const pathToNodeString = JSON.stringify(pathToNode)
|
||||||
if (!parent || !pathToNode) return context.segmentHoverMap
|
if (!parent || !pathToNode) return context.segmentHoverMap
|
||||||
@ -187,10 +183,10 @@ export const ModelingMachineProvider = ({
|
|||||||
event.data.type === 'idle' &&
|
event.data.type === 'idle' &&
|
||||||
context.mouseState.type === 'isHovering'
|
context.mouseState.type === 'isHovering'
|
||||||
) {
|
) {
|
||||||
const mouseOnParent = getParentGroup(context.mouseState.on, [
|
const mouseOnParent = getParentGroup(
|
||||||
STRAIGHT_SEGMENT,
|
context.mouseState.on,
|
||||||
TANGENTIAL_ARC_TO_SEGMENT,
|
SEGMENT_BODIES
|
||||||
])
|
)
|
||||||
if (!mouseOnParent || !mouseOnParent?.userData?.pathToNode)
|
if (!mouseOnParent || !mouseOnParent?.userData?.pathToNode)
|
||||||
return context.segmentHoverMap
|
return context.segmentHoverMap
|
||||||
const pathToNodeString = JSON.stringify(
|
const pathToNodeString = JSON.stringify(
|
||||||
@ -204,8 +200,8 @@ export const ModelingMachineProvider = ({
|
|||||||
pathToNodeString,
|
pathToNodeString,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
// overlay timeout
|
// overlay timeout is 1s
|
||||||
}, 800) as unknown as number
|
}, 1000) as unknown as number
|
||||||
return {
|
return {
|
||||||
...context.segmentHoverMap,
|
...context.segmentHoverMap,
|
||||||
[pathToNodeString]: timeoutId,
|
[pathToNodeString]: timeoutId,
|
||||||
@ -495,43 +491,21 @@ export const ModelingMachineProvider = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
guards: {
|
guards: {
|
||||||
'has valid extrude selection': ({ context: { selectionRanges } }) => {
|
'has valid sweep selection': ({ context: { selectionRanges } }) => {
|
||||||
// A user can begin extruding if they either have 1+ faces selected or nothing selected
|
// A user can begin extruding if they either have 1+ faces selected or nothing selected
|
||||||
// TODO: I believe this guard only allows for extruding a single face at a time
|
// TODO: I believe this guard only allows for extruding a single face at a time
|
||||||
const isPipe = isSketchPipe(selectionRanges)
|
const hasNoSelection =
|
||||||
|
|
||||||
if (
|
|
||||||
selectionRanges.codeBasedSelections.length === 0 ||
|
selectionRanges.codeBasedSelections.length === 0 ||
|
||||||
isRangeInbetweenCharacters(selectionRanges) ||
|
isRangeBetweenCharacters(selectionRanges) ||
|
||||||
isSelectionLastLine(selectionRanges, codeManager.code)
|
isSelectionLastLine(selectionRanges, codeManager.code)
|
||||||
) {
|
|
||||||
|
if (hasNoSelection) {
|
||||||
// they have no selection, we should enable the button
|
// they have no selection, we should enable the button
|
||||||
// so they can select the face through the cmdbar
|
// so they can select the face through the cmdbar
|
||||||
// BUT only if there's extrudable geometry
|
// BUT only if there's extrudable geometry
|
||||||
if (doesSceneHaveSweepableSketch(kclManager.ast)) return true
|
return doesSceneHaveSweepableSketch(kclManager.ast)
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
if (!isPipe) return false
|
if (!isSketchPipe(selectionRanges)) return false
|
||||||
|
|
||||||
return canSweepSelection(selectionRanges)
|
|
||||||
},
|
|
||||||
'has valid revolve selection': ({ context: { selectionRanges } }) => {
|
|
||||||
// A user can begin extruding if they either have 1+ faces selected or nothing selected
|
|
||||||
// TODO: I believe this guard only allows for extruding a single face at a time
|
|
||||||
const isPipe = isSketchPipe(selectionRanges)
|
|
||||||
|
|
||||||
if (
|
|
||||||
selectionRanges.codeBasedSelections.length === 0 ||
|
|
||||||
isRangeInbetweenCharacters(selectionRanges) ||
|
|
||||||
isSelectionLastLine(selectionRanges, codeManager.code)
|
|
||||||
) {
|
|
||||||
// they have no selection, we should enable the button
|
|
||||||
// so they can select the face through the cmdbar
|
|
||||||
// BUT only if there's extrudable geometry
|
|
||||||
if (doesSceneHaveSweepableSketch(kclManager.ast)) return true
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (!isPipe) return false
|
|
||||||
|
|
||||||
return canSweepSelection(selectionRanges)
|
return canSweepSelection(selectionRanges)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -9,10 +9,12 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|||||||
import { kclManager } from 'lib/singletons'
|
import { kclManager } from 'lib/singletons'
|
||||||
import { openExternalBrowserIfDesktop } from 'lib/openWindow'
|
import { openExternalBrowserIfDesktop } from 'lib/openWindow'
|
||||||
import { reportRejection } from 'lib/trap'
|
import { reportRejection } from 'lib/trap'
|
||||||
|
import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||||
|
|
||||||
export const KclEditorMenu = ({ children }: PropsWithChildren) => {
|
export const KclEditorMenu = ({ children }: PropsWithChildren) => {
|
||||||
const { enable: convertToVarEnabled, handleClick: handleConvertToVarClick } =
|
const { enable: convertToVarEnabled, handleClick: handleConvertToVarClick } =
|
||||||
useConvertToVariable()
|
useConvertToVariable()
|
||||||
|
const { commandBarSend } = useCommandsContext()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu>
|
<Menu>
|
||||||
@ -77,6 +79,22 @@ export const KclEditorMenu = ({ children }: PropsWithChildren) => {
|
|||||||
</small>
|
</small>
|
||||||
</a>
|
</a>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
<Menu.Item>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
commandBarSend({
|
||||||
|
type: 'Find and select command',
|
||||||
|
data: {
|
||||||
|
groupId: 'code',
|
||||||
|
name: 'open-kcl-example',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
className={styles.button}
|
||||||
|
>
|
||||||
|
<span>Load a sample model</span>
|
||||||
|
</button>
|
||||||
|
</Menu.Item>
|
||||||
<Menu.Item>
|
<Menu.Item>
|
||||||
<a
|
<a
|
||||||
className={styles.button}
|
className={styles.button}
|
||||||
@ -85,7 +103,7 @@ export const KclEditorMenu = ({ children }: PropsWithChildren) => {
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
onClick={openExternalBrowserIfDesktop()}
|
onClick={openExternalBrowserIfDesktop()}
|
||||||
>
|
>
|
||||||
<span>KCL samples</span>
|
<span>View all samples</span>
|
||||||
<small>
|
<small>
|
||||||
zoo.dev
|
zoo.dev
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
|
|||||||
64
src/components/ToastUpdate.tsx
Normal file
64
src/components/ToastUpdate.tsx
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import toast from 'react-hot-toast'
|
||||||
|
import { ActionButton } from './ActionButton'
|
||||||
|
import { openExternalBrowserIfDesktop } from 'lib/openWindow'
|
||||||
|
|
||||||
|
export function ToastUpdate({
|
||||||
|
version,
|
||||||
|
onRestart,
|
||||||
|
}: {
|
||||||
|
version: string
|
||||||
|
onRestart: () => void
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="inset-0 z-50 grid place-content-center rounded bg-chalkboard-110/50 shadow-md">
|
||||||
|
<div className="max-w-3xl min-w-[35rem] p-8 rounded bg-chalkboard-10 dark:bg-chalkboard-90">
|
||||||
|
<div className="my-4 flex items-baseline">
|
||||||
|
<span
|
||||||
|
className="px-3 py-1 text-xl rounded-full bg-primary text-chalkboard-10"
|
||||||
|
data-testid="update-version"
|
||||||
|
>
|
||||||
|
v{version}
|
||||||
|
</span>
|
||||||
|
<span className="ml-4 text-md text-bold">
|
||||||
|
A new update has downloaded and will be available next time you
|
||||||
|
start the app. You can view the release notes{' '}
|
||||||
|
<a
|
||||||
|
onClick={openExternalBrowserIfDesktop(
|
||||||
|
`https://github.com/KittyCAD/modeling-app/releases/tag/v${version}`
|
||||||
|
)}
|
||||||
|
href={`https://github.com/KittyCAD/modeling-app/releases/tag/v${version}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
here on GitHub.
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between gap-8">
|
||||||
|
<ActionButton
|
||||||
|
Element="button"
|
||||||
|
iconStart={{
|
||||||
|
icon: 'arrowRotateRight',
|
||||||
|
}}
|
||||||
|
name="Restart app now"
|
||||||
|
onClick={onRestart}
|
||||||
|
>
|
||||||
|
Restart app now
|
||||||
|
</ActionButton>
|
||||||
|
<ActionButton
|
||||||
|
Element="button"
|
||||||
|
iconStart={{
|
||||||
|
icon: 'checkmark',
|
||||||
|
}}
|
||||||
|
name="Got it"
|
||||||
|
onClick={() => {
|
||||||
|
toast.dismiss()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Got it
|
||||||
|
</ActionButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,12 +1,13 @@
|
|||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import reportWebVitals from './reportWebVitals'
|
import reportWebVitals from './reportWebVitals'
|
||||||
import { Toaster } from 'react-hot-toast'
|
import toast, { Toaster } from 'react-hot-toast'
|
||||||
import { Router } from './Router'
|
import { Router } from './Router'
|
||||||
import { HotkeysProvider } from 'react-hotkeys-hook'
|
import { HotkeysProvider } from 'react-hotkeys-hook'
|
||||||
import ModalContainer from 'react-modal-promise'
|
import ModalContainer from 'react-modal-promise'
|
||||||
import { isDesktop } from 'lib/isDesktop'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { AppStreamProvider } from 'AppState'
|
import { AppStreamProvider } from 'AppState'
|
||||||
|
import { ToastUpdate } from 'components/ToastUpdate'
|
||||||
|
|
||||||
// uncomment for xstate inspector
|
// uncomment for xstate inspector
|
||||||
// import { DEV } from 'env'
|
// import { DEV } from 'env'
|
||||||
@ -52,4 +53,17 @@ root.render(
|
|||||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||||
reportWebVitals()
|
reportWebVitals()
|
||||||
|
|
||||||
isDesktop()
|
isDesktop() &&
|
||||||
|
window.electron.onUpdateDownloaded((version: string) => {
|
||||||
|
const message = `A new update (${version}) was downloaded and will be available next time you open the app.`
|
||||||
|
console.log(message)
|
||||||
|
toast.custom(
|
||||||
|
ToastUpdate({
|
||||||
|
version,
|
||||||
|
onRestart: () => {
|
||||||
|
window.electron.appRestart()
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{ duration: 30000 }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|||||||
@ -3,8 +3,6 @@ import { createContext, useContext, useEffect, useState } from 'react'
|
|||||||
import { type IndexLoaderData } from 'lib/types'
|
import { type IndexLoaderData } from 'lib/types'
|
||||||
import { useLoaderData } from 'react-router-dom'
|
import { useLoaderData } from 'react-router-dom'
|
||||||
import { codeManager, kclManager } from 'lib/singletons'
|
import { codeManager, kclManager } from 'lib/singletons'
|
||||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
|
||||||
import { Command } from 'lib/commandTypes'
|
|
||||||
|
|
||||||
const KclContext = createContext({
|
const KclContext = createContext({
|
||||||
code: codeManager?.code || '',
|
code: codeManager?.code || '',
|
||||||
@ -37,7 +35,6 @@ export function KclContextProvider({
|
|||||||
const [errors, setErrors] = useState<KCLError[]>([])
|
const [errors, setErrors] = useState<KCLError[]>([])
|
||||||
const [logs, setLogs] = useState<string[]>([])
|
const [logs, setLogs] = useState<string[]>([])
|
||||||
const [wasmInitFailed, setWasmInitFailed] = useState(false)
|
const [wasmInitFailed, setWasmInitFailed] = useState(false)
|
||||||
const { commandBarSend } = useCommandsContext()
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
codeManager.registerCallBacks({
|
codeManager.registerCallBacks({
|
||||||
@ -53,28 +50,6 @@ export function KclContextProvider({
|
|||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
// Add format code to command palette.
|
|
||||||
useEffect(() => {
|
|
||||||
const commands: Command[] = [
|
|
||||||
{
|
|
||||||
name: 'format-code',
|
|
||||||
displayName: 'Format Code',
|
|
||||||
description: 'Nicely formats the KCL code in the editor.',
|
|
||||||
needsReview: false,
|
|
||||||
groupId: 'code',
|
|
||||||
icon: 'code',
|
|
||||||
onSubmit: (data) => {
|
|
||||||
kclManager.format()
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
commandBarSend({ type: 'Add commands', data: { commands } })
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
commandBarSend({ type: 'Remove commands', data: { commands } })
|
|
||||||
}
|
|
||||||
}, [kclManager, commandBarSend])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KclContext.Provider
|
<KclContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
|||||||
@ -416,7 +416,7 @@ export class KclManager {
|
|||||||
ast: Program,
|
ast: Program,
|
||||||
execute: boolean,
|
execute: boolean,
|
||||||
optionalParams?: {
|
optionalParams?: {
|
||||||
focusPath?: PathToNode
|
focusPath?: Array<PathToNode>
|
||||||
zoomToFit?: boolean
|
zoomToFit?: boolean
|
||||||
zoomOnRangeAndType?: {
|
zoomOnRangeAndType?: {
|
||||||
range: SourceRange
|
range: SourceRange
|
||||||
@ -435,27 +435,34 @@ export class KclManager {
|
|||||||
let returnVal: Selections | undefined = undefined
|
let returnVal: Selections | undefined = undefined
|
||||||
|
|
||||||
if (optionalParams?.focusPath) {
|
if (optionalParams?.focusPath) {
|
||||||
const _node1 = getNodeFromPath<any>(
|
|
||||||
astWithUpdatedSource,
|
|
||||||
optionalParams?.focusPath
|
|
||||||
)
|
|
||||||
if (err(_node1)) return Promise.reject(_node1)
|
|
||||||
const { node } = _node1
|
|
||||||
|
|
||||||
const { start, end } = node
|
|
||||||
if (!start || !end)
|
|
||||||
return {
|
|
||||||
selections: undefined,
|
|
||||||
newAst: astWithUpdatedSource,
|
|
||||||
}
|
|
||||||
returnVal = {
|
returnVal = {
|
||||||
codeBasedSelections: [
|
codeBasedSelections: [],
|
||||||
{
|
otherSelections: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const path of optionalParams.focusPath) {
|
||||||
|
const getNodeFromPathResult = getNodeFromPath<any>(
|
||||||
|
astWithUpdatedSource,
|
||||||
|
path
|
||||||
|
)
|
||||||
|
if (err(getNodeFromPathResult))
|
||||||
|
return Promise.reject(getNodeFromPathResult)
|
||||||
|
const { node } = getNodeFromPathResult
|
||||||
|
|
||||||
|
const { start, end } = node
|
||||||
|
|
||||||
|
if (!start || !end)
|
||||||
|
return {
|
||||||
|
selections: undefined,
|
||||||
|
newAst: astWithUpdatedSource,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start && end) {
|
||||||
|
returnVal.codeBasedSelections.push({
|
||||||
type: 'default',
|
type: 'default',
|
||||||
range: [start, end],
|
range: [start, end],
|
||||||
},
|
})
|
||||||
],
|
}
|
||||||
otherSelections: [],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1766,17 +1766,17 @@ const key = 'c'`
|
|||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const { nonCodeMeta } = ast
|
const { nonCodeMeta } = ast
|
||||||
expect(nonCodeMeta.nonCodeNodes[0][0]).toEqual(nonCodeMetaInstance)
|
expect(nonCodeMeta.nonCodeNodes[0]?.[0]).toEqual(nonCodeMetaInstance)
|
||||||
|
|
||||||
// extra whitespace won't change it's position (0) or value (NB the start end would have changed though)
|
// extra whitespace won't change it's position (0) or value (NB the start end would have changed though)
|
||||||
const codeWithExtraStartWhitespace = '\n\n\n' + code
|
const codeWithExtraStartWhitespace = '\n\n\n' + code
|
||||||
const ast2 = parse(codeWithExtraStartWhitespace)
|
const ast2 = parse(codeWithExtraStartWhitespace)
|
||||||
if (err(ast2)) throw ast2
|
if (err(ast2)) throw ast2
|
||||||
const { nonCodeMeta: nonCodeMeta2 } = ast2
|
const { nonCodeMeta: nonCodeMeta2 } = ast2
|
||||||
expect(nonCodeMeta2.nonCodeNodes[0][0].value).toStrictEqual(
|
expect(nonCodeMeta2.nonCodeNodes[0]?.[0].value).toStrictEqual(
|
||||||
nonCodeMetaInstance.value
|
nonCodeMetaInstance.value
|
||||||
)
|
)
|
||||||
expect(nonCodeMeta2.nonCodeNodes[0][0].start).not.toBe(
|
expect(nonCodeMeta2.nonCodeNodes[0]?.[0].start).not.toBe(
|
||||||
nonCodeMetaInstance.start
|
nonCodeMetaInstance.start
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -24,8 +24,9 @@ export type ToolTip =
|
|||||||
| 'yLineTo'
|
| 'yLineTo'
|
||||||
| 'angledLineThatIntersects'
|
| 'angledLineThatIntersects'
|
||||||
| 'tangentialArcTo'
|
| 'tangentialArcTo'
|
||||||
|
| 'circle'
|
||||||
|
|
||||||
export const toolTips = [
|
export const toolTips: Array<ToolTip> = [
|
||||||
'line',
|
'line',
|
||||||
'lineTo',
|
'lineTo',
|
||||||
'angledLine',
|
'angledLine',
|
||||||
|
|||||||
@ -129,7 +129,7 @@ describe('Testing addSketchTo', () => {
|
|||||||
'yz'
|
'yz'
|
||||||
)
|
)
|
||||||
const str = recast(result.modifiedAst)
|
const str = recast(result.modifiedAst)
|
||||||
expect(str).toBe(`const sketch001 = startSketchOn('YZ')
|
expect(str).toBe(`let sketch001 = startSketchOn('YZ')
|
||||||
|> startProfileAt('default', %)
|
|> startProfileAt('default', %)
|
||||||
|> line('default', %)
|
|> line('default', %)
|
||||||
`)
|
`)
|
||||||
@ -156,7 +156,7 @@ function giveSketchFnCallTagTestHelper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('Testing giveSketchFnCallTag', () => {
|
describe('Testing giveSketchFnCallTag', () => {
|
||||||
const code = `const part001 = startSketchOn('XY')
|
const code = `let part001 = startSketchOn('XY')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([-2.57, -0.13], %)
|
|> line([-2.57, -0.13], %)
|
||||||
|> line([0, 0.83], %)
|
|> line([0, 0.83], %)
|
||||||
@ -205,10 +205,10 @@ describe('Testing moveValueIntoNewVariable', () => {
|
|||||||
fn ghi = (x) => {
|
fn ghi = (x) => {
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
const abc = 3
|
let abc = 3
|
||||||
const identifierGuy = 5
|
let identifierGuy = 5
|
||||||
const yo = 5 + 6
|
let yo = 5 + 6
|
||||||
const part001 = startSketchOn('XY')
|
let part001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-1.2, 4.83], %)
|
|> startProfileAt([-1.2, 4.83], %)
|
||||||
|> line([2.8, 0], %)
|
|> line([2.8, 0], %)
|
||||||
|> angledLine([100 + 100, 3.09], %)
|
|> angledLine([100 + 100, 3.09], %)
|
||||||
@ -216,7 +216,7 @@ const part001 = startSketchOn('XY')
|
|||||||
|> angledLine([def(yo), 3.09], %)
|
|> angledLine([def(yo), 3.09], %)
|
||||||
|> angledLine([ghi(%), 3.09], %)
|
|> angledLine([ghi(%), 3.09], %)
|
||||||
|> angledLine([jkl(yo) + 2, 3.09], %)
|
|> angledLine([jkl(yo) + 2, 3.09], %)
|
||||||
const yo2 = hmm([identifierGuy + 5])`
|
let yo2 = hmm([identifierGuy + 5])`
|
||||||
it('should move a binary expression into a new variable', async () => {
|
it('should move a binary expression into a new variable', async () => {
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
@ -229,7 +229,7 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
'newVar'
|
'newVar'
|
||||||
)
|
)
|
||||||
const newCode = recast(modifiedAst)
|
const newCode = recast(modifiedAst)
|
||||||
expect(newCode).toContain(`const newVar = 100 + 100`)
|
expect(newCode).toContain(`let newVar = 100 + 100`)
|
||||||
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
|
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
|
||||||
})
|
})
|
||||||
it('should move a value into a new variable', async () => {
|
it('should move a value into a new variable', async () => {
|
||||||
@ -244,7 +244,7 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
'newVar'
|
'newVar'
|
||||||
)
|
)
|
||||||
const newCode = recast(modifiedAst)
|
const newCode = recast(modifiedAst)
|
||||||
expect(newCode).toContain(`const newVar = 2.8`)
|
expect(newCode).toContain(`let newVar = 2.8`)
|
||||||
expect(newCode).toContain(`line([newVar, 0], %)`)
|
expect(newCode).toContain(`line([newVar, 0], %)`)
|
||||||
})
|
})
|
||||||
it('should move a callExpression into a new variable', async () => {
|
it('should move a callExpression into a new variable', async () => {
|
||||||
@ -259,7 +259,7 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
'newVar'
|
'newVar'
|
||||||
)
|
)
|
||||||
const newCode = recast(modifiedAst)
|
const newCode = recast(modifiedAst)
|
||||||
expect(newCode).toContain(`const newVar = def(yo)`)
|
expect(newCode).toContain(`let newVar = def(yo)`)
|
||||||
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
|
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
|
||||||
})
|
})
|
||||||
it('should move a binary expression with call expression into a new variable', async () => {
|
it('should move a binary expression with call expression into a new variable', async () => {
|
||||||
@ -274,7 +274,7 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
'newVar'
|
'newVar'
|
||||||
)
|
)
|
||||||
const newCode = recast(modifiedAst)
|
const newCode = recast(modifiedAst)
|
||||||
expect(newCode).toContain(`const newVar = jkl(yo) + 2`)
|
expect(newCode).toContain(`let newVar = jkl(yo) + 2`)
|
||||||
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
|
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
|
||||||
})
|
})
|
||||||
it('should move a identifier into a new variable', async () => {
|
it('should move a identifier into a new variable', async () => {
|
||||||
@ -289,14 +289,14 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
'newVar'
|
'newVar'
|
||||||
)
|
)
|
||||||
const newCode = recast(modifiedAst)
|
const newCode = recast(modifiedAst)
|
||||||
expect(newCode).toContain(`const newVar = identifierGuy + 5`)
|
expect(newCode).toContain(`let newVar = identifierGuy + 5`)
|
||||||
expect(newCode).toContain(`const yo2 = hmm([newVar])`)
|
expect(newCode).toContain(`let yo2 = hmm([newVar])`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('testing sketchOnExtrudedFace', () => {
|
describe('testing sketchOnExtrudedFace', () => {
|
||||||
test('it should be able to extrude on regular segments', async () => {
|
test('it should be able to extrude on regular segments', async () => {
|
||||||
const code = `const part001 = startSketchOn('-XZ')
|
const code = `let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([3.58, 2.06], %)
|
|> startProfileAt([3.58, 2.06], %)
|
||||||
|> line([9.7, 9.19], %)
|
|> line([9.7, 9.19], %)
|
||||||
|> line([8.62, -9.57], %)
|
|> line([8.62, -9.57], %)
|
||||||
@ -327,16 +327,16 @@ describe('testing sketchOnExtrudedFace', () => {
|
|||||||
const { modifiedAst } = extruded
|
const { modifiedAst } = extruded
|
||||||
|
|
||||||
const newCode = recast(modifiedAst)
|
const newCode = recast(modifiedAst)
|
||||||
expect(newCode).toContain(`const part001 = startSketchOn('-XZ')
|
expect(newCode).toContain(`let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([3.58, 2.06], %)
|
|> startProfileAt([3.58, 2.06], %)
|
||||||
|> line([9.7, 9.19], %, $seg01)
|
|> line([9.7, 9.19], %, $seg01)
|
||||||
|> line([8.62, -9.57], %)
|
|> line([8.62, -9.57], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> extrude(5 + 7, %)
|
|> extrude(5 + 7, %)
|
||||||
const sketch001 = startSketchOn(part001, seg01)`)
|
let sketch001 = startSketchOn(part001, seg01)`)
|
||||||
})
|
})
|
||||||
test('it should be able to extrude on close segments', async () => {
|
test('it should be able to extrude on close segments', async () => {
|
||||||
const code = `const part001 = startSketchOn('-XZ')
|
const code = `let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([3.58, 2.06], %)
|
|> startProfileAt([3.58, 2.06], %)
|
||||||
|> line([9.7, 9.19], %)
|
|> line([9.7, 9.19], %)
|
||||||
|> line([8.62, -9.57], %)
|
|> line([8.62, -9.57], %)
|
||||||
@ -366,16 +366,16 @@ const sketch001 = startSketchOn(part001, seg01)`)
|
|||||||
const { modifiedAst } = extruded
|
const { modifiedAst } = extruded
|
||||||
|
|
||||||
const newCode = recast(modifiedAst)
|
const newCode = recast(modifiedAst)
|
||||||
expect(newCode).toContain(`const part001 = startSketchOn('-XZ')
|
expect(newCode).toContain(`let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([3.58, 2.06], %)
|
|> startProfileAt([3.58, 2.06], %)
|
||||||
|> line([9.7, 9.19], %)
|
|> line([9.7, 9.19], %)
|
||||||
|> line([8.62, -9.57], %)
|
|> line([8.62, -9.57], %)
|
||||||
|> close(%, $seg01)
|
|> close(%, $seg01)
|
||||||
|> extrude(5 + 7, %)
|
|> extrude(5 + 7, %)
|
||||||
const sketch001 = startSketchOn(part001, seg01)`)
|
let sketch001 = startSketchOn(part001, seg01)`)
|
||||||
})
|
})
|
||||||
test('it should be able to extrude on start-end caps', async () => {
|
test('it should be able to extrude on start-end caps', async () => {
|
||||||
const code = `const part001 = startSketchOn('-XZ')
|
const code = `let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([3.58, 2.06], %)
|
|> startProfileAt([3.58, 2.06], %)
|
||||||
|> line([9.7, 9.19], %)
|
|> line([9.7, 9.19], %)
|
||||||
|> line([8.62, -9.57], %)
|
|> line([8.62, -9.57], %)
|
||||||
@ -406,16 +406,16 @@ const sketch001 = startSketchOn(part001, seg01)`)
|
|||||||
const { modifiedAst } = extruded
|
const { modifiedAst } = extruded
|
||||||
|
|
||||||
const newCode = recast(modifiedAst)
|
const newCode = recast(modifiedAst)
|
||||||
expect(newCode).toContain(`const part001 = startSketchOn('-XZ')
|
expect(newCode).toContain(`let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([3.58, 2.06], %)
|
|> startProfileAt([3.58, 2.06], %)
|
||||||
|> line([9.7, 9.19], %)
|
|> line([9.7, 9.19], %)
|
||||||
|> line([8.62, -9.57], %)
|
|> line([8.62, -9.57], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
|> extrude(5 + 7, %)
|
|> extrude(5 + 7, %)
|
||||||
const sketch001 = startSketchOn(part001, 'END')`)
|
let sketch001 = startSketchOn(part001, 'END')`)
|
||||||
})
|
})
|
||||||
test('it should ensure that the new sketch is inserted after the extrude', async () => {
|
test('it should ensure that the new sketch is inserted after the extrude', async () => {
|
||||||
const code = `const sketch001 = startSketchOn('-XZ')
|
const code = `let sketch001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([3.29, 7.86], %)
|
|> startProfileAt([3.29, 7.86], %)
|
||||||
|> line([2.48, 2.44], %)
|
|> line([2.48, 2.44], %)
|
||||||
|> line([2.66, 1.17], %)
|
|> line([2.66, 1.17], %)
|
||||||
@ -428,7 +428,7 @@ const sketch001 = startSketchOn(part001, 'END')`)
|
|||||||
|> line([-3.86, -2.73], %)
|
|> line([-3.86, -2.73], %)
|
||||||
|> line([-17.67, 0.85], %)
|
|> line([-17.67, 0.85], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const part001 = extrude(5 + 7, sketch001)`
|
let part001 = extrude(5 + 7, sketch001)`
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const segmentSnippet = `line([4.99, -0.46], %)`
|
const segmentSnippet = `line([4.99, -0.46], %)`
|
||||||
@ -451,14 +451,14 @@ const sketch001 = startSketchOn(part001, 'END')`)
|
|||||||
)
|
)
|
||||||
if (err(updatedAst)) throw updatedAst
|
if (err(updatedAst)) throw updatedAst
|
||||||
const newCode = recast(updatedAst.modifiedAst)
|
const newCode = recast(updatedAst.modifiedAst)
|
||||||
expect(newCode).toContain(`const part001 = extrude(5 + 7, sketch001)
|
expect(newCode).toContain(`let part001 = extrude(5 + 7, sketch001)
|
||||||
const sketch002 = startSketchOn(part001, seg01)`)
|
let sketch002 = startSketchOn(part001, seg01)`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Testing deleteSegmentFromPipeExpression', () => {
|
describe('Testing deleteSegmentFromPipeExpression', () => {
|
||||||
it('Should delete a segment withOUT any dependent segments', async () => {
|
it('Should delete a segment withOUT any dependent segments', async () => {
|
||||||
const code = `const part001 = startSketchOn('-XZ')
|
const code = `let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([54.78, -95.91], %)
|
|> startProfileAt([54.78, -95.91], %)
|
||||||
|> line([306.21, 198.82], %)
|
|> line([306.21, 198.82], %)
|
||||||
|> line([306.21, 198.85], %, $a)
|
|> line([306.21, 198.85], %, $a)
|
||||||
@ -481,7 +481,7 @@ describe('Testing deleteSegmentFromPipeExpression', () => {
|
|||||||
)
|
)
|
||||||
if (err(modifiedAst)) throw modifiedAst
|
if (err(modifiedAst)) throw modifiedAst
|
||||||
const newCode = recast(modifiedAst)
|
const newCode = recast(modifiedAst)
|
||||||
expect(newCode).toBe(`const part001 = startSketchOn('-XZ')
|
expect(newCode).toBe(`let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([54.78, -95.91], %)
|
|> startProfileAt([54.78, -95.91], %)
|
||||||
|> line([306.21, 198.82], %)
|
|> line([306.21, 198.82], %)
|
||||||
|> line([306.21, 198.87], %)
|
|> line([306.21, 198.87], %)
|
||||||
@ -492,7 +492,7 @@ describe('Testing deleteSegmentFromPipeExpression', () => {
|
|||||||
line: string,
|
line: string,
|
||||||
replace1 = '',
|
replace1 = '',
|
||||||
replace2 = ''
|
replace2 = ''
|
||||||
) => `const part001 = startSketchOn('-XZ')
|
) => `let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([54.78, -95.91], %)
|
|> startProfileAt([54.78, -95.91], %)
|
||||||
|> line([306.21, 198.82], %, $b)
|
|> line([306.21, 198.82], %, $b)
|
||||||
${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
|
${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
|
||||||
@ -567,7 +567,7 @@ ${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
|
|||||||
|
|
||||||
describe('Testing removeSingleConstraintInfo', () => {
|
describe('Testing removeSingleConstraintInfo', () => {
|
||||||
describe('with mostly object notation', () => {
|
describe('with mostly object notation', () => {
|
||||||
const code = `const part001 = startSketchOn('-XZ')
|
const code = `let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([3 + 0, 4 + 0], %)
|
|> line([3 + 0, 4 + 0], %)
|
||||||
|> angledLine({ angle: 3 + 0, length: 3.14 + 0 }, %)
|
|> angledLine({ angle: 3 + 0, length: 3.14 + 0 }, %)
|
||||||
@ -669,7 +669,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('with array notation', () => {
|
describe('with array notation', () => {
|
||||||
const code = `const part001 = startSketchOn('-XZ')
|
const code = `let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> angledLine([3.14 + 0, 3.14 + 0], %)
|
|> angledLine([3.14 + 0, 3.14 + 0], %)
|
||||||
|> angledLineOfXLength([3 + 0, 3.14 + 0], %)
|
|> angledLineOfXLength([3 + 0, 3.14 + 0], %)
|
||||||
@ -725,14 +725,14 @@ describe('Testing deleteFromSelection', () => {
|
|||||||
[
|
[
|
||||||
'basicCase',
|
'basicCase',
|
||||||
{
|
{
|
||||||
codeBefore: `const myVar = 5
|
codeBefore: `let myVar = 5
|
||||||
const sketch003 = startSketchOn('XZ')
|
let sketch003 = startSketchOn('XZ')
|
||||||
|> startProfileAt([3.82, 13.6], %)
|
|> startProfileAt([3.82, 13.6], %)
|
||||||
|> line([-2.94, 2.7], %)
|
|> line([-2.94, 2.7], %)
|
||||||
|> line([7.7, 0.16], %)
|
|> line([7.7, 0.16], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)`,
|
|> close(%)`,
|
||||||
codeAfter: `const myVar = 5\n`,
|
codeAfter: `let myVar = 5\n`,
|
||||||
lineOfInterest: 'line([-2.94, 2.7], %)',
|
lineOfInterest: 'line([-2.94, 2.7], %)',
|
||||||
type: 'default',
|
type: 'default',
|
||||||
},
|
},
|
||||||
@ -740,7 +740,7 @@ const sketch003 = startSketchOn('XZ')
|
|||||||
[
|
[
|
||||||
'delete extrude',
|
'delete extrude',
|
||||||
{
|
{
|
||||||
codeBefore: `const sketch001 = startSketchOn('XZ')
|
codeBefore: `let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([3.29, 7.86], %)
|
|> startProfileAt([3.29, 7.86], %)
|
||||||
|> line([2.48, 2.44], %)
|
|> line([2.48, 2.44], %)
|
||||||
|> line([2.66, 1.17], %)
|
|> line([2.66, 1.17], %)
|
||||||
@ -750,7 +750,7 @@ const sketch003 = startSketchOn('XZ')
|
|||||||
|> line([-17.67, 0.85], %)
|
|> line([-17.67, 0.85], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(10, sketch001)`,
|
const extrude001 = extrude(10, sketch001)`,
|
||||||
codeAfter: `const sketch001 = startSketchOn('XZ')
|
codeAfter: `let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([3.29, 7.86], %)
|
|> startProfileAt([3.29, 7.86], %)
|
||||||
|> line([2.48, 2.44], %)
|
|> line([2.48, 2.44], %)
|
||||||
|> line([2.66, 1.17], %)
|
|> line([2.66, 1.17], %)
|
||||||
@ -766,8 +766,8 @@ const extrude001 = extrude(10, sketch001)`,
|
|||||||
[
|
[
|
||||||
'delete extrude with sketch on it',
|
'delete extrude with sketch on it',
|
||||||
{
|
{
|
||||||
codeBefore: `const myVar = 5
|
codeBefore: `let myVar = 5
|
||||||
const sketch001 = startSketchOn('XZ')
|
let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([4.46, 5.12], %, $tag)
|
|> startProfileAt([4.46, 5.12], %, $tag)
|
||||||
|> line([0.08, myVar], %)
|
|> line([0.08, myVar], %)
|
||||||
|> line([13.03, 2.02], %, $seg01)
|
|> line([13.03, 2.02], %, $seg01)
|
||||||
@ -778,7 +778,7 @@ const sketch001 = startSketchOn('XZ')
|
|||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(5, sketch001)
|
const extrude001 = extrude(5, sketch001)
|
||||||
const sketch002 = startSketchOn(extrude001, seg01)
|
let sketch002 = startSketchOn(extrude001, seg01)
|
||||||
|> startProfileAt([-12.55, 2.89], %)
|
|> startProfileAt([-12.55, 2.89], %)
|
||||||
|> line([3.02, 1.9], %)
|
|> line([3.02, 1.9], %)
|
||||||
|> line([1.82, -1.49], %, $seg02)
|
|> line([1.82, -1.49], %, $seg02)
|
||||||
@ -787,8 +787,8 @@ const sketch002 = startSketchOn(extrude001, seg01)
|
|||||||
|> line([0.3, 0.84], %)
|
|> line([0.3, 0.84], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)`,
|
|> close(%)`,
|
||||||
codeAfter: `const myVar = 5
|
codeAfter: `let myVar = 5
|
||||||
const sketch001 = startSketchOn('XZ')
|
let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([4.46, 5.12], %, $tag)
|
|> startProfileAt([4.46, 5.12], %, $tag)
|
||||||
|> line([0.08, myVar], %)
|
|> line([0.08, myVar], %)
|
||||||
|> line([13.03, 2.02], %, $seg01)
|
|> line([13.03, 2.02], %, $seg01)
|
||||||
@ -798,7 +798,7 @@ const sketch001 = startSketchOn('XZ')
|
|||||||
|> line([-8.54, -2.51], %)
|
|> line([-8.54, -2.51], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const sketch002 = startSketchOn({
|
let sketch002 = startSketchOn({
|
||||||
plane: {
|
plane: {
|
||||||
origin: { x: 1, y: 2, z: 3 },
|
origin: { x: 1, y: 2, z: 3 },
|
||||||
x_axis: { x: 4, y: 5, z: 6 },
|
x_axis: { x: 4, y: 5, z: 6 },
|
||||||
@ -822,8 +822,8 @@ const sketch002 = startSketchOn({
|
|||||||
[
|
[
|
||||||
'delete extrude with sketch on it',
|
'delete extrude with sketch on it',
|
||||||
{
|
{
|
||||||
codeBefore: `const myVar = 5
|
codeBefore: `let myVar = 5
|
||||||
const sketch001 = startSketchOn('XZ')
|
let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([4.46, 5.12], %, $tag)
|
|> startProfileAt([4.46, 5.12], %, $tag)
|
||||||
|> line([0.08, myVar], %)
|
|> line([0.08, myVar], %)
|
||||||
|> line([13.03, 2.02], %, $seg01)
|
|> line([13.03, 2.02], %, $seg01)
|
||||||
@ -834,7 +834,7 @@ const sketch001 = startSketchOn('XZ')
|
|||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(5, sketch001)
|
const extrude001 = extrude(5, sketch001)
|
||||||
const sketch002 = startSketchOn(extrude001, seg01)
|
let sketch002 = startSketchOn(extrude001, seg01)
|
||||||
|> startProfileAt([-12.55, 2.89], %)
|
|> startProfileAt([-12.55, 2.89], %)
|
||||||
|> line([3.02, 1.9], %)
|
|> line([3.02, 1.9], %)
|
||||||
|> line([1.82, -1.49], %, $seg02)
|
|> line([1.82, -1.49], %, $seg02)
|
||||||
@ -843,8 +843,8 @@ const sketch002 = startSketchOn(extrude001, seg01)
|
|||||||
|> line([0.3, 0.84], %)
|
|> line([0.3, 0.84], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)`,
|
|> close(%)`,
|
||||||
codeAfter: `const myVar = 5
|
codeAfter: `let myVar = 5
|
||||||
const sketch001 = startSketchOn('XZ')
|
let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([4.46, 5.12], %, $tag)
|
|> startProfileAt([4.46, 5.12], %, $tag)
|
||||||
|> line([0.08, myVar], %)
|
|> line([0.08, myVar], %)
|
||||||
|> line([13.03, 2.02], %, $seg01)
|
|> line([13.03, 2.02], %, $seg01)
|
||||||
@ -854,7 +854,7 @@ const sketch001 = startSketchOn('XZ')
|
|||||||
|> line([-8.54, -2.51], %)
|
|> line([-8.54, -2.51], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const sketch002 = startSketchOn({
|
let sketch002 = startSketchOn({
|
||||||
plane: {
|
plane: {
|
||||||
origin: { x: 1, y: 2, z: 3 },
|
origin: { x: 1, y: 2, z: 3 },
|
||||||
x_axis: { x: 4, y: 5, z: 6 },
|
x_axis: { x: 4, y: 5, z: 6 },
|
||||||
|
|||||||
@ -147,16 +147,16 @@ const runGetPathToExtrudeForSegmentSelectionTest = async (
|
|||||||
}
|
}
|
||||||
describe('Testing getPathToExtrudeForSegmentSelection', () => {
|
describe('Testing getPathToExtrudeForSegmentSelection', () => {
|
||||||
it('should return the correct paths for a valid selection and extrusion', async () => {
|
it('should return the correct paths for a valid selection and extrusion', async () => {
|
||||||
const code = `const sketch001 = startSketchOn('XY')
|
const code = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-10, 10], %)
|
|> startProfileAt([-10, 10], %)
|
||||||
|> line([20, 0], %)
|
|> line([20, 0], %)
|
||||||
|> line([0, -20], %)
|
|> line([0, -20], %)
|
||||||
|> line([-20, 0], %)
|
|> line([-20, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-15, sketch001)`
|
let extrude001 = extrude(-15, sketch001)`
|
||||||
const selectedSegmentSnippet = `line([20, 0], %)`
|
const selectedSegmentSnippet = `line([20, 0], %)`
|
||||||
const expectedExtrudeSnippet = `const extrude001 = extrude(-15, sketch001)`
|
const expectedExtrudeSnippet = `let extrude001 = extrude(-15, sketch001)`
|
||||||
await runGetPathToExtrudeForSegmentSelectionTest(
|
await runGetPathToExtrudeForSegmentSelectionTest(
|
||||||
code,
|
code,
|
||||||
selectedSegmentSnippet,
|
selectedSegmentSnippet,
|
||||||
@ -164,32 +164,32 @@ const extrude001 = extrude(-15, sketch001)`
|
|||||||
)
|
)
|
||||||
}, 5_000)
|
}, 5_000)
|
||||||
it('should return the correct paths for a valid selection and extrusion in case of several extrusions and sketches', async () => {
|
it('should return the correct paths for a valid selection and extrusion in case of several extrusions and sketches', async () => {
|
||||||
const code = `const sketch001 = startSketchOn('XY')
|
const code = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-30, 30], %)
|
|> startProfileAt([-30, 30], %)
|
||||||
|> line([15, 0], %)
|
|> line([15, 0], %)
|
||||||
|> line([0, -15], %)
|
|> line([0, -15], %)
|
||||||
|> line([-15, 0], %)
|
|> line([-15, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const sketch002 = startSketchOn('XY')
|
let sketch002 = startSketchOn('XY')
|
||||||
|> startProfileAt([30, 30], %)
|
|> startProfileAt([30, 30], %)
|
||||||
|> line([20, 0], %)
|
|> line([20, 0], %)
|
||||||
|> line([0, -20], %)
|
|> line([0, -20], %)
|
||||||
|> line([-20, 0], %)
|
|> line([-20, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const sketch003 = startSketchOn('XY')
|
let sketch003 = startSketchOn('XY')
|
||||||
|> startProfileAt([30, -30], %)
|
|> startProfileAt([30, -30], %)
|
||||||
|> line([25, 0], %)
|
|> line([25, 0], %)
|
||||||
|> line([0, -25], %)
|
|> line([0, -25], %)
|
||||||
|> line([-25, 0], %)
|
|> line([-25, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-15, sketch001)
|
let extrude001 = extrude(-15, sketch001)
|
||||||
const extrude002 = extrude(-15, sketch002)
|
let extrude002 = extrude(-15, sketch002)
|
||||||
const extrude003 = extrude(-15, sketch003)`
|
let extrude003 = extrude(-15, sketch003)`
|
||||||
const selectedSegmentSnippet = `line([20, 0], %)`
|
const selectedSegmentSnippet = `line([20, 0], %)`
|
||||||
const expectedExtrudeSnippet = `const extrude002 = extrude(-15, sketch002)`
|
const expectedExtrudeSnippet = `let extrude002 = extrude(-15, sketch002)`
|
||||||
await runGetPathToExtrudeForSegmentSelectionTest(
|
await runGetPathToExtrudeForSegmentSelectionTest(
|
||||||
code,
|
code,
|
||||||
selectedSegmentSnippet,
|
selectedSegmentSnippet,
|
||||||
@ -197,29 +197,29 @@ const extrude003 = extrude(-15, sketch003)`
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
it('should not return any path for missing extrusion', async () => {
|
it('should not return any path for missing extrusion', async () => {
|
||||||
const code = `const sketch001 = startSketchOn('XY')
|
const code = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-30, 30], %)
|
|> startProfileAt([-30, 30], %)
|
||||||
|> line([15, 0], %)
|
|> line([15, 0], %)
|
||||||
|> line([0, -15], %)
|
|> line([0, -15], %)
|
||||||
|> line([-15, 0], %)
|
|> line([-15, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const sketch002 = startSketchOn('XY')
|
let sketch002 = startSketchOn('XY')
|
||||||
|> startProfileAt([30, 30], %)
|
|> startProfileAt([30, 30], %)
|
||||||
|> line([20, 0], %)
|
|> line([20, 0], %)
|
||||||
|> line([0, -20], %)
|
|> line([0, -20], %)
|
||||||
|> line([-20, 0], %)
|
|> line([-20, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const sketch003 = startSketchOn('XY')
|
let sketch003 = startSketchOn('XY')
|
||||||
|> startProfileAt([30, -30], %)
|
|> startProfileAt([30, -30], %)
|
||||||
|> line([25, 0], %)
|
|> line([25, 0], %)
|
||||||
|> line([0, -25], %)
|
|> line([0, -25], %)
|
||||||
|> line([-25, 0], %)
|
|> line([-25, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-15, sketch001)
|
let extrude001 = extrude(-15, sketch001)
|
||||||
const extrude003 = extrude(-15, sketch003)`
|
let extrude003 = extrude(-15, sketch003)`
|
||||||
const selectedSegmentSnippet = `line([20, 0], %)`
|
const selectedSegmentSnippet = `line([20, 0], %)`
|
||||||
const expectedExtrudeSnippet = ``
|
const expectedExtrudeSnippet = ``
|
||||||
await runGetPathToExtrudeForSegmentSelectionTest(
|
await runGetPathToExtrudeForSegmentSelectionTest(
|
||||||
@ -282,7 +282,7 @@ describe('Testing addFillet', () => {
|
|||||||
|
|
||||||
it('should add a fillet to a specific segment after extrusion, clean', async () => {
|
it('should add a fillet to a specific segment after extrusion, clean', async () => {
|
||||||
const code = `
|
const code = `
|
||||||
const sketch001 = startSketchOn('XZ')
|
let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([2.16, 49.67], %)
|
|> startProfileAt([2.16, 49.67], %)
|
||||||
|> line([101.49, 139.93], %)
|
|> line([101.49, 139.93], %)
|
||||||
|> line([60.04, -55.72], %)
|
|> line([60.04, -55.72], %)
|
||||||
@ -292,12 +292,12 @@ describe('Testing addFillet', () => {
|
|||||||
|> tangentialArcTo([14.68, -104.52], %)
|
|> tangentialArcTo([14.68, -104.52], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(50, sketch001)
|
let extrude001 = extrude(50, sketch001)
|
||||||
`
|
`
|
||||||
const segmentSnippet = `line([60.04, -55.72], %)`
|
const segmentSnippet = `line([60.04, -55.72], %)`
|
||||||
const extrudeSnippet = `const extrude001 = extrude(50, sketch001)`
|
const extrudeSnippet = `let extrude001 = extrude(50, sketch001)`
|
||||||
const radius = createLiteral(5)
|
const radius = createLiteral(5)
|
||||||
const expectedCode = `const sketch001 = startSketchOn('XZ')
|
const expectedCode = `let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([2.16, 49.67], %)
|
|> startProfileAt([2.16, 49.67], %)
|
||||||
|> line([101.49, 139.93], %)
|
|> line([101.49, 139.93], %)
|
||||||
|> line([60.04, -55.72], %, $seg01)
|
|> line([60.04, -55.72], %, $seg01)
|
||||||
@ -307,7 +307,7 @@ describe('Testing addFillet', () => {
|
|||||||
|> tangentialArcTo([14.68, -104.52], %)
|
|> tangentialArcTo([14.68, -104.52], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(50, sketch001)
|
let extrude001 = extrude(50, sketch001)
|
||||||
|> fillet({ radius: 5, tags: [seg01] }, %)`
|
|> fillet({ radius: 5, tags: [seg01] }, %)`
|
||||||
|
|
||||||
await runFilletTest(
|
await runFilletTest(
|
||||||
@ -325,7 +325,7 @@ const extrude001 = extrude(50, sketch001)
|
|||||||
|
|
||||||
it('should add a fillet to a specific segment after extrusion with existing tag in any other line', async () => {
|
it('should add a fillet to a specific segment after extrusion with existing tag in any other line', async () => {
|
||||||
const code = `
|
const code = `
|
||||||
const sketch001 = startSketchOn('XZ')
|
let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([2.16, 49.67], %)
|
|> startProfileAt([2.16, 49.67], %)
|
||||||
|> line([101.49, 139.93], %)
|
|> line([101.49, 139.93], %)
|
||||||
|> line([60.04, -55.72], %)
|
|> line([60.04, -55.72], %)
|
||||||
@ -335,12 +335,12 @@ const extrude001 = extrude(50, sketch001)
|
|||||||
|> tangentialArcTo([14.68, -104.52], %)
|
|> tangentialArcTo([14.68, -104.52], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(50, sketch001)
|
let extrude001 = extrude(50, sketch001)
|
||||||
`
|
`
|
||||||
const segmentSnippet = `line([60.04, -55.72], %)`
|
const segmentSnippet = `line([60.04, -55.72], %)`
|
||||||
const extrudeSnippet = `const extrude001 = extrude(50, sketch001)`
|
const extrudeSnippet = `let extrude001 = extrude(50, sketch001)`
|
||||||
const radius = createLiteral(5)
|
const radius = createLiteral(5)
|
||||||
const expectedCode = `const sketch001 = startSketchOn('XZ')
|
const expectedCode = `let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([2.16, 49.67], %)
|
|> startProfileAt([2.16, 49.67], %)
|
||||||
|> line([101.49, 139.93], %)
|
|> line([101.49, 139.93], %)
|
||||||
|> line([60.04, -55.72], %, $seg02)
|
|> line([60.04, -55.72], %, $seg02)
|
||||||
@ -350,7 +350,7 @@ const extrude001 = extrude(50, sketch001)
|
|||||||
|> tangentialArcTo([14.68, -104.52], %)
|
|> tangentialArcTo([14.68, -104.52], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(50, sketch001)
|
let extrude001 = extrude(50, sketch001)
|
||||||
|> fillet({ radius: 5, tags: [seg02] }, %)`
|
|> fillet({ radius: 5, tags: [seg02] }, %)`
|
||||||
|
|
||||||
await runFilletTest(
|
await runFilletTest(
|
||||||
@ -368,7 +368,7 @@ const extrude001 = extrude(50, sketch001)
|
|||||||
|
|
||||||
it('should add a fillet to a specific segment after extrusion with existing tag in that exact line', async () => {
|
it('should add a fillet to a specific segment after extrusion with existing tag in that exact line', async () => {
|
||||||
const code = `
|
const code = `
|
||||||
const sketch001 = startSketchOn('XZ')
|
let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([2.16, 49.67], %)
|
|> startProfileAt([2.16, 49.67], %)
|
||||||
|> line([101.49, 139.93], %)
|
|> line([101.49, 139.93], %)
|
||||||
|> line([60.04, -55.72], %)
|
|> line([60.04, -55.72], %)
|
||||||
@ -378,12 +378,12 @@ const extrude001 = extrude(50, sketch001)
|
|||||||
|> tangentialArcTo([14.68, -104.52], %)
|
|> tangentialArcTo([14.68, -104.52], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(50, sketch001)
|
let extrude001 = extrude(50, sketch001)
|
||||||
`
|
`
|
||||||
const segmentSnippet = `line([-87.24, -47.08], %, $seg03)`
|
const segmentSnippet = `line([-87.24, -47.08], %, $seg03)`
|
||||||
const extrudeSnippet = `const extrude001 = extrude(50, sketch001)`
|
const extrudeSnippet = `let extrude001 = extrude(50, sketch001)`
|
||||||
const radius = createLiteral(5)
|
const radius = createLiteral(5)
|
||||||
const expectedCode = `const sketch001 = startSketchOn('XZ')
|
const expectedCode = `let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([2.16, 49.67], %)
|
|> startProfileAt([2.16, 49.67], %)
|
||||||
|> line([101.49, 139.93], %)
|
|> line([101.49, 139.93], %)
|
||||||
|> line([60.04, -55.72], %)
|
|> line([60.04, -55.72], %)
|
||||||
@ -393,7 +393,7 @@ const extrude001 = extrude(50, sketch001)
|
|||||||
|> tangentialArcTo([14.68, -104.52], %)
|
|> tangentialArcTo([14.68, -104.52], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(50, sketch001)
|
let extrude001 = extrude(50, sketch001)
|
||||||
|> fillet({ radius: 5, tags: [seg03] }, %)`
|
|> fillet({ radius: 5, tags: [seg03] }, %)`
|
||||||
|
|
||||||
await runFilletTest(
|
await runFilletTest(
|
||||||
@ -410,7 +410,7 @@ const extrude001 = extrude(50, sketch001)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
it('should add another fillet after the existing fillet', async () => {
|
it('should add another fillet after the existing fillet', async () => {
|
||||||
const code = `const sketch001 = startSketchOn('XZ')
|
const code = `let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([2.16, 49.67], %)
|
|> startProfileAt([2.16, 49.67], %)
|
||||||
|> line([101.49, 139.93], %)
|
|> line([101.49, 139.93], %)
|
||||||
|> line([60.04, -55.72], %)
|
|> line([60.04, -55.72], %)
|
||||||
@ -420,12 +420,12 @@ const extrude001 = extrude(50, sketch001)
|
|||||||
|> tangentialArcTo([14.68, -104.52], %)
|
|> tangentialArcTo([14.68, -104.52], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(50, sketch001)
|
let extrude001 = extrude(50, sketch001)
|
||||||
|> fillet({ radius: 10, tags: [seg03] }, %)`
|
|> fillet({ radius: 10, tags: [seg03] }, %)`
|
||||||
const segmentSnippet = `line([60.04, -55.72], %)`
|
const segmentSnippet = `line([60.04, -55.72], %)`
|
||||||
const extrudeSnippet = `const extrude001 = extrude(50, sketch001)`
|
const extrudeSnippet = `let extrude001 = extrude(50, sketch001)`
|
||||||
const radius = createLiteral(5)
|
const radius = createLiteral(5)
|
||||||
const expectedCode = `const sketch001 = startSketchOn('XZ')
|
const expectedCode = `let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([2.16, 49.67], %)
|
|> startProfileAt([2.16, 49.67], %)
|
||||||
|> line([101.49, 139.93], %)
|
|> line([101.49, 139.93], %)
|
||||||
|> line([60.04, -55.72], %, $seg01)
|
|> line([60.04, -55.72], %, $seg01)
|
||||||
@ -435,7 +435,7 @@ const extrude001 = extrude(50, sketch001)
|
|||||||
|> tangentialArcTo([14.68, -104.52], %)
|
|> tangentialArcTo([14.68, -104.52], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(50, sketch001)
|
let extrude001 = extrude(50, sketch001)
|
||||||
|> fillet({ radius: 10, tags: [seg03] }, %)
|
|> fillet({ radius: 10, tags: [seg03] }, %)
|
||||||
|> fillet({ radius: 5, tags: [seg01] }, %)`
|
|> fillet({ radius: 5, tags: [seg01] }, %)`
|
||||||
|
|
||||||
@ -500,24 +500,24 @@ const runModifyAstWithFilletAndTagTest = async (
|
|||||||
}
|
}
|
||||||
describe('Testing applyFilletToSelection', () => {
|
describe('Testing applyFilletToSelection', () => {
|
||||||
it('should add a fillet to a specific segment after extrusion', async () => {
|
it('should add a fillet to a specific segment after extrusion', async () => {
|
||||||
const code = `const sketch001 = startSketchOn('XY')
|
const code = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-10, 10], %)
|
|> startProfileAt([-10, 10], %)
|
||||||
|> line([20, 0], %)
|
|> line([20, 0], %)
|
||||||
|> line([0, -20], %)
|
|> line([0, -20], %)
|
||||||
|> line([-20, 0], %)
|
|> line([-20, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-15, sketch001)`
|
let extrude001 = extrude(-15, sketch001)`
|
||||||
const segmentSnippets = ['line([0, -20], %)']
|
const segmentSnippets = ['line([0, -20], %)']
|
||||||
const radiusValue = 3
|
const radiusValue = 3
|
||||||
const expectedCode = `const sketch001 = startSketchOn('XY')
|
const expectedCode = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-10, 10], %)
|
|> startProfileAt([-10, 10], %)
|
||||||
|> line([20, 0], %)
|
|> line([20, 0], %)
|
||||||
|> line([0, -20], %, $seg01)
|
|> line([0, -20], %, $seg01)
|
||||||
|> line([-20, 0], %)
|
|> line([-20, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-15, sketch001)
|
let extrude001 = extrude(-15, sketch001)
|
||||||
|> fillet({ radius: 3, tags: [seg01] }, %)`
|
|> fillet({ radius: 3, tags: [seg01] }, %)`
|
||||||
|
|
||||||
await runModifyAstWithFilletAndTagTest(
|
await runModifyAstWithFilletAndTagTest(
|
||||||
@ -528,24 +528,24 @@ const extrude001 = extrude(-15, sketch001)
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
it('should add a fillet to the 2 segments of a single extrusion', async () => {
|
it('should add a fillet to the 2 segments of a single extrusion', async () => {
|
||||||
const code = `const sketch001 = startSketchOn('XY')
|
const code = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-10, 10], %)
|
|> startProfileAt([-10, 10], %)
|
||||||
|> line([20, 0], %)
|
|> line([20, 0], %)
|
||||||
|> line([0, -20], %)
|
|> line([0, -20], %)
|
||||||
|> line([-20, 0], %)
|
|> line([-20, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-15, sketch001)`
|
let extrude001 = extrude(-15, sketch001)`
|
||||||
const segmentSnippets = ['line([20, 0], %)', 'line([-20, 0], %)']
|
const segmentSnippets = ['line([20, 0], %)', 'line([-20, 0], %)']
|
||||||
const radiusValue = 3
|
const radiusValue = 3
|
||||||
const expectedCode = `const sketch001 = startSketchOn('XY')
|
const expectedCode = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-10, 10], %)
|
|> startProfileAt([-10, 10], %)
|
||||||
|> line([20, 0], %, $seg01)
|
|> line([20, 0], %, $seg01)
|
||||||
|> line([0, -20], %)
|
|> line([0, -20], %)
|
||||||
|> line([-20, 0], %, $seg02)
|
|> line([-20, 0], %, $seg02)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-15, sketch001)
|
let extrude001 = extrude(-15, sketch001)
|
||||||
|> fillet({ radius: 3, tags: [seg01] }, %)
|
|> fillet({ radius: 3, tags: [seg01] }, %)
|
||||||
|> fillet({ radius: 3, tags: [seg02] }, %)`
|
|> fillet({ radius: 3, tags: [seg02] }, %)`
|
||||||
|
|
||||||
@ -557,25 +557,25 @@ const extrude001 = extrude(-15, sketch001)
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
it('should add a fillet when the extrude variable previously had an fillet', async () => {
|
it('should add a fillet when the extrude variable previously had an fillet', async () => {
|
||||||
const code = `const sketch001 = startSketchOn('XY')
|
const code = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-10, 10], %)
|
|> startProfileAt([-10, 10], %)
|
||||||
|> line([20, 0], %)
|
|> line([20, 0], %)
|
||||||
|> line([0, -20], %)
|
|> line([0, -20], %)
|
||||||
|> line([-20, 0], %, $seg01)
|
|> line([-20, 0], %, $seg01)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-15, sketch001)
|
let extrude001 = extrude(-15, sketch001)
|
||||||
|> fillet({ radius: 3, tags: [seg01] }, %)` // <--- one fillet already there on input code
|
|> fillet({ radius: 3, tags: [seg01] }, %)` // <--- one fillet already there on input code
|
||||||
const segmentSnippets = ['line([20, 0], %)']
|
const segmentSnippets = ['line([20, 0], %)']
|
||||||
const radiusValue = 3
|
const radiusValue = 3
|
||||||
const expectedCode = `const sketch001 = startSketchOn('XY')
|
const expectedCode = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-10, 10], %)
|
|> startProfileAt([-10, 10], %)
|
||||||
|> line([20, 0], %, $seg02)
|
|> line([20, 0], %, $seg02)
|
||||||
|> line([0, -20], %)
|
|> line([0, -20], %)
|
||||||
|> line([-20, 0], %, $seg01)
|
|> line([-20, 0], %, $seg01)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-15, sketch001)
|
let extrude001 = extrude(-15, sketch001)
|
||||||
|> fillet({ radius: 3, tags: [seg01] }, %)
|
|> fillet({ radius: 3, tags: [seg01] }, %)
|
||||||
|> fillet({ radius: 3, tags: [seg02] }, %)` // <-- able to add a new one
|
|> fillet({ radius: 3, tags: [seg02] }, %)` // <-- able to add a new one
|
||||||
|
|
||||||
@ -587,41 +587,41 @@ const extrude001 = extrude(-15, sketch001)
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
it('should add the fillets to 2 bodies', async () => {
|
it('should add the fillets to 2 bodies', async () => {
|
||||||
const code = `const sketch001 = startSketchOn('XY')
|
const code = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-10, 10], %)
|
|> startProfileAt([-10, 10], %)
|
||||||
|> line([20, 0], %)
|
|> line([20, 0], %)
|
||||||
|> line([0, -20], %)
|
|> line([0, -20], %)
|
||||||
|> line([-20, 0], %)
|
|> line([-20, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-15, sketch001)
|
let extrude001 = extrude(-15, sketch001)
|
||||||
const sketch002 = startSketchOn('XY')
|
let sketch002 = startSketchOn('XY')
|
||||||
|> startProfileAt([30, 10], %)
|
|> startProfileAt([30, 10], %)
|
||||||
|> line([15, 0], %)
|
|> line([15, 0], %)
|
||||||
|> line([0, -15], %)
|
|> line([0, -15], %)
|
||||||
|> line([-15, 0], %)
|
|> line([-15, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude002 = extrude(-25, sketch002)` // <--- body 2
|
let extrude002 = extrude(-25, sketch002)` // <--- body 2
|
||||||
const segmentSnippets = ['line([0, -20], %)', 'line([0, -15], %)']
|
const segmentSnippets = ['line([0, -20], %)', 'line([0, -15], %)']
|
||||||
const radiusValue = 3
|
const radiusValue = 3
|
||||||
const expectedCode = `const sketch001 = startSketchOn('XY')
|
const expectedCode = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-10, 10], %)
|
|> startProfileAt([-10, 10], %)
|
||||||
|> line([20, 0], %)
|
|> line([20, 0], %)
|
||||||
|> line([0, -20], %, $seg01)
|
|> line([0, -20], %, $seg01)
|
||||||
|> line([-20, 0], %)
|
|> line([-20, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-15, sketch001)
|
let extrude001 = extrude(-15, sketch001)
|
||||||
|> fillet({ radius: 3, tags: [seg01] }, %)
|
|> fillet({ radius: 3, tags: [seg01] }, %)
|
||||||
const sketch002 = startSketchOn('XY')
|
let sketch002 = startSketchOn('XY')
|
||||||
|> startProfileAt([30, 10], %)
|
|> startProfileAt([30, 10], %)
|
||||||
|> line([15, 0], %)
|
|> line([15, 0], %)
|
||||||
|> line([0, -15], %, $seg02)
|
|> line([0, -15], %, $seg02)
|
||||||
|> line([-15, 0], %)
|
|> line([-15, 0], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude002 = extrude(-25, sketch002)
|
let extrude002 = extrude(-25, sketch002)
|
||||||
|> fillet({ radius: 3, tags: [seg02] }, %)` // <-- able to add a new one
|
|> fillet({ radius: 3, tags: [seg02] }, %)` // <-- able to add a new one
|
||||||
|
|
||||||
await runModifyAstWithFilletAndTagTest(
|
await runModifyAstWithFilletAndTagTest(
|
||||||
@ -634,13 +634,13 @@ const extrude002 = extrude(-25, sketch002)
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('Testing isTagUsedInFillet', () => {
|
describe('Testing isTagUsedInFillet', () => {
|
||||||
const code = `const sketch001 = startSketchOn('XZ')
|
const code = `let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([7.72, 4.13], %)
|
|> startProfileAt([7.72, 4.13], %)
|
||||||
|> line([7.11, 3.48], %, $seg01)
|
|> line([7.11, 3.48], %, $seg01)
|
||||||
|> line([-3.29, -13.85], %)
|
|> line([-3.29, -13.85], %)
|
||||||
|> line([-6.37, 3.88], %, $seg02)
|
|> line([-6.37, 3.88], %, $seg02)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-5, sketch001)
|
let extrude001 = extrude(-5, sketch001)
|
||||||
|> fillet({
|
|> fillet({
|
||||||
radius: 1.11,
|
radius: 1.11,
|
||||||
tags: [
|
tags: [
|
||||||
@ -750,17 +750,17 @@ describe('Testing button states', () => {
|
|||||||
expect(buttonState).toEqual(expectedState)
|
expect(buttonState).toEqual(expectedState)
|
||||||
}
|
}
|
||||||
const codeWithBody: string = `
|
const codeWithBody: string = `
|
||||||
const sketch001 = startSketchOn('XY')
|
let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-20, -5], %)
|
|> startProfileAt([-20, -5], %)
|
||||||
|> line([0, 10], %)
|
|> line([0, 10], %)
|
||||||
|> line([10, 0], %)
|
|> line([10, 0], %)
|
||||||
|> line([0, -10], %)
|
|> line([0, -10], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-10, sketch001)
|
let extrude001 = extrude(-10, sketch001)
|
||||||
`
|
`
|
||||||
const codeWithoutBodies: string = `
|
const codeWithoutBodies: string = `
|
||||||
const sketch001 = startSketchOn('XY')
|
let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-20, -5], %)
|
|> startProfileAt([-20, -5], %)
|
||||||
|> line([0, 10], %)
|
|> line([0, 10], %)
|
||||||
|> line([10, 0], %)
|
|> line([10, 0], %)
|
||||||
|
|||||||
@ -65,7 +65,7 @@ export function modifyAstWithFilletAndTag(
|
|||||||
ast: Program,
|
ast: Program,
|
||||||
selection: Selections,
|
selection: Selections,
|
||||||
radius: KclCommandValue
|
radius: KclCommandValue
|
||||||
): { modifiedAst: Program; pathToFilletNode: PathToNode } | Error {
|
): { modifiedAst: Program; pathToFilletNode: Array<PathToNode> } | Error {
|
||||||
const astResult = insertRadiusIntoAst(ast, radius)
|
const astResult = insertRadiusIntoAst(ast, radius)
|
||||||
if (err(astResult)) return astResult
|
if (err(astResult)) return astResult
|
||||||
|
|
||||||
@ -73,7 +73,8 @@ export function modifyAstWithFilletAndTag(
|
|||||||
const artifactGraph = engineCommandManager.artifactGraph
|
const artifactGraph = engineCommandManager.artifactGraph
|
||||||
|
|
||||||
let clonedAst = structuredClone(ast)
|
let clonedAst = structuredClone(ast)
|
||||||
let lastPathToFilletNode: PathToNode = []
|
const clonedAstForGetExtrude = structuredClone(ast)
|
||||||
|
let pathToFilletNodes: Array<PathToNode> = []
|
||||||
|
|
||||||
for (const selectionRange of selection.codeBasedSelections) {
|
for (const selectionRange of selection.codeBasedSelections) {
|
||||||
const singleSelection = {
|
const singleSelection = {
|
||||||
@ -82,7 +83,7 @@ export function modifyAstWithFilletAndTag(
|
|||||||
}
|
}
|
||||||
const getPathToExtrudeForSegmentSelectionResult =
|
const getPathToExtrudeForSegmentSelectionResult =
|
||||||
getPathToExtrudeForSegmentSelection(
|
getPathToExtrudeForSegmentSelection(
|
||||||
clonedAst,
|
clonedAstForGetExtrude,
|
||||||
singleSelection,
|
singleSelection,
|
||||||
programMemory,
|
programMemory,
|
||||||
artifactGraph
|
artifactGraph
|
||||||
@ -101,9 +102,9 @@ export function modifyAstWithFilletAndTag(
|
|||||||
if (trap(addFilletResult)) return addFilletResult
|
if (trap(addFilletResult)) return addFilletResult
|
||||||
const { modifiedAst, pathToFilletNode } = addFilletResult
|
const { modifiedAst, pathToFilletNode } = addFilletResult
|
||||||
clonedAst = modifiedAst
|
clonedAst = modifiedAst
|
||||||
lastPathToFilletNode = pathToFilletNode
|
pathToFilletNodes.push(pathToFilletNode)
|
||||||
}
|
}
|
||||||
return { modifiedAst: clonedAst, pathToFilletNode: lastPathToFilletNode }
|
return { modifiedAst: clonedAst, pathToFilletNode: pathToFilletNodes }
|
||||||
}
|
}
|
||||||
|
|
||||||
function insertRadiusIntoAst(
|
function insertRadiusIntoAst(
|
||||||
@ -166,7 +167,7 @@ export function getPathToExtrudeForSegmentSelection(
|
|||||||
|
|
||||||
async function updateAstAndFocus(
|
async function updateAstAndFocus(
|
||||||
modifiedAst: Program,
|
modifiedAst: Program,
|
||||||
pathToFilletNode: PathToNode
|
pathToFilletNode: Array<PathToNode>
|
||||||
) {
|
) {
|
||||||
const updatedAst = await kclManager.updateAst(modifiedAst, true, {
|
const updatedAst = await kclManager.updateAst(modifiedAst, true, {
|
||||||
focusPath: pathToFilletNode,
|
focusPath: pathToFilletNode,
|
||||||
|
|||||||
@ -26,21 +26,21 @@ beforeAll(async () => {
|
|||||||
|
|
||||||
describe('findAllPreviousVariables', () => {
|
describe('findAllPreviousVariables', () => {
|
||||||
it('should find all previous variables', async () => {
|
it('should find all previous variables', async () => {
|
||||||
const code = `const baseThick = 1
|
const code = `let baseThick = 1
|
||||||
const armAngle = 60
|
let armAngle = 60
|
||||||
|
|
||||||
const baseThickHalf = baseThick / 2
|
let baseThickHalf = baseThick / 2
|
||||||
const halfArmAngle = armAngle / 2
|
let halfArmAngle = armAngle / 2
|
||||||
|
|
||||||
const arrExpShouldNotBeIncluded = [1, 2, 3]
|
let arrExpShouldNotBeIncluded = [1, 2, 3]
|
||||||
const objExpShouldNotBeIncluded = { a: 1, b: 2, c: 3 }
|
let objExpShouldNotBeIncluded = { a: 1, b: 2, c: 3 }
|
||||||
|
|
||||||
const part001 = startSketchOn('XY')
|
let part001 = startSketchOn('XY')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> yLineTo(1, %)
|
|> yLineTo(1, %)
|
||||||
|> xLine(3.84, %) // selection-range-7ish-before-this
|
|> xLine(3.84, %) // selection-range-7ish-before-this
|
||||||
|
|
||||||
const variableBelowShouldNotBeIncluded = 3
|
let variableBelowShouldNotBeIncluded = 3
|
||||||
`
|
`
|
||||||
const rangeStart = code.indexOf('// selection-range-7ish-before-this') - 7
|
const rangeStart = code.indexOf('// selection-range-7ish-before-this') - 7
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
@ -67,7 +67,7 @@ const variableBelowShouldNotBeIncluded = 3
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('testing argIsNotIdentifier', () => {
|
describe('testing argIsNotIdentifier', () => {
|
||||||
const code = `const part001 = startSketchOn('XY')
|
const code = `let part001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-1.2, 4.83], %)
|
|> startProfileAt([-1.2, 4.83], %)
|
||||||
|> line([2.8, 0], %)
|
|> line([2.8, 0], %)
|
||||||
|> angledLine([100 + 100, 3.09], %)
|
|> angledLine([100 + 100, 3.09], %)
|
||||||
@ -75,8 +75,8 @@ describe('testing argIsNotIdentifier', () => {
|
|||||||
|> angledLine([def('yo'), 3.09], %)
|
|> angledLine([def('yo'), 3.09], %)
|
||||||
|> angledLine([ghi(%), 3.09], %)
|
|> angledLine([ghi(%), 3.09], %)
|
||||||
|> angledLine([jkl('yo') + 2, 3.09], %)
|
|> angledLine([jkl('yo') + 2, 3.09], %)
|
||||||
const yo = 5 + 6
|
let yo = 5 + 6
|
||||||
const yo2 = hmm([identifierGuy + 5])`
|
let yo2 = hmm([identifierGuy + 5])`
|
||||||
it('find a safe binaryExpression', () => {
|
it('find a safe binaryExpression', () => {
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
@ -150,7 +150,7 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
const replaced = result.replacer(structuredClone(ast), 'replaceName')
|
const replaced = result.replacer(structuredClone(ast), 'replaceName')
|
||||||
if (err(replaced)) throw replaced
|
if (err(replaced)) throw replaced
|
||||||
const outCode = recast(replaced.modifiedAst)
|
const outCode = recast(replaced.modifiedAst)
|
||||||
expect(outCode).toContain(`const yo = replaceName`)
|
expect(outCode).toContain(`let yo = replaceName`)
|
||||||
})
|
})
|
||||||
it('find a safe BinaryExpression that has a CallExpression within', () => {
|
it('find a safe BinaryExpression that has a CallExpression within', () => {
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
@ -186,7 +186,7 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
if (err(replaced)) throw replaced
|
if (err(replaced)) throw replaced
|
||||||
const { modifiedAst } = replaced
|
const { modifiedAst } = replaced
|
||||||
const outCode = recast(modifiedAst)
|
const outCode = recast(modifiedAst)
|
||||||
expect(outCode).toContain(`const yo2 = hmm([replaceName])`)
|
expect(outCode).toContain(`let yo2 = hmm([replaceName])`)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('testing isTypeInValue', () => {
|
describe('testing isTypeInValue', () => {
|
||||||
@ -214,7 +214,7 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('testing getNodePathFromSourceRange', () => {
|
describe('testing getNodePathFromSourceRange', () => {
|
||||||
const code = `const part001 = startSketchOn('XY')
|
const code = `let part001 = startSketchOn('XY')
|
||||||
|> startProfileAt([0.39, -0.05], %)
|
|> startProfileAt([0.39, -0.05], %)
|
||||||
|> line([0.94, 2.61], %)
|
|> line([0.94, 2.61], %)
|
||||||
|> line([-0.21, -1.4], %)`
|
|> line([-0.21, -1.4], %)`
|
||||||
@ -271,7 +271,7 @@ describe('testing getNodePathFromSourceRange', () => {
|
|||||||
describe('testing doesPipeHave', () => {
|
describe('testing doesPipeHave', () => {
|
||||||
it('finds close', () => {
|
it('finds close', () => {
|
||||||
const exampleCode = `const length001 = 2
|
const exampleCode = `const length001 = 2
|
||||||
const part001 = startSketchAt([-1.41, 3.46])
|
let part001 = startSketchAt([-1.41, 3.46])
|
||||||
|> line([19.49, 1.16], %, $seg01)
|
|> line([19.49, 1.16], %, $seg01)
|
||||||
|> angledLine([-35, length001], %)
|
|> angledLine([-35, length001], %)
|
||||||
|> line([-3.22, -7.36], %)
|
|> line([-3.22, -7.36], %)
|
||||||
@ -290,7 +290,7 @@ const part001 = startSketchAt([-1.41, 3.46])
|
|||||||
})
|
})
|
||||||
it('finds extrude', () => {
|
it('finds extrude', () => {
|
||||||
const exampleCode = `const length001 = 2
|
const exampleCode = `const length001 = 2
|
||||||
const part001 = startSketchAt([-1.41, 3.46])
|
let part001 = startSketchAt([-1.41, 3.46])
|
||||||
|> line([19.49, 1.16], %, $seg01)
|
|> line([19.49, 1.16], %, $seg01)
|
||||||
|> angledLine([-35, length001], %)
|
|> angledLine([-35, length001], %)
|
||||||
|> line([-3.22, -7.36], %)
|
|> line([-3.22, -7.36], %)
|
||||||
@ -310,7 +310,7 @@ const part001 = startSketchAt([-1.41, 3.46])
|
|||||||
})
|
})
|
||||||
it('does NOT find close', () => {
|
it('does NOT find close', () => {
|
||||||
const exampleCode = `const length001 = 2
|
const exampleCode = `const length001 = 2
|
||||||
const part001 = startSketchAt([-1.41, 3.46])
|
let part001 = startSketchAt([-1.41, 3.46])
|
||||||
|> line([19.49, 1.16], %, $seg01)
|
|> line([19.49, 1.16], %, $seg01)
|
||||||
|> angledLine([-35, length001], %)
|
|> angledLine([-35, length001], %)
|
||||||
|> line([-3.22, -7.36], %)
|
|> line([-3.22, -7.36], %)
|
||||||
@ -343,7 +343,7 @@ const part001 = startSketchAt([-1.41, 3.46])
|
|||||||
describe('testing hasExtrudeSketchGroup', () => {
|
describe('testing hasExtrudeSketchGroup', () => {
|
||||||
it('find sketch group', async () => {
|
it('find sketch group', async () => {
|
||||||
const exampleCode = `const length001 = 2
|
const exampleCode = `const length001 = 2
|
||||||
const part001 = startSketchAt([-1.41, 3.46])
|
let part001 = startSketchAt([-1.41, 3.46])
|
||||||
|> line([19.49, 1.16], %, $seg01)
|
|> line([19.49, 1.16], %, $seg01)
|
||||||
|> angledLine([-35, length001], %)
|
|> angledLine([-35, length001], %)
|
||||||
|> line([-3.22, -7.36], %)
|
|> line([-3.22, -7.36], %)
|
||||||
@ -361,7 +361,7 @@ const part001 = startSketchAt([-1.41, 3.46])
|
|||||||
})
|
})
|
||||||
it('find extrude group', async () => {
|
it('find extrude group', async () => {
|
||||||
const exampleCode = `const length001 = 2
|
const exampleCode = `const length001 = 2
|
||||||
const part001 = startSketchAt([-1.41, 3.46])
|
let part001 = startSketchAt([-1.41, 3.46])
|
||||||
|> line([19.49, 1.16], %, $seg01)
|
|> line([19.49, 1.16], %, $seg01)
|
||||||
|> angledLine([-35, length001], %)
|
|> angledLine([-35, length001], %)
|
||||||
|> line([-3.22, -7.36], %)
|
|> line([-3.22, -7.36], %)
|
||||||
@ -394,7 +394,7 @@ const part001 = startSketchAt([-1.41, 3.46])
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('Testing findUsesOfTagInPipe', () => {
|
describe('Testing findUsesOfTagInPipe', () => {
|
||||||
const exampleCode = `const part001 = startSketchOn('-XZ')
|
const exampleCode = `let part001 = startSketchOn('-XZ')
|
||||||
|> startProfileAt([68.12, 156.65], %)
|
|> startProfileAt([68.12, 156.65], %)
|
||||||
|> line([306.21, 198.82], %)
|
|> line([306.21, 198.82], %)
|
||||||
|> line([306.21, 198.85], %, $seg01)
|
|> line([306.21, 198.85], %, $seg01)
|
||||||
|
|||||||
@ -903,6 +903,7 @@ export function doesSceneHaveSweepableSketch(ast: Program) {
|
|||||||
let hasStartProfileAt = false
|
let hasStartProfileAt = false
|
||||||
let hasStartSketchOn = false
|
let hasStartSketchOn = false
|
||||||
let hasClose = false
|
let hasClose = false
|
||||||
|
let hasCircle = false
|
||||||
for (const pipe of node.init.body) {
|
for (const pipe of node.init.body) {
|
||||||
if (
|
if (
|
||||||
pipe.type === 'CallExpression' &&
|
pipe.type === 'CallExpression' &&
|
||||||
@ -919,8 +920,15 @@ export function doesSceneHaveSweepableSketch(ast: Program) {
|
|||||||
if (pipe.type === 'CallExpression' && pipe.callee.name === 'close') {
|
if (pipe.type === 'CallExpression' && pipe.callee.name === 'close') {
|
||||||
hasClose = true
|
hasClose = true
|
||||||
}
|
}
|
||||||
|
if (pipe.type === 'CallExpression' && pipe.callee.name === 'circle') {
|
||||||
|
hasCircle = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (hasStartProfileAt && hasStartSketchOn && hasClose) {
|
if (
|
||||||
|
(hasStartProfileAt || hasCircle) &&
|
||||||
|
hasStartSketchOn &&
|
||||||
|
(hasClose || hasCircle)
|
||||||
|
) {
|
||||||
theMap[node.id.name] = true
|
theMap[node.id.name] = true
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
|
|||||||
@ -15,27 +15,27 @@ describe('recast', () => {
|
|||||||
expect(recasted.trim()).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('variable declaration', () => {
|
it('variable declaration', () => {
|
||||||
const code = 'const myVar = 5'
|
const code = 'let myVar = 5'
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
if (err(recasted)) throw recasted
|
if (err(recasted)) throw recasted
|
||||||
expect(recasted.trim()).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it("variable declaration that's binary with string", () => {
|
it("variable declaration that's binary with string", () => {
|
||||||
const code = "const myVar = 5 + 'yo'"
|
const code = "let myVar = 5 + 'yo'"
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
if (err(recasted)) throw recasted
|
if (err(recasted)) throw recasted
|
||||||
expect(recasted.trim()).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
const codeWithOtherQuotes = 'const myVar = 5 + "yo"'
|
const codeWithOtherQuotes = 'let myVar = 5 + "yo"'
|
||||||
const { ast: ast2 } = code2ast(codeWithOtherQuotes)
|
const { ast: ast2 } = code2ast(codeWithOtherQuotes)
|
||||||
const recastRetVal = recast(ast2)
|
const recastRetVal = recast(ast2)
|
||||||
if (err(recastRetVal)) throw recastRetVal
|
if (err(recastRetVal)) throw recastRetVal
|
||||||
expect(recastRetVal.trim()).toBe(codeWithOtherQuotes)
|
expect(recastRetVal.trim()).toBe(codeWithOtherQuotes)
|
||||||
})
|
})
|
||||||
it('test assigning two variables, the second summing with the first', () => {
|
it('test assigning two variables, the second summing with the first', () => {
|
||||||
const code = `const myVar = 5
|
const code = `let myVar = 5
|
||||||
const newVar = myVar + 1
|
let newVar = myVar + 1
|
||||||
`
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
@ -53,7 +53,7 @@ const newVar = myVar + 1
|
|||||||
expect(recasted.trim()).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('test with function call', () => {
|
it('test with function call', () => {
|
||||||
const code = `const myVar = "hello"
|
const code = `let myVar = "hello"
|
||||||
log(5, myVar)
|
log(5, myVar)
|
||||||
`
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
@ -66,8 +66,8 @@ log(5, myVar)
|
|||||||
'fn funcN = (a, b) => {',
|
'fn funcN = (a, b) => {',
|
||||||
' return a + b',
|
' return a + b',
|
||||||
'}',
|
'}',
|
||||||
'const theVar = 60',
|
'let theVar = 60',
|
||||||
'const magicNum = funcN(9, theVar)',
|
'let magicNum = funcN(9, theVar)',
|
||||||
].join('\n')
|
].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
@ -75,7 +75,7 @@ log(5, myVar)
|
|||||||
expect(recasted.trim()).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('recast sketch declaration', () => {
|
it('recast sketch declaration', () => {
|
||||||
let code = `const mySketch = startSketchAt([0, 0])
|
let code = `let mySketch = startSketchAt([0, 0])
|
||||||
|> lineTo([0, 1], %, $myPath)
|
|> lineTo([0, 1], %, $myPath)
|
||||||
|> lineTo([1, 1], %)
|
|> lineTo([1, 1], %)
|
||||||
|> lineTo([1, 0], %, $rightPath)
|
|> lineTo([1, 0], %, $rightPath)
|
||||||
@ -88,7 +88,7 @@ log(5, myVar)
|
|||||||
})
|
})
|
||||||
it('sketch piped into callExpression', () => {
|
it('sketch piped into callExpression', () => {
|
||||||
const code = [
|
const code = [
|
||||||
'const mySk1 = startSketchAt([0, 0])',
|
'let mySk1 = startSketchAt([0, 0])',
|
||||||
' |> lineTo([1, 1], %)',
|
' |> lineTo([1, 1], %)',
|
||||||
' |> lineTo([0, 1], %, $myTag)',
|
' |> lineTo([0, 1], %, $myTag)',
|
||||||
' |> lineTo([1, 1], %)',
|
' |> lineTo([1, 1], %)',
|
||||||
@ -104,7 +104,7 @@ log(5, myVar)
|
|||||||
'fn myFn = (a) => {',
|
'fn myFn = (a) => {',
|
||||||
' return a + 1',
|
' return a + 1',
|
||||||
'}',
|
'}',
|
||||||
'const myVar = 5 + 1',
|
'let myVar = 5 + 1',
|
||||||
' |> myFn(%)',
|
' |> myFn(%)',
|
||||||
].join('\n')
|
].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
@ -113,21 +113,21 @@ log(5, myVar)
|
|||||||
expect(recasted.trim()).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('recast nested binary expression', () => {
|
it('recast nested binary expression', () => {
|
||||||
const code = ['const myVar = 1 + 2 * 5'].join('\n')
|
const code = ['let myVar = 1 + 2 * 5'].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
if (err(recasted)) throw recasted
|
if (err(recasted)) throw recasted
|
||||||
expect(recasted.trim()).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('recast nested binary expression with parans', () => {
|
it('recast nested binary expression with parans', () => {
|
||||||
const code = ['const myVar = 1 + (1 + 2) * 5'].join('\n')
|
const code = ['let myVar = 1 + (1 + 2) * 5'].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
if (err(recasted)) throw recasted
|
if (err(recasted)) throw recasted
|
||||||
expect(recasted.trim()).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('unnecessary paran wrap will be remove', () => {
|
it('unnecessary paran wrap will be remove', () => {
|
||||||
const code = ['const myVar = 1 + (2 * 5)'].join('\n')
|
const code = ['let myVar = 1 + (2 * 5)'].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
if (err(recasted)) throw recasted
|
if (err(recasted)) throw recasted
|
||||||
@ -148,9 +148,7 @@ log(5, myVar)
|
|||||||
expect(recasted.trim()).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('recast array declaration', () => {
|
it('recast array declaration', () => {
|
||||||
const code = ['const three = 3', "const yo = [1, '2', three, 4 + 5]"].join(
|
const code = ['let three = 3', "let yo = [1, '2', three, 4 + 5]"].join('\n')
|
||||||
'\n'
|
|
||||||
)
|
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
if (err(recasted)) throw recasted
|
if (err(recasted)) throw recasted
|
||||||
@ -158,8 +156,8 @@ log(5, myVar)
|
|||||||
})
|
})
|
||||||
it('recast long array declaration', () => {
|
it('recast long array declaration', () => {
|
||||||
const code = [
|
const code = [
|
||||||
'const three = 3',
|
'let three = 3',
|
||||||
'const yo = [',
|
'let yo = [',
|
||||||
' 1,',
|
' 1,',
|
||||||
" '2',",
|
" '2',",
|
||||||
' three,',
|
' three,',
|
||||||
@ -173,8 +171,8 @@ log(5, myVar)
|
|||||||
expect(recasted.trim()).toBe(code.trim())
|
expect(recasted.trim()).toBe(code.trim())
|
||||||
})
|
})
|
||||||
it('recast long object execution', () => {
|
it('recast long object execution', () => {
|
||||||
const code = `const three = 3
|
const code = `let three = 3
|
||||||
const yo = {
|
let yo = {
|
||||||
aStr: 'str',
|
aStr: 'str',
|
||||||
anum: 2,
|
anum: 2,
|
||||||
identifier: three,
|
identifier: three,
|
||||||
@ -187,7 +185,7 @@ const yo = {
|
|||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
})
|
})
|
||||||
it('recast short object execution', () => {
|
it('recast short object execution', () => {
|
||||||
const code = `const yo = { key: 'val' }
|
const code = `let yo = { key: 'val' }
|
||||||
`
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
@ -195,11 +193,11 @@ const yo = {
|
|||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
})
|
})
|
||||||
it('recast object execution with member expression', () => {
|
it('recast object execution with member expression', () => {
|
||||||
const code = `const yo = { a: { b: { c: '123' } } }
|
const code = `let yo = { a: { b: { c: '123' } } }
|
||||||
const key = 'c'
|
let key = 'c'
|
||||||
const myVar = yo.a['b'][key]
|
let myVar = yo.a['b'][key]
|
||||||
const key2 = 'b'
|
let key2 = 'b'
|
||||||
const myVar2 = yo['a'][key2].c
|
let myVar2 = yo['a'][key2].c
|
||||||
`
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
@ -210,9 +208,9 @@ const myVar2 = yo['a'][key2].c
|
|||||||
|
|
||||||
describe('testing recasting with comments and whitespace', () => {
|
describe('testing recasting with comments and whitespace', () => {
|
||||||
it('code with comments', () => {
|
it('code with comments', () => {
|
||||||
const code = `const yo = { a: { b: { c: '123' } } }
|
const code = `let yo = { a: { b: { c: '123' } } }
|
||||||
// this is a comment
|
// this is a comment
|
||||||
const key = 'c'
|
let key = 'c'
|
||||||
`
|
`
|
||||||
|
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
@ -222,12 +220,12 @@ const key = 'c'
|
|||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
})
|
})
|
||||||
it('code with comment and extra lines', () => {
|
it('code with comment and extra lines', () => {
|
||||||
const code = `const yo = 'c'
|
const code = `let yo = 'c'
|
||||||
|
|
||||||
/* this is
|
/* this is
|
||||||
a
|
a
|
||||||
comment */
|
comment */
|
||||||
const yo = 'bing'
|
let yo = 'bing'
|
||||||
`
|
`
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
@ -236,8 +234,8 @@ const yo = 'bing'
|
|||||||
})
|
})
|
||||||
it('comments at the start and end', () => {
|
it('comments at the start and end', () => {
|
||||||
const code = `// this is a comment
|
const code = `// this is a comment
|
||||||
const yo = { a: { b: { c: '123' } } }
|
let yo = { a: { b: { c: '123' } } }
|
||||||
const key = 'c'
|
let key = 'c'
|
||||||
|
|
||||||
// this is also a comment
|
// this is also a comment
|
||||||
`
|
`
|
||||||
@ -249,11 +247,11 @@ const key = 'c'
|
|||||||
it('comments in a fn block', () => {
|
it('comments in a fn block', () => {
|
||||||
const code = `fn myFn = () => {
|
const code = `fn myFn = () => {
|
||||||
// this is a comment
|
// this is a comment
|
||||||
const yo = { a: { b: { c: '123' } } }
|
let yo = { a: { b: { c: '123' } } }
|
||||||
|
|
||||||
/* block
|
/* block
|
||||||
comment */
|
comment */
|
||||||
const key = 'c'
|
let key = 'c'
|
||||||
// this is also a comment
|
// this is also a comment
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@ -264,7 +262,7 @@ const key = 'c'
|
|||||||
})
|
})
|
||||||
it('comments in a pipe expression', () => {
|
it('comments in a pipe expression', () => {
|
||||||
const code = [
|
const code = [
|
||||||
'const mySk1 = startSketchAt([0, 0])',
|
'let mySk1 = startSketchAt([0, 0])',
|
||||||
' |> lineTo([1, 1], %)',
|
' |> lineTo([1, 1], %)',
|
||||||
' |> lineTo([0, 1], %, $myTag)',
|
' |> lineTo([0, 1], %, $myTag)',
|
||||||
' |> lineTo([1, 1], %)',
|
' |> lineTo([1, 1], %)',
|
||||||
@ -280,7 +278,7 @@ const key = 'c'
|
|||||||
const code = `
|
const code = `
|
||||||
/* comment at start */
|
/* comment at start */
|
||||||
|
|
||||||
const mySk1 = startSketchAt([0, 0])
|
let mySk1 = startSketchAt([0, 0])
|
||||||
|> lineTo([1, 1], %)
|
|> lineTo([1, 1], %)
|
||||||
// comment here
|
// comment here
|
||||||
|> lineTo([0, 1], %, $myTag)
|
|> lineTo([0, 1], %, $myTag)
|
||||||
@ -303,7 +301,7 @@ one more for good measure
|
|||||||
if (err(recasted)) throw recasted
|
if (err(recasted)) throw recasted
|
||||||
expect(recasted).toBe(`/* comment at start */
|
expect(recasted).toBe(`/* comment at start */
|
||||||
|
|
||||||
const mySk1 = startSketchAt([0, 0])
|
let mySk1 = startSketchAt([0, 0])
|
||||||
|> lineTo([1, 1], %)
|
|> lineTo([1, 1], %)
|
||||||
// comment here
|
// comment here
|
||||||
|> lineTo([0, 1], %, $myTag)
|
|> lineTo([0, 1], %, $myTag)
|
||||||
@ -321,21 +319,21 @@ const mySk1 = startSketchAt([0, 0])
|
|||||||
|
|
||||||
describe('testing call Expressions in BinaryExpressions and UnaryExpressions', () => {
|
describe('testing call Expressions in BinaryExpressions and UnaryExpressions', () => {
|
||||||
it('nested callExpression in binaryExpression', () => {
|
it('nested callExpression in binaryExpression', () => {
|
||||||
const code = 'const myVar = 2 + min(100, legLen(5, 3))'
|
const code = 'let myVar = 2 + min(100, legLen(5, 3))'
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
if (err(recasted)) throw recasted
|
if (err(recasted)) throw recasted
|
||||||
expect(recasted.trim()).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('nested callExpression in unaryExpression', () => {
|
it('nested callExpression in unaryExpression', () => {
|
||||||
const code = 'const myVar = -min(100, legLen(5, 3))'
|
const code = 'let myVar = -min(100, legLen(5, 3))'
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
if (err(recasted)) throw recasted
|
if (err(recasted)) throw recasted
|
||||||
expect(recasted.trim()).toBe(code)
|
expect(recasted.trim()).toBe(code)
|
||||||
})
|
})
|
||||||
it('with unaryExpression in callExpression', () => {
|
it('with unaryExpression in callExpression', () => {
|
||||||
const code = 'const myVar = min(5, -legLen(5, 4))'
|
const code = 'let myVar = min(5, -legLen(5, 4))'
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
const recasted = recast(ast)
|
const recasted = recast(ast)
|
||||||
if (err(recasted)) throw recasted
|
if (err(recasted)) throw recasted
|
||||||
@ -343,7 +341,7 @@ describe('testing call Expressions in BinaryExpressions and UnaryExpressions', (
|
|||||||
})
|
})
|
||||||
it('with unaryExpression in sketch situation', () => {
|
it('with unaryExpression in sketch situation', () => {
|
||||||
const code = [
|
const code = [
|
||||||
'const part001 = startSketchAt([0, 0])',
|
'let part001 = startSketchAt([0, 0])',
|
||||||
' |> line([-2.21, -legLen(5, min(3, 999))], %)',
|
' |> line([-2.21, -legLen(5, min(3, 999))], %)',
|
||||||
].join('\n')
|
].join('\n')
|
||||||
const { ast } = code2ast(code)
|
const { ast } = code2ast(code)
|
||||||
@ -355,7 +353,7 @@ describe('testing call Expressions in BinaryExpressions and UnaryExpressions', (
|
|||||||
|
|
||||||
describe('it recasts wrapped object expressions in pipe bodies with correct indentation', () => {
|
describe('it recasts wrapped object expressions in pipe bodies with correct indentation', () => {
|
||||||
it('with a single line', () => {
|
it('with a single line', () => {
|
||||||
const code = `const part001 = startSketchAt([-0.01, -0.08])
|
const code = `let part001 = startSketchAt([-0.01, -0.08])
|
||||||
|> line([0.62, 4.15], %, $seg01)
|
|> line([0.62, 4.15], %, $seg01)
|
||||||
|> line([2.77, -1.24], %)
|
|> line([2.77, -1.24], %)
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
@ -386,7 +384,7 @@ describe('it recasts wrapped object expressions in pipe bodies with correct inde
|
|||||||
|
|
||||||
describe('it recasts binary expression using brackets where needed', () => {
|
describe('it recasts binary expression using brackets where needed', () => {
|
||||||
it('when there are two minus in a row', () => {
|
it('when there are two minus in a row', () => {
|
||||||
const code = `const part001 = 1 - (def - abc)
|
const code = `let part001 = 1 - (def - abc)
|
||||||
`
|
`
|
||||||
const recasted = recast(code2ast(code).ast)
|
const recasted = recast(code2ast(code).ast)
|
||||||
expect(recasted).toBe(code)
|
expect(recasted).toBe(code)
|
||||||
|
|||||||
@ -31,52 +31,52 @@ It's needed for testing the artifactGraph, as it is tied to the websocket comman
|
|||||||
const pathStart = 'src/lang/std/artifactMapCache'
|
const pathStart = 'src/lang/std/artifactMapCache'
|
||||||
const fullPath = `${pathStart}/artifactMapCache.json`
|
const fullPath = `${pathStart}/artifactMapCache.json`
|
||||||
|
|
||||||
const exampleCode1 = `const sketch001 = startSketchOn('XY')
|
const exampleCode1 = `let sketch001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-5, -5], %)
|
|> startProfileAt([-5, -5], %)
|
||||||
|> line([0, 10], %)
|
|> line([0, 10], %)
|
||||||
|> line([10.55, 0], %, $seg01)
|
|> line([10.55, 0], %, $seg01)
|
||||||
|> line([0, -10], %, $seg02)
|
|> line([0, -10], %, $seg02)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(-10, sketch001)
|
let extrude001 = extrude(-10, sketch001)
|
||||||
|> fillet({ radius: 5, tags: [seg01] }, %)
|
|> fillet({ radius: 5, tags: [seg01] }, %)
|
||||||
const sketch002 = startSketchOn(extrude001, seg02)
|
let sketch002 = startSketchOn(extrude001, seg02)
|
||||||
|> startProfileAt([-2, -6], %)
|
|> startProfileAt([-2, -6], %)
|
||||||
|> line([2, 3], %)
|
|> line([2, 3], %)
|
||||||
|> line([2, -3], %)
|
|> line([2, -3], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude002 = extrude(5, sketch002)
|
let extrude002 = extrude(5, sketch002)
|
||||||
`
|
`
|
||||||
|
|
||||||
const sketchOnFaceOnFaceEtc = `const sketch001 = startSketchOn('XZ')
|
const sketchOnFaceOnFaceEtc = `let sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line([4, 8], %)
|
|> line([4, 8], %)
|
||||||
|> line([5, -8], %, $seg01)
|
|> line([5, -8], %, $seg01)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude001 = extrude(6, sketch001)
|
let extrude001 = extrude(6, sketch001)
|
||||||
const sketch002 = startSketchOn(extrude001, seg01)
|
let sketch002 = startSketchOn(extrude001, seg01)
|
||||||
|> startProfileAt([-0.5, 0.5], %)
|
|> startProfileAt([-0.5, 0.5], %)
|
||||||
|> line([2, 5], %)
|
|> line([2, 5], %)
|
||||||
|> line([2, -5], %)
|
|> line([2, -5], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude002 = extrude(5, sketch002)
|
let extrude002 = extrude(5, sketch002)
|
||||||
const sketch003 = startSketchOn(extrude002, 'END')
|
let sketch003 = startSketchOn(extrude002, 'END')
|
||||||
|> startProfileAt([1, 1.5], %)
|
|> startProfileAt([1, 1.5], %)
|
||||||
|> line([0.5, 2], %, $seg02)
|
|> line([0.5, 2], %, $seg02)
|
||||||
|> line([1, -2], %)
|
|> line([1, -2], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude003 = extrude(4, sketch003)
|
let extrude003 = extrude(4, sketch003)
|
||||||
const sketch004 = startSketchOn(extrude003, seg02)
|
let sketch004 = startSketchOn(extrude003, seg02)
|
||||||
|> startProfileAt([-3, 14], %)
|
|> startProfileAt([-3, 14], %)
|
||||||
|> line([0.5, 1], %)
|
|> line([0.5, 1], %)
|
||||||
|> line([0.5, -2], %)
|
|> line([0.5, -2], %)
|
||||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|> close(%)
|
|> close(%)
|
||||||
const extrude004 = extrude(3, sketch004)
|
let extrude004 = extrude(3, sketch004)
|
||||||
`
|
`
|
||||||
|
|
||||||
// add more code snippets here and use `getCommands` to get the orderedCommands and responseMap for more tests
|
// add more code snippets here and use `getCommands` to get the orderedCommands and responseMap for more tests
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 378 KiB After Width: | Height: | Size: 244 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 613 KiB After Width: | Height: | Size: 446 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user