Merge remote-tracking branch 'origin' into paultag/import
3
.github/workflows/cargo-bench.yml
vendored
@ -50,12 +50,13 @@ jobs:
|
|||||||
- name: Build the benchmark target(s)
|
- name: Build the benchmark target(s)
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
cargo codspeed build
|
cargo codspeed build --measurement-mode walltime
|
||||||
- name: Run the benchmarks
|
- name: Run the benchmarks
|
||||||
uses: CodSpeedHQ/action@v3
|
uses: CodSpeedHQ/action@v3
|
||||||
with:
|
with:
|
||||||
working-directory: rust
|
working-directory: rust
|
||||||
run: cargo codspeed run
|
run: cargo codspeed run
|
||||||
token: ${{ secrets.CODSPEED_TOKEN }}
|
token: ${{ secrets.CODSPEED_TOKEN }}
|
||||||
|
mode: walltime
|
||||||
env:
|
env:
|
||||||
KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN }}
|
KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN }}
|
||||||
|
26
.github/workflows/e2e-tests.yml
vendored
@ -220,8 +220,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Run ubuntu/chrome snapshots
|
- name: Run ubuntu/chrome snapshots
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
if: needs.conditions.outputs.should-run == 'true'
|
||||||
run: |
|
uses: nick-fields/retry@v3.0.2
|
||||||
yarn test:snapshots
|
with:
|
||||||
|
shell: bash
|
||||||
|
command: yarn test:snapshots
|
||||||
|
timeout_minutes: 30
|
||||||
|
max_attempts: 3
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
NODE_ENV: development
|
NODE_ENV: development
|
||||||
@ -287,10 +291,20 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
# TODO: enable self-hosted-windows-8-cores once available
|
# TODO: enable namespace-profile-windows-8-cores once available
|
||||||
os: [namespace-profile-ubuntu-8-cores, namespace-profile-macos-8-cores, windows-16-cores]
|
os: [namespace-profile-ubuntu-8-cores, namespace-profile-macos-8-cores, windows-16-cores]
|
||||||
shardIndex: [1, 2, 3, 4]
|
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||||
shardTotal: [4]
|
shardTotal: [8]
|
||||||
|
# Disable macos and windows tests on hourly e2e tests since we only care
|
||||||
|
# about server side changes.
|
||||||
|
# Technique from https://github.com/joaomcteixeira/python-project-skeleton/pull/31/files
|
||||||
|
isScheduled:
|
||||||
|
- ${{ github.event_name == 'schedule' }}
|
||||||
|
exclude:
|
||||||
|
- os: namespace-profile-macos-8-cores
|
||||||
|
isScheduled: true
|
||||||
|
- os: windows-16-cores
|
||||||
|
isScheduled: true
|
||||||
# TODO: add ref here for main and latest release tag
|
# TODO: add ref here for main and latest release tag
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
@ -358,7 +372,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
command: .github/ci-cd-scripts/playwright-electron.sh ${{matrix.shardIndex}} ${{matrix.shardTotal}} ${{matrix.os}}
|
command: .github/ci-cd-scripts/playwright-electron.sh ${{matrix.shardIndex}} ${{matrix.shardTotal}} ${{matrix.os}}
|
||||||
timeout_minutes: 30
|
timeout_minutes: 30
|
||||||
max_attempts: 25
|
max_attempts: 15
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
FAIL_ON_CONSOLE_ERRORS: true
|
FAIL_ON_CONSOLE_ERRORS: true
|
||||||
|
3
.gitignore
vendored
@ -53,13 +53,14 @@ e2e/playwright/export-snapshots/*
|
|||||||
|
|
||||||
/public/kcl-samples.zip
|
/public/kcl-samples.zip
|
||||||
/public/kcl-samples/.github
|
/public/kcl-samples/.github
|
||||||
|
/public/kcl-samples/screenshots/main.kcl
|
||||||
|
/public/kcl-samples/step/main.kcl
|
||||||
/test-results/
|
/test-results/
|
||||||
/playwright-report/
|
/playwright-report/
|
||||||
/blob-report/
|
/blob-report/
|
||||||
/playwright/.cache/
|
/playwright/.cache/
|
||||||
/src/lang/std/artifactMapCache
|
/src/lang/std/artifactMapCache
|
||||||
|
|
||||||
|
|
||||||
## generated files
|
## generated files
|
||||||
src/**/*.typegen.ts
|
src/**/*.typegen.ts
|
||||||
|
|
||||||
|
@ -6,13 +6,13 @@ layout: manual
|
|||||||
|
|
||||||
Extend a 2-dimensional sketch through a third dimension in order to create new 3-dimensional volume, or if extruded into an existing volume, cut into an existing solid.
|
Extend a 2-dimensional sketch through a third dimension in order to create new 3-dimensional volume, or if extruded into an existing volume, cut into an existing solid.
|
||||||
|
|
||||||
|
You can provide more than one sketch to extrude, and they will all be extruded in the same direction.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
extrude(
|
extrude(
|
||||||
sketchSet: SketchSet,
|
sketches: [Sketch],
|
||||||
length: number,
|
length: number,
|
||||||
): SolidSet
|
): [Solid]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -20,12 +20,12 @@ extrude(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketchSet` | [`SketchSet`](/docs/kcl/types/SketchSet) | Which sketches should be extruded | Yes |
|
| `sketches` | [`[Sketch]`](/docs/kcl/types/Sketch) | Which sketch or sketches should be extruded | Yes |
|
||||||
| `length` | [`number`](/docs/kcl/types/number) | How far to extrude the given sketches | Yes |
|
| `length` | [`number`](/docs/kcl/types/number) | How far to extrude the given sketches | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`SolidSet`](/docs/kcl/types/SolidSet) - A solid or a group of solids.
|
[`[Solid]`](/docs/kcl/types/Solid)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
@ -10,7 +10,7 @@ Use a 2-dimensional sketch to cut a hole in another 2-dimensional sketch.
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
hole(
|
hole(
|
||||||
holeSketch: SketchSet,
|
holeSketch: [Sketch],
|
||||||
sketch: Sketch,
|
sketch: Sketch,
|
||||||
): Sketch
|
): Sketch
|
||||||
```
|
```
|
||||||
@ -20,7 +20,7 @@ hole(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `holeSketch` | [`SketchSet`](/docs/kcl/types/SketchSet) | A sketch or a group of sketches. | Yes |
|
| `holeSketch` | [`[Sketch]`](/docs/kcl/types/Sketch) | | Yes |
|
||||||
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | | Yes |
|
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
@ -10,7 +10,7 @@ Repeat a 2-dimensional sketch some number of times along a partial or complete c
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
patternCircular2d(
|
patternCircular2d(
|
||||||
sketchSet: SketchSet,
|
sketchSet: [Sketch],
|
||||||
instances: integer,
|
instances: integer,
|
||||||
center: [number],
|
center: [number],
|
||||||
arcDegrees: number,
|
arcDegrees: number,
|
||||||
@ -24,7 +24,7 @@ patternCircular2d(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketchSet` | [`SketchSet`](/docs/kcl/types/SketchSet) | Which sketch(es) to pattern | Yes |
|
| `sketchSet` | [`[Sketch]`](/docs/kcl/types/Sketch) | Which sketch(es) to pattern | Yes |
|
||||||
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `center` | [`[number]`](/docs/kcl/types/number) | The center about which to make the pattern. This is a 2D vector. | Yes |
|
| `center` | [`[number]`](/docs/kcl/types/number) | The center about which to make the pattern. This is a 2D vector. | Yes |
|
||||||
| `arcDegrees` | [`number`](/docs/kcl/types/number) | The arc angle (in degrees) to place the repetitions. Must be greater than 0. | Yes |
|
| `arcDegrees` | [`number`](/docs/kcl/types/number) | The arc angle (in degrees) to place the repetitions. Must be greater than 0. | Yes |
|
||||||
|
@ -10,7 +10,7 @@ Repeat a 3-dimensional solid some number of times along a partial or complete ci
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
patternCircular3d(
|
patternCircular3d(
|
||||||
solidSet: SolidSet,
|
solids: [Solid],
|
||||||
instances: integer,
|
instances: integer,
|
||||||
axis: [number],
|
axis: [number],
|
||||||
center: [number],
|
center: [number],
|
||||||
@ -25,7 +25,7 @@ patternCircular3d(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solidSet` | [`SolidSet`](/docs/kcl/types/SolidSet) | Which solid(s) to pattern | Yes |
|
| `solids` | [`[Solid]`](/docs/kcl/types/Solid) | Which solid(s) to pattern | Yes |
|
||||||
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis around which to make the pattern. This is a 3D vector | Yes |
|
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis around which to make the pattern. This is a 3D vector | Yes |
|
||||||
| `center` | [`[number]`](/docs/kcl/types/number) | The center about which to make the pattern. This is a 3D vector. | Yes |
|
| `center` | [`[number]`](/docs/kcl/types/number) | The center about which to make the pattern. This is a 3D vector. | Yes |
|
||||||
|
@ -10,7 +10,7 @@ Repeat a 2-dimensional sketch along some dimension, with a dynamic amount of dis
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
patternLinear2d(
|
patternLinear2d(
|
||||||
sketchSet: SketchSet,
|
sketches: [Sketch],
|
||||||
instances: integer,
|
instances: integer,
|
||||||
distance: number,
|
distance: number,
|
||||||
axis: [number],
|
axis: [number],
|
||||||
@ -23,7 +23,7 @@ patternLinear2d(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketchSet` | [`SketchSet`](/docs/kcl/types/SketchSet) | The sketch(es) to duplicate | Yes |
|
| `sketches` | [`[Sketch]`](/docs/kcl/types/Sketch) | The sketch(es) to duplicate | Yes |
|
||||||
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `distance` | [`number`](/docs/kcl/types/number) | Distance between each repetition. Also known as 'spacing'. | Yes |
|
| `distance` | [`number`](/docs/kcl/types/number) | Distance between each repetition. Also known as 'spacing'. | Yes |
|
||||||
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis of the pattern. A 2D vector. | Yes |
|
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis of the pattern. A 2D vector. | Yes |
|
||||||
|
@ -10,7 +10,7 @@ Repeat a 3-dimensional solid along a linear path, with a dynamic amount of dista
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
patternLinear3d(
|
patternLinear3d(
|
||||||
solidSet: SolidSet,
|
solids: [Solid],
|
||||||
instances: integer,
|
instances: integer,
|
||||||
distance: number,
|
distance: number,
|
||||||
axis: [number],
|
axis: [number],
|
||||||
@ -23,7 +23,7 @@ patternLinear3d(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solidSet` | [`SolidSet`](/docs/kcl/types/SolidSet) | The solid(s) to duplicate | Yes |
|
| `solids` | [`[Solid]`](/docs/kcl/types/Solid) | The solid(s) to duplicate | Yes |
|
||||||
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `distance` | [`number`](/docs/kcl/types/number) | Distance between each repetition. Also known as 'spacing'. | Yes |
|
| `distance` | [`number`](/docs/kcl/types/number) | Distance between each repetition. Also known as 'spacing'. | Yes |
|
||||||
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis of the pattern. A 2D vector. | Yes |
|
| `axis` | [`[number]`](/docs/kcl/types/number) | The axis of the pattern. A 2D vector. | Yes |
|
||||||
|
@ -36,7 +36,7 @@ The transform function returns a transform object. All properties of the object
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
patternTransform(
|
patternTransform(
|
||||||
solidSet: SolidSet,
|
solids: [Solid],
|
||||||
instances: integer,
|
instances: integer,
|
||||||
transform: FunctionSource,
|
transform: FunctionSource,
|
||||||
useOriginal?: bool,
|
useOriginal?: bool,
|
||||||
@ -48,7 +48,7 @@ patternTransform(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solidSet` | [`SolidSet`](/docs/kcl/types/SolidSet) | The solid(s) to duplicate | Yes |
|
| `solids` | [`[Solid]`](/docs/kcl/types/Solid) | The solid(s) to duplicate | Yes |
|
||||||
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
| `instances` | `integer` | The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. | Yes |
|
||||||
| `transform` | `FunctionSource` | How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument `1`. This simplifies your math: the transform function can rely on id `0` being the original instance passed into the `patternTransform`. See the examples. | Yes |
|
| `transform` | `FunctionSource` | How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument `1`. This simplifies your math: the transform function can rely on id `0` being the original instance passed into the `patternTransform`. See the examples. | Yes |
|
||||||
| `useOriginal` | [`bool`](/docs/kcl/types/bool) | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false. | No |
|
| `useOriginal` | [`bool`](/docs/kcl/types/bool) | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false. | No |
|
||||||
|
@ -10,10 +10,10 @@ Remove volume from a 3-dimensional shape such that a wall of the provided thickn
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
shell(
|
shell(
|
||||||
solidSet: SolidSet,
|
solids: [Solid],
|
||||||
thickness: number,
|
thickness: number,
|
||||||
faces: [FaceTag],
|
faces: [FaceTag],
|
||||||
): SolidSet
|
): [Solid]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -21,13 +21,13 @@ shell(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `solidSet` | [`SolidSet`](/docs/kcl/types/SolidSet) | Which solid (or solids) to shell out | Yes |
|
| `solids` | [`[Solid]`](/docs/kcl/types/Solid) | Which solid (or solids) to shell out | Yes |
|
||||||
| `thickness` | [`number`](/docs/kcl/types/number) | The thickness of the shell | Yes |
|
| `thickness` | [`number`](/docs/kcl/types/number) | The thickness of the shell | Yes |
|
||||||
| `faces` | [`[FaceTag]`](/docs/kcl/types/FaceTag) | The faces you want removed | Yes |
|
| `faces` | [`[FaceTag]`](/docs/kcl/types/FaceTag) | The faces you want removed | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`SolidSet`](/docs/kcl/types/SolidSet) - A solid or a group of solids.
|
[`[Solid]`](/docs/kcl/types/Solid)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
94808
docs/kcl/std.json
@ -24,6 +24,5 @@ A face.
|
|||||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||||
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
|
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
|
||||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,6 +22,5 @@ A helix.
|
|||||||
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
|
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
|
||||||
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
|
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
|
||||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,6 +22,5 @@ A helix.
|
|||||||
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
|
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
|
||||||
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
|
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
|
||||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,5 @@ Data for an imported geometry.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The ID of the imported geometry. | No |
|
| `id` |[`string`](/docs/kcl/types/string)| The ID of the imported geometry. | No |
|
||||||
| `value` |`[` [`string`](/docs/kcl/types/string) `]`| The original file paths. | No |
|
| `value` |`[` [`string`](/docs/kcl/types/string) `]`| The original file paths. | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ Any KCL value.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: `Uuid`| | No |
|
| `type` |enum: `Uuid`| | No |
|
||||||
| `value` |[`string`](/docs/kcl/types/string)| | No |
|
| `value` |[`string`](/docs/kcl/types/string)| | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -42,7 +41,6 @@ Any KCL value.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: `Bool`| | No |
|
| `type` |enum: `Bool`| | No |
|
||||||
| `value` |`boolean`| | No |
|
| `value` |`boolean`| | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -60,7 +58,6 @@ Any KCL value.
|
|||||||
| `type` |enum: `Number`| | No |
|
| `type` |enum: `Number`| | No |
|
||||||
| `value` |[`number`](/docs/kcl/types/number)| | No |
|
| `value` |[`number`](/docs/kcl/types/number)| | No |
|
||||||
| `ty` |[`NumericType`](/docs/kcl/types/NumericType)| | No |
|
| `ty` |[`NumericType`](/docs/kcl/types/NumericType)| | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -77,7 +74,6 @@ Any KCL value.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: `String`| | No |
|
| `type` |enum: `String`| | No |
|
||||||
| `value` |[`string`](/docs/kcl/types/string)| | No |
|
| `value` |[`string`](/docs/kcl/types/string)| | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -94,7 +90,22 @@ Any KCL value.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: `MixedArray`| | No |
|
| `type` |enum: `MixedArray`| | No |
|
||||||
| `value` |`[` [`KclValue`](/docs/kcl/types/KclValue) `]`| | No |
|
| `value` |`[` [`KclValue`](/docs/kcl/types/KclValue) `]`| | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
**Type:** `object`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Property | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `type` |enum: `HomArray`| | No |
|
||||||
|
| `value` |`[` [`KclValue`](/docs/kcl/types/KclValue) `]`| | No |
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -111,7 +122,6 @@ Any KCL value.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: `Object`| | No |
|
| `type` |enum: `Object`| | No |
|
||||||
| `value` |`object`| | No |
|
| `value` |`object`| | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -128,8 +138,6 @@ Any KCL value.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: [`TagIdentifier`](/docs/kcl/types#tag-identifier)| | No |
|
| `type` |enum: [`TagIdentifier`](/docs/kcl/types#tag-identifier)| | No |
|
||||||
| `value` |[`string`](/docs/kcl/types/string)| | No |
|
| `value` |[`string`](/docs/kcl/types/string)| | No |
|
||||||
| `info` |[`TagEngineInfo`](/docs/kcl/types/TagEngineInfo)| | No |
|
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -207,22 +215,6 @@ Any KCL value.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `Sketches`| | No |
|
|
||||||
| `value` |`[` [`Sketch`](/docs/kcl/types/Sketch) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
**Type:** `object`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
## Properties
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
@ -239,22 +231,6 @@ Any KCL value.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `Solids`| | No |
|
|
||||||
| `value` |`[` [`Solid`](/docs/kcl/types/Solid) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
**Type:** `object`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
## Properties
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
@ -279,7 +255,6 @@ Data for an imported geometry.
|
|||||||
| `type` |enum: [`ImportedGeometry`](/docs/kcl/types/ImportedGeometry)| | No |
|
| `type` |enum: [`ImportedGeometry`](/docs/kcl/types/ImportedGeometry)| | No |
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The ID of the imported geometry. | No |
|
| `id` |[`string`](/docs/kcl/types/string)| The ID of the imported geometry. | No |
|
||||||
| `value` |`[` [`string`](/docs/kcl/types/string) `]`| The original file paths. | No |
|
| `value` |`[` [`string`](/docs/kcl/types/string) `]`| The original file paths. | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -295,7 +270,6 @@ Data for an imported geometry.
|
|||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: `Function`| | No |
|
| `type` |enum: `Function`| | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -312,7 +286,6 @@ Data for an imported geometry.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: `Module`| | No |
|
| `type` |enum: `Module`| | No |
|
||||||
| `value` |[`ModuleId`](/docs/kcl/types/ModuleId)| Identifier of a source file. Uses a u32 to keep the size small. | No |
|
| `value` |[`ModuleId`](/docs/kcl/types/ModuleId)| Identifier of a source file. Uses a u32 to keep the size small. | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -328,7 +301,6 @@ Data for an imported geometry.
|
|||||||
| Property | Type | Description | Required |
|
| Property | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: `Type`| | No |
|
| `type` |enum: `Type`| | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -345,24 +317,6 @@ Data for an imported geometry.
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `type` |enum: [`KclNone`](/docs/kcl/types/KclNone)| | No |
|
| `type` |enum: [`KclNone`](/docs/kcl/types/KclNone)| | No |
|
||||||
| `value` |[`KclNone`](/docs/kcl/types/KclNone)| KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application). | No |
|
| `value` |[`KclNone`](/docs/kcl/types/KclNone)| KCL value for an optional parameter which was not given an argument. (remember, parameters are in the function declaration, arguments are in the function call/application). | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
**Type:** `object`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `Tombstone`| | No |
|
|
||||||
| `value` |`null`| | No |
|
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
@ -126,6 +126,30 @@ A base path.
|
|||||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
A base path.
|
||||||
|
|
||||||
|
**Type:** `object`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Property | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `type` |enum: `ArcThreePoint`| | No |
|
||||||
|
| `p1` |`[number, number]`| Point 1 of the arc (base on the end of previous segment) | No |
|
||||||
|
| `p2` |`[number, number]`| Point 2 of the arc (interior kwarg) | No |
|
||||||
|
| `p3` |`[number, number]`| Point 3 of the arc (end kwarg) | No |
|
||||||
|
| `from` |`[number, number]`| The from point. | No |
|
||||||
|
| `to` |`[number, number]`| The to point. | No |
|
||||||
|
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||||
|
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||||
|
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
A path that is horizontal.
|
A path that is horizontal.
|
||||||
|
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
---
|
|
||||||
title: "SketchSet"
|
|
||||||
excerpt: "A sketch or a group of sketches."
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
A sketch or a group of sketches.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**This schema accepts exactly one of the following:**
|
|
||||||
|
|
||||||
|
|
||||||
**Type:** `object`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `sketch`| | No |
|
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the sketch (this will change when the engine's reference to it changes). | No |
|
|
||||||
| `paths` |`[` [`Path`](/docs/kcl/types/Path) `]`| The paths in the sketch. | No |
|
|
||||||
| `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No |
|
|
||||||
| `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No |
|
|
||||||
| `tags` |`object`| Tag identifiers that have been declared in this sketch. | No |
|
|
||||||
| `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The original id of the sketch. This stays the same even if the sketch is is sketched on face etc. | No |
|
|
||||||
| `originalId` |[`string`](/docs/kcl/types/string)| | No |
|
|
||||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
**Type:** `[object, array]`
|
|
||||||
|
|
||||||
`[` [`Sketch`](/docs/kcl/types/Sketch) `]`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `sketches`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -32,7 +32,6 @@ A sketch type.
|
|||||||
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's Y axis be? | No |
|
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's Y axis be? | No |
|
||||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
@ -57,7 +56,6 @@ A face.
|
|||||||
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
|
||||||
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
|
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
|
||||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
@ -12,31 +12,6 @@ Data for a solid or an imported geometry.
|
|||||||
|
|
||||||
**This schema accepts exactly one of the following:**
|
**This schema accepts exactly one of the following:**
|
||||||
|
|
||||||
|
|
||||||
**Type:** `object`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `solid`| | No |
|
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the solid. | No |
|
|
||||||
| `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID of the solid. Unlike `id`, this doesn't change. | No |
|
|
||||||
| `value` |`[` [`ExtrudeSurface`](/docs/kcl/types/ExtrudeSurface) `]`| The extrude surfaces. | No |
|
|
||||||
| `sketch` |[`Sketch`](/docs/kcl/types/Sketch)| The sketch. | No |
|
|
||||||
| `height` |[`number`](/docs/kcl/types/number)| The height of the solid. | No |
|
|
||||||
| `startCapId` |[`string`](/docs/kcl/types/string)| The id of the extrusion start cap | No |
|
|
||||||
| `endCapId` |[`string`](/docs/kcl/types/string)| The id of the extrusion end cap | No |
|
|
||||||
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
|
|
||||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
Data for an imported geometry.
|
Data for an imported geometry.
|
||||||
|
|
||||||
**Type:** `object`
|
**Type:** `object`
|
||||||
@ -52,7 +27,21 @@ Data for an imported geometry.
|
|||||||
| `type` |enum: `importedGeometry`| | No |
|
| `type` |enum: `importedGeometry`| | No |
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The ID of the imported geometry. | No |
|
| `id` |[`string`](/docs/kcl/types/string)| The ID of the imported geometry. | No |
|
||||||
| `value` |`[` [`string`](/docs/kcl/types/string) `]`| The original file paths. | No |
|
| `value` |`[` [`string`](/docs/kcl/types/string) `]`| The original file paths. | No |
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
|
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
**Type:** `[object, array]`
|
||||||
|
|
||||||
|
`[` [`Solid`](/docs/kcl/types/Solid) `]`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Property | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `type` |enum: `solidSet`| | No |
|
||||||
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
---
|
|
||||||
title: "SolidSet"
|
|
||||||
excerpt: "A solid or a group of solids."
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
A solid or a group of solids.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**This schema accepts exactly one of the following:**
|
|
||||||
|
|
||||||
|
|
||||||
**Type:** `object`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `solid`| | No |
|
|
||||||
| `id` |[`string`](/docs/kcl/types/string)| The id of the solid. | No |
|
|
||||||
| `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID of the solid. Unlike `id`, this doesn't change. | No |
|
|
||||||
| `value` |`[` [`ExtrudeSurface`](/docs/kcl/types/ExtrudeSurface) `]`| The extrude surfaces. | No |
|
|
||||||
| `sketch` |[`Sketch`](/docs/kcl/types/Sketch)| The sketch. | No |
|
|
||||||
| `height` |[`number`](/docs/kcl/types/number)| The height of the solid. | No |
|
|
||||||
| `startCapId` |[`string`](/docs/kcl/types/string)| The id of the extrusion start cap | No |
|
|
||||||
| `endCapId` |[`string`](/docs/kcl/types/string)| The id of the extrusion end cap | No |
|
|
||||||
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
|
|
||||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A unit of length. | No |
|
|
||||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
**Type:** `[object, array]`
|
|
||||||
|
|
||||||
`[` [`Solid`](/docs/kcl/types/Solid) `]`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
|
|
||||||
| Property | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `type` |enum: `solids`| | No |
|
|
||||||
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -185,7 +185,7 @@ test(
|
|||||||
},
|
},
|
||||||
{ timeout: 15_000 }
|
{ timeout: 15_000 }
|
||||||
)
|
)
|
||||||
.toBeGreaterThan(100_000)
|
.toBeGreaterThan(70_000)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,30 @@ export class EditorFixture {
|
|||||||
toContain: this._expectEditorToContain(),
|
toContain: this._expectEditorToContain(),
|
||||||
not: { toContain: this._expectEditorToContain(true) },
|
not: { toContain: this._expectEditorToContain(true) },
|
||||||
}
|
}
|
||||||
|
snapshot = async (options?: { timeout?: number; name?: string }) => {
|
||||||
|
const wasPaneOpen = await this.checkIfPaneIsOpen()
|
||||||
|
if (!wasPaneOpen) {
|
||||||
|
await this.openPane()
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Use expect.poll to implement retry logic
|
||||||
|
await expect
|
||||||
|
.poll(
|
||||||
|
async () => {
|
||||||
|
const code = await this.codeContent.textContent()
|
||||||
|
return code || ''
|
||||||
|
},
|
||||||
|
{ timeout: options?.timeout || 5000 }
|
||||||
|
)
|
||||||
|
.toMatchSnapshot(options?.name || 'editor-content')
|
||||||
|
} finally {
|
||||||
|
// Reset pane state if needed
|
||||||
|
if (!wasPaneOpen) {
|
||||||
|
await this.closePane()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
private _serialiseDiagnostics = async (): Promise<Array<string>> => {
|
private _serialiseDiagnostics = async (): Promise<Array<string>> => {
|
||||||
const diagnostics = await this.diagnosticsGutterIcon.all()
|
const diagnostics = await this.diagnosticsGutterIcon.all()
|
||||||
const diagnosticsContent: string[] = []
|
const diagnosticsContent: string[] = []
|
||||||
|
@ -90,8 +90,9 @@ export class ElectronZoo {
|
|||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
|
// Help remote end by signaling we're done with the connection.
|
||||||
|
// If it takes longer than 10s to stop, just resolve.
|
||||||
async makeAvailableAgain() {
|
async makeAvailableAgain() {
|
||||||
// Help remote end by signaling we're done with the connection.
|
|
||||||
await this.page.evaluate(async () => {
|
await this.page.evaluate(async () => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
if (!window.engineCommandManager.engineConnection?.state?.type) {
|
if (!window.engineCommandManager.engineConnection?.state?.type) {
|
||||||
@ -99,7 +100,9 @@ export class ElectronZoo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.engineCommandManager.tearDown()
|
window.engineCommandManager.tearDown()
|
||||||
|
|
||||||
// Keep polling (per js event tick) until state is Disconnected.
|
// Keep polling (per js event tick) until state is Disconnected.
|
||||||
|
const timeA = Date.now()
|
||||||
const checkDisconnected = () => {
|
const checkDisconnected = () => {
|
||||||
// It's possible we never even created an engineConnection
|
// It's possible we never even created an engineConnection
|
||||||
// e.g. never left Projects view.
|
// e.g. never left Projects view.
|
||||||
@ -109,6 +112,11 @@ export class ElectronZoo {
|
|||||||
) {
|
) {
|
||||||
return resolve(undefined)
|
return resolve(undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Date.now() - timeA > 10000) {
|
||||||
|
return resolve(undefined)
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(checkDisconnected, 0)
|
setTimeout(checkDisconnected, 0)
|
||||||
}
|
}
|
||||||
checkDisconnected()
|
checkDisconnected()
|
||||||
@ -130,6 +138,7 @@ export class ElectronZoo {
|
|||||||
const that = this
|
const that = this
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
|
timeout: 120000,
|
||||||
args: ['.', '--no-sandbox'],
|
args: ['.', '--no-sandbox'],
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
@ -155,8 +164,28 @@ export class ElectronZoo {
|
|||||||
// Do this once and then reuse window on subsequent calls.
|
// Do this once and then reuse window on subsequent calls.
|
||||||
if (!this.electron) {
|
if (!this.electron) {
|
||||||
this.electron = await electron.launch(options)
|
this.electron = await electron.launch(options)
|
||||||
|
|
||||||
|
// Mac takes quite a long time to create the first window in CI.
|
||||||
|
// Turns out we can't trust firstWindow() either. So loop.
|
||||||
|
let timeoutId: ReturnType<typeof setTimeout>
|
||||||
|
const tryToGetWindowPage = () =>
|
||||||
|
new Promise((resolve) => {
|
||||||
|
const fn = () => {
|
||||||
|
this.page = this.electron.windows()[0]
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
if (this.page) {
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
return resolve(undefined)
|
||||||
|
}
|
||||||
|
fn()
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
fn()
|
||||||
|
})
|
||||||
|
|
||||||
|
await tryToGetWindowPage()
|
||||||
|
|
||||||
this.context = this.electron.context()
|
this.context = this.electron.context()
|
||||||
this.page = await this.electron.firstWindow()
|
|
||||||
await this.context.tracing.start({ screenshots: true, snapshots: true })
|
await this.context.tracing.start({ screenshots: true, snapshots: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,16 +333,13 @@ const fixturesForElectron = {
|
|||||||
use: FnUse,
|
use: FnUse,
|
||||||
testInfo: TestInfo
|
testInfo: TestInfo
|
||||||
) => {
|
) => {
|
||||||
await tronApp.createInstanceIfMissing(testInfo)
|
|
||||||
await use(tronApp.page)
|
await use(tronApp.page)
|
||||||
await tronApp?.makeAvailableAgain()
|
|
||||||
},
|
},
|
||||||
context: async (
|
context: async (
|
||||||
{ tronApp }: { tronApp: ElectronZoo },
|
{ tronApp }: { tronApp: ElectronZoo },
|
||||||
use: FnUse,
|
use: FnUse,
|
||||||
testInfo: TestInfo
|
testInfo: TestInfo
|
||||||
) => {
|
) => {
|
||||||
await tronApp.createInstanceIfMissing(testInfo)
|
|
||||||
await use(tronApp.context)
|
await use(tronApp.context)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
} from '../test-utils'
|
} from '../test-utils'
|
||||||
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
||||||
import { SIDEBAR_BUTTON_SUFFIX } from 'lib/constants'
|
import { SIDEBAR_BUTTON_SUFFIX } from 'lib/constants'
|
||||||
|
import { ToolbarModeName } from 'lib/toolbar'
|
||||||
|
|
||||||
export class ToolbarFixture {
|
export class ToolbarFixture {
|
||||||
public page: Page
|
public page: Page
|
||||||
@ -120,6 +121,15 @@ export class ToolbarFixture {
|
|||||||
// this is for the engine animation, as it takes 500ms to complete
|
// this is for the engine animation, as it takes 500ms to complete
|
||||||
await this.page.waitForTimeout(600)
|
await this.page.waitForTimeout(600)
|
||||||
}
|
}
|
||||||
|
private _getMode = () =>
|
||||||
|
this.page.locator('[data-current-mode]').getAttribute('data-current-mode')
|
||||||
|
expectToolbarMode = {
|
||||||
|
toBe: (mode: ToolbarModeName) => expect.poll(this._getMode).toEqual(mode),
|
||||||
|
not: {
|
||||||
|
toBe: (mode: ToolbarModeName) =>
|
||||||
|
expect.poll(this._getMode).not.toEqual(mode),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
private _serialiseFileTree = async () => {
|
private _serialiseFileTree = async () => {
|
||||||
return this.page
|
return this.page
|
||||||
@ -176,6 +186,22 @@ export class ToolbarFixture {
|
|||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
await this.page.getByTestId('dropdown-circle-three-points').click()
|
await this.page.getByTestId('dropdown-circle-three-points').click()
|
||||||
}
|
}
|
||||||
|
selectArc = async () => {
|
||||||
|
await this.page
|
||||||
|
.getByRole('button', { name: 'caret down Tangential Arc:' })
|
||||||
|
.click()
|
||||||
|
await expect(this.page.getByTestId('dropdown-arc')).toBeVisible()
|
||||||
|
await this.page.getByTestId('dropdown-arc').click()
|
||||||
|
}
|
||||||
|
selectThreePointArc = async () => {
|
||||||
|
await this.page
|
||||||
|
.getByRole('button', { name: 'caret down Tangential Arc:' })
|
||||||
|
.click()
|
||||||
|
await expect(
|
||||||
|
this.page.getByTestId('dropdown-three-point-arc')
|
||||||
|
).toBeVisible()
|
||||||
|
await this.page.getByTestId('dropdown-three-point-arc').click()
|
||||||
|
}
|
||||||
|
|
||||||
async closePane(paneId: SidebarType) {
|
async closePane(paneId: SidebarType) {
|
||||||
return closePane(this.page, paneId + SIDEBAR_BUTTON_SUFFIX)
|
return closePane(this.page, paneId + SIDEBAR_BUTTON_SUFFIX)
|
||||||
|
@ -1024,7 +1024,7 @@ openSketch = startSketchOn('XY')
|
|||||||
await page.waitForTimeout(15000)
|
await page.waitForTimeout(15000)
|
||||||
|
|
||||||
await test.step(`Look for the blue of the XZ plane`, async () => {
|
await test.step(`Look for the blue of the XZ plane`, async () => {
|
||||||
await scene.expectPixelColor([50, 51, 96], testPoint, 15)
|
//await scene.expectPixelColor([50, 51, 96], testPoint, 15) // FIXME
|
||||||
})
|
})
|
||||||
await test.step(`Go through the command bar flow`, async () => {
|
await test.step(`Go through the command bar flow`, async () => {
|
||||||
await toolbar.offsetPlaneButton.click()
|
await toolbar.offsetPlaneButton.click()
|
||||||
@ -1066,7 +1066,7 @@ openSketch = startSketchOn('XY')
|
|||||||
)
|
)
|
||||||
await operationButton.click({ button: 'left' })
|
await operationButton.click({ button: 'left' })
|
||||||
await page.keyboard.press('Delete')
|
await page.keyboard.press('Delete')
|
||||||
await scene.expectPixelColor([50, 51, 96], testPoint, 15)
|
//await scene.expectPixelColor([50, 51, 96], testPoint, 15) // FIXME
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1408,7 +1408,7 @@ sketch002 = startSketchOn('XZ')
|
|||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||||
await scene.expectPixelColor([135, 64, 73], testPoint, 15)
|
// await scene.expectPixelColor([135, 64, 73], testPoint, 15) // FIXME
|
||||||
await editor.expectEditor.toContain(sweepDeclaration)
|
await editor.expectEditor.toContain(sweepDeclaration)
|
||||||
await editor.expectState({
|
await editor.expectState({
|
||||||
diagnostics: [],
|
diagnostics: [],
|
||||||
@ -2271,8 +2271,8 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
cmdBar,
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const initialCode = `sketch001 = startSketchOn('XZ')
|
const initialCode = `sketch001 = startSketchOn('XZ')
|
||||||
|> circle(center = [0, 0], radius = 30)
|
|> circle(center = [0, 0], radius = 30)
|
||||||
extrude001 = extrude(sketch001, length = 30)
|
extrude001 = extrude(sketch001, length = 30)
|
||||||
`
|
`
|
||||||
await context.addInitScript((initialCode) => {
|
await context.addInitScript((initialCode) => {
|
||||||
localStorage.setItem('persistCode', initialCode)
|
localStorage.setItem('persistCode', initialCode)
|
||||||
@ -2286,6 +2286,8 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
||||||
const shellDeclaration =
|
const shellDeclaration =
|
||||||
"shell001 = shell(extrude001, faces = ['end'], thickness = 5)"
|
"shell001 = shell(extrude001, faces = ['end'], thickness = 5)"
|
||||||
|
const editedShellDeclaration =
|
||||||
|
"shell001 = shell(extrude001, faces = ['end'], thickness = 2)"
|
||||||
|
|
||||||
await test.step(`Look for the grey of the shape`, async () => {
|
await test.step(`Look for the grey of the shape`, async () => {
|
||||||
await scene.expectPixelColor([127, 127, 127], testPoint, 15)
|
await scene.expectPixelColor([127, 127, 127], testPoint, 15)
|
||||||
@ -2352,6 +2354,45 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
})
|
})
|
||||||
await scene.expectPixelColor([146, 146, 146], testPoint, 15)
|
await scene.expectPixelColor([146, 146, 146], testPoint, 15)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await test.step('Edit shell via feature tree selection works', async () => {
|
||||||
|
await toolbar.closePane('code')
|
||||||
|
await toolbar.openPane('feature-tree')
|
||||||
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
|
'Shell',
|
||||||
|
0
|
||||||
|
)
|
||||||
|
await operationButton.dblclick()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'thickness',
|
||||||
|
currentArgValue: '5',
|
||||||
|
headerArguments: {
|
||||||
|
Thickness: '5',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'thickness',
|
||||||
|
commandName: 'Shell',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText('2')
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
Thickness: '2',
|
||||||
|
},
|
||||||
|
commandName: 'Shell',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await toolbar.closePane('feature-tree')
|
||||||
|
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
|
||||||
|
await toolbar.openPane('code')
|
||||||
|
await editor.expectEditor.toContain(editedShellDeclaration)
|
||||||
|
await editor.expectState({
|
||||||
|
diagnostics: [],
|
||||||
|
activeLines: [editedShellDeclaration],
|
||||||
|
highlightedCode: '',
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2387,6 +2428,8 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
const mutatedCode = 'xLine(length = -40, tag = $seg01)'
|
const mutatedCode = 'xLine(length = -40, tag = $seg01)'
|
||||||
const shellDeclaration =
|
const shellDeclaration =
|
||||||
"shell001 = shell(extrude001, faces = ['end', seg01], thickness = 5)"
|
"shell001 = shell(extrude001, faces = ['end', seg01], thickness = 5)"
|
||||||
|
const editedShellDeclaration =
|
||||||
|
"shell001 = shell(extrude001, faces = ['end', seg01], thickness = 1)"
|
||||||
|
|
||||||
await test.step(`Look for the grey of the shape`, async () => {
|
await test.step(`Look for the grey of the shape`, async () => {
|
||||||
await scene.expectPixelColor([99, 99, 99], testPoint, 15)
|
await scene.expectPixelColor([99, 99, 99], testPoint, 15)
|
||||||
@ -2435,6 +2478,41 @@ extrude001 = extrude(sketch001, length = 40)
|
|||||||
await scene.expectPixelColor([49, 49, 49], testPoint, 15)
|
await scene.expectPixelColor([49, 49, 49], testPoint, 15)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await test.step('Edit shell via feature tree selection works', async () => {
|
||||||
|
await editor.closePane()
|
||||||
|
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
|
||||||
|
await operationButton.dblclick({ button: 'left' })
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'thickness',
|
||||||
|
currentArgValue: '5',
|
||||||
|
headerArguments: {
|
||||||
|
Thickness: '5',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'thickness',
|
||||||
|
commandName: 'Shell',
|
||||||
|
})
|
||||||
|
await page.keyboard.insertText('1')
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'review',
|
||||||
|
headerArguments: {
|
||||||
|
Thickness: '1',
|
||||||
|
},
|
||||||
|
commandName: 'Shell',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await toolbar.closePane('feature-tree')
|
||||||
|
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
|
||||||
|
await toolbar.openPane('code')
|
||||||
|
await editor.expectEditor.toContain(editedShellDeclaration)
|
||||||
|
await editor.expectState({
|
||||||
|
diagnostics: [],
|
||||||
|
activeLines: [editedShellDeclaration],
|
||||||
|
highlightedCode: '',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
await test.step('Delete shell via feature tree selection', async () => {
|
await test.step('Delete shell via feature tree selection', async () => {
|
||||||
await editor.closePane()
|
await editor.closePane()
|
||||||
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
|
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
|
||||||
@ -2529,7 +2607,7 @@ extrude002 = extrude(sketch002, length = 50)
|
|||||||
highlightedCode: '',
|
highlightedCode: '',
|
||||||
})
|
})
|
||||||
await toolbar.closePane('code')
|
await toolbar.closePane('code')
|
||||||
await scene.expectPixelColor([73, 73, 73], testPoint, 15)
|
await scene.expectPixelColor([80, 80, 80], testPoint, 15)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -53,46 +53,47 @@ sketch003 = startSketchOn('XY')
|
|||||||
|> close()
|
|> close()
|
||||||
extrude003 = extrude(sketch003, length = 20)
|
extrude003 = extrude(sketch003, length = 20)
|
||||||
`
|
`
|
||||||
|
test.describe('edit with AI example snapshots', () => {
|
||||||
|
test(
|
||||||
|
`change colour`,
|
||||||
|
{ tag: '@snapshot' },
|
||||||
|
async ({ context, homePage, cmdBar, editor, page, scene }) => {
|
||||||
|
await context.addInitScript((file) => {
|
||||||
|
localStorage.setItem('persistCode', file)
|
||||||
|
}, file)
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.waitForExecutionDone()
|
||||||
|
|
||||||
test(
|
const body1CapCoords = { x: 571, y: 351 }
|
||||||
`change colour`,
|
const [clickBody1Cap] = scene.makeMouseHelpers(
|
||||||
{ tag: '@snapshot' },
|
body1CapCoords.x,
|
||||||
async ({ context, homePage, cmdBar, editor, page, scene }) => {
|
body1CapCoords.y
|
||||||
await context.addInitScript((file) => {
|
)
|
||||||
localStorage.setItem('persistCode', file)
|
const yellow: [number, number, number] = [179, 179, 131]
|
||||||
}, file)
|
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
|
||||||
await homePage.goToModelingScene()
|
|
||||||
await scene.waitForExecutionDone()
|
|
||||||
|
|
||||||
const body1CapCoords = { x: 571, y: 351 }
|
await test.step('wait for scene to load select body and check selection came through', async () => {
|
||||||
const [clickBody1Cap] = scene.makeMouseHelpers(
|
await scene.expectPixelColor([134, 134, 134], body1CapCoords, 15)
|
||||||
body1CapCoords.x,
|
await clickBody1Cap()
|
||||||
body1CapCoords.y
|
await scene.expectPixelColor(yellow, body1CapCoords, 20)
|
||||||
)
|
await editor.expectState({
|
||||||
const yellow: [number, number, number] = [179, 179, 131]
|
highlightedCode: '',
|
||||||
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
|
activeLines: ['|>startProfileAt([-73.64,-42.89],%)'],
|
||||||
|
diagnostics: [],
|
||||||
await test.step('wait for scene to load select body and check selection came through', async () => {
|
})
|
||||||
await scene.expectPixelColor([134, 134, 134], body1CapCoords, 15)
|
|
||||||
await clickBody1Cap()
|
|
||||||
await scene.expectPixelColor(yellow, body1CapCoords, 20)
|
|
||||||
await editor.expectState({
|
|
||||||
highlightedCode: '',
|
|
||||||
activeLines: ['|>startProfileAt([-73.64,-42.89],%)'],
|
|
||||||
diagnostics: [],
|
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
await test.step('fire off edit prompt', async () => {
|
await test.step('fire off edit prompt', async () => {
|
||||||
await cmdBar.captureTextToCadRequestSnapshot(test.info())
|
await cmdBar.captureTextToCadRequestSnapshot(test.info())
|
||||||
await cmdBar.openCmdBar('promptToEdit')
|
await cmdBar.openCmdBar('promptToEdit')
|
||||||
// being specific about the color with a hex means asserting pixel color is more stable
|
// being specific about the color with a hex means asserting pixel color is more stable
|
||||||
await page
|
await page
|
||||||
.getByTestId('cmd-bar-arg-value')
|
.getByTestId('cmd-bar-arg-value')
|
||||||
.fill('make this neon green please, use #39FF14')
|
.fill('make this neon green please, use #39FF14')
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await expect(submittingToast).toBeVisible()
|
await expect(submittingToast).toBeVisible()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
})
|
||||||
|
@ -233,7 +233,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
|
|||||||
await cmdBar.openCmdBar('promptToEdit')
|
await cmdBar.openCmdBar('promptToEdit')
|
||||||
await page
|
await page
|
||||||
.getByTestId('cmd-bar-arg-value')
|
.getByTestId('cmd-bar-arg-value')
|
||||||
.fill('Please rename to mySketch')
|
.fill('Please rename to mySketch001')
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await expect(submittingToast).toBeVisible()
|
await expect(submittingToast).toBeVisible()
|
||||||
@ -244,10 +244,10 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
await test.step('verify rename change and accept it', async () => {
|
await test.step('verify rename change and accept it', async () => {
|
||||||
await editor.expectEditor.toContain('mySketch = startSketchOn')
|
await editor.expectEditor.toContain('mySketch001 = startSketchOn')
|
||||||
await editor.expectEditor.not.toContain('sketch002 = startSketchOn')
|
await editor.expectEditor.not.toContain('sketch002 = startSketchOn')
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
'extrude002 = extrude(mySketch, length = 50)'
|
'extrude002 = extrude(mySketch001, length = 50)'
|
||||||
)
|
)
|
||||||
|
|
||||||
await acceptBtn.click()
|
await acceptBtn.click()
|
||||||
|
@ -319,7 +319,6 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
'when engine fails export we handle the failure and alert the user',
|
'when engine fails export we handle the failure and alert the user',
|
||||||
{ tag: '@skipLocalEngine' },
|
{ tag: '@skipLocalEngine' },
|
||||||
async ({ scene, page, homePage, cmdBar }) => {
|
async ({ scene, page, homePage, cmdBar }) => {
|
||||||
const u = await getUtils(page)
|
|
||||||
await page.addInitScript(
|
await page.addInitScript(
|
||||||
async ({ code }) => {
|
async ({ code }) => {
|
||||||
localStorage.setItem('persistCode', code)
|
localStorage.setItem('persistCode', code)
|
||||||
@ -636,11 +635,8 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
})
|
})
|
||||||
|
|
||||||
const toolBarMode = () =>
|
|
||||||
page.locator('[data-currentMode]').getAttribute('data-currentMode')
|
|
||||||
|
|
||||||
await test.step('Start sketch and select a plane', async () => {
|
await test.step('Start sketch and select a plane', async () => {
|
||||||
await expect.poll(toolBarMode).toEqual('modeling')
|
await toolbar.expectToolbarMode.toBe('modeling')
|
||||||
// Click the start sketch button
|
// Click the start sketch button
|
||||||
await toolbar.startSketchPlaneSelection()
|
await toolbar.startSketchPlaneSelection()
|
||||||
|
|
||||||
@ -649,10 +645,10 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
|
|
||||||
// Check that the modeling toolbar doesn't appear during the animation
|
// Check that the modeling toolbar doesn't appear during the animation
|
||||||
// The animation typically takes around 500ms, so we'll check for a second
|
// The animation typically takes around 500ms, so we'll check for a second
|
||||||
await expect.poll(toolBarMode, { timeout: 1000 }).not.toEqual('modeling')
|
await toolbar.expectToolbarMode.not.toBe('modeling')
|
||||||
|
|
||||||
// After animation completes, we should see the sketching toolbar
|
// After animation completes, we should see the sketching toolbar
|
||||||
await expect.poll(toolBarMode).toEqual('sketching')
|
await toolbar.expectToolbarMode.toBe('sketching')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { readFileSync } from 'fs'
|
import { readFileSync } from 'fs'
|
||||||
|
|
||||||
const secrets: Record<string, string> = {}
|
const secrets: Record<string, string> = {}
|
||||||
|
const secretsPath = './e2e/playwright/playwright-secrets.env'
|
||||||
try {
|
try {
|
||||||
const file = readFileSync('./e2e/playwright/playwright-secrets.env', 'utf8')
|
const file = readFileSync(secretsPath, 'utf8')
|
||||||
file
|
file
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.filter((line) => line && line.length > 1)
|
.filter((line) => line && line.length > 1)
|
||||||
@ -15,9 +16,12 @@ try {
|
|||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// probably running in CI
|
// probably running in CI
|
||||||
secrets.token = process.env.token || ''
|
console.warn(
|
||||||
secrets.snapshottoken = process.env.snapshottoken || ''
|
`Error reading ${secretsPath}; environment variables will be used`
|
||||||
// add more env vars here to make them available in CI
|
)
|
||||||
}
|
}
|
||||||
|
secrets.token = secrets.token || process.env.token || ''
|
||||||
|
secrets.snapshottoken = secrets.snapshottoken || process.env.snapshottoken || ''
|
||||||
|
// add more env vars here to make them available in CI
|
||||||
|
|
||||||
export { secrets }
|
export { secrets }
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
} from './test-utils'
|
} from './test-utils'
|
||||||
import { uuidv4, roundOff } from 'lib/utils'
|
import { uuidv4, roundOff } from 'lib/utils'
|
||||||
import { SceneFixture } from './fixtures/sceneFixture'
|
import { SceneFixture } from './fixtures/sceneFixture'
|
||||||
|
import { CmdBarFixture } from './fixtures/cmdBarFixture'
|
||||||
|
|
||||||
test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
|
||||||
test('multi-sketch file shows multiple Edit Sketch buttons', async ({
|
test('multi-sketch file shows multiple Edit Sketch buttons', async ({
|
||||||
@ -191,7 +192,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
page: Page,
|
page: Page,
|
||||||
homePage: HomePageFixture,
|
homePage: HomePageFixture,
|
||||||
openPanes: string[],
|
openPanes: string[],
|
||||||
scene: SceneFixture
|
scene: SceneFixture,
|
||||||
|
cmdBar: CmdBarFixture
|
||||||
) => {
|
) => {
|
||||||
// Load the app with the code panes
|
// Load the app with the code panes
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
@ -201,13 +203,22 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
|> startProfileAt([4.61, -14.01], %)
|
|> startProfileAt([4.61, -14.01], %)
|
||||||
|> line(end = [12.73, -0.09])
|
|> line(end = [12.73, -0.09])
|
||||||
|> tangentialArcTo([24.95, -5.38], %)
|
|> tangentialArcTo([24.95, -5.38], %)
|
||||||
|
|> arcTo({
|
||||||
|
interior = [20.18, -1.7],
|
||||||
|
end = [11.82, -1.16]
|
||||||
|
}, %)
|
||||||
|
|> arc({
|
||||||
|
radius = 5.92,
|
||||||
|
angleStart = -89.36,
|
||||||
|
angleEnd = 135.81
|
||||||
|
}, %)
|
||||||
|> close()`
|
|> close()`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
@ -242,7 +253,17 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
|> startProfileAt([4.61, -14.01], %)
|
|> startProfileAt([4.61, -14.01], %)
|
||||||
|> line(end = [12.73, -0.09])
|
|> line(end = [12.73, -0.09])
|
||||||
|> tangentialArcTo([24.95, -5.38], %)
|
|> tangentialArcTo([24.95, -5.38], %)
|
||||||
|> close()`)
|
|> arcTo({
|
||||||
|
interior = [20.18, -1.7],
|
||||||
|
end = [11.82, -1.16]
|
||||||
|
}, %)
|
||||||
|
|> arc({
|
||||||
|
radius = 5.92,
|
||||||
|
angleStart = -89.36,
|
||||||
|
angleEnd = 135.81
|
||||||
|
}, %)
|
||||||
|
|> close()
|
||||||
|
`)
|
||||||
} else {
|
} else {
|
||||||
// Ensure we don't see the code.
|
// Ensure we don't see the code.
|
||||||
await expect(u.codeLocator).not.toBeVisible()
|
await expect(u.codeLocator).not.toBeVisible()
|
||||||
@ -272,7 +293,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
|
|
||||||
const step5 = { steps: 5 }
|
const step5 = { steps: 5 }
|
||||||
|
|
||||||
await expect(page.getByTestId('segment-overlay')).toHaveCount(2)
|
await expect(page.getByTestId('segment-overlay')).toHaveCount(5)
|
||||||
|
|
||||||
// drag startProfileAt handle
|
// drag startProfileAt handle
|
||||||
await page.mouse.move(startPX[0], startPX[1])
|
await page.mouse.move(startPX[0], startPX[1])
|
||||||
@ -310,22 +331,93 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drag arcTo interior handle (three point arc)
|
||||||
|
const arcToHandle = await u.getBoundingBox('[data-overlay-index="2"]')
|
||||||
|
await page.mouse.move(arcToHandle.x, arcToHandle.y - 5)
|
||||||
|
await page.mouse.down()
|
||||||
|
await page.mouse.move(
|
||||||
|
arcToHandle.x - dragPX,
|
||||||
|
arcToHandle.y + dragPX,
|
||||||
|
step5
|
||||||
|
)
|
||||||
|
await page.mouse.up()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
if (openPanes.includes('code')) {
|
||||||
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
prevContent = await page.locator('.cm-content').innerText()
|
||||||
|
}
|
||||||
|
|
||||||
|
// drag arcTo end handle (three point arc)
|
||||||
|
const arcToEndHandle = await u.getBoundingBox('[data-overlay-index="3"]')
|
||||||
|
await page.mouse.move(arcToEndHandle.x, arcToEndHandle.y - 5)
|
||||||
|
await page.mouse.down()
|
||||||
|
await page.mouse.move(
|
||||||
|
arcToEndHandle.x - dragPX,
|
||||||
|
arcToEndHandle.y + dragPX,
|
||||||
|
step5
|
||||||
|
)
|
||||||
|
await page.mouse.up()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
if (openPanes.includes('code')) {
|
||||||
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
prevContent = await page.locator('.cm-content').innerText()
|
||||||
|
}
|
||||||
|
|
||||||
|
// drag arc radius handle
|
||||||
|
const arcRadiusHandle = await u.getBoundingBox('[data-overlay-index="4"]')
|
||||||
|
await page.mouse.move(arcRadiusHandle.x, arcRadiusHandle.y - 5)
|
||||||
|
await page.mouse.down()
|
||||||
|
await page.mouse.move(
|
||||||
|
arcRadiusHandle.x - dragPX,
|
||||||
|
arcRadiusHandle.y + dragPX,
|
||||||
|
step5
|
||||||
|
)
|
||||||
|
await page.mouse.up()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
if (openPanes.includes('code')) {
|
||||||
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// drag arc center handle (we'll have to hardcode the position because it doesn't have a overlay near the handle)
|
||||||
|
const arcCenterHandle = { x: 745, y: 214 }
|
||||||
|
await page.mouse.move(arcCenterHandle.x, arcCenterHandle.y - 5)
|
||||||
|
await page.mouse.down()
|
||||||
|
await page.mouse.move(
|
||||||
|
arcCenterHandle.x - dragPX,
|
||||||
|
arcCenterHandle.y + dragPX,
|
||||||
|
step5
|
||||||
|
)
|
||||||
|
await page.mouse.up()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
if (openPanes.includes('code')) {
|
||||||
|
await expect(page.locator('.cm-content')).not.toHaveText(prevContent)
|
||||||
|
}
|
||||||
|
|
||||||
// Open the code pane
|
// Open the code pane
|
||||||
await u.openKclCodePanel()
|
await u.openKclCodePanel()
|
||||||
|
|
||||||
// expect the code to have changed
|
// expect the code to have changed
|
||||||
await expect(page.locator('.cm-content'))
|
await expect(page.locator('.cm-content'))
|
||||||
.toHaveText(`sketch001 = startSketchOn('XZ')
|
.toHaveText(`sketch001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([6.44, -12.07], %)
|
|> startProfileAt([6.44, -12.07], %)
|
||||||
|> line(end = [14.72, 1.97])
|
|> line(end = [14.72, 1.97])
|
||||||
|> tangentialArcTo([24.95, -5.38], %)
|
|> tangentialArcTo([26.92, -3.32], %)
|
||||||
|> line(end = [1.97, 2.06])
|
|> arcTo({
|
||||||
|> close()`)
|
interior = [18.11, -3.73],
|
||||||
|
end = [9.77, -3.19]
|
||||||
|
}, %)
|
||||||
|
|> arc({
|
||||||
|
radius = 3.75,
|
||||||
|
angleStart = -58.29,
|
||||||
|
angleEnd = 161.17
|
||||||
|
}, %)
|
||||||
|
|> close()
|
||||||
|
`)
|
||||||
}
|
}
|
||||||
test(
|
test(
|
||||||
'code pane open at start-handles',
|
'code pane open at start-handles',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ page, homePage, scene }) => {
|
async ({ page, homePage, scene, cmdBar }) => {
|
||||||
// Load the app with the code panes
|
// Load the app with the code panes
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -338,14 +430,20 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
await doEditSegmentsByDraggingHandle(page, homePage, ['code'], scene)
|
await doEditSegmentsByDraggingHandle(
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
['code'],
|
||||||
|
scene,
|
||||||
|
cmdBar
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'code pane closed at start-handles',
|
'code pane closed at start-handles',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ page, homePage, scene }) => {
|
async ({ page, homePage, scene, cmdBar }) => {
|
||||||
// Load the app with the code panes
|
// Load the app with the code panes
|
||||||
await page.addInitScript(async (persistModelingContext) => {
|
await page.addInitScript(async (persistModelingContext) => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -353,7 +451,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
JSON.stringify({ openPanes: [] })
|
JSON.stringify({ openPanes: [] })
|
||||||
)
|
)
|
||||||
}, PERSIST_MODELING_CONTEXT)
|
}, PERSIST_MODELING_CONTEXT)
|
||||||
await doEditSegmentsByDraggingHandle(page, homePage, [], scene)
|
await doEditSegmentsByDraggingHandle(page, homePage, [], scene, cmdBar)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -362,6 +460,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
page,
|
page,
|
||||||
editor,
|
editor,
|
||||||
homePage,
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
@ -373,6 +473,8 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|
|||||||
})
|
})
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
@ -1174,7 +1276,7 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
|
|||||||
|> line(endAbsolute = [
|
|> line(endAbsolute = [
|
||||||
railWideWidth / 2,
|
railWideWidth / 2,
|
||||||
railClampable / 2 + railBaseLength
|
railClampable / 2 + railBaseLength
|
||||||
], $seg01)
|
], tag = $seg01)
|
||||||
|> line(endAbsolute = [railTop / 2, railBaseLength])
|
|> line(endAbsolute = [railTop / 2, railBaseLength])
|
||||||
|> line(endAbsolute = [railBaseWidth / 2, railBaseLength])
|
|> line(endAbsolute = [railBaseWidth / 2, railBaseLength])
|
||||||
|> line(endAbsolute = [railBaseWidth / 2, 0])
|
|> line(endAbsolute = [railBaseWidth / 2, 0])
|
||||||
@ -1355,7 +1457,7 @@ test.describe('multi-profile sketching', () => {
|
|||||||
test(
|
test(
|
||||||
`test it removes half-finished expressions when changing tools in sketch mode`,
|
`test it removes half-finished expressions when changing tools in sketch mode`,
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ context, page, scene, toolbar, editor, homePage }) => {
|
async ({ context, page, scene, toolbar, editor, homePage, cmdBar }) => {
|
||||||
// We seed the scene with a single offset plane
|
// We seed the scene with a single offset plane
|
||||||
await context.addInitScript(() => {
|
await context.addInitScript(() => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -1375,7 +1477,10 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [continueProfile2Clk] = scene.makeMouseHelpers(954, 282)
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
@ -1386,7 +1491,13 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
const [circlePoint1] = scene.makeMouseHelpers(700, 200)
|
const [circlePoint1] = scene.makeMouseHelpers(700, 200)
|
||||||
|
|
||||||
await test.step('equip circle tool and click first point', async () => {
|
await test.step('equip circle tool and click first point', async () => {
|
||||||
await toolbar.circleBtn.click()
|
// await page.waitForTimeout(100)
|
||||||
|
await expect
|
||||||
|
.poll(async () => {
|
||||||
|
await toolbar.circleBtn.click()
|
||||||
|
return toolbar.circleBtn.getAttribute('aria-pressed')
|
||||||
|
})
|
||||||
|
.toBe('true')
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await circlePoint1()
|
await circlePoint1()
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
@ -1401,6 +1512,7 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
|
|
||||||
const [circle3Point1] = scene.makeMouseHelpers(650, 200)
|
const [circle3Point1] = scene.makeMouseHelpers(650, 200)
|
||||||
const [circle3Point2] = scene.makeMouseHelpers(750, 200)
|
const [circle3Point2] = scene.makeMouseHelpers(750, 200)
|
||||||
|
// const [circle3Point3] = scene.makeMouseHelpers(700, 150)
|
||||||
|
|
||||||
await test.step('equip three point circle tool and click first two points', async () => {
|
await test.step('equip three point circle tool and click first two points', async () => {
|
||||||
await toolbar.selectCircleThreePoint()
|
await toolbar.selectCircleThreePoint()
|
||||||
@ -1411,25 +1523,40 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
await editor.expectEditor.toContain('profile003 = circleThreePoint(')
|
await editor.expectEditor.toContain('profile003 = circleThreePoint(')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('equip line tool and verify three point circle code is removed', async () => {
|
await test.step('equip line tool and verify three-point circle code is removed', async () => {
|
||||||
await toolbar.lineBtn.click()
|
await toolbar.lineBtn.click()
|
||||||
await editor.expectEditor.not.toContain(
|
await editor.expectEditor.not.toContain(
|
||||||
'profile003 = circleThreePoint('
|
'profile003 = circleThreePoint('
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await test.step('equip three-point-arc tool and click first two points', async () => {
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
await toolbar.selectThreePointArc()
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
await circle3Point1()
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
await circle3Point2()
|
||||||
|
await editor.expectEditor.toContain('arcTo({')
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('equip line tool and verify three-point-arc code is removed after second click', async () => {
|
||||||
|
await toolbar.lineBtn.click()
|
||||||
|
await editor.expectEditor.not.toContain('arcTo({')
|
||||||
|
})
|
||||||
|
|
||||||
const [cornerRectPoint1] = scene.makeMouseHelpers(600, 300)
|
const [cornerRectPoint1] = scene.makeMouseHelpers(600, 300)
|
||||||
|
|
||||||
await test.step('equip corner rectangle tool and click first point', async () => {
|
await test.step('equip corner rectangle tool and click first point', async () => {
|
||||||
await toolbar.rectangleBtn.click()
|
await toolbar.rectangleBtn.click()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await cornerRectPoint1()
|
await cornerRectPoint1()
|
||||||
await editor.expectEditor.toContain('profile003 = startProfileAt(')
|
await editor.expectEditor.toContain('profile004 = startProfileAt(')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('equip line tool and verify corner rectangle code is removed', async () => {
|
await test.step('equip line tool and verify corner rectangle code is removed', async () => {
|
||||||
await toolbar.lineBtn.click()
|
await toolbar.lineBtn.click()
|
||||||
await editor.expectEditor.not.toContain('profile003 = startProfileAt(')
|
await editor.expectEditor.not.toContain('profile004 = startProfileAt(')
|
||||||
})
|
})
|
||||||
|
|
||||||
const [centerRectPoint1] = scene.makeMouseHelpers(700, 300)
|
const [centerRectPoint1] = scene.makeMouseHelpers(700, 300)
|
||||||
@ -1438,12 +1565,24 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
|
|||||||
await toolbar.selectCenterRectangle()
|
await toolbar.selectCenterRectangle()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await centerRectPoint1()
|
await centerRectPoint1()
|
||||||
await editor.expectEditor.toContain('profile003 = startProfileAt(')
|
await editor.expectEditor.toContain('profile004 = startProfileAt(')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('equip line tool and verify center rectangle code is removed', async () => {
|
await test.step('equip line tool and verify center rectangle code is removed', async () => {
|
||||||
await toolbar.lineBtn.click()
|
await toolbar.lineBtn.click()
|
||||||
await editor.expectEditor.not.toContain('profile003 = startProfileAt(')
|
await editor.expectEditor.not.toContain('profile004 = startProfileAt(')
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('continue profile002 with the three point arc tool, and then switch back to the line tool to verify it only removes the last expression in the pipe', async () => {
|
||||||
|
await toolbar.selectThreePointArc()
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
await continueProfile2Clk()
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
await circle3Point1()
|
||||||
|
await editor.expectEditor.toContain('arcTo({')
|
||||||
|
await toolbar.lineBtn.click()
|
||||||
|
await editor.expectEditor.not.toContain('arcTo({')
|
||||||
|
await editor.expectEditor.toContain('profile002')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -1532,6 +1671,7 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
|
|||||||
}) => {
|
}) => {
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
@ -1595,7 +1735,7 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
|
|||||||
// timeout wait for engine animation is unavoidable
|
// timeout wait for engine animation is unavoidable
|
||||||
await page.waitForTimeout(600)
|
await page.waitForTimeout(600)
|
||||||
await editor.expectEditor.toContain(`sketch001 = startSketchOn('XZ')`)
|
await editor.expectEditor.toContain(`sketch001 = startSketchOn('XZ')`)
|
||||||
await test.step('Create a close profile stopping mid profile to equip the tangential arc, and than back to the line tool', async () => {
|
await test.step('Create a close profile stopping mid profile to equip the tangential arc, then three-point arc, and then back to the line tool', async () => {
|
||||||
await startProfile1()
|
await startProfile1()
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
`profile001 = startProfileAt([4.61, 12.21], sketch001)`
|
`profile001 = startProfileAt([4.61, 12.21], sketch001)`
|
||||||
@ -1613,12 +1753,45 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
|
|||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
`|> tangentialArcTo([16.61, 4.14], %)`
|
`|> tangentialArcTo([16.61, 4.14], %)`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Add a three-point arc segment
|
||||||
|
await toolbar.selectThreePointArc()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
|
// select end of profile again
|
||||||
|
await endLineStartTanArc()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
|
// Define points for the three-point arc
|
||||||
|
const [threePointInterior, threePointInteriorMove] =
|
||||||
|
scene.makeMouseHelpers(600, 200)
|
||||||
|
const [threePointEnd, threePointEndMove] = scene.makeMouseHelpers(
|
||||||
|
590,
|
||||||
|
270
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create the three-point arc
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await threePointInteriorMove()
|
||||||
|
await threePointInterior()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await threePointEndMove()
|
||||||
|
await threePointEnd()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
|
// Verify the three-point arc was created correctly
|
||||||
|
await editor.expectEditor.toContain(`|> arcTo(`)
|
||||||
|
|
||||||
|
// Switch back to line tool to continue
|
||||||
await toolbar.lineBtn.click()
|
await toolbar.lineBtn.click()
|
||||||
await page.waitForTimeout(300)
|
await page.waitForTimeout(300)
|
||||||
await endArcStartLine()
|
|
||||||
|
// Continue with the original line segment
|
||||||
|
await threePointEnd()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
await page.mouse.click(572, 110)
|
await page.mouse.click(572, 110)
|
||||||
await editor.expectEditor.toContain(`|> line(end = [-11.73, 5.35])`)
|
await editor.expectEditor.toContain(`|> line(end = [-1.22, 10.85])`)
|
||||||
await startProfile1()
|
await startProfile1()
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
`|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
`|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
@ -1820,8 +1993,68 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('double check that circle three point can be unequiped', async () => {
|
await test.step('create three-point arcs in a row without an unequip', async () => {
|
||||||
// this was tested implicitly for other tools, but not for circle three point since it's last
|
// Define points for the first three-point arc
|
||||||
|
const [arc1Point1, arc1Point1Move] = scene.makeMouseHelpers(700, 397)
|
||||||
|
const [arc1Point2, arc1Point2Move] = scene.makeMouseHelpers(724, 346)
|
||||||
|
const [arc1Point3, arc1Point3Move] = scene.makeMouseHelpers(785, 415)
|
||||||
|
|
||||||
|
// Define points for the second three-point arc
|
||||||
|
const [arc2Point1, arc2Point1Move] = scene.makeMouseHelpers(792, 225)
|
||||||
|
const [arc2Point2, arc2Point2Move] = scene.makeMouseHelpers(820, 207)
|
||||||
|
const [arc2Point3, arc2Point3Move] = scene.makeMouseHelpers(905, 229)
|
||||||
|
|
||||||
|
// Select the three-point arc tool
|
||||||
|
await toolbar.selectThreePointArc()
|
||||||
|
|
||||||
|
// Create the first three-point arc
|
||||||
|
await arc1Point1Move()
|
||||||
|
await arc1Point1()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await arc1Point2Move()
|
||||||
|
await arc1Point2()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await arc1Point3Move()
|
||||||
|
await arc1Point3()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
|
// Verify the first three-point arc was created correctly
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
`profile011 = startProfileAt([13.56, -9.97], sketch001)
|
||||||
|
|> arcTo({
|
||||||
|
interior = [15.19, -6.51],
|
||||||
|
end = [19.33, -11.19]
|
||||||
|
}, %)`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create the second three-point arc
|
||||||
|
await arc2Point1Move()
|
||||||
|
await arc2Point1()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await arc2Point2Move()
|
||||||
|
await arc2Point2()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
await arc2Point3Move()
|
||||||
|
await arc2Point3()
|
||||||
|
await page.waitForTimeout(300)
|
||||||
|
|
||||||
|
// Verify the second three-point arc was created correctly
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
` |> arcTo({
|
||||||
|
interior = [19.8, 1.7],
|
||||||
|
end = [21.7, 2.92]
|
||||||
|
}, %)
|
||||||
|
|> arcTo({
|
||||||
|
interior = [27.47, 1.42],
|
||||||
|
end = [27.57, 1.52]
|
||||||
|
}, %)`,
|
||||||
|
{ shouldNormalise: true }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('double check that three-point arc can be unequipped', async () => {
|
||||||
|
// this was tested implicitly for other tools, but not for three-point arc since it's last
|
||||||
await page.waitForTimeout(300)
|
await page.waitForTimeout(300)
|
||||||
await expect
|
await expect
|
||||||
.poll(async () => {
|
.poll(async () => {
|
||||||
@ -2085,7 +2318,7 @@ profile003 = circle(sketch001, center = [6.92, -4.2], radius = 3.16)
|
|||||||
test(
|
test(
|
||||||
'can enter sketch when there is an extrude',
|
'can enter sketch when there is an extrude',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ homePage, scene, toolbar, page }) => {
|
async ({ homePage, scene, toolbar, page, cmdBar }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -2122,6 +2355,8 @@ extrude001 = extrude(profile003, length = 5)
|
|||||||
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
@ -2134,9 +2369,11 @@ extrude001 = extrude(profile003, length = 5)
|
|||||||
await page.waitForTimeout(600)
|
await page.waitForTimeout(600)
|
||||||
|
|
||||||
await test.step('check the sketch is still drawn properly', async () => {
|
await test.step('check the sketch is still drawn properly', async () => {
|
||||||
await scene.expectPixelColor([255, 255, 255], { x: 596, y: 165 }, 15)
|
await Promise.all([
|
||||||
await scene.expectPixelColor([255, 255, 255], { x: 641, y: 220 }, 15)
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 596, y: 165 }, 15),
|
||||||
await scene.expectPixelColor([255, 255, 255], { x: 763, y: 214 }, 15)
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 641, y: 220 }, 15),
|
||||||
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 763, y: 214 }, 15),
|
||||||
|
])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -2293,7 +2530,7 @@ extrude001 = extrude(thePart, length = 75)
|
|||||||
test(
|
test(
|
||||||
'Can enter sketch on sketch of wall and cap for segment, solid2d, extrude-wall, extrude-cap selections',
|
'Can enter sketch on sketch of wall and cap for segment, solid2d, extrude-wall, extrude-cap selections',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ homePage, scene, toolbar, editor, page }) => {
|
async ({ homePage, scene, toolbar, editor, page, cmdBar }) => {
|
||||||
// TODO this test should include a test for selecting revolve walls and caps
|
// TODO this test should include a test for selecting revolve walls and caps
|
||||||
|
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
@ -2378,6 +2615,8 @@ extrude003 = extrude(profile011, length = 2.5)
|
|||||||
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
).not.toBeDisabled()
|
).not.toBeDisabled()
|
||||||
@ -2440,39 +2679,22 @@ extrude003 = extrude(profile011, length = 2.5)
|
|||||||
|
|
||||||
const verifyWallProfilesAreDrawn = async () =>
|
const verifyWallProfilesAreDrawn = async () =>
|
||||||
test.step('verify wall profiles are drawn', async () => {
|
test.step('verify wall profiles are drawn', async () => {
|
||||||
// open polygon
|
await Promise.all([
|
||||||
await scene.expectPixelColor(
|
// open polygon
|
||||||
TEST_COLORS.WHITE,
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 599, y: 168 }, 15),
|
||||||
{ x: 599, y: 168 },
|
// closed polygon
|
||||||
15
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 656, y: 171 }, 15),
|
||||||
)
|
// revolved profile
|
||||||
// closed polygon
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 655, y: 264 }, 15),
|
||||||
await scene.expectPixelColor(
|
// extruded profile
|
||||||
TEST_COLORS.WHITE,
|
scene.expectPixelColor(TEST_COLORS.WHITE, { x: 808, y: 396 }, 15),
|
||||||
{ x: 656, y: 171 },
|
// circle (When entering via the circle, it's selected and therefore blue)
|
||||||
15
|
scene.expectPixelColor(
|
||||||
)
|
[TEST_COLORS.WHITE, TEST_COLORS.BLUE],
|
||||||
// revolved profile
|
{ x: 742, y: 386 },
|
||||||
await scene.expectPixelColor(
|
15
|
||||||
TEST_COLORS.WHITE,
|
),
|
||||||
{ x: 655, y: 264 },
|
])
|
||||||
15
|
|
||||||
)
|
|
||||||
// extruded profile
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
TEST_COLORS.WHITE,
|
|
||||||
{ x: 808, y: 396 },
|
|
||||||
15
|
|
||||||
)
|
|
||||||
// circle
|
|
||||||
await scene.expectPixelColor(
|
|
||||||
[
|
|
||||||
TEST_COLORS.WHITE,
|
|
||||||
TEST_COLORS.BLUE, // When entering via the circle, it's selected and therefore blue
|
|
||||||
],
|
|
||||||
{ x: 742, y: 386 },
|
|
||||||
15
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const verifyCapProfilesAreDrawn = async () =>
|
const verifyCapProfilesAreDrawn = async () =>
|
||||||
|
@ -410,9 +410,9 @@ test.describe(
|
|||||||
test(
|
test(
|
||||||
'Draft segments should look right',
|
'Draft segments should look right',
|
||||||
{ tag: '@snapshot' },
|
{ tag: '@snapshot' },
|
||||||
async ({ page, context, scene, cmdBar }) => {
|
async ({ page, scene, toolbar }) => {
|
||||||
// FIXME: Skip on macos its being weird.
|
// FIXME: Skip on macos its being weird.
|
||||||
test.skip(process.platform === 'darwin', 'Skip on macos')
|
// test.skip(process.platform === 'darwin', 'Skip on macos')
|
||||||
|
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
@ -421,6 +421,23 @@ test(
|
|||||||
|
|
||||||
await scene.connectionEstablished()
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
|
const startXPx = 600
|
||||||
|
const [endOfTangentClk, endOfTangentMv] = scene.makeMouseHelpers(
|
||||||
|
startXPx + PUR * 30,
|
||||||
|
500 - PUR * 20,
|
||||||
|
{ steps: 10 }
|
||||||
|
)
|
||||||
|
const [threePointArcMidPointClk, threePointArcMidPointMv] =
|
||||||
|
scene.makeMouseHelpers(800, 250, { steps: 10 })
|
||||||
|
const [threePointArcEndPointClk, threePointArcEndPointMv] =
|
||||||
|
scene.makeMouseHelpers(750, 285, { steps: 10 })
|
||||||
|
const [arcCenterClk, arcCenterMv] = scene.makeMouseHelpers(750, 210, {
|
||||||
|
steps: 10,
|
||||||
|
})
|
||||||
|
const [arcEndClk, arcEndMv] = scene.makeMouseHelpers(750, 150, {
|
||||||
|
steps: 10,
|
||||||
|
})
|
||||||
|
|
||||||
// click on "Start Sketch" button
|
// click on "Start Sketch" button
|
||||||
await u.doAndWaitForImageDiff(
|
await u.doAndWaitForImageDiff(
|
||||||
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
|
||||||
@ -435,7 +452,6 @@ test(
|
|||||||
|
|
||||||
await page.waitForTimeout(700) // TODO detect animation ending, or disable animation
|
await page.waitForTimeout(700) // TODO detect animation ending, or disable animation
|
||||||
|
|
||||||
const startXPx = 600
|
|
||||||
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||||
code += `profile001 = startProfileAt([7.19, -9.7], sketch001)`
|
code += `profile001 = startProfileAt([7.19, -9.7], sketch001)`
|
||||||
await expect(page.locator('.cm-content')).toHaveText(code)
|
await expect(page.locator('.cm-content')).toHaveText(code)
|
||||||
@ -471,12 +487,52 @@ test(
|
|||||||
await page.mouse.move(813, 392, { steps: 10 })
|
await page.mouse.move(813, 392, { steps: 10 })
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
await page.mouse.move(startXPx + PUR * 30, 500 - PUR * 20, { steps: 10 })
|
await endOfTangentMv()
|
||||||
|
|
||||||
await expect(page).toHaveScreenshot({
|
await expect(page).toHaveScreenshot({
|
||||||
maxDiffPixels: 100,
|
maxDiffPixels: 100,
|
||||||
mask: [page.getByTestId('model-state-indicator')],
|
mask: [page.getByTestId('model-state-indicator')],
|
||||||
})
|
})
|
||||||
|
await endOfTangentClk()
|
||||||
|
|
||||||
|
await toolbar.selectThreePointArc()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
await endOfTangentClk()
|
||||||
|
await threePointArcMidPointMv()
|
||||||
|
await expect(page).toHaveScreenshot({
|
||||||
|
maxDiffPixels: 100,
|
||||||
|
mask: [page.getByTestId('model-state-indicator')],
|
||||||
|
})
|
||||||
|
await threePointArcMidPointClk()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
|
await threePointArcEndPointMv()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
await expect(page).toHaveScreenshot({
|
||||||
|
maxDiffPixels: 100,
|
||||||
|
mask: [page.getByTestId('model-state-indicator')],
|
||||||
|
})
|
||||||
|
|
||||||
|
await threePointArcEndPointClk()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
|
await toolbar.selectArc()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
|
// continue the profile
|
||||||
|
await threePointArcEndPointClk()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await arcCenterMv()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
await arcCenterClk()
|
||||||
|
|
||||||
|
await arcEndMv()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
await expect(page).toHaveScreenshot({
|
||||||
|
maxDiffPixels: 100,
|
||||||
|
mask: [page.getByTestId('model-state-indicator')],
|
||||||
|
})
|
||||||
|
await arcEndClk()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"original_source_code": "sketch001 = startSketchOn('XZ')\nprofile001 = startProfileAt([57.81, 250.51], sketch001)\n |> line(end = [121.13, 56.63], tag = $seg02)\n |> line(end = [83.37, -34.61], tag = $seg01)\n |> line(end = [19.66, -116.4])\n |> line(end = [-221.8, -41.69])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude001 = extrude(profile001, length = 200)\nsketch002 = startSketchOn('XZ')\n |> startProfileAt([-73.64, -42.89], %)\n |> xLine(length = 173.71)\n |> line(end = [-22.12, -94.4])\n |> xLine(length = -156.98)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude002 = extrude(sketch002, length = 50)\nsketch003 = startSketchOn('XY')\n |> startProfileAt([52.92, 157.81], %)\n |> angledLine([0, 176.4], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 53.4\n ], %, $rectangleSegmentB001)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %, $rectangleSegmentC001)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude003 = extrude(sketch003, length = 20)\n",
|
||||||
|
"prompt": "make this neon green please, use #39FF14",
|
||||||
|
"source_ranges": [
|
||||||
|
{
|
||||||
|
"prompt": "The users main selection is the end cap of a general-sweep (that is an extrusion, revolve, sweep or loft).\nThe source range most likely refers to \"startProfileAt\" simply because this is the start of the profile that was swept.\nIf you need to operate on this cap, for example for sketching on the face, you can use the special string END i.e. `startSketchOn(someSweepVariable, END)`\nWhen they made this selection they main have intended this surface directly or meant something more general like the sweep body.\nSee later source ranges for more context.",
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 11,
|
||||||
|
"column": 5
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 11,
|
||||||
|
"column": 40
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"prompt": "This is the sweep's source range from the user's main selection of the end cap.",
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 17,
|
||||||
|
"column": 13
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 17,
|
||||||
|
"column": 44
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kcl_version": "0.2.47"
|
||||||
|
}
|
@ -84,7 +84,6 @@ test.describe('Test network and connection issues', () => {
|
|||||||
'Engine disconnect & reconnect in sketch mode',
|
'Engine disconnect & reconnect in sketch mode',
|
||||||
{ tag: '@skipLocalEngine' },
|
{ tag: '@skipLocalEngine' },
|
||||||
async ({ page, homePage }) => {
|
async ({ page, homePage }) => {
|
||||||
// TODO: Don't skip Mac for these. After `window.engineCommandManager.tearDown` is working in Safari, these should work on webkit
|
|
||||||
const networkToggle = page.getByTestId('network-toggle')
|
const networkToggle = page.getByTestId('network-toggle')
|
||||||
|
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
@ -159,7 +159,6 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
const unconstrainedLocator = page.locator(
|
const unconstrainedLocator = page.locator(
|
||||||
`[data-constraint-type="${constraintType}"][data-is-constrained="false"]`
|
`[data-constraint-type="${constraintType}"][data-is-constrained="false"]`
|
||||||
)
|
)
|
||||||
await expect(unconstrainedLocator).toBeVisible()
|
|
||||||
await unconstrainedLocator.hover()
|
await unconstrainedLocator.hover()
|
||||||
await expect(
|
await expect(
|
||||||
await page.getByTestId('constraint-symbol-popover').count()
|
await page.getByTestId('constraint-symbol-popover').count()
|
||||||
@ -274,8 +273,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
|
|
||||||
let ang = 0
|
let ang = 0
|
||||||
|
|
||||||
const line = await u.getBoundingBox(`[data-overlay-index="${0}"]`)
|
const line = await u.getBoundingBox('[data-overlay-index="0"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="${0}"]`)
|
ang = await u.getAngle('[data-overlay-index="0"]')
|
||||||
console.log('line1', line, ang)
|
console.log('line1', line, ang)
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: line.x, y: line.y },
|
hoverPos: { x: line.x, y: line.y },
|
||||||
@ -297,8 +296,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
locator: '[data-overlay-index="0"]',
|
locator: '[data-overlay-index="0"]',
|
||||||
})
|
})
|
||||||
|
|
||||||
const angledLine = await u.getBoundingBox(`[data-overlay-index="1"]`)
|
const angledLine = await u.getBoundingBox('[data-overlay-index="1"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="1"]`)
|
ang = await u.getAngle('[data-overlay-index="1"]')
|
||||||
console.log('angledLine1')
|
console.log('angledLine1')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: angledLine.x, y: angledLine.y },
|
hoverPos: { x: angledLine.x, y: angledLine.y },
|
||||||
@ -327,8 +326,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.mouse.move(700, 250)
|
await page.mouse.move(700, 250)
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
let lineTo = await u.getBoundingBox(`[data-overlay-index="2"]`)
|
let lineTo = await u.getBoundingBox('[data-overlay-index="2"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="2"]`)
|
ang = await u.getAngle('[data-overlay-index="2"]')
|
||||||
console.log('lineTo1')
|
console.log('lineTo1')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: lineTo.x, y: lineTo.y },
|
hoverPos: { x: lineTo.x, y: lineTo.y },
|
||||||
@ -353,8 +352,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
locator: '[data-overlay-toolbar-index="2"]',
|
locator: '[data-overlay-toolbar-index="2"]',
|
||||||
})
|
})
|
||||||
|
|
||||||
const xLineTo = await u.getBoundingBox(`[data-overlay-index="3"]`)
|
const xLineTo = await u.getBoundingBox('[data-overlay-index="3"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="3"]`)
|
ang = await u.getAngle('[data-overlay-index="3"]')
|
||||||
console.log('xlineTo1')
|
console.log('xlineTo1')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: xLineTo.x, y: xLineTo.y },
|
hoverPos: { x: xLineTo.x, y: xLineTo.y },
|
||||||
@ -419,8 +418,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
|
|
||||||
let ang = 0
|
let ang = 0
|
||||||
|
|
||||||
const yLineTo = await u.getBoundingBox(`[data-overlay-index="4"]`)
|
const yLineTo = await u.getBoundingBox('[data-overlay-index="4"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="4"]`)
|
ang = await u.getAngle('[data-overlay-index="4"]')
|
||||||
console.log('ylineTo1')
|
console.log('ylineTo1')
|
||||||
await clickUnconstrained({
|
await clickUnconstrained({
|
||||||
hoverPos: { x: yLineTo.x, y: yLineTo.y - 200 },
|
hoverPos: { x: yLineTo.x, y: yLineTo.y - 200 },
|
||||||
@ -432,8 +431,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
locator: '[data-overlay-toolbar-index="4"]',
|
locator: '[data-overlay-toolbar-index="4"]',
|
||||||
})
|
})
|
||||||
|
|
||||||
const xLine = await u.getBoundingBox(`[data-overlay-index="5"]`)
|
const xLine = await u.getBoundingBox('[data-overlay-index="5"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="5"]`)
|
ang = await u.getAngle('[data-overlay-index="5"]')
|
||||||
console.log('xline')
|
console.log('xline')
|
||||||
await clickUnconstrained({
|
await clickUnconstrained({
|
||||||
hoverPos: { x: xLine.x, y: xLine.y },
|
hoverPos: { x: xLine.x, y: xLine.y },
|
||||||
@ -501,8 +500,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
|
|
||||||
let ang = 0
|
let ang = 0
|
||||||
|
|
||||||
const yLine = await u.getBoundingBox(`[data-overlay-index="6"]`)
|
const yLine = await u.getBoundingBox('[data-overlay-index="6"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="6"]`)
|
ang = await u.getAngle('[data-overlay-index="6"]')
|
||||||
console.log('yline1')
|
console.log('yline1')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: yLine.x, y: yLine.y },
|
hoverPos: { x: yLine.x, y: yLine.y },
|
||||||
@ -515,9 +514,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const angledLineOfXLength = await u.getBoundingBox(
|
const angledLineOfXLength = await u.getBoundingBox(
|
||||||
`[data-overlay-index="7"]`
|
'[data-overlay-index="7"]'
|
||||||
)
|
)
|
||||||
ang = await u.getAngle(`[data-overlay-index="7"]`)
|
ang = await u.getAngle('[data-overlay-index="7"]')
|
||||||
console.log('angledLineOfXLength1')
|
console.log('angledLineOfXLength1')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: angledLineOfXLength.x, y: angledLineOfXLength.y },
|
hoverPos: { x: angledLineOfXLength.x, y: angledLineOfXLength.y },
|
||||||
@ -547,9 +546,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const angledLineOfYLength = await u.getBoundingBox(
|
const angledLineOfYLength = await u.getBoundingBox(
|
||||||
`[data-overlay-index="8"]`
|
'[data-overlay-index="8"]'
|
||||||
)
|
)
|
||||||
ang = await u.getAngle(`[data-overlay-index="8"]`)
|
ang = await u.getAngle('[data-overlay-index="8"]')
|
||||||
console.log('angledLineOfYLength1')
|
console.log('angledLineOfYLength1')
|
||||||
await clickUnconstrained({
|
await clickUnconstrained({
|
||||||
hoverPos: { x: angledLineOfYLength.x, y: angledLineOfYLength.y },
|
hoverPos: { x: angledLineOfYLength.x, y: angledLineOfYLength.y },
|
||||||
@ -632,8 +631,8 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
|
|
||||||
let ang = 0
|
let ang = 0
|
||||||
|
|
||||||
const angledLineToX = await u.getBoundingBox(`[data-overlay-index="9"]`)
|
const angledLineToX = await u.getBoundingBox('[data-overlay-index="9"]')
|
||||||
ang = await u.getAngle(`[data-overlay-index="9"]`)
|
ang = await u.getAngle('[data-overlay-index="9"]')
|
||||||
console.log('angledLineToX')
|
console.log('angledLineToX')
|
||||||
await clickConstrained({
|
await clickConstrained({
|
||||||
hoverPos: { x: angledLineToX.x, y: angledLineToX.y },
|
hoverPos: { x: angledLineToX.x, y: angledLineToX.y },
|
||||||
@ -659,9 +658,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const angledLineToY = await u.getBoundingBox(
|
const angledLineToY = await u.getBoundingBox(
|
||||||
`[data-overlay-index="10"]`
|
'[data-overlay-index="10"]'
|
||||||
)
|
)
|
||||||
ang = await u.getAngle(`[data-overlay-index="10"]`)
|
ang = await u.getAngle('[data-overlay-index="10"]')
|
||||||
console.log('angledLineToY')
|
console.log('angledLineToY')
|
||||||
await clickUnconstrained({
|
await clickUnconstrained({
|
||||||
hoverPos: { x: angledLineToY.x, y: angledLineToY.y },
|
hoverPos: { x: angledLineToY.x, y: angledLineToY.y },
|
||||||
@ -689,9 +688,9 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const angledLineThatIntersects = await u.getBoundingBox(
|
const angledLineThatIntersects = await u.getBoundingBox(
|
||||||
`[data-overlay-index="11"]`
|
'[data-overlay-index="11"]'
|
||||||
)
|
)
|
||||||
ang = await u.getAngle(`[data-overlay-index="11"]`)
|
ang = await u.getAngle('[data-overlay-index="11"]')
|
||||||
console.log('angledLineThatIntersects')
|
console.log('angledLineThatIntersects')
|
||||||
await clickUnconstrained({
|
await clickUnconstrained({
|
||||||
hoverPos: {
|
hoverPos: {
|
||||||
@ -821,6 +820,138 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
locator: '[data-overlay-toolbar-index="12"]',
|
locator: '[data-overlay-toolbar-index="12"]',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
test('for segment [arcTo]', async ({
|
||||||
|
page,
|
||||||
|
editor,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
await page.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`sketch001 = startSketchOn('XZ')
|
||||||
|
profile001 = startProfileAt([56.37, 120.33], sketch001)
|
||||||
|
|> line(end = [162.86, 106.48])
|
||||||
|
|> arcTo({
|
||||||
|
interior = [360.16, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)
|
||||||
|
|> yLine(-131.54, %)
|
||||||
|
|> arc({
|
||||||
|
radius = 126.46,
|
||||||
|
angleStart = 33.53,
|
||||||
|
angleEnd = -141.07
|
||||||
|
}, %)
|
||||||
|
`
|
||||||
|
)
|
||||||
|
localStorage.setItem('disableAxis', 'true')
|
||||||
|
})
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
// wait for execution done
|
||||||
|
|
||||||
|
await page.getByText('line(end = [162.86, 106.48])').click()
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
|
await expect(page.getByTestId('segment-overlay')).toHaveCount(5)
|
||||||
|
|
||||||
|
const clickUnconstrained = _clickUnconstrained(page, editor)
|
||||||
|
const clickConstrained = _clickConstrained(page, editor)
|
||||||
|
|
||||||
|
const arcTo = await u.getBoundingBox('[data-overlay-index="1"]')
|
||||||
|
let ang = await u.getAngle('[data-overlay-index="1"]')
|
||||||
|
console.log('arcTo interior x')
|
||||||
|
await clickUnconstrained({
|
||||||
|
hoverPos: { x: arcTo.x, y: arcTo.y },
|
||||||
|
constraintType: 'xAbsolute',
|
||||||
|
expectBeforeUnconstrained: `arcTo({
|
||||||
|
interior = [360.16, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectAfterUnconstrained: `arcTo({
|
||||||
|
interior = [360.16, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectFinal: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
ang: ang,
|
||||||
|
steps: 6,
|
||||||
|
locator: '[data-overlay-toolbar-index="1"]',
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('arcTo interior y')
|
||||||
|
await clickUnconstrained({
|
||||||
|
hoverPos: { x: arcTo.x, y: arcTo.y },
|
||||||
|
constraintType: 'yAbsolute',
|
||||||
|
expectBeforeUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectAfterUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, yAbs001],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectFinal: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
ang: ang,
|
||||||
|
steps: 10,
|
||||||
|
locator: '[data-overlay-toolbar-index="1"]',
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('arcTo end x')
|
||||||
|
await clickConstrained({
|
||||||
|
hoverPos: { x: arcTo.x, y: arcTo.y },
|
||||||
|
constraintType: 'xAbsolute',
|
||||||
|
expectBeforeUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectAfterUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [391.48, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectFinal: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [xAbs002, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
ang: ang + 180,
|
||||||
|
steps: 6,
|
||||||
|
locator: '[data-overlay-toolbar-index="1"]',
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('arcTo end y')
|
||||||
|
await clickUnconstrained({
|
||||||
|
hoverPos: { x: arcTo.x, y: arcTo.y },
|
||||||
|
constraintType: 'yAbsolute',
|
||||||
|
expectBeforeUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [xAbs002, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
expectAfterUnconstrained: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [xAbs002, yAbs002]
|
||||||
|
}, %)`,
|
||||||
|
expectFinal: `arcTo({
|
||||||
|
interior = [xAbs001, 231.76],
|
||||||
|
end = [xAbs002, 131.54]
|
||||||
|
}, %)`,
|
||||||
|
ang: ang + 180,
|
||||||
|
steps: 10,
|
||||||
|
locator: '[data-overlay-toolbar-index="1"]',
|
||||||
|
})
|
||||||
|
})
|
||||||
test('for segment [circle]', async ({ page, editor, homePage }) => {
|
test('for segment [circle]', async ({ page, editor, homePage }) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -928,36 +1059,55 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
shouldNormalise: true,
|
shouldNormalise: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
await page.locator(`[data-stdlib-fn-name="${stdLibFnName}"]`).click()
|
await page
|
||||||
|
.locator(`[data-stdlib-fn-name="${stdLibFnName}"]`)
|
||||||
|
.first()
|
||||||
|
.click()
|
||||||
await page.getByText('Delete Segment').click()
|
await page.getByText('Delete Segment').click()
|
||||||
|
|
||||||
await editor.expectEditor.not.toContain(codeToBeDeleted, {
|
await editor.expectEditor.not.toContain(codeToBeDeleted, {
|
||||||
shouldNormalise: true,
|
shouldNormalise: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
test('all segment types', async ({ page, editor, homePage }) => {
|
test('all segment types', async ({
|
||||||
|
page,
|
||||||
|
editor,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`part001 = startSketchOn('XZ')
|
`part001 = startSketchOn('XZ')
|
||||||
|> startProfileAt([0, 0], %)
|
|>startProfileAt([0, 0], %)
|
||||||
|> line(end = [0.5, -14 + 0])
|
|> line(end = [0.5, -14 + 0])
|
||||||
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
|
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
|
||||||
|> line(endAbsolute = [33, 11.5 + 0])
|
|> line(endAbsolute = [33, 11.5 + 0])
|
||||||
|> xLine(endAbsolute = 9 - 5)
|
|> xLine(endAbsolute = 9 - 5)
|
||||||
|> yLine(endAbsolute = -10.77, tag = $a)
|
|> yLine(endAbsolute = -10.77, tag = $a)
|
||||||
|> xLine(length = 26.04)
|
|> xLine(length = 26.04)
|
||||||
|> yLine(length = 21.14 + 0)
|
|> yLine(length = 21.14 + 0)
|
||||||
|> angledLineOfXLength({ angle = 181 + 0, length = 23.14 }, %)
|
|> angledLineOfXLength({ angle = 181 + 0, length = 23.14 }, %)
|
||||||
|> angledLineOfYLength({ angle = -91, length = 19 + 0 }, %)
|
|> angledLineOfYLength({ angle = -91, length = 19 + 0 }, %)
|
||||||
|> angledLineToX({ angle = 3 + 0, to = 26 }, %)
|
|> angledLineToX({ angle = 3 + 0, to = 26 }, %)
|
||||||
|> angledLineToY({ angle = 89, to = 9.14 + 0 }, %)
|
|> angledLineToY({ angle = 89, to = 9.14 + 0 }, %)
|
||||||
|> angledLineThatIntersects({
|
|> angledLineThatIntersects({
|
||||||
angle = 4.14,
|
angle = 4.14,
|
||||||
intersectTag = a,
|
intersectTag = a,
|
||||||
offset = 9
|
offset = 9
|
||||||
}, %)
|
}, %)
|
||||||
|> tangentialArcTo([3.14 + 13, 1.14], %)
|
|> tangentialArcTo([3.14 + 13, 1.14], %)
|
||||||
|
|> arcTo({
|
||||||
|
interior = [16.25, 5.12],
|
||||||
|
end = [21.61, 4.15]
|
||||||
|
}, %)
|
||||||
|
|> arc({
|
||||||
|
radius = 9.03,
|
||||||
|
angleStart = 40.27,
|
||||||
|
angleEnd = -38.05
|
||||||
|
}, %)
|
||||||
|
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
localStorage.setItem('disableAxis', 'true')
|
localStorage.setItem('disableAxis', 'true')
|
||||||
@ -966,27 +1116,55 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
|
|
||||||
// wait for execution done
|
|
||||||
await u.openDebugPanel()
|
|
||||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
|
||||||
await u.closeDebugPanel()
|
|
||||||
|
|
||||||
await page.getByText('xLine(endAbsolute = 9 - 5)').click()
|
await page.getByText('xLine(endAbsolute = 9 - 5)').click()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
await page.getByRole('button', { name: 'Edit Sketch' }).click()
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
await expect(page.getByTestId('segment-overlay')).toHaveCount(13)
|
await expect(page.getByTestId('segment-overlay')).toHaveCount(16)
|
||||||
const deleteSegmentSequence = _deleteSegmentSequence(page, editor)
|
const deleteSegmentSequence = _deleteSegmentSequence(page, editor)
|
||||||
|
|
||||||
let segmentToDelete
|
let segmentToDelete
|
||||||
|
|
||||||
const getOverlayByIndex = (index: number) =>
|
const getOverlayByIndex = (index: number) =>
|
||||||
u.getBoundingBox(`[data-overlay-index="${index}"]`)
|
u.getBoundingBox(`[data-overlay-index="${index}"]`)
|
||||||
|
|
||||||
|
segmentToDelete = await getOverlayByIndex(14)
|
||||||
|
let ang = await u.getAngle('[data-overlay-index="14"]')
|
||||||
|
|
||||||
|
await editor.scrollToText('angleEnd')
|
||||||
|
|
||||||
|
await deleteSegmentSequence({
|
||||||
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
|
codeToBeDeleted: `arc({
|
||||||
|
radius = 9.03,
|
||||||
|
angleStart = 40.27,
|
||||||
|
angleEnd = -38.05
|
||||||
|
}, %)`,
|
||||||
|
stdLibFnName: 'arc',
|
||||||
|
ang: ang + 180,
|
||||||
|
steps: 6,
|
||||||
|
locator: '[data-overlay-toolbar-index="14"]',
|
||||||
|
})
|
||||||
|
segmentToDelete = await getOverlayByIndex(13)
|
||||||
|
ang = await u.getAngle('[data-overlay-index="13"]')
|
||||||
|
await deleteSegmentSequence({
|
||||||
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
|
codeToBeDeleted: `arcTo({
|
||||||
|
interior = [16.25, 5.12],
|
||||||
|
end = [21.61, 4.15]
|
||||||
|
}, %)`,
|
||||||
|
stdLibFnName: 'arcTo',
|
||||||
|
ang: ang,
|
||||||
|
steps: 6,
|
||||||
|
locator: '[data-overlay-toolbar-index="13"]',
|
||||||
|
})
|
||||||
segmentToDelete = await getOverlayByIndex(12)
|
segmentToDelete = await getOverlayByIndex(12)
|
||||||
let ang = await u.getAngle(`[data-overlay-index="${12}"]`)
|
ang = await u.getAngle('[data-overlay-index="12"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'tangentialArcTo([3.14 + 13, 1.14], %)',
|
codeToBeDeleted: 'tangentialArcTo([3.14 + 13, 1.14], %)',
|
||||||
@ -997,7 +1175,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(11)
|
segmentToDelete = await getOverlayByIndex(11)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${11}"]`)
|
ang = await u.getAngle('[data-overlay-index="11"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: `angledLineThatIntersects({
|
codeToBeDeleted: `angledLineThatIntersects({
|
||||||
@ -1012,7 +1190,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(10)
|
segmentToDelete = await getOverlayByIndex(10)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${10}"]`)
|
ang = await u.getAngle('[data-overlay-index="10"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'angledLineToY({ angle = 89, to = 9.14 + 0 }, %)',
|
codeToBeDeleted: 'angledLineToY({ angle = 89, to = 9.14 + 0 }, %)',
|
||||||
@ -1022,7 +1200,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(9)
|
segmentToDelete = await getOverlayByIndex(9)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${9}"]`)
|
ang = await u.getAngle('[data-overlay-index="9"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'angledLineToX({ angle = 3 + 0, to = 26 }, %)',
|
codeToBeDeleted: 'angledLineToX({ angle = 3 + 0, to = 26 }, %)',
|
||||||
@ -1032,7 +1210,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(8)
|
segmentToDelete = await getOverlayByIndex(8)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${8}"]`)
|
ang = await u.getAngle('[data-overlay-index="8"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted:
|
codeToBeDeleted:
|
||||||
@ -1043,7 +1221,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(7)
|
segmentToDelete = await getOverlayByIndex(7)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${7}"]`)
|
ang = await u.getAngle('[data-overlay-index="7"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted:
|
codeToBeDeleted:
|
||||||
@ -1054,7 +1232,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(6)
|
segmentToDelete = await getOverlayByIndex(6)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${6}"]`)
|
ang = await u.getAngle('[data-overlay-index="6"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'yLine(length = 21.14 + 0)',
|
codeToBeDeleted: 'yLine(length = 21.14 + 0)',
|
||||||
@ -1064,7 +1242,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(5)
|
segmentToDelete = await getOverlayByIndex(5)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${5}"]`)
|
ang = await u.getAngle('[data-overlay-index="5"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'xLine(length = 26.04)',
|
codeToBeDeleted: 'xLine(length = 26.04)',
|
||||||
@ -1074,7 +1252,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(4)
|
segmentToDelete = await getOverlayByIndex(4)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${4}"]`)
|
ang = await u.getAngle('[data-overlay-index="4"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'yLine(endAbsolute = -10.77, tag = $a)',
|
codeToBeDeleted: 'yLine(endAbsolute = -10.77, tag = $a)',
|
||||||
@ -1084,7 +1262,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(3)
|
segmentToDelete = await getOverlayByIndex(3)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${3}"]`)
|
ang = await u.getAngle('[data-overlay-index="3"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'xLine(endAbsolute = 9 - 5)',
|
codeToBeDeleted: 'xLine(endAbsolute = 9 - 5)',
|
||||||
@ -1094,7 +1272,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(2)
|
segmentToDelete = await getOverlayByIndex(2)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${2}"]`)
|
ang = await u.getAngle('[data-overlay-index="2"]')
|
||||||
await expect(page.getByText('Added variable')).not.toBeVisible()
|
await expect(page.getByText('Added variable')).not.toBeVisible()
|
||||||
|
|
||||||
const hoverPos = { x: segmentToDelete.x, y: segmentToDelete.y }
|
const hoverPos = { x: segmentToDelete.x, y: segmentToDelete.y }
|
||||||
@ -1127,7 +1305,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(1)
|
segmentToDelete = await getOverlayByIndex(1)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${1}"]`)
|
ang = await u.getAngle('[data-overlay-index="1"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'angledLine({ angle = 3 + 0, length = 32 + 0 }, %)',
|
codeToBeDeleted: 'angledLine({ angle = 3 + 0, length = 32 + 0 }, %)',
|
||||||
@ -1137,7 +1315,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
segmentToDelete = await getOverlayByIndex(0)
|
segmentToDelete = await getOverlayByIndex(0)
|
||||||
ang = await u.getAngle(`[data-overlay-index="${0}"]`)
|
ang = await u.getAngle('[data-overlay-index="0"]')
|
||||||
await deleteSegmentSequence({
|
await deleteSegmentSequence({
|
||||||
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
hoverPos: { x: segmentToDelete.x, y: segmentToDelete.y },
|
||||||
codeToBeDeleted: 'line(end = [0.5, -14 + 0])',
|
codeToBeDeleted: 'line(end = [0.5, -14 + 0])',
|
||||||
@ -1366,7 +1544,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
|
|||||||
await expect(page.getByText('Added variable')).not.toBeVisible()
|
await expect(page.getByText('Added variable')).not.toBeVisible()
|
||||||
|
|
||||||
const hoverPos = await u.getBoundingBox(`[data-overlay-index="0"]`)
|
const hoverPos = await u.getBoundingBox(`[data-overlay-index="0"]`)
|
||||||
let ang = await u.getAngle(`[data-overlay-index="${0}"]`)
|
let ang = await u.getAngle('[data-overlay-index="0"]')
|
||||||
ang += 180
|
ang += 180
|
||||||
|
|
||||||
await page.mouse.move(0, 0)
|
await page.mouse.move(0, 0)
|
||||||
|
@ -257,6 +257,7 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
|
|||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
test.setTimeout(90_000)
|
test.setTimeout(90_000)
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
@ -352,28 +353,15 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
|
|||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.waitForExecutionDone()
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
await u.openAndClearDebugPanel()
|
const camPosition1 = async () => {
|
||||||
await u.sendCustomCmd({
|
await scene.moveCameraTo(
|
||||||
type: 'modeling_cmd_req',
|
{ x: 1139.49, y: -7053, z: 8597.31 },
|
||||||
cmd_id: uuidv4(),
|
{ x: -2206.68, y: -1298.36, z: 60 }
|
||||||
cmd: {
|
)
|
||||||
type: 'default_camera_look_at',
|
}
|
||||||
vantage: { x: 1139.49, y: -7053, z: 8597.31 },
|
await camPosition1()
|
||||||
center: { x: -2206.68, y: -1298.36, z: 60 },
|
|
||||||
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 revolve = { x: 635, y: 253 }
|
const revolve = { x: 635, y: 253 }
|
||||||
const parentExtrude = { x: 915, y: 133 }
|
const parentExtrude = { x: 915, y: 133 }
|
||||||
@ -386,7 +374,7 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
|
|||||||
await expect(page.locator('.cm-activeLine')).toHaveText(
|
await expect(page.locator('.cm-activeLine')).toHaveText(
|
||||||
'|> line(end = [0, -pipeLength])'
|
'|> line(end = [0, -pipeLength])'
|
||||||
)
|
)
|
||||||
await u.clearCommandLogs()
|
await u.openAndClearDebugPanel()
|
||||||
await page.keyboard.press('Delete')
|
await page.keyboard.press('Delete')
|
||||||
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
|
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
|
||||||
await page.waitForTimeout(200)
|
await page.waitForTimeout(200)
|
||||||
@ -399,11 +387,12 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
|
|||||||
// and replace the sketch on face with a hard coded custom plane, but since there was a sketch on that plane maybe it
|
// and replace the sketch on face with a hard coded custom plane, but since there was a sketch on that plane maybe it
|
||||||
// should have delete the sketch? it's broken atm, but not sure if worth fixing since desired behaviour is a little
|
// should have delete the sketch? it's broken atm, but not sure if worth fixing since desired behaviour is a little
|
||||||
// vague
|
// vague
|
||||||
// // DELETE PARENT EXTRUDE
|
// DELETE PARENT EXTRUDE
|
||||||
|
// await camPosition2()
|
||||||
// await page.mouse.click(parentExtrude.x, parentExtrude.y)
|
// await page.mouse.click(parentExtrude.x, parentExtrude.y)
|
||||||
// await page.waitForTimeout(100)
|
// await page.waitForTimeout(100)
|
||||||
// await expect(page.locator('.cm-activeLine')).toHaveText(
|
// await expect(page.locator('.cm-activeLine')).toHaveText(
|
||||||
// '|> line(end = [170.36, -121.61], tag = $seg01)'
|
// '|> line(end = [112.54, 127.64], tag = $seg02)'
|
||||||
// )
|
// )
|
||||||
// await u.clearCommandLogs()
|
// await u.clearCommandLogs()
|
||||||
// await page.keyboard.press('Backspace')
|
// await page.keyboard.press('Backspace')
|
||||||
@ -463,71 +452,77 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
|
|||||||
await page.waitForTimeout(200)
|
await page.waitForTimeout(200)
|
||||||
await expect(u.codeLocator).not.toContainText(codeToBeDeletedSnippet)
|
await expect(u.codeLocator).not.toContainText(codeToBeDeletedSnippet)
|
||||||
})
|
})
|
||||||
test.fixme(
|
test('parent Solid should be select and deletable and uses custom planes to position children', async ({
|
||||||
"Deleting solid that the AST mod can't handle results in a toast message",
|
page,
|
||||||
async ({ page, homePage }) => {
|
homePage,
|
||||||
const u = await getUtils(page)
|
scene,
|
||||||
await page.addInitScript(async () => {
|
cmdBar,
|
||||||
localStorage.setItem(
|
editor,
|
||||||
'persistCode',
|
}) => {
|
||||||
`sketch001 = startSketchOn('XZ')
|
test.setTimeout(90_000)
|
||||||
|> startProfileAt([-79.26, 95.04], %)
|
const u = await getUtils(page)
|
||||||
|> line(end = [112.54, 127.64], tag = $seg02)
|
await page.addInitScript(async () => {
|
||||||
|> line(end = [170.36, -121.61], tag = $seg01)
|
localStorage.setItem(
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
'persistCode',
|
||||||
|> close()
|
`part001 = startSketchOn('XY')
|
||||||
extrude001 = extrude(sketch001, length = 50)
|
yo = startProfileAt([4.83, 12.56], part001)
|
||||||
launderExtrudeThroughVar = extrude001
|
|> line(end = [15.1, 2.48])
|
||||||
sketch002 = startSketchOn(launderExtrudeThroughVar, seg02)
|
|> line(end = [3.15, -9.85], tag = $seg01)
|
||||||
|> startProfileAt([-100.54, 16.99], %)
|
|> line(end = [-15.17, -4.1])
|
||||||
|> line(end = [0, 20.03])
|
|> angledLine([segAng(seg01), 12.35], %, $seg02)
|
||||||
|> line(end = [62.61, 0], tag = $seg03)
|
|> line(end = [-13.02, 10.03])
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> close()
|
||||||
|> close()
|
yoo = extrude(yo, length = 4)
|
||||||
`
|
sketch002 = startSketchOn(yoo, seg02)
|
||||||
)
|
sketch001 = startSketchOn(yoo, 'END')
|
||||||
}, KCL_DEFAULT_LENGTH)
|
profile002 = startProfileAt([-11.08, 2.39], sketch002)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|> line(end = [4.89, 0.9])
|
||||||
|
|> line(end = [-0.61, -2.41])
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|
|> close()
|
||||||
|
extrude001 = extrude(profile002, length = 15)
|
||||||
|
profile001 = startProfileAt([7.49, 9.96], sketch001)
|
||||||
|
|> angledLine([0, 5.05], %, $rectangleSegmentA001)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001) - 90,
|
||||||
|
4.81
|
||||||
|
], %)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001),
|
||||||
|
-segLen(rectangleSegmentA001)
|
||||||
|
], %)
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|
|> close()
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
`
|
||||||
|
|
||||||
await u.openDebugPanel()
|
|
||||||
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
|
|
||||||
await u.closeDebugPanel()
|
|
||||||
|
|
||||||
await u.openAndClearDebugPanel()
|
|
||||||
await u.sendCustomCmd({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: {
|
|
||||||
type: 'default_camera_look_at',
|
|
||||||
vantage: { x: 1139.49, y: -7053, z: 8597.31 },
|
|
||||||
center: { x: -2206.68, y: -1298.36, z: 60 },
|
|
||||||
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)
|
|
||||||
|
|
||||||
// attempt delete
|
|
||||||
await page.mouse.click(930, 139)
|
|
||||||
await page.waitForTimeout(100)
|
|
||||||
await expect(page.locator('.cm-activeLine')).toHaveText(
|
|
||||||
'|> line(end = [170.36, -121.61], tag = $seg01)'
|
|
||||||
)
|
)
|
||||||
await u.clearCommandLogs()
|
}, KCL_DEFAULT_LENGTH)
|
||||||
await page.keyboard.press('Delete')
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
await expect(page.getByText('Unable to delete selection')).toBeVisible()
|
await homePage.goToModelingScene()
|
||||||
}
|
await scene.settled(cmdBar)
|
||||||
)
|
|
||||||
|
const extrudeWall = { x: 575, y: 238 }
|
||||||
|
|
||||||
|
// DELETE with selection on face of parent
|
||||||
|
await page.mouse.click(extrudeWall.x, extrudeWall.y)
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await expect(page.locator('.cm-activeLine')).toHaveText(
|
||||||
|
'|> line(end = [-15.17, -4.1])'
|
||||||
|
)
|
||||||
|
await u.openAndClearDebugPanel()
|
||||||
|
await page.keyboard.press('Delete')
|
||||||
|
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
|
||||||
|
await page.waitForTimeout(200)
|
||||||
|
|
||||||
|
await editor.expectEditor.not.toContain(`yoo = extrude(yo, length = 4)`, {
|
||||||
|
shouldNormalise: true,
|
||||||
|
})
|
||||||
|
await editor.expectEditor.toContain(`startSketchOn({plane={origin`, {
|
||||||
|
shouldNormalise: true,
|
||||||
|
})
|
||||||
|
await editor.snapshot()
|
||||||
|
})
|
||||||
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({
|
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
part001 = startSketchOn('XY')yo = startProfileAt([4.83, 12.56], part001) |> line(end = [15.1, 2.48]) |> line(end = [3.15, -9.85], tag = $seg01) |> line(end = [-15.17, -4.1]) |> angledLine([segAng(seg01), 12.35], %, $seg02) |> line(end = [-13.02, 10.03]) |> close()sketch002 = startSketchOn({ plane = { origin = { x = 7.49, y = 2.4, z = 0 }, xAxis = { x = -0.3, y = 0.95, z = 0 }, yAxis = { x = 0, y = 0, z = 1 }, zAxis = { x = 0.95, y = 0.3, z = 0 } }})sketch001 = startSketchOn({ plane = { origin = { x = 0, y = 0, z = 4 }, xAxis = { x = 1, y = 0, z = 0 }, yAxis = { x = 0, y = 1, z = 0 }, zAxis = { x = 0, y = 0, z = 1 } }})profile002 = startProfileAt([-11.08, 2.39], sketch002) |> line(end = [4.89, 0.9]) |> line(end = [-0.61, -2.41]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()extrude001 = extrude(profile002, length = 15)profile001 = startProfileAt([7.49, 9.96], sketch001) |> angledLine([0, 5.05], %, $rectangleSegmentA001) |> angledLine([ segAng(rectangleSegmentA001) - 90, 4.81 ], %) |> angledLine([ segAng(rectangleSegmentA001), -segLen(rectangleSegmentA001) ], %) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()
|
@ -430,7 +430,8 @@ test.describe('Text-to-CAD tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await expect(page.getByText(promptWithNewline)).toBeVisible()
|
await expect(page.getByText(promptWithNewline)).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test(
|
// This will be fine once greg makes prompt at top of file deterministic
|
||||||
|
test.fixme(
|
||||||
'can do many at once and get many prompts back, and interact with many',
|
'can do many at once and get many prompts back, and interact with many',
|
||||||
{ tag: ['@skipWin'] },
|
{ tag: ['@skipWin'] },
|
||||||
async ({ page, homePage }) => {
|
async ({ page, homePage }) => {
|
||||||
@ -491,8 +492,15 @@ test.describe('Text-to-CAD tests', { tag: ['@skipWin'] }, () => {
|
|||||||
// Click the button.
|
// Click the button.
|
||||||
await copyToClipboardButton.first().click()
|
await copyToClipboardButton.first().click()
|
||||||
|
|
||||||
// Expect the code to be pasted.
|
// Do NOT do AI tests like this: "Expect the code to be pasted."
|
||||||
await expect(page.locator('.cm-content')).toContainText(`2x8`)
|
// Reason: AI tests are NONDETERMINISTIC. Thus we need to be as most
|
||||||
|
// general as we can for the assertion.
|
||||||
|
// We can use Kolmogorov complexity as a measurement of the
|
||||||
|
// "probably most minimal version of this program" to have a lower
|
||||||
|
// bound to work with. It is completely by feel because there are
|
||||||
|
// no proofs that any program is its smallest self.
|
||||||
|
const code2x8 = await page.locator('.cm-content').innerText()
|
||||||
|
await expect(code2x8.length).toBeGreaterThan(249)
|
||||||
|
|
||||||
// Ensure the final toast remains.
|
// Ensure the final toast remains.
|
||||||
await expect(page.getByText(`a 2x10 lego`)).not.toBeVisible()
|
await expect(page.getByText(`a 2x10 lego`)).not.toBeVisible()
|
||||||
@ -505,7 +513,8 @@ test.describe('Text-to-CAD tests', { tag: ['@skipWin'] }, () => {
|
|||||||
await copyToClipboardButton.click()
|
await copyToClipboardButton.click()
|
||||||
|
|
||||||
// Expect the code to be pasted.
|
// Expect the code to be pasted.
|
||||||
await expect(page.locator('.cm-content')).toContainText(`2x4`)
|
const code2x4 = await page.locator('.cm-content').innerText()
|
||||||
|
await expect(code2x4.length).toBeGreaterThan(249)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -45,7 +45,9 @@ const playwrightTestFnWithFixtures_ = playwrightTestFn.extend<{
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await electronZooInstance.createInstanceIfMissing(testInfo)
|
||||||
await use(electronZooInstance)
|
await use(electronZooInstance)
|
||||||
|
await electronZooInstance.makeAvailableAgain()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
52
package.json
@ -12,17 +12,17 @@
|
|||||||
"main": ".vite/build/main.js",
|
"main": ".vite/build/main.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.17.0",
|
"@codemirror/autocomplete": "^6.18.6",
|
||||||
"@codemirror/commands": "^6.8.0",
|
"@codemirror/commands": "^6.8.0",
|
||||||
"@codemirror/language": "^6.10.8",
|
"@codemirror/language": "^6.11.0",
|
||||||
"@codemirror/lint": "^6.8.4",
|
"@codemirror/lint": "^6.8.4",
|
||||||
"@codemirror/search": "^6.5.10",
|
"@codemirror/search": "^6.5.10",
|
||||||
"@codemirror/state": "^6.4.1",
|
"@codemirror/state": "^6.4.1",
|
||||||
"@codemirror/theme-one-dark": "^6.1.2",
|
"@codemirror/theme-one-dark": "^6.1.2",
|
||||||
"@csstools/postcss-oklab-function": "^4.0.7",
|
"@csstools/postcss-oklab-function": "^4.0.7",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@headlessui/react": "^1.7.19",
|
"@headlessui/react": "^1.7.19",
|
||||||
"@headlessui/tailwindcss": "^0.2.0",
|
"@headlessui/tailwindcss": "^0.2.0",
|
||||||
@ -35,35 +35,35 @@
|
|||||||
"@tweenjs/tween.js": "^23.1.1",
|
"@tweenjs/tween.js": "^23.1.1",
|
||||||
"@xstate/inspect": "^0.8.0",
|
"@xstate/inspect": "^0.8.0",
|
||||||
"@xstate/react": "^4.1.1",
|
"@xstate/react": "^4.1.1",
|
||||||
"bonjour-service": "^1.2.1",
|
"bonjour-service": "^1.3.0",
|
||||||
"chokidar": "^4.0.1",
|
"chokidar": "^4.0.1",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
"decamelize": "^6.0.0",
|
"decamelize": "^6.0.0",
|
||||||
"diff": "^7.0.0",
|
"diff": "^7.0.0",
|
||||||
"electron-updater": "^6.6.0",
|
"electron-updater": "^6.6.0",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.1.0",
|
||||||
"html2canvas-pro": "^1.5.8",
|
"html2canvas-pro": "^1.5.8",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"json-rpc-2.0": "^1.6.0",
|
"json-rpc-2.0": "^1.6.0",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"minimist": "^1.2.8",
|
"minimist": "^1.2.8",
|
||||||
"openid-client": "^5.6.5",
|
"openid-client": "^5.6.5",
|
||||||
"re-resizable": "^6.9.11",
|
"re-resizable": "^6.11.2",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hot-toast": "^2.4.1",
|
"react-hot-toast": "^2.5.2",
|
||||||
"react-hotkeys-hook": "^4.6.1",
|
"react-hotkeys-hook": "^4.6.1",
|
||||||
"react-json-view": "^1.21.3",
|
"react-json-view": "^1.21.3",
|
||||||
"react-modal": "^3.16.3",
|
"react-modal": "^3.16.3",
|
||||||
"react-modal-promise": "^1.0.2",
|
"react-modal-promise": "^1.0.2",
|
||||||
"react-router-dom": "^6.28.0",
|
"react-router-dom": "^6.28.0",
|
||||||
"sketch-helpers": "^0.0.4",
|
"sketch-helpers": "^0.0.4",
|
||||||
"three": "^0.172.0",
|
"three": "^0.174.0",
|
||||||
"ua-parser-js": "^1.0.37",
|
"ua-parser-js": "^1.0.37",
|
||||||
"uuid": "^11.0.2",
|
"uuid": "^11.1.0",
|
||||||
"vscode-jsonrpc": "^8.2.1",
|
"vscode-jsonrpc": "^8.2.1",
|
||||||
"vscode-languageserver-protocol": "^3.17.5",
|
"vscode-languageserver-protocol": "^3.17.5",
|
||||||
"vscode-uri": "^3.0.8",
|
"vscode-uri": "^3.1.0",
|
||||||
"web-vitals": "^3.5.2",
|
"web-vitals": "^3.5.2",
|
||||||
"xstate": "^5.19.2",
|
"xstate": "^5.19.2",
|
||||||
"yargs": "^17.7.2"
|
"yargs": "^17.7.2"
|
||||||
@ -93,11 +93,9 @@
|
|||||||
"fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1",
|
"fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1",
|
||||||
"fetch:samples": "rm -rf public/kcl-samples* && curl -L -o public/kcl-samples.zip https://github.com/KittyCAD/kcl-samples/archive/refs/heads/achalmers/kw-args-xylineto.zip && unzip -o public/kcl-samples.zip -d public && mv public/kcl-samples-* public/kcl-samples",
|
"fetch:samples": "rm -rf public/kcl-samples* && curl -L -o public/kcl-samples.zip https://github.com/KittyCAD/kcl-samples/archive/refs/heads/achalmers/kw-args-xylineto.zip && unzip -o public/kcl-samples.zip -d public && mv public/kcl-samples-* public/kcl-samples",
|
||||||
"build:wasm-dev": "yarn wasm-prep && (cd rust && wasm-pack build kcl-wasm-lib --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 rust && wasm-pack build kcl-wasm-lib --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && yarn isomorphic-copy-wasm && yarn fmt",
|
||||||
"build:wasm:nocopy": "yarn wasm-prep && cd rust && wasm-pack build kcl-wasm-lib --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings",
|
"build:wasm": "./scripts/build-wasm.sh",
|
||||||
"build:wasm": "yarn build:wasm:nocopy && cp rust/kcl-wasm-lib/pkg/kcl_wasm_lib_bg.wasm public && yarn fmt",
|
"build:wasm:windows": "./scripts/build-wasm.ps1",
|
||||||
"build:wasm:windows": "yarn install:wasm-pack:cargo && yarn build:wasm:nocopy && ./scripts/copy-wasm.ps1 && yarn fmt",
|
|
||||||
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\" || echo \"sed for both mac and linux\"",
|
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\" || echo \"sed for both mac and linux\"",
|
||||||
"wasm-prep": "rimraf rust/kcl-wasm-lib/pkg && mkdirp rust/kcl-wasm-lib/pkg && rimraf rust/kcl-lib/bindings",
|
|
||||||
"lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
|
"lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
|
||||||
"lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
|
"lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
|
||||||
"files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
|
"files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
|
||||||
@ -153,16 +151,16 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||||
"@babel/preset-env": "^7.25.4",
|
"@babel/preset-env": "^7.26.9",
|
||||||
"@electron-forge/cli": "^7.6.1",
|
"@electron-forge/cli": "^7.7.0",
|
||||||
"@electron-forge/plugin-fuses": "^7.6.1",
|
"@electron-forge/plugin-fuses": "^7.7.0",
|
||||||
"@electron-forge/plugin-vite": "^7.6.1",
|
"@electron-forge/plugin-vite": "^7.7.0",
|
||||||
"@electron/fuses": "^1.8.0",
|
"@electron/fuses": "^1.8.0",
|
||||||
"@electron/notarize": "^2.5.0",
|
"@electron/notarize": "^2.5.0",
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@lezer/generator": "^1.7.2",
|
"@lezer/generator": "^1.7.2",
|
||||||
"@nabla/vite-plugin-eslint": "^2.0.5",
|
"@nabla/vite-plugin-eslint": "^2.0.5",
|
||||||
"@playwright/test": "^1.49.0",
|
"@playwright/test": "^1.51.0",
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
"@testing-library/jest-dom": "^5.14.1",
|
||||||
"@testing-library/react": "^15.0.2",
|
"@testing-library/react": "^15.0.2",
|
||||||
"@types/diff": "^7.0.1",
|
"@types/diff": "^7.0.1",
|
||||||
@ -176,7 +174,7 @@
|
|||||||
"@types/react": "^18.3.4",
|
"@types/react": "^18.3.4",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@types/react-modal": "^3.16.3",
|
"@types/react-modal": "^3.16.3",
|
||||||
"@types/three": "^0.172.0",
|
"@types/three": "^0.174.0",
|
||||||
"@types/ua-parser-js": "^0.7.39",
|
"@types/ua-parser-js": "^0.7.39",
|
||||||
"@types/uuid": "^9.0.8",
|
"@types/uuid": "^9.0.8",
|
||||||
"@types/wicg-file-system-access": "^2023.10.5",
|
"@types/wicg-file-system-access": "^2023.10.5",
|
||||||
@ -189,11 +187,11 @@
|
|||||||
"electron-builder": "^26.0.6",
|
"electron-builder": "^26.0.6",
|
||||||
"eslint": "^8.0.1",
|
"eslint": "^8.0.1",
|
||||||
"eslint-plugin-css-modules": "^2.12.0",
|
"eslint-plugin-css-modules": "^2.12.0",
|
||||||
"eslint-plugin-import": "^2.30.0",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"eslint-plugin-jest": "^28.10.0",
|
"eslint-plugin-jest": "^28.11.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||||
"eslint-plugin-react": "^7.37.4",
|
"eslint-plugin-react": "^7.37.4",
|
||||||
"eslint-plugin-react-hooks": "^5.1.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"eslint-plugin-react-perf": "^3.3.3",
|
"eslint-plugin-react-perf": "^3.3.3",
|
||||||
"eslint-plugin-suggest-no-throw": "^1.0.0",
|
"eslint-plugin-suggest-no-throw": "^1.0.0",
|
||||||
"eslint-plugin-testing-library": "^7.1.1",
|
"eslint-plugin-testing-library": "^7.1.1",
|
||||||
@ -210,8 +208,8 @@
|
|||||||
"setimmediate": "^1.0.5",
|
"setimmediate": "^1.0.5",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"ts-node": "^10.0.0",
|
"ts-node": "^10.0.0",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.8.2",
|
||||||
"typescript-eslint": "^8.23.0",
|
"typescript-eslint": "^8.26.1",
|
||||||
"vite": "^5.4.12",
|
"vite": "^5.4.12",
|
||||||
"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",
|
||||||
|
@ -19,14 +19,14 @@
|
|||||||
"private": false,
|
"private": false,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "6.18.6",
|
"@codemirror/autocomplete": "6.18.6",
|
||||||
"@codemirror/language": "^6.10.2",
|
"@codemirror/language": "^6.11.0",
|
||||||
"@codemirror/state": "^6.4.1",
|
"@codemirror/state": "^6.5.2",
|
||||||
"@lezer/highlight": "^1.2.0",
|
"@lezer/highlight": "^1.2.0",
|
||||||
"@ts-stack/markdown": "^1.5.0",
|
"@ts-stack/markdown": "^1.5.0",
|
||||||
"json-rpc-2.0": "^1.7.0",
|
"json-rpc-2.0": "^1.7.0",
|
||||||
"typescript": "^5.7.2",
|
"typescript": "^5.8.2",
|
||||||
"vscode-languageserver-protocol": "^3.17.5",
|
"vscode-languageserver-protocol": "^3.17.5",
|
||||||
"vscode-uri": "^3.0.8"
|
"vscode-uri": "^3.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.13.9",
|
"@types/node": "^22.13.9",
|
||||||
|
@ -12,10 +12,10 @@
|
|||||||
"@codemirror/view" "^6.17.0"
|
"@codemirror/view" "^6.17.0"
|
||||||
"@lezer/common" "^1.0.0"
|
"@lezer/common" "^1.0.0"
|
||||||
|
|
||||||
"@codemirror/language@^6.0.0", "@codemirror/language@^6.10.2":
|
"@codemirror/language@^6.0.0", "@codemirror/language@^6.11.0":
|
||||||
version "6.10.2"
|
version "6.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.10.2.tgz#4056dc219619627ffe995832eeb09cea6060be61"
|
resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.11.0.tgz#5ae90972601497f4575f30811519d720bf7232c9"
|
||||||
integrity sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==
|
integrity sha512-A7+f++LodNNc1wGgoRDTt78cOwWm9KVezApgjOMp1W4hM0898nsqBXwF+sbePE7ZRcjN7Sa1Z5m2oN27XkmEjQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@codemirror/state" "^6.0.0"
|
"@codemirror/state" "^6.0.0"
|
||||||
"@codemirror/view" "^6.23.0"
|
"@codemirror/view" "^6.23.0"
|
||||||
@ -24,10 +24,12 @@
|
|||||||
"@lezer/lr" "^1.0.0"
|
"@lezer/lr" "^1.0.0"
|
||||||
style-mod "^4.0.0"
|
style-mod "^4.0.0"
|
||||||
|
|
||||||
"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.0", "@codemirror/state@^6.4.1":
|
"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.0", "@codemirror/state@^6.5.2":
|
||||||
version "6.4.1"
|
version "6.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.4.1.tgz#da57143695c056d9a3c38705ed34136e2b68171b"
|
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6"
|
||||||
integrity sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==
|
integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==
|
||||||
|
dependencies:
|
||||||
|
"@marijn/find-cluster-break" "^1.0.0"
|
||||||
|
|
||||||
"@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0":
|
"@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0":
|
||||||
version "6.28.2"
|
version "6.28.2"
|
||||||
@ -82,6 +84,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@lezer/common" "^1.0.0"
|
"@lezer/common" "^1.0.0"
|
||||||
|
|
||||||
|
"@marijn/find-cluster-break@^1.0.0":
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8"
|
||||||
|
integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==
|
||||||
|
|
||||||
"@ts-stack/markdown@^1.5.0":
|
"@ts-stack/markdown@^1.5.0":
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/@ts-stack/markdown/-/markdown-1.5.0.tgz#5dc298a20dc3dc040143c5a5948201eb6bf5419d"
|
resolved "https://registry.yarnpkg.com/@ts-stack/markdown/-/markdown-1.5.0.tgz#5dc298a20dc3dc040143c5a5948201eb6bf5419d"
|
||||||
@ -182,10 +189,10 @@ tslib@^2.3.0:
|
|||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
|
||||||
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
||||||
|
|
||||||
typescript@^5.7.2:
|
typescript@^5.8.2:
|
||||||
version "5.7.2"
|
version "5.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4"
|
||||||
integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==
|
integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==
|
||||||
|
|
||||||
undici-types@~6.20.0:
|
undici-types@~6.20.0:
|
||||||
version "6.20.0"
|
version "6.20.0"
|
||||||
@ -215,10 +222,10 @@ vscode-languageserver-types@3.17.5:
|
|||||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a"
|
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a"
|
||||||
integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==
|
integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==
|
||||||
|
|
||||||
vscode-uri@^3.0.8:
|
vscode-uri@^3.1.0:
|
||||||
version "3.0.8"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f"
|
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.1.0.tgz#dd09ec5a66a38b5c3fffc774015713496d14e09c"
|
||||||
integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==
|
integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==
|
||||||
|
|
||||||
w3c-keyname@^2.2.4:
|
w3c-keyname@^2.2.4:
|
||||||
version "2.2.8"
|
version "2.2.8"
|
||||||
|
@ -13,7 +13,7 @@ export default defineConfig({
|
|||||||
/* Do not retry */
|
/* Do not retry */
|
||||||
retries: 0,
|
retries: 0,
|
||||||
/* Different amount of parallelism on CI and local. */
|
/* Different amount of parallelism on CI and local. */
|
||||||
workers: 8,
|
workers: 1,
|
||||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
reporter: [
|
reporter: [
|
||||||
['dot'],
|
['dot'],
|
||||||
|
@ -23,14 +23,14 @@ KCL samples conform to a set of style guidelines to ensure consistency and reada
|
|||||||
When you submit a PR to add or modify KCL samples, images and STEP files will be generated and added to the repository automatically.
|
When you submit a PR to add or modify KCL samples, images and STEP files will be generated and added to the repository automatically.
|
||||||
|
|
||||||
---
|
---
|
||||||
#### [3d-boaty](3d-boaty/main.kcl) ([step](step/3d-boaty.step)) ([screenshot](screenshots/3d-boaty.png))
|
|
||||||
[](3d-boaty/main.kcl)
|
|
||||||
#### [80-20-rail](80-20-rail/main.kcl) ([step](step/80-20-rail.step)) ([screenshot](screenshots/80-20-rail.png))
|
#### [80-20-rail](80-20-rail/main.kcl) ([step](step/80-20-rail.step)) ([screenshot](screenshots/80-20-rail.png))
|
||||||
[](80-20-rail/main.kcl)
|
[](80-20-rail/main.kcl)
|
||||||
#### [a-parametric-bearing-pillow-block](a-parametric-bearing-pillow-block/main.kcl) ([step](step/a-parametric-bearing-pillow-block.step)) ([screenshot](screenshots/a-parametric-bearing-pillow-block.png))
|
#### [a-parametric-bearing-pillow-block](a-parametric-bearing-pillow-block/main.kcl) ([step](step/a-parametric-bearing-pillow-block.step)) ([screenshot](screenshots/a-parametric-bearing-pillow-block.png))
|
||||||
[](a-parametric-bearing-pillow-block/main.kcl)
|
[](a-parametric-bearing-pillow-block/main.kcl)
|
||||||
#### [ball-bearing](ball-bearing/main.kcl) ([step](step/ball-bearing.step)) ([screenshot](screenshots/ball-bearing.png))
|
#### [ball-bearing](ball-bearing/main.kcl) ([step](step/ball-bearing.step)) ([screenshot](screenshots/ball-bearing.png))
|
||||||
[](ball-bearing/main.kcl)
|
[](ball-bearing/main.kcl)
|
||||||
|
#### [bench](bench/main.kcl) ([step](step/bench.step)) ([screenshot](screenshots/bench.png))
|
||||||
|
[](bench/main.kcl)
|
||||||
#### [bracket](bracket/main.kcl) ([step](step/bracket.step)) ([screenshot](screenshots/bracket.png))
|
#### [bracket](bracket/main.kcl) ([step](step/bracket.step)) ([screenshot](screenshots/bracket.png))
|
||||||
[](bracket/main.kcl)
|
[](bracket/main.kcl)
|
||||||
#### [car-wheel-assembly](car-wheel-assembly/main.kcl) ([step](step/car-wheel-assembly.step)) ([screenshot](screenshots/car-wheel-assembly.png))
|
#### [car-wheel-assembly](car-wheel-assembly/main.kcl) ([step](step/car-wheel-assembly.step)) ([screenshot](screenshots/car-wheel-assembly.png))
|
||||||
@ -45,10 +45,8 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
|
|||||||
[](enclosure/main.kcl)
|
[](enclosure/main.kcl)
|
||||||
#### [exhaust-manifold](exhaust-manifold/main.kcl) ([step](step/exhaust-manifold.step)) ([screenshot](screenshots/exhaust-manifold.png))
|
#### [exhaust-manifold](exhaust-manifold/main.kcl) ([step](step/exhaust-manifold.step)) ([screenshot](screenshots/exhaust-manifold.png))
|
||||||
[](exhaust-manifold/main.kcl)
|
[](exhaust-manifold/main.kcl)
|
||||||
#### [flange-with-patterns](flange-with-patterns/main.kcl) ([step](step/flange-with-patterns.step)) ([screenshot](screenshots/flange-with-patterns.png))
|
#### [flange](flange/main.kcl) ([step](step/flange.step)) ([screenshot](screenshots/flange.png))
|
||||||
[](flange-with-patterns/main.kcl)
|
[](flange/main.kcl)
|
||||||
#### [flange-xy](flange-xy/main.kcl) ([step](step/flange-xy.step)) ([screenshot](screenshots/flange-xy.png))
|
|
||||||
[](flange-xy/main.kcl)
|
|
||||||
#### [focusrite-scarlett-mounting-bracket](focusrite-scarlett-mounting-bracket/main.kcl) ([step](step/focusrite-scarlett-mounting-bracket.step)) ([screenshot](screenshots/focusrite-scarlett-mounting-bracket.png))
|
#### [focusrite-scarlett-mounting-bracket](focusrite-scarlett-mounting-bracket/main.kcl) ([step](step/focusrite-scarlett-mounting-bracket.step)) ([screenshot](screenshots/focusrite-scarlett-mounting-bracket.png))
|
||||||
[](focusrite-scarlett-mounting-bracket/main.kcl)
|
[](focusrite-scarlett-mounting-bracket/main.kcl)
|
||||||
#### [food-service-spatula](food-service-spatula/main.kcl) ([step](step/food-service-spatula.step)) ([screenshot](screenshots/food-service-spatula.png))
|
#### [food-service-spatula](food-service-spatula/main.kcl) ([step](step/food-service-spatula.step)) ([screenshot](screenshots/food-service-spatula.png))
|
||||||
|
@ -15,90 +15,57 @@ padding = 1.5
|
|||||||
bearingDia = 3
|
bearingDia = 3
|
||||||
|
|
||||||
// (Needs to be updated). Sketch the block and extrude up to where the counterbore diameter starts.
|
// (Needs to be updated). Sketch the block and extrude up to where the counterbore diameter starts.
|
||||||
block = startSketchOn('XY')
|
extrude001 = startSketchOn('XY')
|
||||||
|> startProfileAt([-width / 2, -length / 2], %)
|
|> startProfileAt([-width / 2, -length / 2], %)
|
||||||
|> line(endAbsolute = [width / 2, -length / 2])
|
|> line(endAbsolute = [width / 2, -length / 2])
|
||||||
|> line(endAbsolute = [width / 2, length / 2])
|
|> line(endAbsolute = [width / 2, length / 2])
|
||||||
|> line(endAbsolute = [-width / 2, length / 2])
|
|> line(endAbsolute = [-width / 2, length / 2])
|
||||||
|> close()
|
|> close()
|
||||||
|> hole(circle(
|
|> extrude(length = height)
|
||||||
center = [
|
|
||||||
-(width / 2 - (padding / 2)),
|
|
||||||
-(length / 2 - (padding / 2))
|
|
||||||
],
|
|
||||||
radius = holeDia / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [
|
|
||||||
-(width / 2 - (padding / 2)),
|
|
||||||
length / 2 - (padding / 2)
|
|
||||||
],
|
|
||||||
radius = holeDia / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [
|
|
||||||
width / 2 - (padding / 2),
|
|
||||||
length / 2 - (padding / 2)
|
|
||||||
],
|
|
||||||
radius = holeDia / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [
|
|
||||||
width / 2 - (padding / 2),
|
|
||||||
-(length / 2 - (padding / 2))
|
|
||||||
],
|
|
||||||
radius = holeDia / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = bearingDia / 2
|
|
||||||
), %)
|
|
||||||
|> extrude(length = height - cbDepth)
|
|
||||||
|
|
||||||
// Create a second sketch that creates the counterbore diameters and extrude the rest of the way to get the total height. Note: You cannot use startSketchOn(block, 'end'). The extrude lives outside the bounds, and the engine will not execute. This is a known issue.
|
extrude002 = startSketchOn(extrude001, 'end')
|
||||||
secondHalf = startSketchOn({
|
|> circle(
|
||||||
plane = {
|
center = [
|
||||||
origin = { x = 0, y = 0, z = height - cbDepth },
|
|
||||||
xAxis = { x = 1, y = 0, z = 0 },
|
|
||||||
yAxis = { x = 0, y = 1, z = 0 },
|
|
||||||
zAxis = { x = 0, y = 0, z = 1 }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|> startProfileAt([-width / 2, -length / 2], %)
|
|
||||||
|> line(endAbsolute = [width / 2, -length / 2])
|
|
||||||
|> line(endAbsolute = [width / 2, length / 2])
|
|
||||||
|> line(endAbsolute = [-width / 2, length / 2])
|
|
||||||
|> close()
|
|
||||||
|> hole(circle(
|
|
||||||
center = [
|
|
||||||
-(width / 2 - (padding / 2)),
|
-(width / 2 - (padding / 2)),
|
||||||
-(length / 2 - (padding / 2))
|
-(length / 2 - (padding / 2))
|
||||||
],
|
],
|
||||||
radius = cbDia / 2
|
radius = cbDia / 2,
|
||||||
), %)
|
)
|
||||||
|> hole(circle(
|
|> patternLinear2d(
|
||||||
center = [
|
instances = 2,
|
||||||
-(width / 2 - (padding / 2)),
|
distance = length - padding,
|
||||||
length / 2 - (padding / 2)
|
axis = [0, 1],
|
||||||
],
|
)
|
||||||
radius = cbDia / 2
|
|> patternLinear2d(
|
||||||
), %)
|
instances = 2,
|
||||||
|> hole(circle(
|
distance = width - padding,
|
||||||
center = [
|
axis = [1, 0],
|
||||||
width / 2 - (padding / 2),
|
)
|
||||||
length / 2 - (padding / 2)
|
|> extrude(%, length = -cbDepth)
|
||||||
],
|
|
||||||
radius = cbDia / 2
|
extrude003 = startSketchOn(extrude001, 'start')
|
||||||
), %)
|
|> circle(
|
||||||
|> hole(circle(
|
center = [
|
||||||
center = [
|
-(width / 2 - (padding / 2)),
|
||||||
width / 2 - (padding / 2),
|
-(length / 2 - (padding / 2))
|
||||||
-(length / 2 - (padding / 2))
|
],
|
||||||
],
|
radius = holeDia / 2,
|
||||||
radius = cbDia / 2
|
)
|
||||||
), %)
|
|> patternLinear2d(
|
||||||
|> hole(circle(
|
instances = 2,
|
||||||
center = [0, 0],
|
distance = length - padding,
|
||||||
radius = bearingDia / 2
|
axis = [0, 1],
|
||||||
), %)
|
)
|
||||||
|> extrude(length = cbDepth)
|
|> patternLinear2d(
|
||||||
|
instances = 2,
|
||||||
|
distance = width - padding,
|
||||||
|
axis = [1, 0],
|
||||||
|
)
|
||||||
|
|> extrude(length = -height + cbDepth)
|
||||||
|
|
||||||
|
extrude004 = startSketchOn(extrude001, 'end')
|
||||||
|
|> circle(
|
||||||
|
center = [0, 0],
|
||||||
|
radius = bearingDia/2,
|
||||||
|
)
|
||||||
|
|> extrude(length = -height)
|
@ -16,21 +16,8 @@ chainWidth = sphereDia / 2
|
|||||||
chainThickness = sphereDia / 8
|
chainThickness = sphereDia / 8
|
||||||
linkDiameter = sphereDia / 4
|
linkDiameter = sphereDia / 4
|
||||||
|
|
||||||
customPlane = {
|
|
||||||
plane = {
|
|
||||||
origin = {
|
|
||||||
x = 0,
|
|
||||||
y = 0,
|
|
||||||
z = -overallThickness / 2
|
|
||||||
},
|
|
||||||
xAxis = { x = 1, y = 0, z = 0 },
|
|
||||||
yAxis = { x = 0, y = 1, z = 0 },
|
|
||||||
zAxis = { x = 0, y = 0, z = 1 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sketch the inside bearing piece
|
// Sketch the inside bearing piece
|
||||||
insideWallSketch = startSketchOn(customPlane)
|
insideWallSketch = startSketchOn(offsetPlane("XY", offset = -overallThickness / 2))
|
||||||
|> circle(
|
|> circle(
|
||||||
center = [0, 0],
|
center = [0, 0],
|
||||||
radius = shaftDia / 2 + wallThickness
|
radius = shaftDia / 2 + wallThickness
|
||||||
@ -109,7 +96,7 @@ linkRevolve = revolve({ axis = 'Y', angle = 360 / nBalls }, linkSketch)
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Create the sketch for the outside walls
|
// Create the sketch for the outside walls
|
||||||
outsideWallSketch = startSketchOn(customPlane)
|
outsideWallSketch = startSketchOn(offsetPlane("XY", offset = -overallThickness / 2))
|
||||||
|> circle(
|
|> circle(
|
||||||
center = [0, 0],
|
center = [0, 0],
|
||||||
radius = outsideDiameter / 2
|
radius = outsideDiameter / 2
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// 3D Boaty
|
// Bench
|
||||||
// This is a slight remix of Depep1's original 3D Boaty (https://www.printables.com/model/1141963-3d-boaty). This is a tool used for benchmarking 3D FDM printers for bed adhesion, overhangs, bridging and top surface quality. The name of this file is a bit of misnomer, the shape of the object is a typical park bench.
|
// This is a slight remix of Depep1's original 3D Boaty (https://www.printables.com/model/1141963-3d-boaty). This is a tool used for benchmarking 3D FDM printers for bed adhesion, overhangs, bridging and top surface quality. The name of this file is a bit of misnomer, the shape of the object is a typical park bench.
|
||||||
|
|
||||||
// Set units in millimeters (mm)
|
// Set units in millimeters (mm)
|
||||||
@ -8,12 +8,12 @@
|
|||||||
benchLength = 56
|
benchLength = 56
|
||||||
|
|
||||||
// Import various constants and functions from our library
|
// Import various constants and functions from our library
|
||||||
import dividerThickness from "boat-parts.kcl"
|
import dividerThickness from "bench-parts.kcl"
|
||||||
import divider from "boat-parts.kcl"
|
import divider from "bench-parts.kcl"
|
||||||
import connector from "boat-parts.kcl"
|
import connector from "bench-parts.kcl"
|
||||||
import seatSlats from "boat-parts.kcl"
|
import seatSlats from "bench-parts.kcl"
|
||||||
import backSlats from "boat-parts.kcl"
|
import backSlats from "bench-parts.kcl"
|
||||||
import armRest from "boat-parts.kcl"
|
import armRest from "bench-parts.kcl"
|
||||||
|
|
||||||
// Create the dividers, these hold the seat and back slats
|
// Create the dividers, these hold the seat and back slats
|
||||||
divider("YZ")
|
divider("YZ")
|
@ -1,113 +1,76 @@
|
|||||||
// Shelf Bracket
|
// Shelf Bracket
|
||||||
// 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.
|
// 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.
|
||||||
|
|
||||||
// Set units
|
|
||||||
@settings(defaultLengthUnit = in)
|
|
||||||
|
|
||||||
// Define constants
|
// Define constants
|
||||||
sigmaAllow = 35000 // psi (6061-T6 aluminum)
|
sigmaAllow = 35000 // psi (6061-T6 aluminum)
|
||||||
width = 6
|
width = 6 // inch
|
||||||
p = 300 // Force on shelf - lbs
|
p = 300 // Force on shelf - lbs
|
||||||
factorOfSafety = 1.2 // FOS of 1.2
|
factorOfSafety = 1.2 // FOS of 1.2
|
||||||
shelfMountL = 5
|
shelfMountL = 5 // inches
|
||||||
wallMountL = 2
|
wallMountL = 2 // inches
|
||||||
shelfDepth = 12 // Shelf is 12 inches in depth from the wall
|
shelfDepth = 12 // Shelf is 12 inches in depth from the wall
|
||||||
moment = shelfDepth * p // assume the force is applied at the end of the shelf to be conservative (lb-in)
|
moment = shelfDepth * p // assume the force is applied at the end of the shelf to be conservative (lb-in)
|
||||||
|
|
||||||
|
|
||||||
filletRadius = .375
|
|
||||||
extFilletRadius = .25
|
|
||||||
mountingHoleDiameter = 0.5
|
|
||||||
|
|
||||||
// Calculate required thickness of bracket
|
// Calculate required thickness of bracket
|
||||||
thickness = sqrt(moment * factorOfSafety * 6 / (sigmaAllow * width)) // this is the calculation of two brackets holding up the shelf (inches)
|
thickness = sqrt(moment * factorOfSafety * 6 / (sigmaAllow * width)) // this is the calculation of two brackets holding up the shelf (inches)
|
||||||
|
|
||||||
|
filletRadius = .25
|
||||||
|
extFilletRadius = filletRadius + thickness
|
||||||
|
mountingHoleDiameter = 0.5
|
||||||
|
|
||||||
// Sketch the bracket body and fillet the inner and outer edges of the bend
|
sketch001 = startSketchOn('XZ')
|
||||||
bracketLeg1Sketch = startSketchOn('XY')
|
|
||||||
|> startProfileAt([0, 0], %)
|
|> startProfileAt([0, 0], %)
|
||||||
|> line(end = [shelfMountL - filletRadius, 0], tag = $fillet1)
|
|> xLine(length = shelfMountL - thickness, tag = $seg01)
|
||||||
|> line(end = [0, width], tag = $fillet2)
|
|> yLine(length = thickness, tag = $seg02)
|
||||||
|> line(end = [-shelfMountL + filletRadius, 0])
|
|> xLine(length = -shelfMountL, tag = $seg03)
|
||||||
|
|> yLine(length = -wallMountL, tag = $seg04)
|
||||||
|
|> xLine(length = thickness, tag = $seg05)
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg06)
|
||||||
|> close()
|
|> close()
|
||||||
|> hole(circle(
|
|> extrude(%, length = width)
|
||||||
center = [1, 1],
|
|
||||||
radius = mountingHoleDiameter / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [shelfMountL - 1.5, width - 1],
|
|
||||||
radius = mountingHoleDiameter / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [1, width - 1],
|
|
||||||
radius = mountingHoleDiameter / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [shelfMountL - 1.5, 1],
|
|
||||||
radius = mountingHoleDiameter / 2
|
|
||||||
), %)
|
|
||||||
|
|
||||||
// Extrude the leg 2 bracket sketch
|
|
||||||
bracketLeg1Extrude = extrude(bracketLeg1Sketch, length = thickness)
|
|
||||||
|> fillet(
|
|> fillet(
|
||||||
radius = extFilletRadius,
|
radius = extFilletRadius,
|
||||||
tags = [
|
tags = [getNextAdjacentEdge(seg03)],
|
||||||
getNextAdjacentEdge(fillet1),
|
|
||||||
getNextAdjacentEdge(fillet2)
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sketch the fillet arc
|
|
||||||
filletSketch = startSketchOn('XZ')
|
|
||||||
|> startProfileAt([0, 0], %)
|
|
||||||
|> line(end = [0, thickness])
|
|
||||||
|> arc({
|
|
||||||
angleEnd = 180,
|
|
||||||
angleStart = 90,
|
|
||||||
radius = filletRadius + thickness
|
|
||||||
}, %)
|
|
||||||
|> line(end = [thickness, 0])
|
|
||||||
|> arc({
|
|
||||||
angleEnd = 90,
|
|
||||||
angleStart = 180,
|
|
||||||
radius = filletRadius
|
|
||||||
}, %)
|
|
||||||
|
|
||||||
// Sketch the bend
|
|
||||||
filletExtrude = extrude(filletSketch, length = -width)
|
|
||||||
|
|
||||||
// Create a custom plane for the leg that sits on the wall
|
|
||||||
customPlane = {
|
|
||||||
plane = {
|
|
||||||
origin = { x = -filletRadius, y = 0, z = 0 },
|
|
||||||
xAxis = { x = 0, y = 1, z = 0 },
|
|
||||||
yAxis = { x = 0, y = 0, z = 1 },
|
|
||||||
zAxis = { x = 1, y = 0, z = 0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a sketch for the second leg
|
|
||||||
bracketLeg2Sketch = startSketchOn(customPlane)
|
|
||||||
|> startProfileAt([0, -filletRadius], %)
|
|
||||||
|> line(end = [width, 0])
|
|
||||||
|> line(end = [0, -wallMountL], tag = $fillet3)
|
|
||||||
|> line(end = [-width, 0], tag = $fillet4)
|
|
||||||
|> close()
|
|
||||||
|> hole(circle(
|
|
||||||
center = [1, -1.5],
|
|
||||||
radius = mountingHoleDiameter / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [5, -1.5],
|
|
||||||
radius = mountingHoleDiameter / 2
|
|
||||||
), %)
|
|
||||||
|
|
||||||
// Extrude the second leg
|
|
||||||
bracketLeg2Extrude = extrude(bracketLeg2Sketch, length = -thickness)
|
|
||||||
|> fillet(
|
|> fillet(
|
||||||
radius = extFilletRadius,
|
radius = filletRadius,
|
||||||
tags = [
|
tags = [getNextAdjacentEdge(seg06)],
|
||||||
getNextAdjacentEdge(fillet3),
|
|
||||||
getNextAdjacentEdge(fillet4)
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|> fillet(
|
||||||
|
radius = filletRadius,
|
||||||
|
tags = [seg02, getOppositeEdge(seg02)],
|
||||||
|
)
|
||||||
|
|> fillet(
|
||||||
|
radius = filletRadius,
|
||||||
|
tags = [seg05, getOppositeEdge(seg05)],
|
||||||
|
)
|
||||||
|
|
||||||
|
sketch002 = startSketchOn(sketch001, seg03)
|
||||||
|
|> circle(
|
||||||
|
center = [-1.25, 1],
|
||||||
|
radius = mountingHoleDiameter / 2,
|
||||||
|
)
|
||||||
|
|> patternLinear2d(
|
||||||
|
instances = 2,
|
||||||
|
distance = 2.5,
|
||||||
|
axis = [-1, 0],
|
||||||
|
)
|
||||||
|
|> patternLinear2d(
|
||||||
|
instances = 2,
|
||||||
|
distance = 4,
|
||||||
|
axis = [0, 1],
|
||||||
|
)
|
||||||
|
|> extrude(%, length = -thickness-.01)
|
||||||
|
|
||||||
|
sketch003 = startSketchOn(sketch001, seg04)
|
||||||
|
|> circle(
|
||||||
|
center = [1, -1],
|
||||||
|
radius = mountingHoleDiameter / 2,
|
||||||
|
)
|
||||||
|
|> patternLinear2d(
|
||||||
|
instances = 2,
|
||||||
|
distance = 4,
|
||||||
|
axis = [1, 0],
|
||||||
|
)
|
||||||
|
|> extrude(%, length = -thickness-0.1)
|
||||||
|
@ -9,18 +9,8 @@
|
|||||||
// Import Constants
|
// Import Constants
|
||||||
import caliperTolerance, caliperPadLength, caliperThickness, caliperOuterEdgeRadius, caliperInnerEdgeRadius, rotorDiameter, rotorTotalThickness, yAxisOffset from "globals.kcl"
|
import caliperTolerance, caliperPadLength, caliperThickness, caliperOuterEdgeRadius, caliperInnerEdgeRadius, rotorDiameter, rotorTotalThickness, yAxisOffset from "globals.kcl"
|
||||||
|
|
||||||
// Create the plane for the brake caliper. This is so it can match up with the rotor model.
|
|
||||||
brakeCaliperPlane = {
|
|
||||||
plane = {
|
|
||||||
origin = { x = 0, y = yAxisOffset, z = 0 },
|
|
||||||
xAxis = { x = 1, y = 0, z = 0 },
|
|
||||||
yAxis = { x = 0, y = 1, z = 0 },
|
|
||||||
zAxis = { x = 0, y = 0, z = 1 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sketch the brake caliper profile
|
// Sketch the brake caliper profile
|
||||||
brakeCaliperSketch = startSketchOn(brakeCaliperPlane)
|
brakeCaliperSketch = startSketchOn('XY')
|
||||||
|> startProfileAt([
|
|> startProfileAt([
|
||||||
rotorDiameter / 2 + caliperTolerance,
|
rotorDiameter / 2 + caliperTolerance,
|
||||||
0
|
0
|
||||||
|
@ -9,64 +9,61 @@
|
|||||||
// Import Constants
|
// Import Constants
|
||||||
import rotorDiameter, rotorInnerDiameter, rotorSinglePlateThickness, rotorInnerDiameterThickness, lugHolePatternDia, lugSpacing, rotorTotalThickness, spacerPatternDiameter, spacerDiameter, spacerLength, spacerCount, wheelDiameter, lugCount, yAxisOffset, drillAndSlotCount from "globals.kcl"
|
import rotorDiameter, rotorInnerDiameter, rotorSinglePlateThickness, rotorInnerDiameterThickness, lugHolePatternDia, lugSpacing, rotorTotalThickness, spacerPatternDiameter, spacerDiameter, spacerLength, spacerCount, wheelDiameter, lugCount, yAxisOffset, drillAndSlotCount from "globals.kcl"
|
||||||
|
|
||||||
rotorPlane = {
|
rotorSketch = startSketchOn('XZ')
|
||||||
plane = {
|
|
||||||
origin = { x = 0, y = yAxisOffset, z = 0 },
|
|
||||||
xAxis = { x = -1, y = 0, z = 0 },
|
|
||||||
yAxis = { x = 0, y = 0, z = 1 },
|
|
||||||
zAxis = { x = 0, y = 1, z = 0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn lugPattern(plane) {
|
|
||||||
lugHolePattern = circle(
|
|
||||||
plane,
|
|
||||||
center = [-lugSpacing / 2, 0],
|
|
||||||
radius = 0.315
|
|
||||||
)
|
|
||||||
|> patternCircular2d(
|
|
||||||
arcDegrees = 360,
|
|
||||||
center = [0, 0],
|
|
||||||
instances = lugCount,
|
|
||||||
rotateDuplicates = true
|
|
||||||
)
|
|
||||||
return lugHolePattern
|
|
||||||
}
|
|
||||||
rotorSketch = startSketchOn(rotorPlane)
|
|
||||||
|> circle(
|
|> circle(
|
||||||
center = [0, 0],
|
center = [0, 0],
|
||||||
radius = rotorDiameter / 2
|
radius = rotorDiameter / 2
|
||||||
)
|
)
|
||||||
|> hole(lugPattern(%), %)
|
|
||||||
rotor = extrude(rotorSketch, length = rotorSinglePlateThickness)
|
rotor = extrude(rotorSketch, length = rotorSinglePlateThickness)
|
||||||
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
||||||
rotorBumpSketch = startSketchOn(rotorPlane)
|
|
||||||
|
rotorBumpSketch = startSketchOn(rotor, 'end')
|
||||||
|> circle(
|
|> circle(
|
||||||
center = [0, 0],
|
center = [0, 0],
|
||||||
radius = rotorInnerDiameter / 2
|
radius = rotorInnerDiameter / 2
|
||||||
)
|
)
|
||||||
|> hole(lugPattern(%), %)
|
rotorBump = extrude(rotorBumpSketch, length = rotorInnerDiameterThickness)
|
||||||
rotorBump = extrude(rotorBumpSketch, length = -rotorInnerDiameterThickness)
|
|
||||||
|
lugHoles = startSketchOn(rotorBump, 'end')
|
||||||
|
|> circle(
|
||||||
|
center = [-lugSpacing / 2, 0],
|
||||||
|
radius = 0.315
|
||||||
|
)
|
||||||
|
|> patternCircular2d(
|
||||||
|
arcDegrees = 360,
|
||||||
|
center = [0, 0],
|
||||||
|
instances = lugCount,
|
||||||
|
rotateDuplicates = true
|
||||||
|
)
|
||||||
|
|> extrude(%, length = -(rotorInnerDiameterThickness + rotorSinglePlateThickness))
|
||||||
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
||||||
rotorSecondaryPlatePlane = {
|
|
||||||
plane = {
|
// (update when boolean is available)
|
||||||
origin = {
|
centerSpacer = startSketchOn(rotor, 'start')
|
||||||
x = 0,
|
|> circle(%, center = [0, 0], radius = .25)
|
||||||
y = yAxisOffset + rotorTotalThickness * 0.75,
|
|> extrude(%, length = spacerLength)
|
||||||
z = 0
|
|
||||||
},
|
secondaryRotorSketch = startSketchOn(centerSpacer, 'end')
|
||||||
xAxis = { x = -1, y = 0, z = 0 },
|
|
||||||
yAxis = { x = 0, y = 0, z = 1 },
|
|
||||||
zAxis = { x = 0, y = 1, z = 0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
secondaryRotorSketch = startSketchOn(rotorSecondaryPlatePlane)
|
|
||||||
|> circle(
|
|> circle(
|
||||||
center = [0, 0],
|
center = [0, 0],
|
||||||
radius = rotorDiameter / 2
|
radius = rotorDiameter / 2
|
||||||
)
|
)
|
||||||
|> hole(lugPattern(%), %)
|
|
||||||
secondRotor = extrude(secondaryRotorSketch, length = rotorSinglePlateThickness)
|
secondRotor = extrude(secondaryRotorSketch, length = rotorSinglePlateThickness)
|
||||||
spacerSketch = startSketchOn(rotorSecondaryPlatePlane)
|
|
||||||
|
lugHoles2 = startSketchOn(secondRotor, 'end')
|
||||||
|
|> circle(
|
||||||
|
center = [-lugSpacing / 2, 0],
|
||||||
|
radius = 0.315
|
||||||
|
)
|
||||||
|
|> patternCircular2d(
|
||||||
|
arcDegrees = 360,
|
||||||
|
center = [0, 0],
|
||||||
|
instances = lugCount,
|
||||||
|
rotateDuplicates = true
|
||||||
|
)
|
||||||
|
|> extrude(length = -rotorSinglePlateThickness)
|
||||||
|
|
||||||
|
spacerSketch = startSketchOn(rotor, 'start')
|
||||||
|> circle(
|
|> circle(
|
||||||
center = [spacerPatternDiameter / 2, 0],
|
center = [spacerPatternDiameter / 2, 0],
|
||||||
radius = spacerDiameter
|
radius = spacerDiameter
|
||||||
@ -77,8 +74,8 @@ spacerSketch = startSketchOn(rotorSecondaryPlatePlane)
|
|||||||
instances = spacerCount,
|
instances = spacerCount,
|
||||||
rotateDuplicates = true
|
rotateDuplicates = true
|
||||||
)
|
)
|
||||||
spacers = extrude(spacerSketch, length = -spacerLength)
|
spacers = extrude(spacerSketch, length = spacerLength)
|
||||||
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
|
||||||
rotorSlottedSketch = startSketchOn(rotor, 'START')
|
rotorSlottedSketch = startSketchOn(rotor, 'START')
|
||||||
|> startProfileAt([2.17, 2.56], %)
|
|> startProfileAt([2.17, 2.56], %)
|
||||||
|> xLine(length = 0.12)
|
|> xLine(length = 0.12)
|
||||||
@ -107,5 +104,6 @@ secondRotorSlottedSketch = startSketchOn(secondRotor, 'END')
|
|||||||
arcDegrees = 360,
|
arcDegrees = 360,
|
||||||
rotateDuplicates = true
|
rotateDuplicates = true
|
||||||
)
|
)
|
||||||
secondRotorSlotted = extrude(secondRotorSlottedSketch, length = -rotorSinglePlateThickness / 2)
|
|
||||||
|
extrude(secondRotorSlottedSketch, length = -rotorSinglePlateThickness / 2)
|
||||||
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
|
||||||
|
@ -12,6 +12,7 @@ import 'car-tire.kcl' as carTire
|
|||||||
import lugCount from 'globals.kcl'
|
import lugCount from 'globals.kcl'
|
||||||
|
|
||||||
carRotor
|
carRotor
|
||||||
|
|> translate(translate = [0, 0.5, 0])
|
||||||
carWheel
|
carWheel
|
||||||
lugNut
|
lugNut
|
||||||
|> patternCircular3d(
|
|> patternCircular3d(
|
||||||
@ -22,4 +23,5 @@ lugNut
|
|||||||
rotateDuplicates = false
|
rotateDuplicates = false
|
||||||
)
|
)
|
||||||
brakeCaliper
|
brakeCaliper
|
||||||
|
|> translate(translate = [0, 0.5, 0])
|
||||||
carTire
|
carTire
|
||||||
|
@ -1,87 +0,0 @@
|
|||||||
// Flange with XY coordinates
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
// Set units
|
|
||||||
@settings(defaultLengthUnit = in)
|
|
||||||
|
|
||||||
// Define constants
|
|
||||||
mountingHoleDia = .625
|
|
||||||
baseDia = 4.625
|
|
||||||
pipeDia = 1.25
|
|
||||||
thickness = .625
|
|
||||||
totalThickness = 0.813
|
|
||||||
topTotalDiameter = 2.313
|
|
||||||
bottomThickness = 0.06
|
|
||||||
bottomTotalDiameter = 2.5
|
|
||||||
mountingHolePlacementDiameter = 3.5
|
|
||||||
baseThickness = .625
|
|
||||||
topTotalThickness = totalThickness - (bottomThickness + baseThickness)
|
|
||||||
holeLocator = baseDia - 8
|
|
||||||
nHoles = 4
|
|
||||||
|
|
||||||
// Add assertion so nHoles are always greater than 1
|
|
||||||
assertGreaterThan(nHoles, 1, "nHoles must be greater than 1")
|
|
||||||
|
|
||||||
// Create the flange base and the six mounting holes
|
|
||||||
flangeBase = startSketchOn('XY')
|
|
||||||
|> circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = baseDia / 2
|
|
||||||
)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [mountingHolePlacementDiameter / 2, 0],
|
|
||||||
radius = mountingHoleDia / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [0, mountingHolePlacementDiameter / 2],
|
|
||||||
radius = mountingHoleDia / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [-mountingHolePlacementDiameter / 2, 0],
|
|
||||||
radius = mountingHoleDia / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [0, -mountingHolePlacementDiameter / 2],
|
|
||||||
radius = mountingHoleDia / 2
|
|
||||||
), %)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = pipeDia / 2
|
|
||||||
), %)
|
|
||||||
|> extrude(length = baseThickness)
|
|
||||||
|
|
||||||
// Plane for top face
|
|
||||||
topFacePlane = {
|
|
||||||
plane = {
|
|
||||||
origin = { x = 0, y = 0, z = baseThickness },
|
|
||||||
xAxis = { x = 1, y = 0, z = 0 },
|
|
||||||
yAxis = { x = 0, y = 1, z = 0 },
|
|
||||||
zAxis = { x = 0, y = 0, z = 1 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the extrusion on the top of the flange base
|
|
||||||
topExtrusion = startSketchOn(topFacePlane, 'end')
|
|
||||||
|> circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = topTotalDiameter / 2
|
|
||||||
)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = pipeDia / 2
|
|
||||||
), %)
|
|
||||||
|> extrude(length = topTotalThickness)
|
|
||||||
|
|
||||||
// Create the extrusion on the bottom of the flange base
|
|
||||||
bottomExtrusion = startSketchOn("XY")
|
|
||||||
|> circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = bottomTotalDiameter / 2
|
|
||||||
)
|
|
||||||
|> hole(circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = pipeDia / 2
|
|
||||||
), %)
|
|
||||||
|> extrude(length = -bottomThickness)
|
|
||||||
|
|
||||||
// https://www.mcmaster.com/44685K193/
|
|
@ -8,7 +8,6 @@
|
|||||||
mountingHoleDia = .625
|
mountingHoleDia = .625
|
||||||
baseDia = 4.625
|
baseDia = 4.625
|
||||||
pipeDia = 1.25
|
pipeDia = 1.25
|
||||||
thickness = .625
|
|
||||||
totalThickness = 0.813
|
totalThickness = 0.813
|
||||||
topTotalDiameter = 2.313
|
topTotalDiameter = 2.313
|
||||||
bottomThickness = 0.06
|
bottomThickness = 0.06
|
||||||
@ -16,7 +15,6 @@ bottomTotalDiameter = 2.5
|
|||||||
mountingHolePlacementDiameter = 3.5
|
mountingHolePlacementDiameter = 3.5
|
||||||
baseThickness = .625
|
baseThickness = .625
|
||||||
topTotalThickness = totalThickness - (bottomThickness + baseThickness)
|
topTotalThickness = totalThickness - (bottomThickness + baseThickness)
|
||||||
holeLocator = baseDia - 8
|
|
||||||
nHoles = 4
|
nHoles = 4
|
||||||
|
|
||||||
// Add assertion so nHoles are always greater than 1
|
// Add assertion so nHoles are always greater than 1
|
||||||
@ -42,42 +40,25 @@ flangeBase = startSketchOn('XY')
|
|||||||
radius = baseDia / 2
|
radius = baseDia / 2
|
||||||
)
|
)
|
||||||
|> hole(circles, %)
|
|> hole(circles, %)
|
||||||
|> hole(circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = pipeDia / 2
|
|
||||||
), %)
|
|
||||||
|> extrude(length = baseThickness)
|
|> extrude(length = baseThickness)
|
||||||
|
|
||||||
// Plane for top face
|
|
||||||
topFacePlane = {
|
|
||||||
plane = {
|
|
||||||
origin = { x = 0, y = 0, z = baseThickness },
|
|
||||||
xAxis = { x = 1, y = 0, z = 0 },
|
|
||||||
yAxis = { x = 0, y = 1, z = 0 },
|
|
||||||
zAxis = { x = 0, y = 0, z = 1 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the extrusion on the top of the flange base
|
// Create the extrusion on the top of the flange base
|
||||||
topExtrusion = startSketchOn(topFacePlane)
|
topExtrusion = startSketchOn(flangeBase, 'end')
|
||||||
|> circle(
|
|> circle(
|
||||||
center = [0, 0],
|
center = [0, 0],
|
||||||
radius = topTotalDiameter / 2
|
radius = topTotalDiameter / 2
|
||||||
)
|
)
|
||||||
|> hole(circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = pipeDia / 2
|
|
||||||
), %)
|
|
||||||
|> extrude(length = topTotalThickness)
|
|> extrude(length = topTotalThickness)
|
||||||
|
|
||||||
// Create the extrusion on the bottom of the flange base
|
// Create the extrusion on the bottom of the flange base
|
||||||
bottomExtrusion = startSketchOn("XY")
|
bottomExtrusion = startSketchOn(flangeBase, 'start')
|
||||||
|> circle(
|
|> circle(
|
||||||
center = [0, 0],
|
center = [0, 0],
|
||||||
radius = bottomTotalDiameter / 2
|
radius = bottomTotalDiameter / 2
|
||||||
)
|
)
|
||||||
|> hole(circle(
|
|> extrude(length = bottomThickness)
|
||||||
center = [0, 0],
|
|
||||||
radius = pipeDia / 2
|
// Cut a hole through the entire body
|
||||||
), %)
|
pipeHole = startSketchOn(topExtrusion, 'end')
|
||||||
|> extrude(length = -bottomThickness)
|
|> circle(center = [0, 0], radius = pipeDia/2)
|
||||||
|
|> extrude(%, length = -(topTotalThickness + baseThickness + bottomThickness))
|
@ -5,8 +5,8 @@
|
|||||||
@settings(defaultLengthUnit = in)
|
@settings(defaultLengthUnit = in)
|
||||||
|
|
||||||
// Define constants
|
// Define constants
|
||||||
lbumps = 5 // number of bumps long
|
lbumps = 10 // number of bumps long
|
||||||
wbumps = 3 // number of bumps wide
|
wbumps = 5 // number of bumps wide
|
||||||
pitch = 8.0
|
pitch = 8.0
|
||||||
clearance = 0.1
|
clearance = 0.1
|
||||||
bumpDiam = 4.8
|
bumpDiam = 4.8
|
||||||
@ -25,28 +25,8 @@ wSegments = totalWidth / wbumps
|
|||||||
assertGreaterThan(lbumps, 1, "lbumps must be greater than 1")
|
assertGreaterThan(lbumps, 1, "lbumps must be greater than 1")
|
||||||
assertGreaterThan(wbumps, 1, "wbumps must be greater than 1")
|
assertGreaterThan(wbumps, 1, "wbumps must be greater than 1")
|
||||||
|
|
||||||
// Create the plane for the pegs. This is a hack so that the pegs can be patterned along the face of the lego base.
|
|
||||||
pegFace = {
|
|
||||||
plane = {
|
|
||||||
origin = { x = 0, y = 0, z = height },
|
|
||||||
xAxis = { x = 1, y = 0, z = 0 },
|
|
||||||
yAxis = { x = 0, y = 1, z = 0 },
|
|
||||||
zAxis = { x = 0, y = 0, z = 1 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the plane for the tubes underneath the lego. This is a hack so that the tubes can be patterned underneath the lego.
|
|
||||||
tubeFace = {
|
|
||||||
plane = {
|
|
||||||
origin = { x = 0, y = 0, z = height - t },
|
|
||||||
xAxis = { x = 1, y = 0, z = 0 },
|
|
||||||
yAxis = { x = 0, y = 1, z = 0 },
|
|
||||||
zAxis = { x = 0, y = 0, z = 1 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the base
|
// Make the base
|
||||||
s = startSketchOn('XY')
|
base = startSketchOn('XY')
|
||||||
|> startProfileAt([-totalWidth / 2, -totalLength / 2], %)
|
|> startProfileAt([-totalWidth / 2, -totalLength / 2], %)
|
||||||
|> line(end = [totalWidth, 0])
|
|> line(end = [totalWidth, 0])
|
||||||
|> line(end = [0, totalLength])
|
|> line(end = [0, totalLength])
|
||||||
@ -54,8 +34,8 @@ s = startSketchOn('XY')
|
|||||||
|> close()
|
|> close()
|
||||||
|> extrude(length = height)
|
|> extrude(length = height)
|
||||||
|
|
||||||
// Sketch and extrude a rectangular shape to create the shell underneath the lego. This is a hack until we have a shell function.
|
// Sketch and extrude a rectangular shape to create the shell underneath the lego. Will replace with shell function when able to call a face created from shell.
|
||||||
shellExtrude = startSketchOn(s, "start")
|
shellExtrude = startSketchOn(base, "start")
|
||||||
|> startProfileAt([
|
|> startProfileAt([
|
||||||
-(totalWidth / 2 - t),
|
-(totalWidth / 2 - t),
|
||||||
-(totalLength / 2 - t)
|
-(totalLength / 2 - t)
|
||||||
@ -67,7 +47,7 @@ shellExtrude = startSketchOn(s, "start")
|
|||||||
|> extrude(length = -(height - t))
|
|> extrude(length = -(height - t))
|
||||||
|
|
||||||
// Create the pegs on the top of the base
|
// Create the pegs on the top of the base
|
||||||
peg = startSketchOn(s, 'end')
|
peg = startSketchOn(base, 'end')
|
||||||
|> circle(
|
|> circle(
|
||||||
center = [
|
center = [
|
||||||
-(pitch * (wbumps - 1) / 2),
|
-(pitch * (wbumps - 1) / 2),
|
||||||
@ -88,7 +68,7 @@ peg = startSketchOn(s, 'end')
|
|||||||
|> extrude(length = bumpHeight)
|
|> extrude(length = bumpHeight)
|
||||||
|
|
||||||
// Create the pegs on the bottom of the base
|
// Create the pegs on the bottom of the base
|
||||||
tubePattern = startSketchOn(tubeFace)
|
tubePattern = startSketchOn(shellExtrude, 'start')
|
||||||
|> circle(
|
|> circle(
|
||||||
center = [
|
center = [
|
||||||
-(pitch * (wbumps - 1) / 2 - (pitch / 2)),
|
-(pitch * (wbumps - 1) / 2 - (pitch / 2)),
|
||||||
@ -106,4 +86,4 @@ tubePattern = startSketchOn(tubeFace)
|
|||||||
instances = lbumps - 1,
|
instances = lbumps - 1,
|
||||||
distance = pitch
|
distance = pitch
|
||||||
)
|
)
|
||||||
|> extrude(length = -bumpHeight)
|
|> extrude(length = bumpHeight)
|
||||||
|
@ -1,11 +1,4 @@
|
|||||||
[
|
[
|
||||||
{
|
|
||||||
"file": "main.kcl",
|
|
||||||
"pathFromProjectDirectoryToFirstFile": "3d-boaty/main.kcl",
|
|
||||||
"multipleFiles": true,
|
|
||||||
"title": "3D Boaty",
|
|
||||||
"description": "This is a slight remix of Depep1's original 3D Boaty (https://www.printables.com/model/1141963-3d-boaty). This is a tool used for benchmarking 3D FDM printers for bed adhesion, overhangs, bridging and top surface quality. The name of this file is a bit of misnomer, the shape of the object is a typical park bench."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "80-20-rail/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "80-20-rail/main.kcl",
|
||||||
@ -27,6 +20,13 @@
|
|||||||
"title": "Ball Bearing",
|
"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."
|
"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": "main.kcl",
|
||||||
|
"pathFromProjectDirectoryToFirstFile": "bench/main.kcl",
|
||||||
|
"multipleFiles": true,
|
||||||
|
"title": "Bench",
|
||||||
|
"description": "This is a slight remix of Depep1's original 3D Boaty (https://www.printables.com/model/1141963-3d-boaty). This is a tool used for benchmarking 3D FDM printers for bed adhesion, overhangs, bridging and top surface quality. The name of this file is a bit of misnomer, the shape of the object is a typical park bench."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"file": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "bracket/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "bracket/main.kcl",
|
||||||
@ -78,18 +78,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "flange-with-patterns/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "flange/main.kcl",
|
||||||
"multipleFiles": false,
|
"multipleFiles": false,
|
||||||
"title": "Flange",
|
"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."
|
"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": "main.kcl",
|
|
||||||
"pathFromProjectDirectoryToFirstFile": "flange-xy/main.kcl",
|
|
||||||
"multipleFiles": false,
|
|
||||||
"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": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "focusrite-scarlett-mounting-bracket/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "focusrite-scarlett-mounting-bracket/main.kcl",
|
||||||
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 215 KiB After Width: | Height: | Size: 216 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 116 KiB |
BIN
public/kcl-samples/screenshots/flange.png
Normal file
After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 96 KiB |
@ -1,7 +1,7 @@
|
|||||||
ISO-10303-21;
|
ISO-10303-21;
|
||||||
HEADER;
|
HEADER;
|
||||||
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
||||||
FILE_NAME('test.step', '2021-01-01T00:00:00Z', ('Test'), ('Zoo'), 'zoo.dev beta', 'zoo.dev', 'Test');
|
FILE_NAME('dump.step', '2021-01-01T00:00:00+00:00', ('Author unknown'), ('Organization unknown'), 'zoo.dev beta', 'zoo.dev', 'Authorization unknown');
|
||||||
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
||||||
ENDSEC;
|
ENDSEC;
|
||||||
DATA;
|
DATA;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
ISO-10303-21;
|
ISO-10303-21;
|
||||||
HEADER;
|
HEADER;
|
||||||
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
||||||
FILE_NAME('test.step', '2021-01-01T00:00:00Z', ('Test'), ('Zoo'), 'zoo.dev beta', 'zoo.dev', 'Test');
|
FILE_NAME('dump.step', '2021-01-01T00:00:00+00:00', ('Author unknown'), ('Organization unknown'), 'zoo.dev beta', 'zoo.dev', 'Authorization unknown');
|
||||||
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
||||||
ENDSEC;
|
ENDSEC;
|
||||||
DATA;
|
DATA;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
ISO-10303-21;
|
ISO-10303-21;
|
||||||
HEADER;
|
HEADER;
|
||||||
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
||||||
FILE_NAME('test.step', '2021-01-01T00:00:00Z', ('Test'), ('Zoo'), 'zoo.dev beta', 'zoo.dev', 'Test');
|
FILE_NAME('dump.step', '2021-01-01T00:00:00+00:00', ('Author unknown'), ('Organization unknown'), 'zoo.dev beta', 'zoo.dev', 'Authorization unknown');
|
||||||
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
||||||
ENDSEC;
|
ENDSEC;
|
||||||
DATA;
|
DATA;
|
||||||
|
11603
public/kcl-samples/step/bench.step
Normal file
@ -1,7 +1,7 @@
|
|||||||
ISO-10303-21;
|
ISO-10303-21;
|
||||||
HEADER;
|
HEADER;
|
||||||
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
||||||
FILE_NAME('test.step', '2021-01-01T00:00:00Z', ('Test'), ('Zoo'), 'zoo.dev beta', 'zoo.dev', 'Test');
|
FILE_NAME('dump.step', '2021-01-01T00:00:00+00:00', ('Author unknown'), ('Organization unknown'), 'zoo.dev beta', 'zoo.dev', 'Authorization unknown');
|
||||||
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
||||||
ENDSEC;
|
ENDSEC;
|
||||||
DATA;
|
DATA;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
ISO-10303-21;
|
ISO-10303-21;
|
||||||
HEADER;
|
HEADER;
|
||||||
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
||||||
FILE_NAME('test.step', '2021-01-01T00:00:00Z', ('Test'), ('Zoo'), 'zoo.dev beta', 'zoo.dev', 'Test');
|
FILE_NAME('dump.step', '2021-01-01T00:00:00+00:00', ('Author unknown'), ('Organization unknown'), 'zoo.dev beta', 'zoo.dev', 'Authorization unknown');
|
||||||
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
||||||
ENDSEC;
|
ENDSEC;
|
||||||
DATA;
|
DATA;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
ISO-10303-21;
|
ISO-10303-21;
|
||||||
HEADER;
|
HEADER;
|
||||||
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
||||||
FILE_NAME('test.step', '2021-01-01T00:00:00Z', ('Test'), ('Zoo'), 'zoo.dev beta', 'zoo.dev', 'Test');
|
FILE_NAME('dump.step', '2021-01-01T00:00:00+00:00', ('Author unknown'), ('Organization unknown'), 'zoo.dev beta', 'zoo.dev', 'Authorization unknown');
|
||||||
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
||||||
ENDSEC;
|
ENDSEC;
|
||||||
DATA;
|
DATA;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
ISO-10303-21;
|
ISO-10303-21;
|
||||||
HEADER;
|
HEADER;
|
||||||
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
FILE_DESCRIPTION((('zoo.dev export')), '2;1');
|
||||||
FILE_NAME('test.step', '2021-01-01T00:00:00Z', ('Test'), ('Zoo'), 'zoo.dev beta', 'zoo.dev', 'Test');
|
FILE_NAME('dump.step', '2021-01-01T00:00:00+00:00', ('Author unknown'), ('Organization unknown'), 'zoo.dev beta', 'zoo.dev', 'Authorization unknown');
|
||||||
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
FILE_SCHEMA(('AP203_CONFIGURATION_CONTROLLED_3D_DESIGN_OF_MECHANICAL_PARTS_AND_ASSEMBLIES_MIM_LF'));
|
||||||
ENDSEC;
|
ENDSEC;
|
||||||
DATA;
|
DATA;
|
||||||
|