merge main
12
.github/ci-cd-scripts/playwright-electron.sh
vendored
@ -7,11 +7,11 @@ if [[ ! -f "test-results/.last-run.json" ]]; then
|
||||
# If no last run artifact, than run Playwright normally
|
||||
echo "run playwright normally"
|
||||
if [[ "$3" == *ubuntu* ]]; then
|
||||
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test:playwright:electron -- --shard=$1/$2 || true
|
||||
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test:e2e:desktop -- --shard=$1/$2 || true
|
||||
elif [[ "$3" == *windows* ]]; then
|
||||
npm run test:playwright:electron -- --grep=@windows --shard=$1/$2 || true
|
||||
npm run test:e2e:desktop -- --grep=@windows --shard=$1/$2 || true
|
||||
elif [[ "$3" == *macos* ]]; then
|
||||
npm run test:playwright:electron -- --grep=@macos --shard=$1/$2 || true
|
||||
npm run test:e2e:desktop -- --grep=@macos --shard=$1/$2 || true
|
||||
else
|
||||
echo "Do not run Playwright. Unable to detect os runtime."
|
||||
exit 1
|
||||
@ -31,11 +31,11 @@ while [[ $retry -le $max_retries ]]; do
|
||||
echo "retried=true" >>$GITHUB_OUTPUT
|
||||
echo "run playwright with last failed tests and retry $retry"
|
||||
if [[ "$3" == *ubuntu* ]]; then
|
||||
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test:playwright:electron -- --last-failed || true
|
||||
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run test:e2e:desktop -- --last-failed || true
|
||||
elif [[ "$3" == *windows* ]]; then
|
||||
npm run test:playwright:electron -- --grep=@windows --last-failed || true
|
||||
npm run test:e2e:desktop -- --grep=@windows --last-failed || true
|
||||
elif [[ "$3" == *macos* ]]; then
|
||||
npm run test:playwright:electron -- --grep=@macos --last-failed || true
|
||||
npm run test:e2e:desktop -- --grep=@macos --last-failed || true
|
||||
else
|
||||
echo "Do not run playwright. Unable to detect os runtime."
|
||||
exit 1
|
||||
|
853
.github/dependabot.yml
vendored
33
.github/workflows/e2e-tests.yml
vendored
@ -20,9 +20,11 @@ permissions:
|
||||
jobs:
|
||||
|
||||
prepare-wasm:
|
||||
|
||||
# separate job on Ubuntu to build or fetch the wasm blob once on the fastest runner
|
||||
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- id: filter
|
||||
@ -103,9 +105,10 @@ jobs:
|
||||
needs: [prepare-wasm]
|
||||
|
||||
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
||||
name: playwright:snapshots:ubuntu
|
||||
name: e2e:snapshots
|
||||
|
||||
steps:
|
||||
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
@ -135,7 +138,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Cache browsers
|
||||
- name: Download browser cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
@ -145,7 +148,7 @@ jobs:
|
||||
- name: Install browsers
|
||||
run: npm run playwright install --with-deps
|
||||
|
||||
- name: Test snapshots
|
||||
- name: npm run test:snapshots
|
||||
uses: nick-fields/retry@v3.0.2
|
||||
with:
|
||||
shell: bash
|
||||
@ -214,8 +217,12 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
include:
|
||||
- os: "runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64"
|
||||
- os: namespace-profile-macos-8-cores
|
||||
- os: windows-latest-8-cores
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: e2e:web (${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }})
|
||||
env:
|
||||
OS_NAME: ${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }}
|
||||
|
||||
@ -250,7 +257,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
- name: Cache browsers
|
||||
- name: Download browser cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
@ -267,7 +274,7 @@ jobs:
|
||||
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
||||
OS_NAME: ${{ env.OS_NAME }}
|
||||
|
||||
- name: Test web
|
||||
- name: npm run test:e2e:web
|
||||
uses: nick-fields/retry@v3.0.2
|
||||
with:
|
||||
shell: bash
|
||||
@ -336,7 +343,7 @@ jobs:
|
||||
shardIndex: 2
|
||||
shardTotal: 2
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: playwright:electron:${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }} (shard ${{ matrix.shardIndex }})
|
||||
name: e2e:desktop (${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }}, shard ${{ matrix.shardIndex }})
|
||||
env:
|
||||
OS_NAME: ${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }}
|
||||
|
||||
@ -346,7 +353,7 @@ jobs:
|
||||
- uses: actions/download-artifact@v4
|
||||
name: prepared-wasm
|
||||
|
||||
- name: Copy prepared wasm
|
||||
- name: Copy prepared Wasm
|
||||
run: |
|
||||
ls -R prepared-wasm
|
||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||
@ -362,7 +369,7 @@ jobs:
|
||||
id: deps-install
|
||||
run: npm install
|
||||
|
||||
- name: Cache browsers
|
||||
- name: Download browser cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
@ -372,9 +379,6 @@ jobs:
|
||||
- name: Install browsers
|
||||
run: npm run playwright install --with-deps
|
||||
|
||||
- name: Build web
|
||||
run: npm run tronb:vite:dev
|
||||
|
||||
- name: Start Vector
|
||||
if: ${{ !contains(matrix.os, 'windows') }}
|
||||
run: .github/ci-cd-scripts/start-vector-${{ env.OS_NAME }}.sh
|
||||
@ -382,6 +386,9 @@ jobs:
|
||||
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
||||
OS_NAME: ${{ env.OS_NAME }}
|
||||
|
||||
- name: Build app
|
||||
run: npm run tronb:vite:dev
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
if: ${{ !cancelled() && (success() || failure()) }}
|
||||
continue-on-error: true
|
||||
@ -389,7 +396,7 @@ jobs:
|
||||
name: test-results-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||
path: test-results/
|
||||
|
||||
- name: Run playwright/electron flow (with retries)
|
||||
- name: npm run test:e2e:desktop
|
||||
id: retry
|
||||
if: ${{ !cancelled() && steps.deps-install.outcome == 'success' }}
|
||||
uses: nick-fields/retry@v3.0.2
|
||||
|
@ -213,14 +213,21 @@ npm run test:snapshots
|
||||
```
|
||||
You may use `-- --update-snapshots` as needed.
|
||||
|
||||
#### Electron flow tests (Chromium on Ubuntu, macOS, Windows)
|
||||
#### Desktop tests (Electron on all platforms)
|
||||
|
||||
```
|
||||
npm run playwright -- install chromium
|
||||
npm run test:playwright:electron:local
|
||||
npm run test:e2e:desktop:local
|
||||
```
|
||||
|
||||
You may use `-- -g "my test"` to match specific test titles, or `-- path/to/file.spec.ts` for a test file.
|
||||
|
||||
#### Web tests (Google Chrome on all platforms)
|
||||
|
||||
```
|
||||
npm run test:e2e:web
|
||||
```
|
||||
|
||||
#### Debugger
|
||||
|
||||
However, if you want a debugger I recommend using VSCode and the `playwright` extension, as the above command is a cruder debugger that steps into every function call which is annoying.
|
||||
|
4
Makefile
@ -129,9 +129,9 @@ endif
|
||||
.PHONY: test-e2e-desktop
|
||||
test-e2e-desktop: install build ## Run the desktop e2e tests
|
||||
ifdef E2E_GREP
|
||||
npm run test:playwright:electron -- --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES)
|
||||
npm run test:e2e:desktop -- --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES)
|
||||
else
|
||||
npm run test:playwright:electron -- --workers='100%'
|
||||
npm run test:e2e:desktop -- --workers='100%'
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
|
@ -1,24 +1,23 @@
|
||||
---
|
||||
title: "appearance::hexString"
|
||||
subtitle: "Function in std::appearance"
|
||||
excerpt: ""
|
||||
excerpt: "Build a color from its red, green and blue components. These must be between 0 and 255."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
|
||||
Build a color from its red, green and blue components. These must be between 0 and 255.
|
||||
|
||||
```kcl
|
||||
appearance::hexString(@rgb: [number(_); 3]): string
|
||||
```
|
||||
|
||||
Build a color from its red, green and blue components.
|
||||
These must be between 0 and 255.
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `rgb` | [`[number(_); 3]`](/docs/kcl-std/types/std-types-number) | | Yes |
|
||||
| `rgb` | [`[number(_); 3]`](/docs/kcl-std/types/std-types-number) | The red, blue and green components of the color. Must be between 0 and 255. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "reduce"
|
||||
subtitle: "Function in std::array"
|
||||
excerpt: ""
|
||||
excerpt: "Take a starting value. Then, for each element of an array, calculate the next value, using the previous value and the element."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
|
||||
Take a starting value. Then, for each element of an array, calculate the next value, using the previous value and the element.
|
||||
|
||||
```kcl
|
||||
reduce(
|
||||
@ -15,8 +15,7 @@ reduce(
|
||||
): any
|
||||
```
|
||||
|
||||
Take a starting value. Then, for each element of an array, calculate the next value,
|
||||
using the previous value and the element.
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
@ -28,7 +27,7 @@ using the previous value and the element.
|
||||
|
||||
### Returns
|
||||
|
||||
[`any`](/docs/kcl-std/types/std-types-any)
|
||||
[`any`](/docs/kcl-std/types/std-types-any) - The [`any`](/docs/kcl-std/types/std-types-any) type is the type of all possible values in KCL. I.e., if a function accepts an argument with type [`any`](/docs/kcl-std/types/std-types-any), then it can accept any value.
|
||||
|
||||
|
||||
### Examples
|
||||
|
49
docs/kcl-std/functions/std-assert.md
Normal file
@ -0,0 +1,49 @@
|
||||
---
|
||||
title: "assert"
|
||||
subtitle: "Function in std"
|
||||
excerpt: "Check a value meets some expected conditions at runtime. Program terminates with an error if conditions aren't met. If you provide multiple conditions, they will all be checked and all must be met."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Check a value meets some expected conditions at runtime. Program terminates with an error if conditions aren't met. If you provide multiple conditions, they will all be checked and all must be met.
|
||||
|
||||
```kcl
|
||||
assert(
|
||||
@actual: number,
|
||||
isGreaterThan?: number,
|
||||
isLessThan?: number,
|
||||
isGreaterThanOrEqual?: number,
|
||||
isLessThanOrEqual?: number,
|
||||
isEqualTo?: number,
|
||||
tolerance?: number,
|
||||
error?: string,
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `actual` | [`number`](/docs/kcl-std/types/std-types-number) | Value to check. If this is the boolean value true, assert passes. Otherwise it fails.. | Yes |
|
||||
| `isGreaterThan` | [`number`](/docs/kcl-std/types/std-types-number) | Comparison argument. If given, checks the `actual` value is greater than this. | No |
|
||||
| `isLessThan` | [`number`](/docs/kcl-std/types/std-types-number) | Comparison argument. If given, checks the `actual` value is less than this. | No |
|
||||
| `isGreaterThanOrEqual` | [`number`](/docs/kcl-std/types/std-types-number) | Comparison argument. If given, checks the `actual` value is greater than or equal to this. | No |
|
||||
| `isLessThanOrEqual` | [`number`](/docs/kcl-std/types/std-types-number) | Comparison argument. If given, checks the `actual` value is less than or equal to this. | No |
|
||||
| `isEqualTo` | [`number`](/docs/kcl-std/types/std-types-number) | Comparison argument. If given, checks the `actual` value is less than or equal to this. | No |
|
||||
| `tolerance` | [`number`](/docs/kcl-std/types/std-types-number) | If `isEqualTo` is used, this is the tolerance to allow for the comparison. This tolerance is used because KCL's number system has some floating-point imprecision when used with very large decimal places. | No |
|
||||
| `error` | [`string`](/docs/kcl-std/types/std-types-string) | If the value was false, the program will terminate with this error message | No |
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```kcl
|
||||
n = 10
|
||||
assert(n, isEqualTo = 10)
|
||||
assert(n, isGreaterThanOrEqual = 0, isLessThan = 100, error = "number should be between 0 and 100")
|
||||
assert(1.0000000000012, isEqualTo = 1, tolerance = 0.0001, error = "number should be almost exactly 1")
|
||||
```
|
||||
|
||||
|
||||
|
35
docs/kcl-std/functions/std-assertIs.md
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
title: "assertIs"
|
||||
subtitle: "Function in std"
|
||||
excerpt: "Asserts that a value is the boolean value true."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Asserts that a value is the boolean value true.
|
||||
|
||||
```kcl
|
||||
assertIs(
|
||||
@actual: bool,
|
||||
error?: string,
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `actual` | [`bool`](/docs/kcl-std/types/std-types-bool) | Value to check. If this is the boolean value true, assert passes. Otherwise it fails.. | Yes |
|
||||
| `error` | [`string`](/docs/kcl-std/types/std-types-string) | If the value was false, the program will terminate with this error message | No |
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
```kcl
|
||||
kclIsFun = true
|
||||
assertIs(kclIsFun)
|
||||
```
|
||||
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "polar"
|
||||
subtitle: "Function in std::math"
|
||||
excerpt: ""
|
||||
excerpt: "Convert polar/sphere (azimuth, elevation, distance) coordinates to cartesian (x/y/z grid) coordinates."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
|
||||
Convert polar/sphere (azimuth, elevation, distance) coordinates to cartesian (x/y/z grid) coordinates.
|
||||
|
||||
```kcl
|
||||
polar(
|
||||
@ -14,8 +14,7 @@ polar(
|
||||
): Point2d
|
||||
```
|
||||
|
||||
Convert polar/sphere (azimuth, elevation, distance) coordinates to
|
||||
cartesian (x/y/z grid) coordinates.
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "rem"
|
||||
subtitle: "Function in std::math"
|
||||
excerpt: ""
|
||||
excerpt: "Compute the remainder after dividing `num` by `div`. If `num` is negative, the result will be too."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
|
||||
Compute the remainder after dividing `num` by `div`. If `num` is negative, the result will be too.
|
||||
|
||||
```kcl
|
||||
rem(
|
||||
@ -14,8 +14,7 @@ rem(
|
||||
): number
|
||||
```
|
||||
|
||||
Compute the remainder after dividing `num` by `div`.
|
||||
If `num` is negative, the result will be too.
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
|
@ -10,13 +10,13 @@ Draw a line segment relative to the current origin using the polar measure of so
|
||||
```kcl
|
||||
angledLine(
|
||||
@sketch: Sketch,
|
||||
angle: number,
|
||||
length?: number,
|
||||
lengthX?: number,
|
||||
lengthY?: number,
|
||||
endAbsoluteX?: number,
|
||||
endAbsoluteY?: number,
|
||||
tag?: TagDeclarator,
|
||||
angle: number(Angle),
|
||||
length?: number(Length),
|
||||
lengthX?: number(Length),
|
||||
lengthY?: number(Length),
|
||||
endAbsoluteX?: number(Length),
|
||||
endAbsoluteY?: number(Length),
|
||||
tag?: tag,
|
||||
): Sketch
|
||||
```
|
||||
|
||||
@ -27,13 +27,13 @@ angledLine(
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
||||
| `angle` | [`number`](/docs/kcl-std/types/std-types-number) | Which angle should the line be drawn at? | Yes |
|
||||
| `length` | [`number`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the given angle. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
|
||||
| `lengthX` | [`number`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
|
||||
| `lengthY` | [`number`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
|
||||
| `endAbsoluteX` | [`number`](/docs/kcl-std/types/std-types-number) | Draw the line along the given angle until it reaches this point along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
|
||||
| `endAbsoluteY` | [`number`](/docs/kcl-std/types/std-types-number) | Draw the line along the given angle until it reaches this point along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
|
||||
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Which angle should the line be drawn at? | Yes |
|
||||
| `length` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the given angle. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
|
||||
| `lengthX` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
|
||||
| `lengthY` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Draw the line this distance along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
|
||||
| `endAbsoluteX` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Draw the line along the given angle until it reaches this point along the X axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
|
||||
| `endAbsoluteY` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Draw the line along the given angle until it reaches this point along the Y axis. Only one of `length`, `lengthX`, `lengthY`, `endAbsoluteX`, `endAbsoluteY` can be given. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this line. | No |
|
||||
|
||||
### Returns
|
||||
|
||||
@ -46,7 +46,10 @@ angledLine(
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> yLine(endAbsolute = 15)
|
||||
|> angledLine(angle = 30, length = 15)
|
||||
|> angledLine(
|
||||
angle = 30,
|
||||
length = 15,
|
||||
)
|
||||
|> line(end = [8, -10])
|
||||
|> yLine(endAbsolute = 0)
|
||||
|> close()
|
@ -10,10 +10,10 @@ Draw an angled line from the current origin, constructing a line segment such th
|
||||
```kcl
|
||||
angledLineThatIntersects(
|
||||
@sketch: Sketch,
|
||||
angle: number,
|
||||
intersectTag: TagIdentifier,
|
||||
offset?: number,
|
||||
tag?: TagDeclarator,
|
||||
angle: number(Angle),
|
||||
intersectTag: tag,
|
||||
offset?: number(Length),
|
||||
tag?: tag,
|
||||
): Sketch
|
||||
```
|
||||
|
||||
@ -24,10 +24,10 @@ angledLineThatIntersects(
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
||||
| `angle` | [`number`](/docs/kcl-std/types/std-types-number) | Which angle should the line be drawn at? | Yes |
|
||||
| `intersectTag` | [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier) | The tag of the line to intersect with | Yes |
|
||||
| `offset` | [`number`](/docs/kcl-std/types/std-types-number) | The offset from the intersecting line. Defaults to 0. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
|
||||
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Which angle should the line be drawn at? | Yes |
|
||||
| `intersectTag` | [`tag`](/docs/kcl-std/types/std-types-tag) | The tag of the line to intersect with. | Yes |
|
||||
| `offset` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The offset from the intersecting line. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this line. | No |
|
||||
|
||||
### Returns
|
||||
|
||||
@ -42,7 +42,11 @@ exampleSketch = startSketchOn(XZ)
|
||||
|> line(endAbsolute = [5, 10])
|
||||
|> line(endAbsolute = [-10, 10], tag = $lineToIntersect)
|
||||
|> line(endAbsolute = [0, 20])
|
||||
|> angledLineThatIntersects(angle = 80, intersectTag = lineToIntersect, offset = 10)
|
||||
|> angledLineThatIntersects(
|
||||
angle = 80,
|
||||
intersectTag = lineToIntersect,
|
||||
offset = 10,
|
||||
)
|
||||
|> close()
|
||||
|
||||
example = extrude(exampleSketch, length = 10)
|
@ -10,30 +10,37 @@ Draw a curved line segment along an imaginary circle.
|
||||
```kcl
|
||||
arc(
|
||||
@sketch: Sketch,
|
||||
angleStart?: number,
|
||||
angleEnd?: number,
|
||||
radius?: number,
|
||||
angleStart?: number(Angle),
|
||||
angleEnd?: number(Angle),
|
||||
radius?: number(Length),
|
||||
diameter?: number(Length),
|
||||
interiorAbsolute?: Point2d,
|
||||
endAbsolute?: Point2d,
|
||||
tag?: TagDeclarator,
|
||||
tag?: tag,
|
||||
): Sketch
|
||||
```
|
||||
|
||||
The arc is constructed such that the current position of the sketch is placed along an imaginary circle of the specified radius, at angleStart degrees. The resulting arc is the segment of the imaginary circle from that origin point to angleEnd, radius away from the center of the imaginary circle.
|
||||
The arc is constructed such that the current position of the sketch is
|
||||
placed along an imaginary circle of the specified radius, at angleStart
|
||||
degrees. The resulting arc is the segment of the imaginary circle from
|
||||
that origin point to angleEnd, radius away from the center of the imaginary
|
||||
circle.
|
||||
|
||||
Unless this makes a lot of sense and feels like what you're looking for to construct your shape, you're likely looking for tangentialArc.
|
||||
Unless this makes a lot of sense and feels like what you're looking
|
||||
for to construct your shape, you're likely looking for tangentialArc.
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
||||
| `angleStart` | [`number`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc start? | No |
|
||||
| `angleEnd` | [`number`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc end? | No |
|
||||
| `radius` | [`number`](/docs/kcl-std/types/std-types-number) | How large should the circle be? | No |
|
||||
| `interiorAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Any point between the arc's start and end? Requires `endAbsolute`. Incompatible with `angleStart` or `angleEnd` | No |
|
||||
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Where should this arc end? Requires `interiorAbsolute`. Incompatible with `angleStart` or `angleEnd` | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
|
||||
| `angleStart` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc start? | No |
|
||||
| `angleEnd` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Where along the circle should this arc end? | No |
|
||||
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | How large should the circle be? Incompatible with `diameter`. | No |
|
||||
| `diameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | How large should the circle be? Incompatible with `radius`. | No |
|
||||
| `interiorAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Any point between the arc's start and end? Requires `endAbsolute`. Incompatible with `angleStart` or `angleEnd`. | No |
|
||||
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Where should this arc end? Requires `interiorAbsolute`. Incompatible with `angleStart` or `angleEnd`. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this arc. | No |
|
||||
|
||||
### Returns
|
||||
|
||||
@ -46,7 +53,11 @@ Unless this makes a lot of sense and feels like what you're looking for to const
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> line(end = [10, 0])
|
||||
|> arc(angleStart = 0, angleEnd = 280, radius = 16)
|
||||
|> arc(
|
||||
angleStart = 0,
|
||||
angleEnd = 280,
|
||||
radius = 16
|
||||
)
|
||||
|> close()
|
||||
example = extrude(exampleSketch, length = 10)
|
||||
```
|
||||
@ -56,7 +67,10 @@ example = extrude(exampleSketch, length = 10)
|
||||
```kcl
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> arc(endAbsolute = [10, 0], interiorAbsolute = [5, 5])
|
||||
|> arc(
|
||||
endAbsolute = [10,0],
|
||||
interiorAbsolute = [5,5]
|
||||
)
|
||||
|> close()
|
||||
example = extrude(exampleSketch, length = 10)
|
||||
```
|
74
docs/kcl-std/functions/std-sketch-bezierCurve.md
Normal file
@ -1,15 +1,15 @@
|
||||
---
|
||||
title: "circle"
|
||||
subtitle: "Function in std::sketch"
|
||||
excerpt: ""
|
||||
excerpt: "Construct a 2-dimensional circle, of the specified radius, centered at the provided (x, y) origin point."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
|
||||
Construct a 2-dimensional circle, of the specified radius, centered at the provided (x, y) origin point.
|
||||
|
||||
```kcl
|
||||
circle(
|
||||
@sketch_or_surface: Sketch | Plane | Face,
|
||||
@sketchOrSurface: Sketch | Plane | Face,
|
||||
center: Point2d,
|
||||
radius?: number(Length),
|
||||
diameter?: number(Length),
|
||||
@ -17,14 +17,13 @@ circle(
|
||||
): Sketch
|
||||
```
|
||||
|
||||
Construct a 2-dimensional circle, of the specified radius, centered at
|
||||
the provided (x, y) origin point.
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketch_or_surface` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
|
||||
| `sketchOrSurface` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
|
||||
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center of the circle. | Yes |
|
||||
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The radius of the circle. Incompatible with `diameter`. | No |
|
||||
| `diameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The diameter of the circle. Incompatible with `radius`. | No |
|
||||
|
@ -9,11 +9,11 @@ Construct a circle derived from 3 points.
|
||||
|
||||
```kcl
|
||||
circleThreePoint(
|
||||
@sketchSurfaceOrGroup: Sketch | Plane | Face,
|
||||
@sketchOrSurface: Sketch | Plane | Face,
|
||||
p1: Point2d,
|
||||
p2: Point2d,
|
||||
p3: Point2d,
|
||||
tag?: TagDeclarator,
|
||||
tag?: tag,
|
||||
): Sketch
|
||||
```
|
||||
|
||||
@ -23,11 +23,11 @@ circleThreePoint(
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketchSurfaceOrGroup` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Plane or surface to sketch on. | Yes |
|
||||
| `sketchOrSurface` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Plane or surface to sketch on. | Yes |
|
||||
| `p1` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | 1st point to derive the circle. | Yes |
|
||||
| `p2` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | 2nd point to derive the circle. | Yes |
|
||||
| `p3` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | 3rd point to derive the circle. | Yes |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Identifier for the circle to reference elsewhere. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Identifier for the circle to reference elsewhere. | No |
|
||||
|
||||
### Returns
|
||||
|
||||
@ -38,7 +38,7 @@ circleThreePoint(
|
||||
|
||||
```kcl
|
||||
exampleSketch = startSketchOn(XY)
|
||||
|> circleThreePoint(p1 = [10, 10], p2 = [20, 8], p3 = [15, 5])
|
||||
|> circleThreePoint(p1 = [10,10], p2 = [20,8], p3 = [15,5])
|
||||
|> extrude(length = 5)
|
||||
```
|
||||
|
@ -9,31 +9,32 @@ Extend a 2-dimensional sketch through a third dimension in order to create new 3
|
||||
|
||||
```kcl
|
||||
extrude(
|
||||
@sketches: [Sketch],
|
||||
length: number,
|
||||
@sketches: [Sketch; 1+],
|
||||
length: number(Length),
|
||||
symmetric?: bool,
|
||||
bidirectionalLength?: number,
|
||||
tagStart?: TagDeclarator,
|
||||
tagEnd?: TagDeclarator,
|
||||
): [Solid]
|
||||
bidirectionalLength?: number(Length),
|
||||
tagStart?: tag,
|
||||
tagEnd?: tag,
|
||||
): [Solid; 1+]
|
||||
```
|
||||
|
||||
You can provide more than one sketch to extrude, and they will all be extruded in the same direction.
|
||||
You can provide more than one sketch to extrude, and they will all be
|
||||
extruded in the same direction.
|
||||
|
||||
### Arguments
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketches` | [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) | Which sketch or sketches should be extruded | Yes |
|
||||
| `length` | [`number`](/docs/kcl-std/types/std-types-number) | How far to extrude the given sketches | Yes |
|
||||
| `sketches` | [`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch) | Which sketch or sketches should be extruded. | Yes |
|
||||
| `length` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | How far to extrude the given sketches. | Yes |
|
||||
| `symmetric` | [`bool`](/docs/kcl-std/types/std-types-bool) | If true, the extrusion will happen symmetrically around the sketch. Otherwise, the extrusion will happen on only one side of the sketch. | No |
|
||||
| `bidirectionalLength` | [`number`](/docs/kcl-std/types/std-types-number) | If specified, will also extrude in the opposite direction to 'distance' to the specified distance. If 'symmetric' is true, this value is ignored. | No |
|
||||
| `tagStart` | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | A named tag for the face at the start of the extrusion, i.e. the original sketch | No |
|
||||
| `tagEnd` | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | A named tag for the face at the end of the extrusion, i.e. the new face created by extruding the original sketch | No |
|
||||
| `bidirectionalLength` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | If specified, will also extrude in the opposite direction to 'distance' to the specified distance. If 'symmetric' is true, this value is ignored. | No |
|
||||
| `tagStart` | [`tag`](/docs/kcl-std/types/std-types-tag) | A named tag for the face at the start of the extrusion, i.e. the original sketch. | No |
|
||||
| `tagEnd` | [`tag`](/docs/kcl-std/types/std-types-tag) | A named tag for the face at the end of the extrusion, i.e. the new face created by extruding the original sketch. | No |
|
||||
|
||||
### Returns
|
||||
|
||||
[`[Solid]`](/docs/kcl-std/types/std-types-Solid)
|
||||
[`[Solid; 1+]`](/docs/kcl-std/types/std-types-Solid)
|
||||
|
||||
|
||||
### Examples
|
||||
@ -42,10 +43,18 @@ You can provide more than one sketch to extrude, and they will all be extruded i
|
||||
example = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> line(end = [10, 0])
|
||||
|> arc(angleStart = 120, angleEnd = 0, radius = 5)
|
||||
|> arc(
|
||||
angleStart = 120,
|
||||
angleEnd = 0,
|
||||
radius = 5,
|
||||
)
|
||||
|> line(end = [5, 0])
|
||||
|> line(end = [0, 10])
|
||||
|> bezierCurve(control1 = [-10, 0], control2 = [2, 10], end = [-5, 10])
|
||||
|> bezierCurve(
|
||||
control1 = [-10, 0],
|
||||
control2 = [2, 10],
|
||||
end = [-5, 10],
|
||||
)
|
||||
|> line(end = [-5, -2])
|
||||
|> close()
|
||||
|> extrude(length = 10)
|
||||
@ -56,10 +65,18 @@ example = startSketchOn(XZ)
|
||||
```kcl
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [-10, 0])
|
||||
|> arc(angleStart = 120, angleEnd = -60, radius = 5)
|
||||
|> arc(
|
||||
angleStart = 120,
|
||||
angleEnd = -60,
|
||||
radius = 5,
|
||||
)
|
||||
|> line(end = [10, 0])
|
||||
|> line(end = [5, 0])
|
||||
|> bezierCurve(control1 = [-3, 0], control2 = [2, 10], end = [-5, 10])
|
||||
|> bezierCurve(
|
||||
control1 = [-3, 0],
|
||||
control2 = [2, 10],
|
||||
end = [-5, 10],
|
||||
)
|
||||
|> line(end = [-4, 10])
|
||||
|> line(end = [-5, -2])
|
||||
|> close()
|
||||
@ -72,10 +89,18 @@ example = extrude(exampleSketch, length = 10)
|
||||
```kcl
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [-10, 0])
|
||||
|> arc(angleStart = 120, angleEnd = -60, radius = 5)
|
||||
|> arc(
|
||||
angleStart = 120,
|
||||
angleEnd = -60,
|
||||
radius = 5,
|
||||
)
|
||||
|> line(end = [10, 0])
|
||||
|> line(end = [5, 0])
|
||||
|> bezierCurve(control1 = [-3, 0], control2 = [2, 10], end = [-5, 10])
|
||||
|> bezierCurve(
|
||||
control1 = [-3, 0],
|
||||
control2 = [2, 10],
|
||||
end = [-5, 10],
|
||||
)
|
||||
|> line(end = [-4, 10])
|
||||
|> line(end = [-5, -2])
|
||||
|> close()
|
||||
@ -88,10 +113,18 @@ example = extrude(exampleSketch, length = 20, symmetric = true)
|
||||
```kcl
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [-10, 0])
|
||||
|> arc(angleStart = 120, angleEnd = -60, radius = 5)
|
||||
|> arc(
|
||||
angleStart = 120,
|
||||
angleEnd = -60,
|
||||
radius = 5,
|
||||
)
|
||||
|> line(end = [10, 0])
|
||||
|> line(end = [5, 0])
|
||||
|> bezierCurve(control1 = [-3, 0], control2 = [2, 10], end = [-5, 10])
|
||||
|> bezierCurve(
|
||||
control1 = [-3, 0],
|
||||
control2 = [2, 10],
|
||||
end = [-5, 10],
|
||||
)
|
||||
|> line(end = [-4, 10])
|
||||
|> line(end = [-5, -2])
|
||||
|> close()
|
@ -8,7 +8,7 @@ layout: manual
|
||||
Get the shared edge between two faces.
|
||||
|
||||
```kcl
|
||||
getCommonEdge(faces: [TagIdentifier]): Uuid
|
||||
getCommonEdge(faces: [tag; 2]): Edge
|
||||
```
|
||||
|
||||
|
||||
@ -17,11 +17,11 @@ getCommonEdge(faces: [TagIdentifier]): Uuid
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `faces` | [`[TagIdentifier]`](/docs/kcl-lang/types#TagIdentifier) | The tags of the faces you want to find the common edge between | Yes |
|
||||
| `faces` | `[tag; 2]` | The tags of the faces you want to find the common edge between. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
`Uuid`
|
||||
[`Edge`](/docs/kcl-std/types/std-types-Edge) - An edge of a solid.
|
||||
|
||||
|
||||
### Examples
|
||||
@ -29,17 +29,16 @@ getCommonEdge(faces: [TagIdentifier]): Uuid
|
||||
```kcl
|
||||
// Get an edge shared between two faces, created after a chamfer.
|
||||
|
||||
|
||||
scale = 20
|
||||
part001 = startSketchOn(XY)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> line(end = [0, scale])
|
||||
|> line(end = [scale, 0])
|
||||
|> line(end = [0, -scale])
|
||||
|> close(tag = $line0)
|
||||
|> extrude(length = 20, tagEnd = $end0)
|
||||
// We tag the chamfer to reference it later.
|
||||
|> chamfer(length = 10, tags = [getOppositeEdge(line0)], tag = $chamfer0)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> line(end = [0, scale])
|
||||
|> line(end = [scale, 0])
|
||||
|> line(end = [0, -scale])
|
||||
|> close(tag = $line0)
|
||||
|> extrude(length = 20, tagEnd = $end0)
|
||||
// We tag the chamfer to reference it later.
|
||||
|> chamfer(length = 10, tags = [getOppositeEdge(line0)], tag = $chamfer0)
|
||||
|
||||
// Get the shared edge between the chamfer and the extrusion.
|
||||
commonEdge = getCommonEdge(faces = [chamfer0, end0])
|
@ -8,7 +8,7 @@ layout: manual
|
||||
Extract the 'x' axis value of the last line segment in the provided 2-d sketch.
|
||||
|
||||
```kcl
|
||||
lastSegX(@sketch: Sketch): number
|
||||
lastSegX(@sketch: Sketch): number(Length)
|
||||
```
|
||||
|
||||
|
||||
@ -17,11 +17,11 @@ lastSegX(@sketch: Sketch): number
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | The sketch whose line segment is being queried | Yes |
|
||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | The sketch whose line segment is being queried. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
[`number(Length)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
@ -8,7 +8,7 @@ layout: manual
|
||||
Extract the 'y' axis value of the last line segment in the provided 2-d sketch.
|
||||
|
||||
```kcl
|
||||
lastSegY(@sketch: Sketch): number
|
||||
lastSegY(@sketch: Sketch): number(Length)
|
||||
```
|
||||
|
||||
|
||||
@ -17,11 +17,11 @@ lastSegY(@sketch: Sketch): number
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | The sketch whose line segment is being queried | Yes |
|
||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | The sketch whose line segment is being queried. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
[`number(Length)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
@ -12,7 +12,7 @@ line(
|
||||
@sketch: Sketch,
|
||||
endAbsolute?: Point2d,
|
||||
end?: Point2d,
|
||||
tag?: TagDeclarator,
|
||||
tag?: tag,
|
||||
): Sketch
|
||||
```
|
||||
|
||||
@ -25,7 +25,7 @@ line(
|
||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
||||
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Which absolute point should this line go to? Incompatible with `end`. | No |
|
||||
| `end` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | How far away (along the X and Y axes) should this line go? Incompatible with `endAbsolute`. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this line. | No |
|
||||
|
||||
### Returns
|
||||
|
@ -9,13 +9,13 @@ Repeat a 2-dimensional sketch some number of times along a partial or complete c
|
||||
|
||||
```kcl
|
||||
patternCircular2d(
|
||||
@sketchSet: [Sketch],
|
||||
instances: number,
|
||||
@sketches: [Sketch; 1+],
|
||||
instances: number(_),
|
||||
center: Point2d,
|
||||
arcDegrees?: number,
|
||||
arcDegrees?: number(Angle),
|
||||
rotateDuplicates?: bool,
|
||||
useOriginal?: bool,
|
||||
): [Sketch]
|
||||
): [Sketch; 1+]
|
||||
```
|
||||
|
||||
|
||||
@ -24,16 +24,16 @@ patternCircular2d(
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketchSet` | [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) | Which sketch(es) to pattern | Yes |
|
||||
| `instances` | [`number`](/docs/kcl-std/types/std-types-number) | 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 |
|
||||
| `sketches` | [`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch) | The sketch(es) to duplicate. | Yes |
|
||||
| `instances` | [`number(_)`](/docs/kcl-std/types/std-types-number) | 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` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center about which to make the pattern. This is a 2D vector. | Yes |
|
||||
| `arcDegrees` | [`number`](/docs/kcl-std/types/std-types-number) | The arc angle (in degrees) to place the repetitions. Must be greater than 0. Defaults to 360. | No |
|
||||
| `rotateDuplicates` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether or not to rotate the duplicates as they are copied. Defaults to true. | No |
|
||||
| `useOriginal` | [`bool`](/docs/kcl-std/types/std-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 |
|
||||
| `arcDegrees` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | The arc angle (in degrees) to place the repetitions. Must be greater than 0. | No |
|
||||
| `rotateDuplicates` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether or not to rotate the duplicates as they are copied. | No |
|
||||
| `useOriginal` | [`bool`](/docs/kcl-std/types/std-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. | No |
|
||||
|
||||
### Returns
|
||||
|
||||
[`[Sketch]`](/docs/kcl-std/types/std-types-Sketch)
|
||||
[`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch)
|
||||
|
||||
|
||||
### Examples
|
||||
@ -49,7 +49,7 @@ exampleSketch = startSketchOn(XZ)
|
||||
center = [0, 0],
|
||||
instances = 13,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true,
|
||||
rotateDuplicates = true
|
||||
)
|
||||
|
||||
example = extrude(exampleSketch, length = 1)
|
@ -9,9 +9,9 @@ Create a regular polygon with the specified number of sides that is either inscr
|
||||
|
||||
```kcl
|
||||
polygon(
|
||||
@sketchSurfaceOrGroup: Sketch | Plane | Face,
|
||||
radius: number,
|
||||
numSides: u64,
|
||||
@sketchOrSurface: Sketch | Plane | Face,
|
||||
radius: number(Length),
|
||||
numSides: number(_),
|
||||
center: Point2d,
|
||||
inscribed?: bool,
|
||||
): Sketch
|
||||
@ -23,11 +23,11 @@ polygon(
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketchSurfaceOrGroup` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Plane or surface to sketch on | Yes |
|
||||
| `radius` | [`number`](/docs/kcl-std/types/std-types-number) | The radius of the polygon | Yes |
|
||||
| `numSides` | `u64` | The number of sides in the polygon | Yes |
|
||||
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center point of the polygon | Yes |
|
||||
| `inscribed` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether the polygon is inscribed (true, the default) or circumscribed (false) about a circle with the specified radius | No |
|
||||
| `sketchOrSurface` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) or [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | Plane or surface to sketch on. | Yes |
|
||||
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The radius of the polygon. | Yes |
|
||||
| `numSides` | [`number(_)`](/docs/kcl-std/types/std-types-number) | The number of sides in the polygon. | Yes |
|
||||
| `center` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | The center point of the polygon. | Yes |
|
||||
| `inscribed` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether the polygon is inscribed (true, the default) or circumscribed (false) about a circle with the specified radius. | No |
|
||||
|
||||
### Returns
|
||||
|
||||
@ -40,11 +40,11 @@ polygon(
|
||||
// Create a regular hexagon inscribed in a circle of radius 10
|
||||
hex = startSketchOn(XY)
|
||||
|> polygon(
|
||||
radius = 10,
|
||||
numSides = 6,
|
||||
center = [0, 0],
|
||||
inscribed = true,
|
||||
)
|
||||
radius = 10,
|
||||
numSides = 6,
|
||||
center = [0, 0],
|
||||
inscribed = true,
|
||||
)
|
||||
|
||||
example = extrude(hex, length = 5)
|
||||
```
|
||||
@ -55,11 +55,11 @@ example = extrude(hex, length = 5)
|
||||
// Create a square circumscribed around a circle of radius 5
|
||||
square = startSketchOn(XY)
|
||||
|> polygon(
|
||||
radius = 5.0,
|
||||
numSides = 4,
|
||||
center = [10, 10],
|
||||
inscribed = false,
|
||||
)
|
||||
radius = 5.0,
|
||||
numSides = 4,
|
||||
center = [10, 10],
|
||||
inscribed = false,
|
||||
)
|
||||
example = extrude(square, length = 5)
|
||||
```
|
||||
|
@ -8,7 +8,7 @@ layout: manual
|
||||
Compute the angle (in degrees) of the provided line segment.
|
||||
|
||||
```kcl
|
||||
segAng(@tag: TagIdentifier): number
|
||||
segAng(@tag: tag): number(Angle)
|
||||
```
|
||||
|
||||
|
||||
@ -17,11 +17,11 @@ segAng(@tag: TagIdentifier): number
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier) | The line segment being queried by its tag | Yes |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | The line segment being queried by its tag. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
[`number(Angle)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
@ -8,7 +8,7 @@ layout: manual
|
||||
Compute the ending point of the provided line segment.
|
||||
|
||||
```kcl
|
||||
segEnd(@tag: TagIdentifier): Point2d
|
||||
segEnd(@tag: tag): Point2d
|
||||
```
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ segEnd(@tag: TagIdentifier): Point2d
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier) | The line segment being queried by its tag | Yes |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | The line segment being queried by its tag. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
@ -39,9 +39,9 @@ cube = startSketchOn(XY)
|
||||
|
||||
fn cylinder(radius, tag) {
|
||||
return startSketchOn(XY)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> circle(radius = radius, center = segEnd(tag))
|
||||
|> extrude(length = radius)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> circle(radius = radius, center = segEnd(tag) )
|
||||
|> extrude(length = radius)
|
||||
}
|
||||
|
||||
cylinder(radius = 1, tag = line1)
|
@ -8,7 +8,7 @@ layout: manual
|
||||
Compute the ending point of the provided line segment along the 'x' axis.
|
||||
|
||||
```kcl
|
||||
segEndX(@tag: TagIdentifier): number
|
||||
segEndX(@tag: tag): number(Length)
|
||||
```
|
||||
|
||||
|
||||
@ -17,11 +17,11 @@ segEndX(@tag: TagIdentifier): number
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier) | The line segment being queried by its tag | Yes |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | The line segment being queried by its tag. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
[`number(Length)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
@ -8,7 +8,7 @@ layout: manual
|
||||
Compute the ending point of the provided line segment along the 'y' axis.
|
||||
|
||||
```kcl
|
||||
segEndY(@tag: TagIdentifier): number
|
||||
segEndY(@tag: tag): number(Length)
|
||||
```
|
||||
|
||||
|
||||
@ -17,11 +17,11 @@ segEndY(@tag: TagIdentifier): number
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier) | The line segment being queried by its tag | Yes |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | The line segment being queried by its tag. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
[`number(Length)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
@ -8,7 +8,7 @@ layout: manual
|
||||
Compute the length of the provided line segment.
|
||||
|
||||
```kcl
|
||||
segLen(@tag: TagIdentifier): number
|
||||
segLen(@tag: tag): number(Length)
|
||||
```
|
||||
|
||||
|
||||
@ -17,11 +17,11 @@ segLen(@tag: TagIdentifier): number
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier) | The line segment being queried by its tag | Yes |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | The line segment being queried by its tag. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
[`number(Length)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
||||
@ -29,9 +29,16 @@ segLen(@tag: TagIdentifier): number
|
||||
```kcl
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> angledLine(angle = 60, length = 10, tag = $thing)
|
||||
|> angledLine(
|
||||
angle = 60,
|
||||
length = 10,
|
||||
tag = $thing,
|
||||
)
|
||||
|> tangentialArc(angle = -120, radius = 5)
|
||||
|> angledLine(angle = -60, length = segLen(thing))
|
||||
|> angledLine(
|
||||
angle = -60,
|
||||
length = segLen(thing),
|
||||
)
|
||||
|> close()
|
||||
|
||||
example = extrude(exampleSketch, length = 5)
|
@ -8,7 +8,7 @@ layout: manual
|
||||
Compute the starting point of the provided line segment.
|
||||
|
||||
```kcl
|
||||
segStart(@tag: TagIdentifier): Point2d
|
||||
segStart(@tag: tag): Point2d
|
||||
```
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ segStart(@tag: TagIdentifier): Point2d
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier) | The line segment being queried by its tag | Yes |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | The line segment being queried by its tag. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
@ -39,9 +39,9 @@ cube = startSketchOn(XY)
|
||||
|
||||
fn cylinder(radius, tag) {
|
||||
return startSketchOn(XY)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> circle(radius = radius, center = segStart(tag))
|
||||
|> extrude(length = radius)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> circle( radius = radius, center = segStart(tag) )
|
||||
|> extrude(length = radius)
|
||||
}
|
||||
|
||||
cylinder(radius = 1, tag = line1)
|
@ -8,7 +8,7 @@ layout: manual
|
||||
Compute the starting point of the provided line segment along the 'x' axis.
|
||||
|
||||
```kcl
|
||||
segStartX(@tag: TagIdentifier): number
|
||||
segStartX(@tag: tag): number(Length)
|
||||
```
|
||||
|
||||
|
||||
@ -17,11 +17,11 @@ segStartX(@tag: TagIdentifier): number
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier) | The line segment being queried by its tag | Yes |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | The line segment being queried by its tag. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
[`number(Length)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
@ -8,7 +8,7 @@ layout: manual
|
||||
Compute the starting point of the provided line segment along the 'y' axis.
|
||||
|
||||
```kcl
|
||||
segStartY(@tag: TagIdentifier): number
|
||||
segStartY(@tag: tag): number(Length)
|
||||
```
|
||||
|
||||
|
||||
@ -17,11 +17,11 @@ segStartY(@tag: TagIdentifier): number
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier) | The line segment being queried by its tag | Yes |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | The line segment being queried by its tag. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
[`number(Length)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
||||
@ -32,7 +32,7 @@ exampleSketch = startSketchOn(XZ)
|
||||
|> line(end = [20, 0])
|
||||
|> line(end = [0, 3], tag = $thing)
|
||||
|> line(end = [-10, 0])
|
||||
|> line(end = [0, 20 - segStartY(thing)])
|
||||
|> line(end = [0, 20-segStartY(thing)])
|
||||
|> line(end = [-10, 0])
|
||||
|> close()
|
||||
|
@ -9,9 +9,9 @@ Start a new profile at a given point.
|
||||
|
||||
```kcl
|
||||
startProfile(
|
||||
@sketchSurface: Plane | Face,
|
||||
@startProfileOn: Plane | Face,
|
||||
at: Point2d,
|
||||
tag?: TagDeclarator,
|
||||
tag?: tag,
|
||||
): Sketch
|
||||
```
|
||||
|
||||
@ -21,9 +21,9 @@ startProfile(
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketchSurface` | [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | What to start the profile on | Yes |
|
||||
| `startProfileOn` | [`Plane`](/docs/kcl-std/types/std-types-Plane) or [`Face`](/docs/kcl-std/types/std-types-Face) | What to start the profile on. | Yes |
|
||||
| `at` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Where to start the profile. An absolute point. | Yes |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Tag this first starting point | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Tag this first starting point. | No |
|
||||
|
||||
### Returns
|
||||
|
67
docs/kcl-std/functions/std-sketch-subtract2d.md
Normal file
@ -8,7 +8,7 @@ layout: manual
|
||||
Returns the angle coming out of the end of the segment in degrees.
|
||||
|
||||
```kcl
|
||||
tangentToEnd(@tag: TagIdentifier): number
|
||||
tangentToEnd(@tag: tag): number(Angle)
|
||||
```
|
||||
|
||||
|
||||
@ -17,11 +17,11 @@ tangentToEnd(@tag: TagIdentifier): number
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier) | The line segment being queried by its tag | Yes |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | The line segment being queried by its tag. | Yes |
|
||||
|
||||
### Returns
|
||||
|
||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
[`number(Angle)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||
|
||||
|
||||
### Examples
|
||||
@ -32,7 +32,10 @@ pillSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> line(end = [20, 0])
|
||||
|> tangentialArc(end = [0, 10], tag = $arc1)
|
||||
|> angledLine(angle = tangentToEnd(arc1), length = 20)
|
||||
|> angledLine(
|
||||
angle = tangentToEnd(arc1),
|
||||
length = 20,
|
||||
)
|
||||
|> tangentialArc(end = [0, -10])
|
||||
|> close()
|
||||
|
||||
@ -47,7 +50,10 @@ pillSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> line(end = [0, 20])
|
||||
|> tangentialArc(endAbsolute = [10, 20], tag = $arc1)
|
||||
|> angledLine(angle = tangentToEnd(arc1), length = 20)
|
||||
|> angledLine(
|
||||
angle = tangentToEnd(arc1),
|
||||
length = 20,
|
||||
)
|
||||
|> tangentialArc(end = [-10, 0])
|
||||
|> close()
|
||||
|
||||
@ -60,7 +66,10 @@ pillExtrude = extrude(pillSketch, length = 10)
|
||||
rectangleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> line(end = [10, 0], tag = $seg1)
|
||||
|> angledLine(angle = tangentToEnd(seg1), length = 10)
|
||||
|> angledLine(
|
||||
angle = tangentToEnd(seg1),
|
||||
length = 10,
|
||||
)
|
||||
|> line(end = [0, 10])
|
||||
|> line(end = [-20, 0])
|
||||
|> close()
|
||||
@ -73,7 +82,11 @@ rectangleExtrude = extrude(rectangleSketch, length = 10)
|
||||
```kcl
|
||||
bottom = startSketchOn(XY)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> arc(endAbsolute = [10, 10], interiorAbsolute = [5, 1], tag = $arc1)
|
||||
|> arc(
|
||||
endAbsolute = [10, 10],
|
||||
interiorAbsolute = [5, 1],
|
||||
tag = $arc1,
|
||||
)
|
||||
|> angledLine(angle = tangentToEnd(arc1), length = 20)
|
||||
|> close()
|
||||
```
|
||||
@ -82,7 +95,7 @@ bottom = startSketchOn(XY)
|
||||
|
||||
```kcl
|
||||
circSketch = startSketchOn(XY)
|
||||
|> circle(center = [0, 0], radius = 3, tag = $circ)
|
||||
|> circle(center = [0, 0], radius= 3, tag = $circ)
|
||||
|
||||
triangleSketch = startSketchOn(XY)
|
||||
|> startProfile(at = [-5, 0])
|
@ -12,13 +12,18 @@ tangentialArc(
|
||||
@sketch: Sketch,
|
||||
endAbsolute?: Point2d,
|
||||
end?: Point2d,
|
||||
radius?: number,
|
||||
angle?: number,
|
||||
tag?: TagDeclarator,
|
||||
radius?: number(Length),
|
||||
diameter?: number(Length),
|
||||
angle?: number(Angle),
|
||||
tag?: tag,
|
||||
): Sketch
|
||||
```
|
||||
|
||||
When using radius and angle, draw a curved line segment along part of an imaginary circle. The arc is constructed such that the last line segment is placed tangent to the imaginary circle of the specified radius. The resulting arc is the segment of the imaginary circle from that tangent point for 'angle' degrees along the imaginary circle.
|
||||
When using radius and angle, draw a curved line segment along part of an
|
||||
imaginary circle. The arc is constructed such that the last line segment is
|
||||
placed tangent to the imaginary circle of the specified radius. The
|
||||
resulting arc is the segment of the imaginary circle from that tangent point
|
||||
for 'angle' degrees along the imaginary circle.
|
||||
|
||||
### Arguments
|
||||
|
||||
@ -27,9 +32,10 @@ When using radius and angle, draw a curved line segment along part of an imagina
|
||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
||||
| `endAbsolute` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | Which absolute point should this arc go to? Incompatible with `end`, `radius`, and `offset`. | No |
|
||||
| `end` | [`Point2d`](/docs/kcl-std/types/std-types-Point2d) | How far away (along the X and Y axes) should this arc go? Incompatible with `endAbsolute`, `radius`, and `offset`. | No |
|
||||
| `radius` | [`number`](/docs/kcl-std/types/std-types-number) | Radius of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute`. | No |
|
||||
| `angle` | [`number`](/docs/kcl-std/types/std-types-number) | Offset of the arc in degrees. `radius` must be given. Incompatible with `end` and `endAbsolute`. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this arc | No |
|
||||
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Radius of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `diameter`. | No |
|
||||
| `diameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Diameter of the imaginary circle. `angle` must be given. Incompatible with `end` and `endAbsolute` and `radius`. | No |
|
||||
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Offset of the arc. `radius` must be given. Incompatible with `end` and `endAbsolute`. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this arc. | No |
|
||||
|
||||
### Returns
|
||||
|
||||
@ -41,7 +47,10 @@ When using radius and angle, draw a curved line segment along part of an imagina
|
||||
```kcl
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> angledLine(angle = 45, length = 10)
|
||||
|> angledLine(
|
||||
angle = 45,
|
||||
length = 10,
|
||||
)
|
||||
|> tangentialArc(end = [0, -10])
|
||||
|> line(end = [-10, 0])
|
||||
|> close()
|
||||
@ -54,7 +63,10 @@ example = extrude(exampleSketch, length = 10)
|
||||
```kcl
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> angledLine(angle = 60, length = 10)
|
||||
|> angledLine(
|
||||
angle = 60,
|
||||
length = 10,
|
||||
)
|
||||
|> tangentialArc(endAbsolute = [15, 15])
|
||||
|> line(end = [10, -15])
|
||||
|> close()
|
||||
@ -67,9 +79,15 @@ example = extrude(exampleSketch, length = 10)
|
||||
```kcl
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> angledLine(angle = 60, length = 10)
|
||||
|> angledLine(
|
||||
angle = 60,
|
||||
length = 10,
|
||||
)
|
||||
|> tangentialArc(radius = 10, angle = -120)
|
||||
|> angledLine(angle = -60, length = 10)
|
||||
|> angledLine(
|
||||
angle = -60,
|
||||
length = 10,
|
||||
)
|
||||
|> close()
|
||||
|
||||
example = extrude(exampleSketch, length = 10)
|
@ -10,9 +10,9 @@ Draw a line relative to the current origin to a specified distance away from the
|
||||
```kcl
|
||||
xLine(
|
||||
@sketch: Sketch,
|
||||
length?: number,
|
||||
endAbsolute?: number,
|
||||
tag?: TagDeclarator,
|
||||
length?: number(Length),
|
||||
endAbsolute?: number(Length),
|
||||
tag?: tag,
|
||||
): Sketch
|
||||
```
|
||||
|
||||
@ -23,9 +23,9 @@ xLine(
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
||||
| `length` | [`number`](/docs/kcl-std/types/std-types-number) | How far away along the X axis should this line go? Incompatible with `endAbsolute`. | No |
|
||||
| `endAbsolute` | [`number`](/docs/kcl-std/types/std-types-number) | Which absolute X value should this line go to? Incompatible with `length`. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
|
||||
| `length` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | How far away along the X axis should this line go? Incompatible with `endAbsolute`. | No |
|
||||
| `endAbsolute` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Which absolute X value should this line go to? Incompatible with `length`. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this line. | No |
|
||||
|
||||
### Returns
|
||||
|
||||
@ -38,10 +38,16 @@ xLine(
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> xLine(length = 15)
|
||||
|> angledLine(angle = 80, length = 15)
|
||||
|> angledLine(
|
||||
angle = 80,
|
||||
length = 15,
|
||||
)
|
||||
|> line(end = [8, -10])
|
||||
|> xLine(length = 10)
|
||||
|> angledLine(angle = 120, length = 30)
|
||||
|> angledLine(
|
||||
angle = 120,
|
||||
length = 30,
|
||||
)
|
||||
|> xLine(length = -15)
|
||||
|> close()
|
||||
|
@ -10,9 +10,9 @@ Draw a line relative to the current origin to a specified distance away from the
|
||||
```kcl
|
||||
yLine(
|
||||
@sketch: Sketch,
|
||||
length?: number,
|
||||
endAbsolute?: number,
|
||||
tag?: TagDeclarator,
|
||||
length?: number(Length),
|
||||
endAbsolute?: number(Length),
|
||||
tag?: tag,
|
||||
): Sketch
|
||||
```
|
||||
|
||||
@ -23,9 +23,9 @@ yLine(
|
||||
| Name | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
|
||||
| `length` | [`number`](/docs/kcl-std/types/std-types-number) | How far away along the Y axis should this line go? Incompatible with `endAbsolute`. | No |
|
||||
| `endAbsolute` | [`number`](/docs/kcl-std/types/std-types-number) | Which absolute Y value should this line go to? Incompatible with `length`. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | Create a new tag which refers to this line | No |
|
||||
| `length` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | How far away along the Y axis should this line go? Incompatible with `endAbsolute`. | No |
|
||||
| `endAbsolute` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Which absolute Y value should this line go to? Incompatible with `length`. | No |
|
||||
| [`tag`](/docs/kcl-std/types/std-types-tag) | [`tag`](/docs/kcl-std/types/std-types-tag) | Create a new tag which refers to this line. | No |
|
||||
|
||||
### Returns
|
||||
|
||||
@ -38,7 +38,10 @@ yLine(
|
||||
exampleSketch = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
|> yLine(length = 15)
|
||||
|> angledLine(angle = 30, length = 15)
|
||||
|> angledLine(
|
||||
angle = 30,
|
||||
length = 15,
|
||||
)
|
||||
|> line(end = [8, -10])
|
||||
|> yLine(length = -5)
|
||||
|> close()
|
@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "intersect"
|
||||
subtitle: "Function in std::solid"
|
||||
excerpt: ""
|
||||
excerpt: "Intersect returns the shared volume between multiple solids, preserving only overlapping regions."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
|
||||
Intersect returns the shared volume between multiple solids, preserving only overlapping regions.
|
||||
|
||||
```kcl
|
||||
intersect(
|
||||
@ -14,8 +14,6 @@ intersect(
|
||||
): [Solid; 1+]
|
||||
```
|
||||
|
||||
Intersect returns the shared volume between multiple solids, preserving only
|
||||
overlapping regions.
|
||||
Intersect computes the geometric intersection of multiple solid bodies,
|
||||
returning a new solid representing the volume that is common to all input
|
||||
solids. This operation is useful for determining shared material regions,
|
||||
|
@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "patternCircular3d"
|
||||
subtitle: "Function in std::solid"
|
||||
excerpt: ""
|
||||
excerpt: "Repeat a 3-dimensional solid some number of times along a partial or complete circle some specified number of times. Each object may additionally be rotated along the circle, ensuring orientation of the solid with respect to the center of the circle is maintained."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
|
||||
Repeat a 3-dimensional solid some number of times along a partial or complete circle some specified number of times. Each object may additionally be rotated along the circle, ensuring orientation of the solid with respect to the center of the circle is maintained.
|
||||
|
||||
```kcl
|
||||
patternCircular3d(
|
||||
@ -19,9 +19,7 @@ patternCircular3d(
|
||||
): [Solid; 1+]
|
||||
```
|
||||
|
||||
Repeat a 3-dimensional solid some number of times along a partial or
|
||||
complete circle some specified number of times. Each object mayadditionally be rotated along the circle, ensuring orientation of the
|
||||
solid with respect to the center of the circle is maintained.
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "patternLinear3d"
|
||||
subtitle: "Function in std::solid"
|
||||
excerpt: ""
|
||||
excerpt: "Repeat a 3-dimensional solid along a linear path, with a dynamic amount of distance between each repetition, some specified number of times."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
|
||||
Repeat a 3-dimensional solid along a linear path, with a dynamic amount of distance between each repetition, some specified number of times.
|
||||
|
||||
```kcl
|
||||
patternLinear3d(
|
||||
@ -17,8 +17,7 @@ patternLinear3d(
|
||||
): [Solid; 1+]
|
||||
```
|
||||
|
||||
Repeat a 3-dimensional solid along a linear path, with a dynamic amount
|
||||
of distance between each repetition, some specified number of times.
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
---
|
||||
title: "shell"
|
||||
subtitle: "Function in std::solid"
|
||||
excerpt: ""
|
||||
excerpt: "Remove volume from a 3-dimensional shape such that a wall of the provided thickness remains, taking volume starting at the provided face, leaving it open in that direction."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
|
||||
Remove volume from a 3-dimensional shape such that a wall of the provided thickness remains, taking volume starting at the provided face, leaving it open in that direction.
|
||||
|
||||
```kcl
|
||||
shell(
|
||||
@ -15,8 +15,7 @@ shell(
|
||||
): [Solid]
|
||||
```
|
||||
|
||||
Remove volume from a 3-dimensional shape such that a wall of the
|
||||
provided thickness remains, taking volume starting at the providedface, leaving it open in that direction.
|
||||
|
||||
|
||||
### Arguments
|
||||
|
||||
|
@ -9,12 +9,11 @@ layout: manual
|
||||
### Functions
|
||||
|
||||
* [**std**](/docs/kcl-std/modules/std)
|
||||
* [`assert`](/docs/kcl-std/assert)
|
||||
* [`assertIs`](/docs/kcl-std/assertIs)
|
||||
* [`assert`](/docs/kcl-std/functions/std-assert)
|
||||
* [`assertIs`](/docs/kcl-std/functions/std-assertIs)
|
||||
* [`clone`](/docs/kcl-std/functions/std-clone)
|
||||
* [`helix`](/docs/kcl-std/functions/std-helix)
|
||||
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
||||
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
||||
* [**std::appearance**](/docs/kcl-std/modules/std-appearance)
|
||||
* [`appearance::hexString`](/docs/kcl-std/functions/std-appearance-hexString)
|
||||
* [**std::array**](/docs/kcl-std/modules/std-array)
|
||||
@ -48,46 +47,47 @@ layout: manual
|
||||
* [`sqrt`](/docs/kcl-std/functions/std-math-sqrt)
|
||||
* [`tan`](/docs/kcl-std/functions/std-math-tan)
|
||||
* [**std::sketch**](/docs/kcl-std/modules/std-sketch)
|
||||
* [`angledLine`](/docs/kcl-std/angledLine)
|
||||
* [`angledLineThatIntersects`](/docs/kcl-std/angledLineThatIntersects)
|
||||
* [`arc`](/docs/kcl-std/arc)
|
||||
* [`bezierCurve`](/docs/kcl-std/bezierCurve)
|
||||
* [`angledLine`](/docs/kcl-std/functions/std-sketch-angledLine)
|
||||
* [`angledLineThatIntersects`](/docs/kcl-std/functions/std-sketch-angledLineThatIntersects)
|
||||
* [`arc`](/docs/kcl-std/functions/std-sketch-arc)
|
||||
* [`bezierCurve`](/docs/kcl-std/functions/std-sketch-bezierCurve)
|
||||
* [`circle`](/docs/kcl-std/functions/std-sketch-circle)
|
||||
* [`circleThreePoint`](/docs/kcl-std/circleThreePoint)
|
||||
* [`close`](/docs/kcl-std/close)
|
||||
* [`extrude`](/docs/kcl-std/extrude)
|
||||
* [`getCommonEdge`](/docs/kcl-std/getCommonEdge)
|
||||
* [`getNextAdjacentEdge`](/docs/kcl-std/getNextAdjacentEdge)
|
||||
* [`getOppositeEdge`](/docs/kcl-std/getOppositeEdge)
|
||||
* [`getPreviousAdjacentEdge`](/docs/kcl-std/getPreviousAdjacentEdge)
|
||||
* [`involuteCircular`](/docs/kcl-std/involuteCircular)
|
||||
* [`lastSegX`](/docs/kcl-std/lastSegX)
|
||||
* [`lastSegY`](/docs/kcl-std/lastSegY)
|
||||
* [`line`](/docs/kcl-std/line)
|
||||
* [`loft`](/docs/kcl-std/loft)
|
||||
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
|
||||
* [`circleThreePoint`](/docs/kcl-std/functions/std-sketch-circleThreePoint)
|
||||
* [`close`](/docs/kcl-std/functions/std-sketch-close)
|
||||
* [`extrude`](/docs/kcl-std/functions/std-sketch-extrude)
|
||||
* [`getCommonEdge`](/docs/kcl-std/functions/std-sketch-getCommonEdge)
|
||||
* [`getNextAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getNextAdjacentEdge)
|
||||
* [`getOppositeEdge`](/docs/kcl-std/functions/std-sketch-getOppositeEdge)
|
||||
* [`getPreviousAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getPreviousAdjacentEdge)
|
||||
* [`involuteCircular`](/docs/kcl-std/functions/std-sketch-involuteCircular)
|
||||
* [`lastSegX`](/docs/kcl-std/functions/std-sketch-lastSegX)
|
||||
* [`lastSegY`](/docs/kcl-std/functions/std-sketch-lastSegY)
|
||||
* [`line`](/docs/kcl-std/functions/std-sketch-line)
|
||||
* [`loft`](/docs/kcl-std/functions/std-sketch-loft)
|
||||
* [`patternCircular2d`](/docs/kcl-std/functions/std-sketch-patternCircular2d)
|
||||
* [`patternLinear2d`](/docs/kcl-std/functions/std-sketch-patternLinear2d)
|
||||
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
|
||||
* [`polygon`](/docs/kcl-std/polygon)
|
||||
* [`profileStart`](/docs/kcl-std/profileStart)
|
||||
* [`profileStartX`](/docs/kcl-std/profileStartX)
|
||||
* [`profileStartY`](/docs/kcl-std/profileStartY)
|
||||
* [`polygon`](/docs/kcl-std/functions/std-sketch-polygon)
|
||||
* [`profileStart`](/docs/kcl-std/functions/std-sketch-profileStart)
|
||||
* [`profileStartX`](/docs/kcl-std/functions/std-sketch-profileStartX)
|
||||
* [`profileStartY`](/docs/kcl-std/functions/std-sketch-profileStartY)
|
||||
* [`revolve`](/docs/kcl-std/functions/std-sketch-revolve)
|
||||
* [`segAng`](/docs/kcl-std/segAng)
|
||||
* [`segEnd`](/docs/kcl-std/segEnd)
|
||||
* [`segEndX`](/docs/kcl-std/segEndX)
|
||||
* [`segEndY`](/docs/kcl-std/segEndY)
|
||||
* [`segLen`](/docs/kcl-std/segLen)
|
||||
* [`segStart`](/docs/kcl-std/segStart)
|
||||
* [`segStartX`](/docs/kcl-std/segStartX)
|
||||
* [`segStartY`](/docs/kcl-std/segStartY)
|
||||
* [`startProfile`](/docs/kcl-std/startProfile)
|
||||
* [`startSketchOn`](/docs/kcl-std/startSketchOn)
|
||||
* [`subtract2d`](/docs/kcl-std/subtract2d)
|
||||
* [`sweep`](/docs/kcl-std/sweep)
|
||||
* [`tangentToEnd`](/docs/kcl-std/tangentToEnd)
|
||||
* [`tangentialArc`](/docs/kcl-std/tangentialArc)
|
||||
* [`xLine`](/docs/kcl-std/xLine)
|
||||
* [`yLine`](/docs/kcl-std/yLine)
|
||||
* [`segAng`](/docs/kcl-std/functions/std-sketch-segAng)
|
||||
* [`segEnd`](/docs/kcl-std/functions/std-sketch-segEnd)
|
||||
* [`segEndX`](/docs/kcl-std/functions/std-sketch-segEndX)
|
||||
* [`segEndY`](/docs/kcl-std/functions/std-sketch-segEndY)
|
||||
* [`segLen`](/docs/kcl-std/functions/std-sketch-segLen)
|
||||
* [`segStart`](/docs/kcl-std/functions/std-sketch-segStart)
|
||||
* [`segStartX`](/docs/kcl-std/functions/std-sketch-segStartX)
|
||||
* [`segStartY`](/docs/kcl-std/functions/std-sketch-segStartY)
|
||||
* [`startProfile`](/docs/kcl-std/functions/std-sketch-startProfile)
|
||||
* [`startSketchOn`](/docs/kcl-std/functions/std-sketch-startSketchOn)
|
||||
* [`subtract2d`](/docs/kcl-std/functions/std-sketch-subtract2d)
|
||||
* [`sweep`](/docs/kcl-std/functions/std-sketch-sweep)
|
||||
* [`tangentToEnd`](/docs/kcl-std/functions/std-sketch-tangentToEnd)
|
||||
* [`tangentialArc`](/docs/kcl-std/functions/std-sketch-tangentialArc)
|
||||
* [`xLine`](/docs/kcl-std/functions/std-sketch-xLine)
|
||||
* [`yLine`](/docs/kcl-std/functions/std-sketch-yLine)
|
||||
* [**std::solid**](/docs/kcl-std/modules/std-solid)
|
||||
* [`appearance`](/docs/kcl-std/functions/std-solid-appearance)
|
||||
* [`chamfer`](/docs/kcl-std/functions/std-solid-chamfer)
|
||||
@ -102,9 +102,9 @@ layout: manual
|
||||
* [`union`](/docs/kcl-std/functions/std-solid-union)
|
||||
* [**std::transform**](/docs/kcl-std/modules/std-transform)
|
||||
* [`mirror2d`](/docs/kcl-std/functions/std-transform-mirror2d)
|
||||
* [`rotate`](/docs/kcl-std/rotate)
|
||||
* [`scale`](/docs/kcl-std/scale)
|
||||
* [`translate`](/docs/kcl-std/translate)
|
||||
* [`rotate`](/docs/kcl-std/functions/std-transform-rotate)
|
||||
* [`scale`](/docs/kcl-std/functions/std-transform-scale)
|
||||
* [`translate`](/docs/kcl-std/functions/std-transform-translate)
|
||||
* [**std::units**](/docs/kcl-std/modules/std-units)
|
||||
* [`units::toCentimeters`](/docs/kcl-std/functions/std-units-toCentimeters)
|
||||
* [`units::toDegrees`](/docs/kcl-std/functions/std-units-toDegrees)
|
||||
@ -144,11 +144,7 @@ layout: manual
|
||||
See also the [types overview](/docs/kcl-lang/types)
|
||||
|
||||
* [**Primitive types**](/docs/kcl-lang/types)
|
||||
* [`End`](/docs/kcl-lang/types#End)
|
||||
* [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry)
|
||||
* [`Start`](/docs/kcl-lang/types#Start)
|
||||
* [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator)
|
||||
* [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier)
|
||||
* [`any`](/docs/kcl-std/types/std-types-any)
|
||||
* [`bool`](/docs/kcl-std/types/std-types-bool)
|
||||
* [`fn`](/docs/kcl-std/types/std-types-fn)
|
||||
|
@ -12,45 +12,46 @@ This module contains functions for creating and manipulating sketches, and makin
|
||||
|
||||
## Functions and constants
|
||||
|
||||
* [`angledLine`](/docs/kcl-std/angledLine)
|
||||
* [`angledLineThatIntersects`](/docs/kcl-std/angledLineThatIntersects)
|
||||
* [`arc`](/docs/kcl-std/arc)
|
||||
* [`bezierCurve`](/docs/kcl-std/bezierCurve)
|
||||
* [`angledLine`](/docs/kcl-std/functions/std-sketch-angledLine)
|
||||
* [`angledLineThatIntersects`](/docs/kcl-std/functions/std-sketch-angledLineThatIntersects)
|
||||
* [`arc`](/docs/kcl-std/functions/std-sketch-arc)
|
||||
* [`bezierCurve`](/docs/kcl-std/functions/std-sketch-bezierCurve)
|
||||
* [`circle`](/docs/kcl-std/functions/std-sketch-circle)
|
||||
* [`circleThreePoint`](/docs/kcl-std/circleThreePoint)
|
||||
* [`close`](/docs/kcl-std/close)
|
||||
* [`circleThreePoint`](/docs/kcl-std/functions/std-sketch-circleThreePoint)
|
||||
* [`close`](/docs/kcl-std/functions/std-sketch-close)
|
||||
* [`ellipse`](/doc/kcl-std/ellipse)
|
||||
* [`extrude`](/docs/kcl-std/extrude)
|
||||
* [`getCommonEdge`](/docs/kcl-std/getCommonEdge)
|
||||
* [`getNextAdjacentEdge`](/docs/kcl-std/getNextAdjacentEdge)
|
||||
* [`getOppositeEdge`](/docs/kcl-std/getOppositeEdge)
|
||||
* [`getPreviousAdjacentEdge`](/docs/kcl-std/getPreviousAdjacentEdge)
|
||||
* [`involuteCircular`](/docs/kcl-std/involuteCircular)
|
||||
* [`lastSegX`](/docs/kcl-std/lastSegX)
|
||||
* [`lastSegY`](/docs/kcl-std/lastSegY)
|
||||
* [`line`](/docs/kcl-std/line)
|
||||
* [`loft`](/docs/kcl-std/loft)
|
||||
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
|
||||
* [`extrude`](/docs/kcl-std/functions/std-sketch-extrude)
|
||||
* [`getCommonEdge`](/docs/kcl-std/functions/std-sketch-getCommonEdge)
|
||||
* [`getNextAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getNextAdjacentEdge)
|
||||
* [`getOppositeEdge`](/docs/kcl-std/functions/std-sketch-getOppositeEdge)
|
||||
* [`getPreviousAdjacentEdge`](/docs/kcl-std/functions/std-sketch-getPreviousAdjacentEdge)
|
||||
* [`involuteCircular`](/docs/kcl-std/functions/std-sketch-involuteCircular)
|
||||
* [`lastSegX`](/docs/kcl-std/functions/std-sketch-lastSegX)
|
||||
* [`lastSegY`](/docs/kcl-std/functions/std-sketch-lastSegY)
|
||||
* [`line`](/docs/kcl-std/functions/std-sketch-line)
|
||||
* [`loft`](/docs/kcl-std/functions/std-sketch-loft)
|
||||
* [`patternCircular2d`](/docs/kcl-std/functions/std-sketch-patternCircular2d)
|
||||
* [`patternLinear2d`](/docs/kcl-std/functions/std-sketch-patternLinear2d)
|
||||
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
|
||||
* [`polygon`](/docs/kcl-std/polygon)
|
||||
* [`profileStart`](/docs/kcl-std/profileStart)
|
||||
* [`profileStartX`](/docs/kcl-std/profileStartX)
|
||||
* [`profileStartY`](/docs/kcl-std/profileStartY)
|
||||
* [`polygon`](/docs/kcl-std/functions/std-sketch-polygon)
|
||||
* [`profileStart`](/docs/kcl-std/functions/std-sketch-profileStart)
|
||||
* [`profileStartX`](/docs/kcl-std/functions/std-sketch-profileStartX)
|
||||
* [`profileStartY`](/docs/kcl-std/functions/std-sketch-profileStartY)
|
||||
* [`revolve`](/docs/kcl-std/functions/std-sketch-revolve)
|
||||
* [`segAng`](/docs/kcl-std/segAng)
|
||||
* [`segEnd`](/docs/kcl-std/segEnd)
|
||||
* [`segEndX`](/docs/kcl-std/segEndX)
|
||||
* [`segEndY`](/docs/kcl-std/segEndY)
|
||||
* [`segLen`](/docs/kcl-std/segLen)
|
||||
* [`segStart`](/docs/kcl-std/segStart)
|
||||
* [`segStartX`](/docs/kcl-std/segStartX)
|
||||
* [`segStartY`](/docs/kcl-std/segStartY)
|
||||
* [`startProfile`](/docs/kcl-std/startProfile)
|
||||
* [`startSketchOn`](/docs/kcl-std/startSketchOn)
|
||||
* [`subtract2d`](/docs/kcl-std/subtract2d)
|
||||
* [`sweep`](/docs/kcl-std/sweep)
|
||||
* [`tangentToEnd`](/docs/kcl-std/tangentToEnd)
|
||||
* [`tangentialArc`](/docs/kcl-std/tangentialArc)
|
||||
* [`xLine`](/docs/kcl-std/xLine)
|
||||
* [`yLine`](/docs/kcl-std/yLine)
|
||||
* [`segAng`](/docs/kcl-std/functions/std-sketch-segAng)
|
||||
* [`segEnd`](/docs/kcl-std/functions/std-sketch-segEnd)
|
||||
* [`segEndX`](/docs/kcl-std/functions/std-sketch-segEndX)
|
||||
* [`segEndY`](/docs/kcl-std/functions/std-sketch-segEndY)
|
||||
* [`segLen`](/docs/kcl-std/functions/std-sketch-segLen)
|
||||
* [`segStart`](/docs/kcl-std/functions/std-sketch-segStart)
|
||||
* [`segStartX`](/docs/kcl-std/functions/std-sketch-segStartX)
|
||||
* [`segStartY`](/docs/kcl-std/functions/std-sketch-segStartY)
|
||||
* [`startProfile`](/docs/kcl-std/functions/std-sketch-startProfile)
|
||||
* [`startSketchOn`](/docs/kcl-std/functions/std-sketch-startSketchOn)
|
||||
* [`subtract2d`](/docs/kcl-std/functions/std-sketch-subtract2d)
|
||||
* [`sweep`](/docs/kcl-std/functions/std-sketch-sweep)
|
||||
* [`tangentToEnd`](/docs/kcl-std/functions/std-sketch-tangentToEnd)
|
||||
* [`tangentialArc`](/docs/kcl-std/functions/std-sketch-tangentialArc)
|
||||
* [`xLine`](/docs/kcl-std/functions/std-sketch-xLine)
|
||||
* [`yLine`](/docs/kcl-std/functions/std-sketch-yLine)
|
||||
|
||||
|
@ -13,7 +13,7 @@ This module contains functions for transforming sketches and solids.
|
||||
## Functions and constants
|
||||
|
||||
* [`mirror2d`](/docs/kcl-std/functions/std-transform-mirror2d)
|
||||
* [`rotate`](/docs/kcl-std/rotate)
|
||||
* [`scale`](/docs/kcl-std/scale)
|
||||
* [`translate`](/docs/kcl-std/translate)
|
||||
* [`rotate`](/docs/kcl-std/functions/std-transform-rotate)
|
||||
* [`scale`](/docs/kcl-std/functions/std-transform-scale)
|
||||
* [`translate`](/docs/kcl-std/functions/std-transform-translate)
|
||||
|
||||
|
@ -36,10 +36,9 @@ You might also want the [KCL language reference](/docs/kcl-lang) or the [KCL gui
|
||||
* [`Y`](/docs/kcl-std/consts/std-Y)
|
||||
* [`YZ`](/docs/kcl-std/consts/std-YZ)
|
||||
* [`Z`](/docs/kcl-std/consts/std-Z)
|
||||
* [`assert`](/docs/kcl-std/assert)
|
||||
* [`assertIs`](/docs/kcl-std/assertIs)
|
||||
* [`assert`](/docs/kcl-std/functions/std-assert)
|
||||
* [`assertIs`](/docs/kcl-std/functions/std-assertIs)
|
||||
* [`clone`](/docs/kcl-std/functions/std-clone)
|
||||
* [`helix`](/docs/kcl-std/functions/std-helix)
|
||||
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
||||
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
||||
|
||||
|
241060
docs/kcl-std/std.json
@ -1,14 +1,13 @@
|
||||
---
|
||||
title: "any"
|
||||
subtitle: "Type in std::types"
|
||||
excerpt: ""
|
||||
excerpt: "The [`any`](/docs/kcl-std/types/std-types-any) type is the type of all possible values in KCL. I.e., if a function accepts an argument with type [`any`](/docs/kcl-std/types/std-types-any), then it can accept any value."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
The [`any`](/docs/kcl-std/types/std-types-any) type is the type of all possible values in KCL. I.e., if a function accepts an argument with type [`any`](/docs/kcl-std/types/std-types-any), then it can accept any value.
|
||||
|
||||
|
||||
The [`any`](/docs/kcl-std/types/std-types-any) type is the type of all possible values in KCL. I.e., if a function accepts an argument
|
||||
with type [`any`](/docs/kcl-std/types/std-types-any), then it can accept any value.
|
||||
|
||||
|
||||
### Examples
|
||||
|
@ -5,7 +5,7 @@ import * as fsp from 'fs/promises'
|
||||
test.describe('Electron app header tests', () => {
|
||||
test(
|
||||
'Open Command Palette button has correct shortcut',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page }, testInfo) => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
@ -30,7 +30,7 @@ test.describe('Electron app header tests', () => {
|
||||
|
||||
test(
|
||||
'User settings has correct shortcut',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, toolbar }, testInfo) => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
|
@ -4,7 +4,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
||||
test.describe('Authentication tests', () => {
|
||||
test(
|
||||
`The user can sign out and back in`,
|
||||
{ tag: ['@electron'] },
|
||||
{ tag: ['@desktop'] },
|
||||
async ({ page, homePage, signInPage, toolbar, tronApp }) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
|
@ -265,6 +265,7 @@ middle(0)
|
||||
})
|
||||
await expect(
|
||||
page.getByText(`assert failed: Expected 0 to be greater than 0 but it wasn't
|
||||
assert()
|
||||
check()
|
||||
middle()`)
|
||||
).toBeVisible()
|
||||
@ -275,7 +276,7 @@ middle()`)
|
||||
|
||||
test(
|
||||
'Opening multiple panes persists when switching projects',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
// Setup multiple projects.
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
@ -346,7 +347,7 @@ test(
|
||||
|
||||
test(
|
||||
'external change of file contents are reflected in editor',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const PROJECT_DIR_NAME = 'lee-was-here'
|
||||
const { dir: projectsDir } = await context.folderSetupFn(async (dir) => {
|
||||
|
@ -534,7 +534,7 @@ profile001 = startProfile(sketch001, at = [-484.34, 484.95])
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
`
|
||||
const targetURL = `?create-file&name=test&units=mm&code=${encodeURIComponent(btoa(code))}&ask-open-desktop`
|
||||
const targetURL = `?create-file=true&name=test&units=mm&code=${encodeURIComponent(btoa(code))}&ask-open-desktop=true`
|
||||
await page.goto(page.url() + targetURL)
|
||||
expect(page.url()).toContain(targetURL)
|
||||
})
|
||||
|
@ -10,7 +10,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
||||
|
||||
test(
|
||||
'export works on the first try',
|
||||
{ tag: ['@electron', '@macos', '@windows', '@skipLocalEngine'] },
|
||||
{ tag: ['@desktop', '@macos', '@windows', '@skipLocalEngine'] },
|
||||
async ({ page, context, scene, tronApp, cmdBar }, testInfo) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
|
@ -964,8 +964,6 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
|
||||
await page.waitForTimeout(100)
|
||||
await page.keyboard.press('Enter') // accepting the auto complete, not a new line
|
||||
|
||||
await page.keyboard.press('Tab')
|
||||
await page.waitForTimeout(100)
|
||||
await page.keyboard.press('Tab')
|
||||
await page.waitForTimeout(100)
|
||||
await page.keyboard.type('12')
|
||||
@ -984,8 +982,6 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
|
||||
await page.keyboard.press('ArrowDown')
|
||||
await page.keyboard.press('Enter')
|
||||
// finish line with comment
|
||||
await page.keyboard.press('Tab')
|
||||
await page.waitForTimeout(100)
|
||||
await page.keyboard.type('5')
|
||||
await page.waitForTimeout(100)
|
||||
await page.keyboard.press('Tab')
|
||||
@ -1001,8 +997,8 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
|
||||
await expect(page.locator('.cm-content')).toHaveText(
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
|> startProfile(%, at = [0, 12])
|
||||
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|
||||
|> startProfile(at = [0, 12])
|
||||
|> xLine(length = 5) // lin`.replaceAll('\n', '')
|
||||
)
|
||||
|
||||
// expect there to be no KCL errors
|
||||
@ -1040,8 +1036,6 @@ sketch001 = startSketchOn(XZ)
|
||||
await page.waitForTimeout(100)
|
||||
await page.keyboard.press('Tab') // accepting the auto complete, not a new line
|
||||
|
||||
await page.keyboard.press('Tab')
|
||||
await page.waitForTimeout(100)
|
||||
await page.keyboard.press('Tab')
|
||||
await page.keyboard.type('12')
|
||||
await page.waitForTimeout(100)
|
||||
@ -1057,7 +1051,6 @@ sketch001 = startSketchOn(XZ)
|
||||
await page.waitForTimeout(100)
|
||||
// press arrow down then tab to accept xLine
|
||||
await page.keyboard.press('ArrowDown')
|
||||
await page.keyboard.press('Tab')
|
||||
// finish line with comment
|
||||
await page.keyboard.press('Tab')
|
||||
await page.waitForTimeout(100)
|
||||
@ -1076,8 +1069,8 @@ sketch001 = startSketchOn(XZ)
|
||||
await expect(page.locator('.cm-content')).toHaveText(
|
||||
`@settings(defaultLengthUnit = in)
|
||||
sketch001 = startSketchOn(XZ)
|
||||
|> startProfile(%, at = [0, 12])
|
||||
|> xLine(%, length = 5) // lin`.replaceAll('\n', '')
|
||||
|> startProfile(at = [0, 12])
|
||||
|> xLine(length = 5) // lin`.replaceAll('\n', '')
|
||||
)
|
||||
})
|
||||
})
|
||||
@ -1337,7 +1330,7 @@ sketch001 = startSketchOn(XZ)
|
||||
|
||||
test(
|
||||
`Can import a local OBJ file`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, context }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = join(dir, 'cube')
|
||||
|
@ -57,7 +57,7 @@ sketch003 = startSketchOn(plane001)
|
||||
test.describe('Feature Tree pane', () => {
|
||||
test(
|
||||
'User can go to definition and go to function definition',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, homePage, scene, editor, toolbar, cmdBar, page }) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = join(dir, 'test-sample')
|
||||
@ -150,7 +150,7 @@ test.describe('Feature Tree pane', () => {
|
||||
|
||||
test(
|
||||
`User can edit sketch (but not on offset plane yet) from the feature tree`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, homePage, scene, editor, toolbar, page }) => {
|
||||
await context.addInitScript((initialCode) => {
|
||||
localStorage.setItem('persistCode', initialCode)
|
||||
|
@ -13,7 +13,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
||||
test.describe('integrations tests', () => {
|
||||
test(
|
||||
'Creating a new file or switching file while in sketchMode should exit sketchMode',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, context, homePage, scene, editor, toolbar, cmdBar }) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = join(dir, 'test-sample')
|
||||
@ -100,7 +100,7 @@ test.describe('when using the file tree to', () => {
|
||||
|
||||
test(
|
||||
`rename ${fromFile} to ${toFile}, and doesn't crash on reload and settings load`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page }, testInfo) => {
|
||||
const { panesOpen, pasteCodeInEditor, renameFile, editorTextMatches } =
|
||||
await getUtils(page, test)
|
||||
@ -142,7 +142,7 @@ test.describe('when using the file tree to', () => {
|
||||
|
||||
test(
|
||||
`create many new files of the same name, incrementing their names`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page }, testInfo) => {
|
||||
const { panesOpen, createNewFile } = await getUtils(page, test)
|
||||
|
||||
@ -174,7 +174,7 @@ test.describe('when using the file tree to', () => {
|
||||
|
||||
test(
|
||||
'create a new file with the same name as an existing file cancels the operation',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, homePage, scene, editor, toolbar }, testInfo) => {
|
||||
const projectName = 'cube'
|
||||
const mainFile = 'main.kcl'
|
||||
@ -240,7 +240,7 @@ test.describe('when using the file tree to', () => {
|
||||
|
||||
test(
|
||||
`create new folders and that doesn't trigger a navigation`,
|
||||
{ tag: ['@electron', '@macos', '@windows'] },
|
||||
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||
async ({ page, homePage, scene, toolbar, cmdBar }) => {
|
||||
await homePage.goToModelingScene()
|
||||
await scene.settled(cmdBar)
|
||||
@ -260,7 +260,7 @@ test.describe('when using the file tree to', () => {
|
||||
|
||||
test(
|
||||
'deleting all files recreates a default main.kcl with no code',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page }, testInfo) => {
|
||||
const { panesOpen, pasteCodeInEditor, deleteFile, editorTextMatches } =
|
||||
await getUtils(page, test)
|
||||
@ -291,7 +291,7 @@ test.describe('when using the file tree to', () => {
|
||||
test(
|
||||
'loading small file, then large, then back to small',
|
||||
{
|
||||
tag: '@electron',
|
||||
tag: '@desktop',
|
||||
},
|
||||
async ({ page }, testInfo) => {
|
||||
const {
|
||||
@ -361,7 +361,7 @@ test.describe('when using the file tree to', () => {
|
||||
test.describe('Renaming in the file tree', () => {
|
||||
test(
|
||||
'A file you have open',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const { dir } = await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||
@ -450,7 +450,7 @@ test.describe('Renaming in the file tree', () => {
|
||||
|
||||
test(
|
||||
'A file you do not have open',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const { dir } = await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||
@ -536,7 +536,7 @@ test.describe('Renaming in the file tree', () => {
|
||||
|
||||
test(
|
||||
`A folder you're not inside`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const { dir } = await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||
@ -618,7 +618,7 @@ test.describe('Renaming in the file tree', () => {
|
||||
|
||||
test(
|
||||
`A folder you are inside`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, context }, testInfo) => {
|
||||
const { dir } = await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||
@ -721,7 +721,7 @@ test.describe('Renaming in the file tree', () => {
|
||||
test.describe('Deleting items from the file pane', () => {
|
||||
test(
|
||||
`delete file when main.kcl exists, navigate to main.kcl`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, context }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const testDir = join(dir, 'testProject')
|
||||
@ -786,7 +786,7 @@ test.describe('Deleting items from the file pane', () => {
|
||||
|
||||
test(
|
||||
`Delete folder we are not in, don't navigate`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||
@ -840,7 +840,7 @@ test.describe('Deleting items from the file pane', () => {
|
||||
|
||||
test(
|
||||
`Delete folder we are in, navigate to main.kcl`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(join(dir, 'Test Project'), { recursive: true })
|
||||
@ -906,7 +906,7 @@ test.describe('Deleting items from the file pane', () => {
|
||||
// Copied from tests above.
|
||||
test(
|
||||
`external deletion of project navigates back home`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const TEST_PROJECT_NAME = 'Test Project'
|
||||
const { dir: projectsDirName } = await context.folderSetupFn(
|
||||
@ -970,7 +970,7 @@ test.describe('Deleting items from the file pane', () => {
|
||||
// Similar to the above
|
||||
test(
|
||||
`external deletion of file in sub-directory updates the file tree and recreates it on code editor typing`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const TEST_PROJECT_NAME = 'Test Project'
|
||||
const { dir: projectsDirName } = await context.folderSetupFn(
|
||||
@ -1045,7 +1045,7 @@ test.describe('Deleting items from the file pane', () => {
|
||||
test.describe('Undo and redo do not keep history when navigating between files', () => {
|
||||
test(
|
||||
`open a file, change something, open a different file, hitting undo should do nothing`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const testDir = join(dir, 'testProject')
|
||||
@ -1112,7 +1112,7 @@ test.describe('Undo and redo do not keep history when navigating between files',
|
||||
|
||||
test(
|
||||
`open a file, change something, undo it, open a different file, hitting redo should do nothing`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const testDir = join(dir, 'testProject')
|
||||
@ -1212,7 +1212,7 @@ test.describe('Undo and redo do not keep history when navigating between files',
|
||||
|
||||
test(
|
||||
`cloned file has an incremented name and same contents`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, context, homePage }, testInfo) => {
|
||||
const { panesOpen, cloneFile } = await getUtils(page, test)
|
||||
|
||||
|
@ -5,7 +5,7 @@ import * as fsp from 'fs/promises'
|
||||
test.describe('Import UI tests', () => {
|
||||
test(
|
||||
'shows toast when trying to sketch on imported face, and hovering over imported geometry should NOT highlight any code',
|
||||
{ tag: ['@electron', '@macos', '@windows'] },
|
||||
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||
async ({ context, page, homePage, toolbar, scene, editor, cmdBar }) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const projectDir = path.join(dir, 'import-test')
|
||||
|
@ -6,7 +6,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
||||
|
||||
test(
|
||||
'When machine-api server not found butt is disabled and shows the reason',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = join(dir, 'bracket')
|
||||
@ -43,7 +43,7 @@ test(
|
||||
|
||||
test(
|
||||
'When machine-api server not found home screen & project status shows the reason',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = join(dir, 'bracket')
|
||||
|
@ -13,7 +13,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
||||
*/
|
||||
test.describe(
|
||||
'Native file menu',
|
||||
{ tag: ['@electron', '@macos', '@windows'] },
|
||||
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||
() => {
|
||||
test('Home page', async ({ tronApp, cmdBar, page, homePage }) => {
|
||||
if (!tronApp) fail()
|
||||
|
@ -43,7 +43,7 @@ async function insertPartIntoAssembly(
|
||||
test.describe('Point-and-click assemblies tests', () => {
|
||||
test(
|
||||
`Insert kcl parts into assembly as whole module import`,
|
||||
{ tag: ['@electron', '@macos', '@windows'] },
|
||||
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||
async ({
|
||||
context,
|
||||
page,
|
||||
@ -198,7 +198,7 @@ test.describe('Point-and-click assemblies tests', () => {
|
||||
|
||||
test(
|
||||
`Can still translate, rotate, and delete inserted parts even with non standard code`,
|
||||
{ tag: ['@electron', '@macos', '@windows'] },
|
||||
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||
async ({
|
||||
context,
|
||||
page,
|
||||
@ -394,7 +394,7 @@ test.describe('Point-and-click assemblies tests', () => {
|
||||
|
||||
test(
|
||||
`Insert the bracket part into an assembly and transform it`,
|
||||
{ tag: ['@electron', '@macos', '@windows'] },
|
||||
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||
async ({
|
||||
context,
|
||||
page,
|
||||
@ -585,7 +585,7 @@ test.describe('Point-and-click assemblies tests', () => {
|
||||
|
||||
test(
|
||||
`Insert foreign parts into assembly and delete them`,
|
||||
{ tag: ['@electron', '@macos', '@windows'] },
|
||||
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||
async ({
|
||||
context,
|
||||
page,
|
||||
@ -736,7 +736,7 @@ test.describe('Point-and-click assemblies tests', () => {
|
||||
|
||||
test(
|
||||
'Assembly gets reexecuted when imported models are updated externally',
|
||||
{ tag: ['@electron', '@macos', '@windows'] },
|
||||
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||
async ({ context, page, homePage, scene, toolbar, cmdBar, tronApp }) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
@ -826,7 +826,7 @@ foreign
|
||||
|
||||
test(
|
||||
`Point-and-click clone`,
|
||||
{ tag: ['@electron', '@macos', '@windows'] },
|
||||
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||
async ({
|
||||
context,
|
||||
page,
|
||||
|
@ -1766,7 +1766,7 @@ loft001 = loft([sketch001, sketch002])
|
||||
sketch001 = startSketchOn(YZ)
|
||||
profile001 = circle(sketch001, center = [0, 0], radius = 500)
|
||||
sketch002 = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
profile002 = startProfile(sketch002, at = [0, 0])
|
||||
|> xLine(length = -500)
|
||||
|> tangentialArc(endAbsolute = [-2000, 500])`,
|
||||
},
|
||||
@ -1782,7 +1782,7 @@ profile001 = startProfile(sketch001, at = [-400, -400])
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
sketch002 = startSketchOn(XZ)
|
||||
|> startProfile(at = [0, 0])
|
||||
profile002 = startProfile(sketch002, at = [0, 0])
|
||||
|> xLine(length = -500)
|
||||
|> tangentialArc(endAbsolute = [-2000, 500])`,
|
||||
},
|
||||
@ -1810,9 +1810,9 @@ sketch002 = startSketchOn(XZ)
|
||||
testPoint.x - 50,
|
||||
testPoint.y
|
||||
)
|
||||
const sweepDeclaration = 'sweep001 = sweep(profile001, path = sketch002)'
|
||||
const sweepDeclaration = 'sweep001 = sweep(profile001, path = profile002)'
|
||||
const editedSweepDeclaration =
|
||||
'sweep001 = sweep(profile001, path = sketch002, sectional = true)'
|
||||
'sweep001 = sweep(profile001, path = profile002, sectional = true)'
|
||||
|
||||
await test.step(`Look for sketch001`, async () => {
|
||||
await toolbar.closePane('code')
|
||||
|
@ -17,7 +17,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
|
||||
|
||||
test(
|
||||
'projects reload if a new one is created, deleted, or renamed externally',
|
||||
{ tag: ['@electron', '@macos', '@windows'] },
|
||||
{ tag: ['@desktop', '@macos', '@windows'] },
|
||||
async ({ context, page }, testInfo) => {
|
||||
let externalCreatedProjectName = 'external-created-project'
|
||||
|
||||
@ -63,7 +63,7 @@ test(
|
||||
|
||||
test(
|
||||
'click help/keybindings from home page',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page }, testInfo) => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
@ -81,7 +81,7 @@ test(
|
||||
|
||||
test(
|
||||
'click help/keybindings from project page',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'bracket')
|
||||
@ -112,7 +112,7 @@ test(
|
||||
|
||||
test(
|
||||
'open a file in a project works and renders, open another file in different project with errors, it should clear the scene',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ scene, cmdBar, context, page, editor }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'bracket')
|
||||
@ -169,7 +169,7 @@ test(
|
||||
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-error')
|
||||
const crypticErrorText = `The arg tag was given, but it was the wrong type`
|
||||
const crypticErrorText = 'tag requires a value with type `tag`, but found string'
|
||||
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
|
||||
|
||||
// black pixel means the scene has been cleared.
|
||||
@ -184,7 +184,7 @@ test(
|
||||
|
||||
test(
|
||||
'open a file in a project works and renders, open another file in different project that is empty, it should clear the scene',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'bracket')
|
||||
@ -244,7 +244,7 @@ test(
|
||||
|
||||
test(
|
||||
'open a file in a project works and renders, open empty file, it should clear the scene',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'bracket')
|
||||
@ -310,7 +310,7 @@ test(
|
||||
|
||||
test(
|
||||
'open a file in a project works and renders, open another file in the same project with errors, it should clear the scene',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'bracket')
|
||||
@ -367,7 +367,7 @@ test(
|
||||
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-error')
|
||||
const crypticErrorText = `The arg tag was given, but it was the wrong type`
|
||||
const crypticErrorText = 'tag requires a value with type `tag`, but found string'
|
||||
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
|
||||
|
||||
// black pixel means the scene has been cleared.
|
||||
@ -382,7 +382,7 @@ test(
|
||||
|
||||
test(
|
||||
'when code with error first loads you get errors in console',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, editor }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(path.join(dir, 'broken-code'), { recursive: true })
|
||||
@ -405,7 +405,7 @@ test(
|
||||
|
||||
// error text on hover
|
||||
await page.hover('.cm-lint-marker-error')
|
||||
const crypticErrorText = `The arg tag was given, but it was the wrong type`
|
||||
const crypticErrorText = 'tag requires a value with type `tag`, but found string'
|
||||
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
|
||||
}
|
||||
)
|
||||
@ -416,7 +416,7 @@ test.describe('Can export from electron app', () => {
|
||||
for (const method of exportMethods) {
|
||||
test(
|
||||
`Can export using ${method}`,
|
||||
{ tag: ['@electron', '@skipLocalEngine'] },
|
||||
{ tag: ['@desktop', '@skipLocalEngine'] },
|
||||
async ({ scene, cmdBar, context, page, tronApp }, testInfo) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
@ -507,7 +507,7 @@ test.describe('Can export from electron app', () => {
|
||||
})
|
||||
test(
|
||||
'Rename and delete projects, also spam arrow keys when renaming',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true })
|
||||
@ -723,7 +723,7 @@ test(
|
||||
|
||||
test(
|
||||
'pressing "delete" on home screen should do nothing',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, homePage }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true })
|
||||
@ -753,7 +753,7 @@ test(
|
||||
test.describe(`Project management commands`, () => {
|
||||
test(
|
||||
`Rename from project page`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||
const projectName = `my_project_to_rename`
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
@ -815,7 +815,7 @@ test.describe(`Project management commands`, () => {
|
||||
|
||||
test(
|
||||
`Delete from project page`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||
const projectName = `my_project_to_delete`
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
@ -869,7 +869,7 @@ test.describe(`Project management commands`, () => {
|
||||
)
|
||||
test(
|
||||
`Rename from home page`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, homePage, scene, cmdBar }, testInfo) => {
|
||||
const projectName = `my_project_to_rename`
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
@ -927,7 +927,7 @@ test.describe(`Project management commands`, () => {
|
||||
)
|
||||
test(
|
||||
`Delete from home page`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||
const projectName = `my_project_to_delete`
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
@ -1103,7 +1103,7 @@ test(`Create a few projects using the default project name`, async ({
|
||||
|
||||
test(
|
||||
'File in the file pane should open with a single click',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, homePage, page }, testInfo) => {
|
||||
const projectName = 'router-template-slate'
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
@ -1145,7 +1145,7 @@ test(
|
||||
|
||||
test(
|
||||
'Nested directories in project without main.kcl do not create main.kcl',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||
let testDir: string | undefined
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
@ -1202,7 +1202,7 @@ test(
|
||||
|
||||
test(
|
||||
'Deleting projects, can delete individual project, can still create projects after deleting all',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const projectData = [
|
||||
['router-template-slate', 'cylinder.kcl'],
|
||||
@ -1280,7 +1280,7 @@ test(
|
||||
|
||||
test(
|
||||
'Can load a file with CRLF line endings',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, scene, cmdBar }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const routerTemplateDir = path.join(dir, 'router-template-slate')
|
||||
@ -1312,7 +1312,7 @@ test(
|
||||
|
||||
test(
|
||||
'Can sort projects on home page',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const projectData = [
|
||||
['router-template-slate', 'cylinder.kcl'],
|
||||
@ -1419,7 +1419,7 @@ test(
|
||||
|
||||
test(
|
||||
'When the project folder is empty, user can create new project and open it.',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page }, testInfo) => {
|
||||
const u = await getUtils(page)
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
@ -1515,7 +1515,7 @@ extrude001 = extrude(sketch001, length = 200)`)
|
||||
|
||||
test(
|
||||
'Opening a project should successfully load the stream, (regression test that this also works when switching between projects)',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, cmdBar, homePage, scene }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
await fsp.mkdir(path.join(dir, 'router-template-slate'), {
|
||||
@ -1628,7 +1628,7 @@ test(
|
||||
|
||||
test(
|
||||
'You can change the root projects directory and nothing is lost',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page, tronApp, homePage }, testInfo) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
@ -1735,7 +1735,7 @@ test(
|
||||
|
||||
test(
|
||||
'Search projects on desktop home',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const projectData = [
|
||||
['basic bracket', 'focusrite_scarlett_mounting_bracket.kcl'],
|
||||
@ -1791,7 +1791,7 @@ test(
|
||||
|
||||
test(
|
||||
'file pane is scrollable when there are many files',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ scene, cmdBar, context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const testDir = path.join(dir, 'testProject')
|
||||
@ -1892,7 +1892,7 @@ test(
|
||||
|
||||
test(
|
||||
'select all in code editor does not actually select all, just what is visible (regression)',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
// rust/kcl-lib/e2e/executor/inputs/mike_stress_test.kcl
|
||||
@ -1950,7 +1950,7 @@ test(
|
||||
|
||||
test(
|
||||
'Settings persist across restarts',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, toolbar }, testInfo) => {
|
||||
await test.step('We can change a user setting like theme', async () => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
@ -1982,7 +1982,7 @@ test(
|
||||
|
||||
test(
|
||||
'Original project name persist after onboarding',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, toolbar }, testInfo) => {
|
||||
const nextButton = page.getByTestId('onboarding-next')
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
@ -2022,7 +2022,7 @@ test(
|
||||
|
||||
test(
|
||||
'project name with foreign characters should open',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'العربية')
|
||||
@ -2067,7 +2067,7 @@ test(
|
||||
|
||||
test(
|
||||
'import from nested directory',
|
||||
{ tag: ['@electron', '@windows', '@macos'] },
|
||||
{ tag: ['@desktop', '@windows', '@macos'] },
|
||||
async ({ scene, cmdBar, context, page }) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'bracket')
|
||||
@ -2116,3 +2116,74 @@ test(
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
test(
|
||||
'segment position changes persist after dragging and reopening project',
|
||||
{ tag: '@desktop' },
|
||||
async ({ scene, cmdBar, context, page, editor, toolbar }, testInfo) => {
|
||||
const projectName = 'segment-drag-test'
|
||||
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const projectDir = path.join(dir, projectName)
|
||||
await fsp.mkdir(projectDir, { recursive: true })
|
||||
await fsp.writeFile(
|
||||
path.join(projectDir, 'main.kcl'),
|
||||
`sketch001 = startSketchOn(XZ)
|
||||
profile001 = startProfile(sketch001, at = [0, 0])
|
||||
|> line(end = [0, 6])
|
||||
|> line(end = [10, 0])
|
||||
|> line(end = [-8, -5])
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
await page.setBodyDimensions({ width: 1200, height: 600 })
|
||||
const u = await getUtils(page)
|
||||
|
||||
await test.step('Opening the project and entering sketch mode', async () => {
|
||||
await expect(page.getByText(projectName)).toBeVisible()
|
||||
await page.getByText(projectName).click()
|
||||
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
// go to sketch mode
|
||||
await (await toolbar.getFeatureTreeOperation('Sketch', 0)).dblclick()
|
||||
|
||||
// Without this, "add axis n grid" action runs after editing the sketch and invokes codeManager.writeToFile()
|
||||
// so we wait for that action to run first before we start editing the sketch and making sure it's saving
|
||||
// because of those edits.
|
||||
await page.waitForTimeout(2000)
|
||||
})
|
||||
|
||||
const changedLine = 'line(end = [-6.54, -4.99])'
|
||||
|
||||
await test.step('Dragging the line endpoint to modify it', async () => {
|
||||
// Get the last line's endpoint position
|
||||
const lineEnd = await u.getBoundingBox('[data-overlay-index="3"]')
|
||||
|
||||
await page.mouse.move(lineEnd.x, lineEnd.y - 5)
|
||||
await page.mouse.down()
|
||||
await page.mouse.move(lineEnd.x + 80, lineEnd.y)
|
||||
await page.mouse.up()
|
||||
|
||||
await editor.expectEditor.toContain(changedLine)
|
||||
|
||||
// Exit sketch mode
|
||||
await page.keyboard.press('Escape')
|
||||
await page.waitForTimeout(100)
|
||||
})
|
||||
|
||||
await test.step('Going back to dashboard', async () => {
|
||||
await page.getByTestId('app-logo').click()
|
||||
await page.waitForTimeout(1000)
|
||||
})
|
||||
|
||||
await test.step('Reopening the project and verifying changes are saved', async () => {
|
||||
await page.getByText(projectName).click()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
// Check if new line coordinates were saved
|
||||
await editor.expectEditor.toContain(changedLine)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
@ -63,7 +63,7 @@ test.describe('edit with AI example snapshots', () => {
|
||||
test(
|
||||
`change colour`,
|
||||
// TODO this is more of a snapshot, but atm it needs to be manually run locally to update the files
|
||||
{ tag: ['@electron'] },
|
||||
{ tag: ['@desktop'] },
|
||||
async ({ context, homePage, cmdBar, editor, page, scene }) => {
|
||||
const project = 'test-dir'
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
|
@ -558,7 +558,7 @@ extrude002 = extrude(profile002, length = 150)
|
||||
|
||||
test(
|
||||
`Network health indicator only appears in modeling view`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'bracket')
|
||||
|
@ -1733,7 +1733,7 @@ profile003 = startProfile(sketch001, at = [206.63, -56.73])
|
||||
await page.waitForTimeout(600)
|
||||
})
|
||||
|
||||
const codeFromTangentialArc = ` |> tangentialArc(endAbsolute = [39.49, 88.22])`
|
||||
const codeFromTangentialArc = ` |> tangentialArc(end = [-10.82, 144.95])`
|
||||
await test.step('check that tangential tool does not snap to other profile starts', async () => {
|
||||
await toolbar.selectTangentialArc()
|
||||
await page.waitForTimeout(1000)
|
||||
@ -1755,7 +1755,7 @@ profile003 = startProfile(sketch001, at = [206.63, -56.73])
|
||||
// check pixel is now gray at tanArcLocation to verify code has executed
|
||||
await scene.expectPixelColor([26, 26, 26], tanArcLocation, 15)
|
||||
await editor.expectEditor.not.toContain(
|
||||
`tangentialArc(endAbsolute = [39.49, 88.22])`
|
||||
`tangentialArc(end = [-10.82, 144.95])`
|
||||
)
|
||||
})
|
||||
|
||||
@ -1955,7 +1955,7 @@ profile003 = startProfile(sketch001, at = [206.63, -56.73])
|
||||
|
||||
await endArcStartLine()
|
||||
await editor.expectEditor.toContain(
|
||||
`|> tangentialArc(endAbsolute = [16.61, 4.14])`
|
||||
`|> tangentialArc(end = [2.98, -7.52])`
|
||||
)
|
||||
|
||||
// Add a three-point arc segment
|
||||
@ -2362,7 +2362,7 @@ profile004 = circleThreePoint(sketch001, p1 = [13.44, -6.8], p2 = [13.39, -2.07]
|
||||
|
||||
await test.step('add new profile', async () => {
|
||||
await toolbar.rectangleBtn.click()
|
||||
await page.waitForTimeout(100)
|
||||
await page.waitForTimeout(200)
|
||||
await rectStart()
|
||||
await editor.expectEditor.toContain(
|
||||
`profile005 = startProfile(sketch001, at = [15.68, -3.84])`
|
||||
@ -3181,7 +3181,7 @@ test.describe('Redirecting to home page and back to the original file should cle
|
||||
sketch001 = startSketchOn(XZ)
|
||||
profile001 = startProfile(sketch001, at = [0, 0])
|
||||
|> line(end = [191.39, 191.39])
|
||||
|> tangentialArc(endAbsolute = [287.08, 95.69], tag = $seg01)
|
||||
|> tangentialArc(end = [95.69, -95.7], tag = $seg01)
|
||||
|> angledLine(angle = tangentToEnd(seg01), length = 135.34)
|
||||
|> arc(interiorAbsolute = [191.39, -95.69], endAbsolute = [287.08, -95.69], tag = $seg02)
|
||||
|> angledLine(angle = tangentToEnd(seg02) + turns::HALF_TURN, length = 270.67)
|
||||
|
@ -375,22 +375,22 @@ test.describe(
|
||||
await expect(u.codeLocator).toHaveText(code)
|
||||
|
||||
await toolbar.selectTangentialArc()
|
||||
await page.waitForTimeout(100)
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
// click to continue profile
|
||||
await page.mouse.click(813, 392)
|
||||
await page.waitForTimeout(100)
|
||||
await page.waitForTimeout(300)
|
||||
|
||||
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
||||
|
||||
code += `
|
||||
|> tangentialArc(endAbsolute = [551.2, -62.01])`
|
||||
|> tangentialArc(end = [184.31, 184.31])`
|
||||
await expect(u.codeLocator).toHaveText(code)
|
||||
|
||||
// click tangential arc tool again to unequip it
|
||||
// it will be available directly in the toolbar since it was last equipped
|
||||
await toolbar.tangentialArcBtn.click()
|
||||
await page.waitForTimeout(100)
|
||||
await page.waitForTimeout(1000)
|
||||
|
||||
// screen shot should show the sketch
|
||||
await expect(page).toHaveScreenshot({
|
||||
@ -472,20 +472,20 @@ test.describe(
|
||||
await expect(u.codeLocator).toHaveText(code)
|
||||
|
||||
await toolbar.selectTangentialArc()
|
||||
await page.waitForTimeout(100)
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
// click to continue profile
|
||||
await page.mouse.click(813, 392)
|
||||
await page.waitForTimeout(100)
|
||||
await page.waitForTimeout(300)
|
||||
|
||||
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
||||
|
||||
code += `
|
||||
|> tangentialArc(endAbsolute = [551.2, -62.01])`
|
||||
|> tangentialArc(end = [184.31, 184.31])`
|
||||
await expect(u.codeLocator).toHaveText(code)
|
||||
|
||||
await toolbar.tangentialArcBtn.click()
|
||||
await page.waitForTimeout(100)
|
||||
await page.waitForTimeout(1000)
|
||||
|
||||
// screen shot should show the sketch
|
||||
await expect(page).toHaveScreenshot({
|
||||
@ -823,7 +823,7 @@ test('theme persists', async ({ page, context, homePage }) => {
|
||||
uploadThroughput: -1,
|
||||
})
|
||||
|
||||
await expect(networkToggle).toContainText('Connected')
|
||||
await expect(networkToggle).toContainText('Network health (Strong)')
|
||||
|
||||
await expect(page.getByText('building scene')).not.toBeVisible()
|
||||
|
||||
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
@ -14,8 +14,10 @@ test.describe('Test network related behaviors', () => {
|
||||
'simulate network down and network little widget',
|
||||
{ tag: '@skipLocalEngine' },
|
||||
async ({ page, homePage }) => {
|
||||
const networkToggleConnectedText = page.getByText('Connected')
|
||||
const networkToggleWeakText = page.getByText('Network health (Weak)')
|
||||
const networkToggleConnectedText = page.getByText(
|
||||
'Network health (Strong)'
|
||||
)
|
||||
const networkToggleWeakText = page.getByText('Network health (Ok)')
|
||||
|
||||
const u = await getUtils(page)
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
@ -61,7 +63,7 @@ test.describe('Test network related behaviors', () => {
|
||||
})
|
||||
|
||||
// Expect the network to be down
|
||||
await expect(networkToggle).toContainText('Problem')
|
||||
await expect(networkToggle).toContainText('Network health (Offline)')
|
||||
|
||||
// Click the network widget
|
||||
await networkWidget.click()
|
||||
@ -98,8 +100,10 @@ test.describe('Test network related behaviors', () => {
|
||||
{ tag: '@skipLocalEngine' },
|
||||
async ({ page, homePage, toolbar, scene, cmdBar }) => {
|
||||
const networkToggle = page.getByTestId('network-toggle')
|
||||
const networkToggleConnectedText = page.getByText('Connected')
|
||||
const networkToggleWeakText = page.getByText('Network health (Weak)')
|
||||
const networkToggleConnectedText = page.getByText(
|
||||
'Network health (Strong)'
|
||||
)
|
||||
const networkToggleWeakText = page.getByText('Network health (Ok)')
|
||||
|
||||
const u = await getUtils(page)
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
@ -156,7 +160,8 @@ test.describe('Test network related behaviors', () => {
|
||||
|
||||
// Expect the network to be down
|
||||
await networkToggle.hover()
|
||||
await expect(networkToggle).toContainText('Problem')
|
||||
|
||||
await expect(networkToggle).toContainText('Network health (Offline)')
|
||||
|
||||
// Ensure we are not in sketch mode
|
||||
await expect(
|
||||
@ -279,11 +284,13 @@ profile001 = startProfile(sketch001, at = [12.34, -12.34])
|
||||
|
||||
test(
|
||||
'Paused stream freezes view frame, unpause reconnect is seamless to user',
|
||||
{ tag: ['@electron', '@skipLocalEngine'] },
|
||||
{ tag: ['@desktop', '@skipLocalEngine'] },
|
||||
async ({ page, homePage, scene, cmdBar, toolbar, tronApp }) => {
|
||||
const networkToggle = page.getByTestId('network-toggle')
|
||||
const networkToggleConnectedText = page.getByText('Connected')
|
||||
const networkToggleWeakText = page.getByText('Network health (Weak)')
|
||||
const networkToggleConnectedText = page.getByText(
|
||||
'Network health (Strong)'
|
||||
)
|
||||
const networkToggleWeakText = page.getByText('Network health (Ok)')
|
||||
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
|
@ -79,20 +79,6 @@ export function runningOnWindows() {
|
||||
return process.platform === 'win32'
|
||||
}
|
||||
|
||||
async function waitForPageLoadWithRetry(page: Page) {
|
||||
await expect(async () => {
|
||||
await page.goto('/')
|
||||
const errorMessage = 'App failed to load - 🔃 Retrying ...'
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'sketch Start Sketch' }),
|
||||
errorMessage
|
||||
).toBeEnabled({
|
||||
timeout: 20_000,
|
||||
})
|
||||
}).toPass({ timeout: 70_000, intervals: [1_000] })
|
||||
}
|
||||
|
||||
// lee: This needs to be replaced by scene.settled() eventually.
|
||||
async function waitForPageLoad(page: Page) {
|
||||
await expect(page.getByRole('button', { name: 'Start Sketch' })).toBeEnabled({
|
||||
@ -354,13 +340,8 @@ async function waitForAuthAndLsp(page: Page) {
|
||||
},
|
||||
timeout: 45_000,
|
||||
})
|
||||
if (process.env.CI) {
|
||||
await waitForPageLoadWithRetry(page)
|
||||
} else {
|
||||
await page.goto('/')
|
||||
await waitForPageLoad(page)
|
||||
}
|
||||
|
||||
await page.goto('/')
|
||||
await waitForPageLoad(page)
|
||||
return waitForLspPromise
|
||||
}
|
||||
|
||||
@ -383,15 +364,9 @@ export async function getUtils(page: Page, test_?: typeof test) {
|
||||
)
|
||||
}
|
||||
|
||||
// Chrome devtools protocol session only works in Chromium
|
||||
const browserType = page.context().browser()?.browserType().name()
|
||||
const cdpSession =
|
||||
browserType !== 'chromium' ? null : await page.context().newCDPSession(page)
|
||||
|
||||
const util = {
|
||||
waitForAuthSkipAppStart: () => waitForAuthAndLsp(page),
|
||||
waitForPageLoad: () => waitForPageLoad(page),
|
||||
waitForPageLoadWithRetry: () => waitForPageLoadWithRetry(page),
|
||||
removeCurrentCode: () => removeCurrentCode(page),
|
||||
sendCustomCmd: (cmd: EngineCommand) => sendCustomCmd(page, cmd),
|
||||
updateCamPosition: async (xyz: [number, number, number]) => {
|
||||
@ -509,15 +484,9 @@ export async function getUtils(page: Page, test_?: typeof test) {
|
||||
emulateNetworkConditions: async (
|
||||
networkOptions: Protocol.Network.emulateNetworkConditionsParameters
|
||||
) => {
|
||||
if (cdpSession === null) {
|
||||
// Use a fail safe if we can't simulate disconnect (on Safari)
|
||||
return page.evaluate('window.engineCommandManager.tearDown()')
|
||||
}
|
||||
|
||||
return cdpSession?.send(
|
||||
'Network.emulateNetworkConditions',
|
||||
networkOptions
|
||||
)
|
||||
return networkOptions.offline
|
||||
? page.evaluate('window.engineCommandManager.offline()')
|
||||
: page.evaluate('window.engineCommandManager.online()')
|
||||
},
|
||||
|
||||
toNormalizedCode(text: string) {
|
||||
|
@ -3,187 +3,250 @@ import { uuidv4 } from '@src/lib/utils'
|
||||
|
||||
import { getUtils } from '@e2e/playwright/test-utils'
|
||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||
import type { Page } from '@playwright/test'
|
||||
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||
|
||||
test.describe('Testing Camera Movement', () => {
|
||||
test('Can move camera reliably', async ({
|
||||
/**
|
||||
* hack that we're implemented our own retry instead of using retries built into playwright.
|
||||
* however each of these camera drags can be flaky, because of udp
|
||||
* and so putting them together means only one needs to fail to make this test extra flaky.
|
||||
* this way we can retry within the test
|
||||
* We could break them out into separate tests, but the longest past of the test is waiting
|
||||
* for the stream to start, so it can be good to bundle related things together.
|
||||
*/
|
||||
const bakeInRetries = async ({
|
||||
mouseActions,
|
||||
afterPosition,
|
||||
beforePosition,
|
||||
retryCount = 0,
|
||||
page,
|
||||
context,
|
||||
homePage,
|
||||
scene,
|
||||
}: {
|
||||
mouseActions: () => Promise<void>
|
||||
beforePosition: [number, number, number]
|
||||
afterPosition: [number, number, number]
|
||||
retryCount?: number
|
||||
page: Page
|
||||
scene: SceneFixture
|
||||
}) => {
|
||||
const acceptableCamError = 5
|
||||
const u = await getUtils(page)
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
await scene.connectionEstablished()
|
||||
await test.step('Set up initial camera position', async () =>
|
||||
await scene.moveCameraTo({
|
||||
x: beforePosition[0],
|
||||
y: beforePosition[1],
|
||||
z: beforePosition[2],
|
||||
}))
|
||||
|
||||
await u.openAndClearDebugPanel()
|
||||
await u.closeKclCodePanel()
|
||||
|
||||
const camPos: [number, number, number] = [0, 85, 85]
|
||||
const bakeInRetries = async (
|
||||
mouseActions: any,
|
||||
xyz: [number, number, number],
|
||||
cnt = 0
|
||||
) => {
|
||||
// hack that we're implemented our own retry instead of using retries built into playwright.
|
||||
// however each of these camera drags can be flaky, because of udp
|
||||
// and so putting them together means only one needs to fail to make this test extra flaky.
|
||||
// this way we can retry within the test
|
||||
// We could break them out into separate tests, but the longest past of the test is waiting
|
||||
// for the stream to start, so it can be good to bundle related things together.
|
||||
|
||||
const camCommand: EngineCommand = {
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_look_at',
|
||||
center: { x: 0, y: 0, z: 0 },
|
||||
vantage: { x: camPos[0], y: camPos[1], z: camPos[2] },
|
||||
up: { x: 0, y: 0, z: 1 },
|
||||
},
|
||||
}
|
||||
const updateCamCommand: EngineCommand = {
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_get_settings',
|
||||
},
|
||||
}
|
||||
await u.sendCustomCmd(camCommand)
|
||||
await page.waitForTimeout(100)
|
||||
await u.sendCustomCmd(updateCamCommand)
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
// rotate
|
||||
await u.closeDebugPanel()
|
||||
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
||||
await page.waitForTimeout(100)
|
||||
// const yo = page.getByTestId('cam-x-position').inputValue()
|
||||
|
||||
await u.doAndWaitForImageDiff(async () => {
|
||||
await test.step('Do actions and watch for changes', async () =>
|
||||
u.doAndWaitForImageDiff(async () => {
|
||||
await mouseActions()
|
||||
|
||||
await u.openAndClearDebugPanel()
|
||||
|
||||
await u.closeDebugPanel()
|
||||
await page.waitForTimeout(100)
|
||||
}, 300)
|
||||
}, 300))
|
||||
|
||||
await u.openAndClearDebugPanel()
|
||||
await expect(page.getByTestId('cam-x-position')).toBeAttached()
|
||||
|
||||
const vals = await Promise.all([
|
||||
page.getByTestId('cam-x-position').inputValue(),
|
||||
page.getByTestId('cam-y-position').inputValue(),
|
||||
page.getByTestId('cam-z-position').inputValue(),
|
||||
])
|
||||
const errors = vals.map((v, i) => Math.abs(Number(v) - afterPosition[i]))
|
||||
let shouldRetry = false
|
||||
|
||||
if (errors.some((e) => e > acceptableCamError)) {
|
||||
if (retryCount > 2) {
|
||||
console.log('xVal', vals[0], 'xError', errors[0])
|
||||
console.log('yVal', vals[1], 'yError', errors[1])
|
||||
console.log('zVal', vals[2], 'zError', errors[2])
|
||||
|
||||
throw new Error('Camera position not as expected', {
|
||||
cause: {
|
||||
vals,
|
||||
errors,
|
||||
},
|
||||
})
|
||||
}
|
||||
shouldRetry = true
|
||||
}
|
||||
if (shouldRetry) {
|
||||
await bakeInRetries({
|
||||
mouseActions,
|
||||
afterPosition: afterPosition,
|
||||
beforePosition: beforePosition,
|
||||
retryCount: retryCount + 1,
|
||||
page,
|
||||
scene,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
test(
|
||||
'Can pan and zoom camera reliably',
|
||||
{
|
||||
tag: '@web',
|
||||
},
|
||||
async ({ page, homePage, scene, cmdBar }) => {
|
||||
const u = await getUtils(page)
|
||||
const camInitialPosition: [number, number, number] = [0, 85, 85]
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
await u.openAndClearDebugPanel()
|
||||
await page.getByTestId('cam-x-position').isVisible()
|
||||
await u.closeKclCodePanel()
|
||||
|
||||
const vals = await Promise.all([
|
||||
page.getByTestId('cam-x-position').inputValue(),
|
||||
page.getByTestId('cam-y-position').inputValue(),
|
||||
page.getByTestId('cam-z-position').inputValue(),
|
||||
])
|
||||
const xError = Math.abs(Number(vals[0]) + xyz[0])
|
||||
const yError = Math.abs(Number(vals[1]) + xyz[1])
|
||||
const zError = Math.abs(Number(vals[2]) + xyz[2])
|
||||
await test.step('Pan', async () => {
|
||||
await bakeInRetries({
|
||||
mouseActions: async () => {
|
||||
await page.keyboard.down('Shift')
|
||||
await page.mouse.move(600, 200)
|
||||
await page.mouse.down({ button: 'right' })
|
||||
// Gotcha: remove steps:2 from this 700,200 mouse move. This bricked the test on local host engine.
|
||||
await page.mouse.move(700, 200)
|
||||
await page.mouse.up({ button: 'right' })
|
||||
await page.keyboard.up('Shift')
|
||||
await page.waitForTimeout(200)
|
||||
},
|
||||
afterPosition: [19, 85, 85],
|
||||
beforePosition: camInitialPosition,
|
||||
page,
|
||||
scene,
|
||||
})
|
||||
})
|
||||
|
||||
let shouldRetry = false
|
||||
await test.step('Zoom with click and drag', async () => {
|
||||
await bakeInRetries({
|
||||
mouseActions: async () => {
|
||||
await page.keyboard.down('Control')
|
||||
await page.mouse.move(700, 400)
|
||||
await page.mouse.down({ button: 'right' })
|
||||
await page.mouse.move(700, 300)
|
||||
await page.mouse.up({ button: 'right' })
|
||||
await page.keyboard.up('Control')
|
||||
},
|
||||
afterPosition: [0, 118, 118],
|
||||
beforePosition: camInitialPosition,
|
||||
page,
|
||||
scene,
|
||||
})
|
||||
})
|
||||
|
||||
if (xError > 5 || yError > 5 || zError > 5) {
|
||||
if (cnt > 2) {
|
||||
console.log('xVal', vals[0], 'xError', xError)
|
||||
console.log('yVal', vals[1], 'yError', yError)
|
||||
console.log('zVal', vals[2], 'zError', zError)
|
||||
|
||||
throw new Error('Camera position not as expected')
|
||||
await test.step('Zoom with scrollwheel', async () => {
|
||||
const refreshCamValuesCmd: EngineCommand = {
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_get_settings',
|
||||
},
|
||||
}
|
||||
shouldRetry = true
|
||||
}
|
||||
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
||||
await page.waitForTimeout(100)
|
||||
if (shouldRetry) await bakeInRetries(mouseActions, xyz, cnt + 1)
|
||||
await bakeInRetries({
|
||||
mouseActions: async () => {
|
||||
await page.mouse.move(700, 400)
|
||||
await page.mouse.wheel(0, -150)
|
||||
|
||||
// Scroll zooming doesn't update the debug pane's cam position values,
|
||||
// so we have to force a refresh.
|
||||
await u.openAndClearDebugPanel()
|
||||
await u.sendCustomCmd(refreshCamValuesCmd)
|
||||
await u.waitForCmdReceive('default_camera_get_settings')
|
||||
await u.closeDebugPanel()
|
||||
},
|
||||
afterPosition: [0, 42.5, 42.5],
|
||||
beforePosition: camInitialPosition,
|
||||
page,
|
||||
scene,
|
||||
})
|
||||
})
|
||||
}
|
||||
await bakeInRetries(async () => {
|
||||
await page.mouse.move(700, 200)
|
||||
await page.mouse.down({ button: 'right' })
|
||||
await page.waitForTimeout(100)
|
||||
)
|
||||
|
||||
const appLogoBBox = await page.getByTestId('app-logo').boundingBox()
|
||||
expect(appLogoBBox).not.toBeNull()
|
||||
if (!appLogoBBox) throw new Error('app logo not found')
|
||||
await page.mouse.move(
|
||||
appLogoBBox.x + appLogoBBox.width / 2,
|
||||
appLogoBBox.y + appLogoBBox.height / 2
|
||||
)
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.move(600, 303)
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.up({ button: 'right' })
|
||||
}, [4, -10.5, -120])
|
||||
test(
|
||||
'Can orbit camera reliably',
|
||||
{
|
||||
tag: '@web',
|
||||
},
|
||||
async ({ page, homePage, scene, cmdBar }) => {
|
||||
const u = await getUtils(page)
|
||||
const initialCamPosition: [number, number, number] = [0, 85, 85]
|
||||
|
||||
await bakeInRetries(async () => {
|
||||
await page.keyboard.down('Shift')
|
||||
await page.mouse.move(600, 200)
|
||||
await page.mouse.down({ button: 'right' })
|
||||
// Gotcha: remove steps:2 from this 700,200 mouse move. This bricked the test on local host engine.
|
||||
await page.mouse.move(700, 200)
|
||||
await page.mouse.up({ button: 'right' })
|
||||
await page.keyboard.up('Shift')
|
||||
}, [-19, -85, -85])
|
||||
await homePage.goToModelingScene()
|
||||
// this turns on the debug pane setting as well
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
const camCommand: EngineCommand = {
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_look_at',
|
||||
center: { x: 0, y: 0, z: 0 },
|
||||
vantage: { x: camPos[0], y: camPos[1], z: camPos[2] },
|
||||
up: { x: 0, y: 0, z: 1 },
|
||||
},
|
||||
await u.openAndClearDebugPanel()
|
||||
await u.closeKclCodePanel()
|
||||
|
||||
await test.step('Test orbit with spherical mode', async () => {
|
||||
await bakeInRetries({
|
||||
mouseActions: async () => {
|
||||
await page.mouse.move(700, 200)
|
||||
await page.mouse.down({ button: 'right' })
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
const appLogoBBox = await page.getByTestId('app-logo').boundingBox()
|
||||
expect(appLogoBBox).not.toBeNull()
|
||||
if (!appLogoBBox) throw new Error('app logo not found')
|
||||
await page.mouse.move(
|
||||
appLogoBBox.x + appLogoBBox.width / 2,
|
||||
appLogoBBox.y + appLogoBBox.height / 2
|
||||
)
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.move(600, 303)
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.up({ button: 'right' })
|
||||
},
|
||||
afterPosition: [-4, 10.5, 120],
|
||||
beforePosition: initialCamPosition,
|
||||
page,
|
||||
scene,
|
||||
})
|
||||
})
|
||||
|
||||
await test.step('Test orbit with trackball mode', async () => {
|
||||
await test.step('Set orbitMode to trackball', async () => {
|
||||
await cmdBar.openCmdBar()
|
||||
await cmdBar.selectOption({ name: 'camera orbit' }).click()
|
||||
await cmdBar.selectOption({ name: 'trackball' }).click()
|
||||
await expect(
|
||||
page.getByText(`camera orbit to "trackball"`)
|
||||
).toBeVisible()
|
||||
})
|
||||
|
||||
await bakeInRetries({
|
||||
mouseActions: async () => {
|
||||
await page.mouse.move(700, 200)
|
||||
await page.mouse.down({ button: 'right' })
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
const appLogoBBox = await page.getByTestId('app-logo').boundingBox()
|
||||
expect(appLogoBBox).not.toBeNull()
|
||||
if (!appLogoBBox) {
|
||||
throw new Error('app logo not found')
|
||||
}
|
||||
await page.mouse.move(
|
||||
appLogoBBox.x + appLogoBBox.width / 2,
|
||||
appLogoBBox.y + appLogoBBox.height / 2
|
||||
)
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.move(600, 303)
|
||||
await page.waitForTimeout(100)
|
||||
await page.mouse.up({ button: 'right' })
|
||||
},
|
||||
afterPosition: [18.06, -42.79, 110.87],
|
||||
beforePosition: initialCamPosition,
|
||||
page,
|
||||
scene,
|
||||
})
|
||||
})
|
||||
}
|
||||
const updateCamCommand: EngineCommand = {
|
||||
type: 'modeling_cmd_req',
|
||||
cmd_id: uuidv4(),
|
||||
cmd: {
|
||||
type: 'default_camera_get_settings',
|
||||
},
|
||||
}
|
||||
await u.sendCustomCmd(camCommand)
|
||||
await page.waitForTimeout(100)
|
||||
await u.sendCustomCmd(updateCamCommand)
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
await u.clearCommandLogs()
|
||||
await u.closeDebugPanel()
|
||||
|
||||
await page.getByRole('button', { name: 'Start Sketch' }).click()
|
||||
await page.waitForTimeout(200)
|
||||
|
||||
// zoom
|
||||
await u.doAndWaitForImageDiff(async () => {
|
||||
await page.keyboard.down('Control')
|
||||
await page.mouse.move(700, 400)
|
||||
await page.mouse.down({ button: 'right' })
|
||||
await page.mouse.move(700, 300)
|
||||
await page.mouse.up({ button: 'right' })
|
||||
await page.keyboard.up('Control')
|
||||
|
||||
await u.openDebugPanel()
|
||||
await page.waitForTimeout(300)
|
||||
await u.clearCommandLogs()
|
||||
|
||||
await u.closeDebugPanel()
|
||||
}, 300)
|
||||
|
||||
// zoom with scroll
|
||||
await u.openAndClearDebugPanel()
|
||||
// TODO, it appears we don't get the cam setting back from the engine when the interaction is zoom into `backInRetries` once the information is sent back on zoom
|
||||
// await expect(Math.abs(Number(await page.getByTestId('cam-x-position').inputValue()) + 12)).toBeLessThan(1.5)
|
||||
// await expect(Math.abs(Number(await page.getByTestId('cam-y-position').inputValue()) - 85)).toBeLessThan(1.5)
|
||||
// await expect(Math.abs(Number(await page.getByTestId('cam-z-position').inputValue()) - 85)).toBeLessThan(1.5)
|
||||
|
||||
await page.getByRole('button', { name: 'Exit Sketch' }).click()
|
||||
|
||||
await bakeInRetries(async () => {
|
||||
await page.mouse.move(700, 400)
|
||||
await page.mouse.wheel(0, -100)
|
||||
}, [0, -85, -85])
|
||||
})
|
||||
)
|
||||
|
||||
// TODO: fix after electron migration is merged
|
||||
test('Zoom should be consistent when exiting or entering sketches', async ({
|
||||
|
@ -1120,7 +1120,7 @@ part002 = startSketchOn(XZ)
|
||||
test.describe('Electron constraint tests', () => {
|
||||
test(
|
||||
'Able to double click label to set constraint',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, context, homePage, scene, editor, toolbar, cmdBar }) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = path.join(dir, 'test-sample')
|
||||
|
@ -84,7 +84,7 @@ test.describe('Testing loading external models', () => {
|
||||
*/
|
||||
test(
|
||||
'Desktop: should create new file by default, creates a second file with automatic unique name',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ editor, context, page, scene, cmdBar, toolbar }) => {
|
||||
if (runningOnWindows()) {
|
||||
}
|
||||
@ -196,7 +196,7 @@ test.describe('Testing loading external models', () => {
|
||||
externalModelCases.map(({ modelName, deconflictedModelName, modelPath }) => {
|
||||
test(
|
||||
`Load external models from local drive - ${modelName}`,
|
||||
{ tag: ['@electron'] },
|
||||
{ tag: ['@desktop'] },
|
||||
async ({ page, homePage, scene, toolbar, cmdBar, tronApp }) => {
|
||||
if (!tronApp) {
|
||||
fail()
|
||||
|
@ -278,7 +278,7 @@ test.describe(
|
||||
|
||||
test(
|
||||
`Project settings override user settings on desktop`,
|
||||
{ tag: ['@electron'] },
|
||||
{ tag: ['@desktop'] },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const projectName = 'bracket'
|
||||
const { dir: projectDirName } = await context.folderSetupFn(
|
||||
@ -373,7 +373,7 @@ test.describe(
|
||||
test(
|
||||
`Load desktop app with no settings file`,
|
||||
{
|
||||
tag: '@electron',
|
||||
tag: '@desktop',
|
||||
},
|
||||
async ({ page }, testInfo) => {
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
@ -393,7 +393,7 @@ test.describe(
|
||||
test(
|
||||
`Load desktop app with a settings file, but no project directory setting`,
|
||||
{
|
||||
tag: '@electron',
|
||||
tag: '@desktop',
|
||||
},
|
||||
async ({ context, page, tronApp }, testInfo) => {
|
||||
if (!tronApp) {
|
||||
@ -425,7 +425,7 @@ test.describe(
|
||||
test(
|
||||
'user settings reload on external change, on project and modeling view',
|
||||
{
|
||||
tag: '@electron',
|
||||
tag: '@desktop',
|
||||
},
|
||||
async ({ context, page, tronApp }, testInfo) => {
|
||||
if (!tronApp) {
|
||||
@ -486,7 +486,7 @@ test.describe(
|
||||
|
||||
test(
|
||||
'project settings reload on external change',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const { dir: projectDirName } = await context.folderSetupFn(
|
||||
async () => {}
|
||||
@ -536,7 +536,7 @@ test.describe(
|
||||
|
||||
test(
|
||||
`Closing settings modal should go back to the original file being viewed`,
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
await context.folderSetupFn(async (dir) => {
|
||||
const bracketDir = join(dir, 'project-000')
|
||||
|
@ -640,7 +640,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> New Project -> Stay in home page -> Reject -> Project should be deleted',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const projectName = 'my-project-name'
|
||||
const prompt = '2x2x2 cube'
|
||||
@ -678,7 +678,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> New Project -> Stay in home page -> Accept -> should navigate to file',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ context, page }, testInfo) => {
|
||||
const u = await getUtils(page)
|
||||
const projectName = 'my-project-name'
|
||||
@ -724,7 +724,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> Existing Project -> Stay in home page -> Reject -> should delete single file',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ homePage, page }, testInfo) => {
|
||||
const projectName = 'my-project-name'
|
||||
const prompt = '2x2x2 cube'
|
||||
@ -767,7 +767,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> Existing Project -> Stay in home page -> Accept -> should navigate to file',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ homePage, page }, testInfo) => {
|
||||
const u = await getUtils(page)
|
||||
const projectName = 'my-project-name'
|
||||
@ -818,7 +818,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> New Project -> Navigate to the project -> Reject -> should go to home page',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ homePage, page }, testInfo) => {
|
||||
const projectName = 'my-project-name'
|
||||
const prompt = '2x2x2 cube'
|
||||
@ -864,7 +864,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> New Project -> Navigate to the project -> Accept -> should stay in same file',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ homePage, page }, testInfo) => {
|
||||
const projectName = 'my-project-name'
|
||||
const prompt = '2x2x2 cube'
|
||||
@ -907,7 +907,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> Existing Project -> Navigate to the project -> Reject -> should load main.kcl',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ homePage, page }, testInfo) => {
|
||||
const u = await getUtils(page)
|
||||
const projectName = 'my-project-name'
|
||||
@ -962,7 +962,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> Existing Project -> Navigate to the project -> Accept -> should load 2x2x2-cube.kcl',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ homePage, page }, testInfo) => {
|
||||
const u = await getUtils(page)
|
||||
const projectName = 'my-project-name'
|
||||
@ -1019,7 +1019,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> New Project -> Navigate to different project -> Reject -> should stay in project',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ homePage, page }, testInfo) => {
|
||||
const u = await getUtils(page)
|
||||
const projectName = 'my-project-name'
|
||||
@ -1096,7 +1096,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> New Project -> Navigate to different project -> Accept -> should go to new project',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, homePage }, testInfo) => {
|
||||
const u = await getUtils(page)
|
||||
const projectName = 'my-project-name'
|
||||
@ -1165,7 +1165,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> Existing Project -> Navigate to different project -> Reject -> should stay in same project',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, homePage }, testInfo) => {
|
||||
const u = await getUtils(page)
|
||||
const projectName = 'my-project-name'
|
||||
@ -1240,7 +1240,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
||||
|
||||
test(
|
||||
'Home Page -> Text To CAD -> Existing Project -> Navigate to different project -> Accept -> should navigate to new project',
|
||||
{ tag: '@electron' },
|
||||
{ tag: '@desktop' },
|
||||
async ({ page, homePage }, testInfo) => {
|
||||
const u = await getUtils(page)
|
||||
const projectName = 'my-project-name'
|
||||
|
@ -133,9 +133,9 @@
|
||||
"test:unit": "vitest run --mode development --exclude **/jest-component-unit-tests/*",
|
||||
"test:unit:components": "jest -c jest-component-unit-tests/jest.config.ts --rootDir jest-component-unit-tests/",
|
||||
"test:e2e:web": "cross-env TARGET=web NODE_ENV=development playwright test --config=playwright.config.ts --project=\"Google Chrome\" --grep=@web",
|
||||
"test:playwright:electron": "playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot",
|
||||
"test:playwright:electron:local": "npm run tronb:vite:dev && playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot --grep-invert=\"$(curl --silent https://test-analysis-bot.hawk-dinosaur.ts.net/projects/KittyCAD/modeling-app/tests/disabled/regex)\"",
|
||||
"test:playwright:electron:local-engine": "npm run tronb:vite:dev && playwright test --config=playwright.electron.config.ts --grep-invert='@snapshot|@skipLocalEngine' --grep-invert=\"$(curl --silent https://test-analysis-bot.hawk-dinosaur.ts.net/projects/KittyCAD/modeling-app/tests/disabled/regex)\"",
|
||||
"test:e2e:desktop": "cross-env TARGET=desktop playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot",
|
||||
"test:e2e:desktop:local": "cross-env TARGET=desktop npm run tronb:vite:dev && playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot --grep-invert=\"$(curl --silent https://test-analysis-bot.hawk-dinosaur.ts.net/projects/KittyCAD/modeling-app/tests/disabled/regex)\"",
|
||||
"test:e2e:desktop:local-engine": "cross-env TARGET=desktop npm run tronb:vite:dev && playwright test --config=playwright.electron.config.ts --grep-invert='@snapshot|@skipLocalEngine' --grep-invert=\"$(curl --silent https://test-analysis-bot.hawk-dinosaur.ts.net/projects/KittyCAD/modeling-app/tests/disabled/regex)\"",
|
||||
"test:unit:local": "npm run simpleserver:bg && npm run test:unit; kill-port 3000"
|
||||
},
|
||||
"browserslist": {
|
||||
|
@ -27,7 +27,7 @@ if len(modified_release_body) > max_length:
|
||||
# Message to send to Discord
|
||||
data = {
|
||||
"content": textwrap.dedent(f'''
|
||||
**{release_version}** is now available! Check out the latest features and improvements here: <https://zoo.dev/design-studio>
|
||||
**{release_version}** is now available! Check out the latest features and improvements here: <https://zoo.dev/design-studio/download#added>
|
||||
|
||||
{modified_release_body}
|
||||
'''),
|
||||
|
@ -27,6 +27,8 @@ When you submit a PR to add or modify KCL samples, images will be generated and
|
||||
[](axial-fan/main.kcl)
|
||||
#### [ball-bearing](ball-bearing/main.kcl) ([screenshot](screenshots/ball-bearing.png))
|
||||
[](ball-bearing/main.kcl)
|
||||
#### [ball-joint-rod-end](ball-joint-rod-end/main.kcl) ([screenshot](screenshots/ball-joint-rod-end.png))
|
||||
[](ball-joint-rod-end/main.kcl)
|
||||
#### [bench](bench/main.kcl) ([screenshot](screenshots/bench.png))
|
||||
[](bench/main.kcl)
|
||||
#### [bone-plate](bone-plate/main.kcl) ([screenshot](screenshots/bone-plate.png))
|
||||
|