Compare commits
1 Commits
nested_dir
...
franknoiro
Author | SHA1 | Date | |
---|---|---|---|
a07307bd0a |
2
.github/ci-cd-scripts/upload-results.sh
vendored
@ -6,7 +6,6 @@ if [ -z "${TAB_API_URL:-}" ] || [ -z "${TAB_API_KEY:-}" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
project="https://github.com/KittyCAD/modeling-app"
|
project="https://github.com/KittyCAD/modeling-app"
|
||||||
suite="${CI_SUITE:-unit}"
|
|
||||||
branch="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-}}"
|
branch="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-}}"
|
||||||
commit="${CI_COMMIT_SHA:-${GITHUB_SHA:-}}"
|
commit="${CI_COMMIT_SHA:-${GITHUB_SHA:-}}"
|
||||||
|
|
||||||
@ -14,7 +13,6 @@ echo "Uploading batch results"
|
|||||||
curl --silent --request POST \
|
curl --silent --request POST \
|
||||||
--header "X-API-Key: ${TAB_API_KEY}" \
|
--header "X-API-Key: ${TAB_API_KEY}" \
|
||||||
--form "project=${project}" \
|
--form "project=${project}" \
|
||||||
--form "suite=${suite}" \
|
|
||||||
--form "branch=${branch}" \
|
--form "branch=${branch}" \
|
||||||
--form "commit=${commit}" \
|
--form "commit=${commit}" \
|
||||||
--form "tests=@test-results/junit.xml" \
|
--form "tests=@test-results/junit.xml" \
|
||||||
|
56
.github/workflows/build-wasm.yml
vendored
@ -1,56 +0,0 @@
|
|||||||
name: Build WASM
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
npm-build-wasm:
|
|
||||||
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm install
|
|
||||||
|
|
||||||
- name: Use correct Rust toolchain
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
|
||||||
|
|
||||||
- name: Install rust
|
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
||||||
with:
|
|
||||||
cache: false # configured below
|
|
||||||
|
|
||||||
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
|
||||||
with:
|
|
||||||
tool: wasm-pack
|
|
||||||
|
|
||||||
- name: Use Rust cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: './rust'
|
|
||||||
|
|
||||||
- name: Build Wasm
|
|
||||||
shell: bash
|
|
||||||
run: npm run build:wasm
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: prepared-wasm
|
|
||||||
path: |
|
|
||||||
rust/kcl-wasm-lib/pkg/kcl_wasm_lib*
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: prepared-ts-rs-bindings
|
|
||||||
path: |
|
|
||||||
rust/kcl-lib/bindings/*
|
|
55
.github/workflows/cargo-test.yml
vendored
@ -88,7 +88,6 @@ jobs:
|
|||||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN_DEV}}
|
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN_DEV}}
|
||||||
ZOO_HOST: https://api.dev.zoo.dev
|
ZOO_HOST: https://api.dev.zoo.dev
|
||||||
RUST_BACKTRACE: full
|
RUST_BACKTRACE: full
|
||||||
RUST_MIN_STACK: 10485760000
|
|
||||||
- name: Commit differences
|
- name: Commit differences
|
||||||
if: steps.path-changes.outputs.outside-kcl-samples == 'false' && steps.cargo-test-kcl-samples.outcome == 'failure'
|
if: steps.path-changes.outputs.outside-kcl-samples == 'false' && steps.cargo-test-kcl-samples.outcome == 'failure'
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -120,7 +119,6 @@ jobs:
|
|||||||
# Configure nextest when it's run by insta (via just).
|
# Configure nextest when it's run by insta (via just).
|
||||||
NEXTEST_PROFILE: ci
|
NEXTEST_PROFILE: ci
|
||||||
RUST_BACKTRACE: full
|
RUST_BACKTRACE: full
|
||||||
RUST_MIN_STACK: 10485760000
|
|
||||||
- name: Build and archive tests
|
- name: Build and archive tests
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
@ -157,7 +155,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||||
- name: Install Rust
|
- name: Install rust
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: false # Configured below.
|
cache: false # Configured below.
|
||||||
@ -184,7 +182,6 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN_DEV}}
|
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN_DEV}}
|
||||||
ZOO_HOST: https://api.dev.zoo.dev
|
ZOO_HOST: https://api.dev.zoo.dev
|
||||||
RUST_MIN_STACK: 10485760000
|
|
||||||
- name: Upload results
|
- name: Upload results
|
||||||
if: always()
|
if: always()
|
||||||
run: .github/ci-cd-scripts/upload-results.sh
|
run: .github/ci-cd-scripts/upload-results.sh
|
||||||
@ -193,56 +190,6 @@ jobs:
|
|||||||
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
||||||
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
CI_SUITE: unit:kcl
|
|
||||||
run-internal-kcl-samples:
|
|
||||||
name: cargo test (internal-kcl-samples)
|
|
||||||
runs-on:
|
|
||||||
- runs-on=${{ github.run_id }}
|
|
||||||
- runner=32cpu-linux-x64
|
|
||||||
- extras=s3-cache
|
|
||||||
steps:
|
|
||||||
- uses: runs-on/action@v1
|
|
||||||
- uses: actions/create-github-app-token@v1
|
|
||||||
id: app-token
|
|
||||||
with:
|
|
||||||
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
|
||||||
private-key: ${{ secrets.MODELING_APP_GH_APP_PRIVATE_KEY }}
|
|
||||||
owner: ${{ github.repository_owner }}
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ steps.app-token.outputs.token }}
|
|
||||||
- name: Use correct Rust toolchain
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
|
||||||
- name: Install Rust
|
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
||||||
with:
|
|
||||||
cache: false # Configured below.
|
|
||||||
- name: Start Vector
|
|
||||||
run: .github/ci-cd-scripts/start-vector-ubuntu.sh
|
|
||||||
env:
|
|
||||||
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
|
||||||
OS_NAME: ${{ env.OS_NAME }}
|
|
||||||
- uses: taiki-e/install-action@nextest
|
|
||||||
- name: Download internal KCL samples
|
|
||||||
run: git clone --depth=1 https://x-access-token:${{ secrets.GH_PAT_KCL_SAMPLES_INTERNAL }}@github.com/KittyCAD/kcl-samples-internal public/kcl-samples/internal
|
|
||||||
- name: Run tests
|
|
||||||
shell: bash
|
|
||||||
run: |-
|
|
||||||
cd rust/kcl-lib
|
|
||||||
cargo nextest run \
|
|
||||||
--retries=10 --no-fail-fast --features artifact-graph --profile=ci \
|
|
||||||
internal \
|
|
||||||
2>&1 | tee /tmp/github-actions.log
|
|
||||||
env:
|
|
||||||
TWENTY_TWENTY: overwrite
|
|
||||||
INSTA_UPDATE: always
|
|
||||||
EXPECTORATE: overwrite
|
|
||||||
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN_DEV}}
|
|
||||||
ZOO_HOST: https://api.dev.zoo.dev
|
|
||||||
MODELING_APP_INTERNAL_SAMPLES_SECRET: ${{secrets.MODELING_APP_INTERNAL_SAMPLES_SECRET}}
|
|
||||||
RUST_MIN_STACK: 10485760000
|
|
||||||
run-wasm-tests:
|
run-wasm-tests:
|
||||||
name: Run wasm tests
|
name: Run wasm tests
|
||||||
strategy:
|
strategy:
|
||||||
|
17
.github/workflows/e2e-tests.yml
vendored
@ -143,7 +143,7 @@ jobs:
|
|||||||
- name: Install browsers
|
- name: Install browsers
|
||||||
run: npm run playwright install --with-deps
|
run: npm run playwright install --with-deps
|
||||||
|
|
||||||
- name: Test snapshots
|
- name: Capture snapshots
|
||||||
uses: nick-fields/retry@v3.0.2
|
uses: nick-fields/retry@v3.0.2
|
||||||
with:
|
with:
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -156,19 +156,6 @@ jobs:
|
|||||||
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
||||||
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
CI_SUITE: snapshots
|
|
||||||
TARGET: web
|
|
||||||
|
|
||||||
- name: Update snapshots
|
|
||||||
if: always()
|
|
||||||
run: npm run test:snapshots -- --last-failed --update-snapshots
|
|
||||||
env:
|
|
||||||
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
|
||||||
TAB_API_URL: ${{ secrets.TAB_API_URL }}
|
|
||||||
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
|
||||||
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
|
||||||
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
||||||
CI_SUITE: snapshots
|
|
||||||
TARGET: web
|
TARGET: web
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
@ -186,7 +173,7 @@ jobs:
|
|||||||
id: git-check
|
id: git-check
|
||||||
run: |
|
run: |
|
||||||
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
||||||
if git status | grep --quiet "Changes to be committed"
|
if git status | grep -q "Changes to be committed"
|
||||||
then echo "modified=true" >> $GITHUB_OUTPUT
|
then echo "modified=true" >> $GITHUB_OUTPUT
|
||||||
else echo "modified=false" >> $GITHUB_OUTPUT
|
else echo "modified=false" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
|
99
.github/workflows/kcl-language-server.yml
vendored
@ -21,11 +21,14 @@ on:
|
|||||||
- '**.rs'
|
- '**.rs'
|
||||||
- .github/workflows/kcl-language-server.yml
|
- .github/workflows/kcl-language-server.yml
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_INCREMENTAL: 0
|
CARGO_INCREMENTAL: 0
|
||||||
CARGO_NET_RETRY: 10
|
CARGO_NET_RETRY: 10
|
||||||
@ -35,9 +38,10 @@ env:
|
|||||||
MACOSX_DEPLOYMENT_TARGET: 10.15
|
MACOSX_DEPLOYMENT_TARGET: 10.15
|
||||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||||
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: kcl-language-server (vscode tests)
|
name: vscode tests
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@ -73,20 +77,22 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
target: x86_64-pc-windows-msvc
|
target: x86_64-pc-windows-msvc
|
||||||
code-target: win32-x64
|
code-target:
|
||||||
#- os: windows-latest
|
win32-x64
|
||||||
#target: i686-pc-windows-msvc
|
#- os: windows-latest
|
||||||
#code-target:
|
#target: i686-pc-windows-msvc
|
||||||
#win32-ia32
|
#code-target:
|
||||||
#- os: windows-latest
|
#win32-ia32
|
||||||
#target: aarch64-pc-windows-msvc
|
#- os: windows-latest
|
||||||
#code-target: win32-arm64
|
#target: aarch64-pc-windows-msvc
|
||||||
|
#code-target: win32-arm64
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
target: x86_64-unknown-linux-gnu
|
target: x86_64-unknown-linux-gnu
|
||||||
code-target: linux-x64
|
code-target:
|
||||||
#- os: ubuntu-latest
|
linux-x64
|
||||||
#target: aarch64-unknown-linux-musl
|
#- os: ubuntu-latest
|
||||||
#code-target: linux-arm64
|
#target: aarch64-unknown-linux-musl
|
||||||
|
#code-target: linux-arm64
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
target: aarch64-unknown-linux-gnu
|
target: aarch64-unknown-linux-gnu
|
||||||
code-target: linux-arm64
|
code-target: linux-arm64
|
||||||
@ -99,33 +105,41 @@ jobs:
|
|||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
target: aarch64-apple-darwin
|
target: aarch64-apple-darwin
|
||||||
code-target: darwin-arm64
|
code-target: darwin-arm64
|
||||||
name: kcl-language-server build-release (${{ matrix.target }})
|
|
||||||
|
name: build-release (${{ matrix.target }})
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
container: ${{ matrix.container }}
|
container: ${{ matrix.container }}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
RA_TARGET: ${{ matrix.target }}
|
RA_TARGET: ${{ matrix.target }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: ${{ env.FETCH_DEPTH }}
|
fetch-depth: ${{ env.FETCH_DEPTH }}
|
||||||
|
|
||||||
- name: Use correct Rust toolchain
|
- name: Use correct Rust toolchain
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
rm rust/rust-toolchain.toml
|
rm rust/rust-toolchain.toml
|
||||||
|
|
||||||
- name: Install rust
|
- name: Install rust
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: rust
|
cache: rust
|
||||||
components: rust-src
|
components: rust-src
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
|
|
||||||
- name: Update apt repositories
|
- name: Update apt repositories
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'arm-unknown-linux-gnueabihf' || matrix.os == 'ubuntu-latest'
|
if: matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'arm-unknown-linux-gnueabihf' || matrix.os == 'ubuntu-latest'
|
||||||
run: sudo apt-get update
|
run: sudo apt-get update
|
||||||
|
|
||||||
- if: ${{ matrix.os == 'ubuntu-latest' }}
|
- if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||||
name: Install deps
|
name: Install deps
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -150,53 +164,64 @@ jobs:
|
|||||||
zlib1g-dev
|
zlib1g-dev
|
||||||
|
|
||||||
cargo install cross
|
cargo install cross
|
||||||
|
|
||||||
- name: Install AArch64 target toolchain
|
- name: Install AArch64 target toolchain
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||||
run: sudo apt-get install gcc-aarch64-linux-gnu
|
run: sudo apt-get install gcc-aarch64-linux-gnu
|
||||||
|
|
||||||
- name: Install ARM target toolchain
|
- name: Install ARM target toolchain
|
||||||
if: matrix.target == 'arm-unknown-linux-gnueabihf'
|
if: matrix.target == 'arm-unknown-linux-gnueabihf'
|
||||||
run: sudo apt-get install gcc-arm-linux-gnueabihf
|
run: sudo apt-get install gcc-arm-linux-gnueabihf
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
# npm will symlink which will cause issues w tarballing later
|
# npm will symlink which will cause issues w tarballing later
|
||||||
yarn install
|
yarn install
|
||||||
|
|
||||||
- name: Package Extension (release)
|
- name: Package Extension (release)
|
||||||
if: startsWith(github.event.ref, 'refs/tags/')
|
if: startsWith(github.event.ref, 'refs/tags/')
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }}
|
npx vsce package --yarn -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }}
|
||||||
|
|
||||||
- name: Package Extension (nightly)
|
- name: Package Extension (nightly)
|
||||||
if: startsWith(github.event.ref, 'refs/tags/') == false
|
if: startsWith(github.event.ref, 'refs/tags/') == false
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} --pre-release
|
npx vsce package --yarn -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} --pre-release
|
||||||
|
|
||||||
- name: remove server
|
- name: remove server
|
||||||
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
rm -rf server
|
rm -rf server
|
||||||
|
|
||||||
- name: Package Extension (no server, release)
|
- name: Package Extension (no server, release)
|
||||||
if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/')
|
if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/')
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o ../build/kcl-language-server-no-server.vsix
|
npx vsce package --yarn -o ../build/kcl-language-server-no-server.vsix
|
||||||
|
|
||||||
- name: Package Extension (no server, nightly)
|
- name: Package Extension (no server, nightly)
|
||||||
if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/') == false
|
if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/') == false
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o ../build/kcl-language-server-no-server.vsix --pre-release
|
npx vsce package --yarn -o ../build/kcl-language-server-no-server.vsix --pre-release
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-${{ matrix.target }}
|
name: release-${{ matrix.target }}
|
||||||
path: ./rust/build
|
path: ./rust/build
|
||||||
|
|
||||||
build-release-x86_64-unknown-linux-musl:
|
build-release-x86_64-unknown-linux-musl:
|
||||||
name: kcl-language-server build-release (x86_64-unknown-linux-musl)
|
name: build-release (x86_64-unknown-linux-musl)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
RA_TARGET: x86_64-unknown-linux-musl
|
RA_TARGET: x86_64-unknown-linux-musl
|
||||||
@ -206,6 +231,7 @@ jobs:
|
|||||||
image: alpine:latest
|
image: alpine:latest
|
||||||
volumes:
|
volumes:
|
||||||
- /usr/local/cargo/registry:/usr/local/cargo/registry
|
- /usr/local/cargo/registry:/usr/local/cargo/registry
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
@ -219,46 +245,55 @@ jobs:
|
|||||||
nodejs \
|
nodejs \
|
||||||
npm \
|
npm \
|
||||||
yarn
|
yarn
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: ${{ env.FETCH_DEPTH }}
|
fetch-depth: ${{ env.FETCH_DEPTH }}
|
||||||
|
|
||||||
- name: Use correct Rust toolchain
|
- name: Use correct Rust toolchain
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
rm rust/rust-toolchain.toml
|
rm rust/rust-toolchain.toml
|
||||||
|
|
||||||
- name: Install rust
|
- name: Install rust
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: rust
|
cache: rust
|
||||||
components: rust-src
|
components: rust-src
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
# npm will symlink which will cause issues w tarballing later
|
# npm will symlink which will cause issues w tarballing later
|
||||||
yarn install
|
yarn install
|
||||||
|
|
||||||
- name: Package Extension (release)
|
- name: Package Extension (release)
|
||||||
if: startsWith(github.event.ref, 'refs/tags/')
|
if: startsWith(github.event.ref, 'refs/tags/')
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64
|
npx vsce package --yarn -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64
|
||||||
|
|
||||||
- name: Package Extension (release)
|
- name: Package Extension (release)
|
||||||
if: startsWith(github.event.ref, 'refs/tags/') == false
|
if: startsWith(github.event.ref, 'refs/tags/') == false
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64 --pre-release
|
npx vsce package --yarn -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64 --pre-release
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-x86_64-unknown-linux-musl
|
name: release-x86_64-unknown-linux-musl
|
||||||
path: ./rust/build
|
path: ./rust/build
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
name: kcl-language-server (publish)
|
name: publish
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: ["build-release", "build-release-x86_64-unknown-linux-musl"]
|
needs: ["build-release", "build-release-x86_64-unknown-linux-musl"]
|
||||||
if: startsWith(github.event.ref, 'refs/tags')
|
if: startsWith(github.event.ref, 'refs/tags')
|
||||||
@ -266,17 +301,22 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- run: echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
- run: echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- run: 'echo "TAG: $TAG"'
|
- run: 'echo "TAG: $TAG"'
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: ${{ env.FETCH_DEPTH }}
|
fetch-depth: ${{ env.FETCH_DEPTH }}
|
||||||
|
|
||||||
- name: Install Nodejs
|
- name: Install Nodejs
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
|
|
||||||
- run: echo "HEAD_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
- run: echo "HEAD_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
||||||
- run: 'echo "HEAD_SHA: $HEAD_SHA"'
|
- run: 'echo "HEAD_SHA: $HEAD_SHA"'
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-aarch64-apple-darwin
|
name: release-aarch64-apple-darwin
|
||||||
@ -304,29 +344,33 @@ jobs:
|
|||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-x86_64-pc-windows-msvc
|
name: release-x86_64-pc-windows-msvc
|
||||||
path: rust/build
|
path:
|
||||||
#- uses: actions/download-artifact@v4
|
rust/build
|
||||||
#with:
|
#- uses: actions/download-artifact@v4
|
||||||
#name: release-i686-pc-windows-msvc
|
#with:
|
||||||
#path:
|
#name: release-i686-pc-windows-msvc
|
||||||
#build
|
#path:
|
||||||
#- uses: actions/download-artifact@v4
|
#build
|
||||||
#with:
|
#- uses: actions/download-artifact@v4
|
||||||
#name: release-aarch64-pc-windows-msvc
|
#with:
|
||||||
#path: rust/build
|
#name: release-aarch64-pc-windows-msvc
|
||||||
|
#path: rust/build
|
||||||
- run: ls -al ./rust/build
|
- run: ls -al ./rust/build
|
||||||
|
|
||||||
- name: Publish Release
|
- name: Publish Release
|
||||||
uses: ./.github/actions/github-release
|
uses: ./.github/actions/github-release
|
||||||
with:
|
with:
|
||||||
files: "rust/build/*"
|
files: "rust/build/*"
|
||||||
name: ${{ env.TAG }}
|
name: ${{ env.TAG }}
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: move files to dir for upload
|
- name: move files to dir for upload
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
mkdir -p releases/language-server/${{ env.TAG }}
|
mkdir -p releases/language-server/${{ env.TAG }}
|
||||||
cp -r build/* releases/language-server/${{ env.TAG }}
|
cp -r build/* releases/language-server/${{ env.TAG }}
|
||||||
|
|
||||||
- name: "Authenticate to Google Cloud"
|
- name: "Authenticate to Google Cloud"
|
||||||
uses: "google-github-actions/auth@v2.1.8"
|
uses: "google-github-actions/auth@v2.1.8"
|
||||||
with:
|
with:
|
||||||
@ -341,12 +385,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: rust/releases
|
path: rust/releases
|
||||||
destination: dl.kittycad.io
|
destination: dl.kittycad.io
|
||||||
|
|
||||||
- run: rm rust/build/kcl-language-server-no-server.vsix
|
- run: rm rust/build/kcl-language-server-no-server.vsix
|
||||||
|
|
||||||
- name: Publish Extension (Code Marketplace, release)
|
- name: Publish Extension (Code Marketplace, release)
|
||||||
# token from https://dev.azure.com/kcl-language-server/
|
# token from https://dev.azure.com/kcl-language-server/
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce publish --pat ${{ secrets.VSCE_PAT }} --packagePath ../build/kcl-language-server-*.vsix
|
npx vsce publish --pat ${{ secrets.VSCE_PAT }} --packagePath ../build/kcl-language-server-*.vsix
|
||||||
|
|
||||||
- name: Publish Extension (OpenVSX, release)
|
- name: Publish Extension (OpenVSX, release)
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
|
32
.github/workflows/kcl-python-bindings.yml
vendored
@ -4,6 +4,7 @@
|
|||||||
# maturin generate-ci github
|
# maturin generate-ci github
|
||||||
#
|
#
|
||||||
name: kcl-python-bindings
|
name: kcl-python-bindings
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@ -26,14 +27,16 @@ on:
|
|||||||
- '**.rs'
|
- '**.rs'
|
||||||
- .github/workflows/kcl-python-bindings.yml
|
- .github/workflows/kcl-python-bindings.yml
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
linux-x86_64:
|
linux-x86_64:
|
||||||
name: kcl-python-bindings (linux-x86_64)
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@ -55,8 +58,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-linux-x86_64
|
name: wheels-linux-x86_64
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
name: kcl-python-bindings (windows)
|
|
||||||
runs-on: windows-16-cores
|
runs-on: windows-16-cores
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -81,8 +84,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-windows-${{ matrix.target }}
|
name: wheels-windows-${{ matrix.target }}
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
name: kcl-python-bindings (macos)
|
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -107,8 +110,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-macos-${{ matrix.target }}
|
name: wheels-macos-${{ matrix.target }}
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
test:
|
test:
|
||||||
name: kcl-python-bindings (test)
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@ -124,8 +127,8 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
ZOO_HOST: https://api.dev.zoo.dev
|
ZOO_HOST: https://api.dev.zoo.dev
|
||||||
|
|
||||||
sdist:
|
sdist:
|
||||||
name: kcl-python-bindings (sdist)
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@ -133,10 +136,10 @@ jobs:
|
|||||||
uses: astral-sh/setup-uv@v5
|
uses: astral-sh/setup-uv@v5
|
||||||
- name: Install codespell
|
- name: Install codespell
|
||||||
run: |
|
run: |
|
||||||
uv venv .venv
|
uv venv .venv
|
||||||
echo "VIRTUAL_ENV=.venv" >> $GITHUB_ENV
|
echo "VIRTUAL_ENV=.venv" >> $GITHUB_ENV
|
||||||
echo "$PWD/.venv/bin" >> $GITHUB_PATH
|
echo "$PWD/.venv/bin" >> $GITHUB_PATH
|
||||||
uv pip install pip --upgrade
|
uv pip install pip --upgrade
|
||||||
- name: Build sdist
|
- name: Build sdist
|
||||||
uses: PyO3/maturin-action@v1
|
uses: PyO3/maturin-action@v1
|
||||||
with:
|
with:
|
||||||
@ -148,6 +151,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-sdist
|
name: wheels-sdist
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -164,11 +168,11 @@ jobs:
|
|||||||
uses: astral-sh/setup-uv@v5
|
uses: astral-sh/setup-uv@v5
|
||||||
- name: do uv things
|
- name: do uv things
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-python-bindings
|
cd rust/kcl-python-bindings
|
||||||
uv venv .venv
|
uv venv .venv
|
||||||
echo "VIRTUAL_ENV=.venv" >> $GITHUB_ENV
|
echo "VIRTUAL_ENV=.venv" >> $GITHUB_ENV
|
||||||
echo "$PWD/.venv/bin" >> $GITHUB_PATH
|
echo "$PWD/.venv/bin" >> $GITHUB_PATH
|
||||||
uv pip install pip --upgrade
|
uv pip install pip --upgrade
|
||||||
- name: Publish to PyPI
|
- name: Publish to PyPI
|
||||||
uses: PyO3/maturin-action@v1
|
uses: PyO3/maturin-action@v1
|
||||||
env:
|
env:
|
||||||
|
167
.github/workflows/static-analysis.yml
vendored
@ -28,7 +28,53 @@ jobs:
|
|||||||
- run: npm run fmt:check
|
- run: npm run fmt:check
|
||||||
|
|
||||||
npm-build-wasm:
|
npm-build-wasm:
|
||||||
uses: ./.github/workflows/build-wasm.yml
|
# Build 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
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Use correct Rust toolchain
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||||
|
|
||||||
|
- name: Install rust
|
||||||
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
cache: false # Configured below.
|
||||||
|
|
||||||
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
|
with:
|
||||||
|
tool: wasm-pack
|
||||||
|
|
||||||
|
- name: Rust Cache
|
||||||
|
uses: Swatinem/rust-cache@v2
|
||||||
|
with:
|
||||||
|
workspaces: './rust'
|
||||||
|
|
||||||
|
- name: Build Wasm
|
||||||
|
shell: bash
|
||||||
|
run: npm run build:wasm
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: prepared-wasm
|
||||||
|
path: |
|
||||||
|
rust/kcl-wasm-lib/pkg/kcl_wasm_lib*
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: prepared-ts-rs-bindings
|
||||||
|
path: |
|
||||||
|
rust/kcl-lib/bindings/*
|
||||||
|
|
||||||
npm-tsc:
|
npm-tsc:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -127,3 +173,122 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Run codespell
|
- name: Run codespell
|
||||||
uses: crate-ci/typos@v1.32.0
|
uses: crate-ci/typos@v1.32.0
|
||||||
|
|
||||||
|
npm-unit-test-kcl-samples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: npm-build-wasm
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- run: npm install
|
||||||
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
|
with:
|
||||||
|
tool: wasm-pack
|
||||||
|
|
||||||
|
- name: Download all artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
|
- name: Copy prepared wasm
|
||||||
|
run: |
|
||||||
|
ls -R prepared-wasm
|
||||||
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
|
mkdir rust/kcl-wasm-lib/pkg
|
||||||
|
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
|
- name: Copy prepared ts-rs bindings
|
||||||
|
run: |
|
||||||
|
ls -R prepared-ts-rs-bindings
|
||||||
|
mkdir rust/kcl-lib/bindings
|
||||||
|
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
||||||
|
|
||||||
|
- run: npm run simpleserver:bg
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
|
||||||
|
- name: Install Chromium Browser
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
run: npm run playwright install chromium --with-deps
|
||||||
|
|
||||||
|
- name: Download internal KCL samples
|
||||||
|
run: git clone --depth=1 https://x-access-token:${{ secrets.GH_PAT_KCL_SAMPLES_INTERNAL }}@github.com/KittyCAD/kcl-samples-internal public/kcl-samples/internal
|
||||||
|
|
||||||
|
- name: Regenerate KCL samples manifest
|
||||||
|
run: cd rust/kcl-lib && EXPECTORATE=overwrite cargo test generate_manifest
|
||||||
|
|
||||||
|
- name: Check public and internal KCL samples
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
run: npm run test:unit:kcl-samples
|
||||||
|
env:
|
||||||
|
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
|
|
||||||
|
npm-unit-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: npm-build-wasm
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- run: npm install
|
||||||
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
|
with:
|
||||||
|
tool: wasm-pack
|
||||||
|
|
||||||
|
- name: Download all artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
|
- name: Copy prepared wasm
|
||||||
|
run: |
|
||||||
|
ls -R prepared-wasm
|
||||||
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
|
mkdir rust/kcl-wasm-lib/pkg
|
||||||
|
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
|
- name: Copy prepared ts-rs bindings
|
||||||
|
run: |
|
||||||
|
ls -R prepared-ts-rs-bindings
|
||||||
|
mkdir rust/kcl-lib/bindings
|
||||||
|
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
||||||
|
|
||||||
|
- run: npm run simpleserver:bg
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
|
||||||
|
- name: Install Chromium Browser
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
run: npm run playwright install chromium --with-deps
|
||||||
|
|
||||||
|
- name: Run unit tests
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
run: xvfb-run -a npm run test:unit
|
||||||
|
env:
|
||||||
|
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
|
|
||||||
|
- name: Check for changes
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
id: git-check
|
||||||
|
run: |
|
||||||
|
git add src/lang/std/artifactMapGraphs
|
||||||
|
if git status src/lang/std/artifactMapGraphs | grep -q "Changes to be committed"
|
||||||
|
then echo "modified=true" >> $GITHUB_OUTPUT
|
||||||
|
else echo "modified=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
- name: Commit changes, if any
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' && steps.git-check.outputs.modified == 'true' }}
|
||||||
|
run: |
|
||||||
|
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git config --local user.name "github-actions[bot]"
|
||||||
|
git remote set-url origin https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
|
||||||
|
git fetch origin
|
||||||
|
echo ${{ github.head_ref }}
|
||||||
|
git checkout ${{ github.head_ref }}
|
||||||
|
# TODO when webkit works on ubuntu remove the os part of the commit message
|
||||||
|
git commit -am "Look at this (photo)Graph *in the voice of Nickelback*" || true
|
||||||
|
git push
|
||||||
|
git push origin ${{ github.head_ref }}
|
||||||
|
124
.github/workflows/unit-tests.yml
vendored
@ -1,124 +0,0 @@
|
|||||||
name: Unit Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
npm-build-wasm:
|
|
||||||
uses: ./.github/workflows/build-wasm.yml
|
|
||||||
|
|
||||||
npm-test-unit:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: npm-build-wasm
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- run: npm install
|
|
||||||
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
|
||||||
with:
|
|
||||||
tool: wasm-pack
|
|
||||||
|
|
||||||
- name: Download all artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
|
|
||||||
- name: Copy prepared wasm
|
|
||||||
run: |
|
|
||||||
ls -R prepared-wasm
|
|
||||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
|
||||||
mkdir rust/kcl-wasm-lib/pkg
|
|
||||||
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
|
||||||
|
|
||||||
- name: Copy prepared ts-rs bindings
|
|
||||||
run: |
|
|
||||||
ls -R prepared-ts-rs-bindings
|
|
||||||
mkdir rust/kcl-lib/bindings
|
|
||||||
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
|
||||||
|
|
||||||
- run: npm run simpleserver:bg
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
|
|
||||||
- name: Install Chromium Browser
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
run: npm run playwright install chromium --with-deps
|
|
||||||
|
|
||||||
- name: Run unit tests
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
run: xvfb-run -a npm run test:unit
|
|
||||||
env:
|
|
||||||
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
|
||||||
|
|
||||||
- name: Check for changes
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
id: git-check
|
|
||||||
run: |
|
|
||||||
git add src/lang/std/artifactMapGraphs
|
|
||||||
if git status src/lang/std/artifactMapGraphs | grep -q "Changes to be committed"
|
|
||||||
then echo "modified=true" >> $GITHUB_OUTPUT
|
|
||||||
else echo "modified=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Commit changes, if any
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' && steps.git-check.outputs.modified == 'true' }}
|
|
||||||
run: |
|
|
||||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git config --local user.name "github-actions[bot]"
|
|
||||||
git remote set-url origin https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
|
|
||||||
git fetch origin
|
|
||||||
echo ${{ github.head_ref }}
|
|
||||||
git checkout ${{ github.head_ref }}
|
|
||||||
# TODO when webkit works on ubuntu remove the os part of the commit message
|
|
||||||
git commit -am "Look at this (photo)Graph *in the voice of Nickelback*" || true
|
|
||||||
git push
|
|
||||||
git push origin ${{ github.head_ref }}
|
|
||||||
|
|
||||||
npm-test-unit-components:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: npm-build-wasm
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- run: npm install
|
|
||||||
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
|
||||||
with:
|
|
||||||
tool: wasm-pack
|
|
||||||
|
|
||||||
- name: Download all artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
|
|
||||||
- name: Copy prepared wasm
|
|
||||||
run: |
|
|
||||||
ls -R prepared-wasm
|
|
||||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
|
||||||
mkdir rust/kcl-wasm-lib/pkg
|
|
||||||
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
|
||||||
|
|
||||||
- name: Copy prepared ts-rs bindings
|
|
||||||
run: |
|
|
||||||
ls -R prepared-ts-rs-bindings
|
|
||||||
mkdir rust/kcl-lib/bindings
|
|
||||||
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
|
||||||
|
|
||||||
- name: Run component tests
|
|
||||||
run: npm run test:unit:components
|
|
2
.gitignore
vendored
@ -58,8 +58,6 @@ trace.zip
|
|||||||
/public/kcl-samples/.github
|
/public/kcl-samples/.github
|
||||||
/public/kcl-samples/screenshots/main.kcl
|
/public/kcl-samples/screenshots/main.kcl
|
||||||
/public/kcl-samples/step/main.kcl
|
/public/kcl-samples/step/main.kcl
|
||||||
/public/kcl-samples/internal
|
|
||||||
/rust/kcl-lib/tests/kcl_samples/internal
|
|
||||||
/test-results/
|
/test-results/
|
||||||
/playwright-report/
|
/playwright-report/
|
||||||
/blob-report/
|
/blob-report/
|
||||||
|
1
Makefile
@ -114,6 +114,7 @@ test-unit: install ## Run the unit tests
|
|||||||
npm run test:unit:components
|
npm run test:unit:components
|
||||||
@ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
|
@ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
|
||||||
npm run test:unit
|
npm run test:unit
|
||||||
|
npm run test:unit:kcl-samples
|
||||||
|
|
||||||
.PHONY: test-e2e
|
.PHONY: test-e2e
|
||||||
test-e2e: test-e2e-$(TARGET)
|
test-e2e: test-e2e-$(TARGET)
|
||||||
|
@ -42,6 +42,8 @@ The 3D view in Design Studio is just a video stream from our hosted geometry eng
|
|||||||
|
|
||||||
We recommend downloading the latest application binary from our [releases](https://github.com/KittyCAD/modeling-app/releases) page. If you don't see your platform or architecture supported there, please file an issue.
|
We recommend downloading the latest application binary from our [releases](https://github.com/KittyCAD/modeling-app/releases) page. If you don't see your platform or architecture supported there, please file an issue.
|
||||||
|
|
||||||
|
If you'd like to try out upcoming changes sooner, you can also download those from our [nightly releases](https://zoo.dev/modeling-app/download/nightly) page.
|
||||||
|
|
||||||
## Developing
|
## Developing
|
||||||
|
|
||||||
Finally, if you'd like to run a development build or contribute to the project, please visit our [contributor guide](CONTRIBUTING.md) to get started.
|
Finally, if you'd like to run a development build or contribute to the project, please visit our [contributor guide](CONTRIBUTING.md) to get started.
|
||||||
|
@ -21,7 +21,7 @@ extend-exclude = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[default.extend-words]
|
[default.extend-words]
|
||||||
metalness = "metalness" # appearance API
|
metalness = "metalness" # appearance API
|
||||||
Hom = "Hom" # short for homogenous
|
Hom = "Hom" # short for homogenous
|
||||||
typ = "typ" # used to declare a variable named 'type' which is a reserved keyword in Rust
|
typ = "typ" # used to declare a variable named 'type' which is a reserved keyword in Rust
|
||||||
ue = "ue" # short for UnaryExpression
|
ue = "ue" # short for UnaryExpression
|
||||||
@ -29,7 +29,6 @@ THRE = "THRE" # Weird bug that wrongly detects THREEjs as a typo
|
|||||||
nwo = "nwo" # don't know what this is about tbh
|
nwo = "nwo" # don't know what this is about tbh
|
||||||
"ot" = "ot" # some abbreviation, idk what
|
"ot" = "ot" # some abbreviation, idk what
|
||||||
"oe" = "oe" # some abbreviation, idk what
|
"oe" = "oe" # some abbreviation, idk what
|
||||||
"colinear" = "colinear" # some engine shit, kidding
|
|
||||||
|
|
||||||
[default]
|
[default]
|
||||||
extend-ignore-identifiers-re = [
|
extend-ignore-identifiers-re = [
|
||||||
|
@ -4,7 +4,7 @@ excerpt: "Documentation of the KCL language for the Zoo Design Studio."
|
|||||||
layout: manual
|
layout: manual
|
||||||
---
|
---
|
||||||
|
|
||||||
This is a reference for KCL. If you are learning KCL, you may prefer the [guide](https://zoo.dev/docs/kcl-book/intro.html) which explains
|
This is a reference for KCL. If you are learning KCL, you may prefer the [guide]() which explains
|
||||||
things in a more tutorial fashion. See also our documentation of the [standard library](/docs/kcl-std).
|
things in a more tutorial fashion. See also our documentation of the [standard library](/docs/kcl-std).
|
||||||
|
|
||||||
## Topics
|
## Topics
|
||||||
|
@ -27,6 +27,9 @@ import increment from "util.kcl"
|
|||||||
answer = increment(41)
|
answer = increment(41)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Imported files _must_ be in the same project so that units are uniform across
|
||||||
|
modules. This means that it must be in the same directory.
|
||||||
|
|
||||||
Import statements must be at the top-level of a file. It is not allowed to have
|
Import statements must be at the top-level of a file. It is not allowed to have
|
||||||
an `import` statement inside a function or in the body of an if‑else.
|
an `import` statement inside a function or in the body of an if‑else.
|
||||||
|
|
||||||
@ -55,9 +58,6 @@ Imported symbols can be renamed for convenience or to avoid name collisions.
|
|||||||
import increment as inc, decrement as dec from "util.kcl"
|
import increment as inc, decrement as dec from "util.kcl"
|
||||||
```
|
```
|
||||||
|
|
||||||
You can import files from the current directory or from subdirectories, but if importing from a
|
|
||||||
subdirectory you can only import `main.kcl`.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Functions vs `clone`
|
## Functions vs `clone`
|
||||||
@ -177,7 +177,7 @@ You can also import the whole module. This is useful if you want to use the
|
|||||||
result of a module as a variable, like a part.
|
result of a module as a variable, like a part.
|
||||||
|
|
||||||
```norun
|
```norun
|
||||||
import "cube.kcl"
|
import "tests/inputs/cube.kcl" as cube
|
||||||
cube
|
cube
|
||||||
|> translate(x=10)
|
|> translate(x=10)
|
||||||
```
|
```
|
||||||
@ -229,19 +229,6 @@ The final statement is what's important because it's the return value of the
|
|||||||
entire module. The module is expected to return a single object that can be used
|
entire module. The module is expected to return a single object that can be used
|
||||||
as a variable by the file that imports it.
|
as a variable by the file that imports it.
|
||||||
|
|
||||||
The name of the file or subdirectory is used as the name of the variable within the importing program.
|
|
||||||
If you want to use a different name, you can do so by using the `as` keyword:
|
|
||||||
|
|
||||||
```kcl,norun
|
|
||||||
import "cube.kcl" // Introduces a new variable called `cube`.
|
|
||||||
import "cube.kcl" as block // Introduces a new variable called `block`.
|
|
||||||
import "cube/main.kcl" // Introduces a new variable called `cube`.
|
|
||||||
import "cube/main.kcl" as block // Introduces a new variable called `block`.
|
|
||||||
```
|
|
||||||
|
|
||||||
If the filename includes hyphens (`-`) or starts with an underscore (`_`), then you must specify a
|
|
||||||
variable name.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Multiple instances of the same import
|
## Multiple instances of the same import
|
||||||
@ -254,7 +241,7 @@ If you want to have multiple instances of the same object, you can use the
|
|||||||
[`clone`](/docs/kcl/clone) function. This will render a new instance of the object in memory.
|
[`clone`](/docs/kcl/clone) function. This will render a new instance of the object in memory.
|
||||||
|
|
||||||
```norun
|
```norun
|
||||||
import cube from "cube.kcl"
|
import cube from "tests/inputs/cube.kcl"
|
||||||
|
|
||||||
cube
|
cube
|
||||||
|> translate(x=10)
|
|> translate(x=10)
|
||||||
@ -270,7 +257,7 @@ separate objects in memory, and can be manipulated independently.
|
|||||||
Here is an example with a file from another CAD system:
|
Here is an example with a file from another CAD system:
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
import "tests/inputs/cube.step"
|
import "tests/inputs/cube.step" as cube
|
||||||
|
|
||||||
cube
|
cube
|
||||||
|> translate(x=10)
|
|> translate(x=10)
|
||||||
|
@ -12,7 +12,7 @@ reduce(
|
|||||||
@array: [any],
|
@array: [any],
|
||||||
initial: any,
|
initial: any,
|
||||||
f: fn(any, accum: any): any,
|
f: fn(any, accum: any): any,
|
||||||
): any
|
): [any]
|
||||||
```
|
```
|
||||||
|
|
||||||
Take a starting value. Then, for each element of an array, calculate the next value,
|
Take a starting value. Then, for each element of an array, calculate the next value,
|
||||||
@ -28,7 +28,7 @@ using the previous value and the element.
|
|||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`any`](/docs/kcl-std/types/std-types-any)
|
[`[any]`](/docs/kcl-std/types/std-types-any)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
@ -11,7 +11,7 @@ Compute the length of the given leg.
|
|||||||
legLen(
|
legLen(
|
||||||
hypotenuse: number(Length),
|
hypotenuse: number(Length),
|
||||||
leg: number(Length),
|
leg: number(Length),
|
||||||
): number(Length)
|
): number(deg)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ legLen(
|
|||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`number(Length)`](/docs/kcl-std/types/std-types-number) - A number.
|
[`number(deg)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
@ -14,6 +14,8 @@ mirror2d(
|
|||||||
): Sketch
|
): Sketch
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Only works on unclosed sketches for now.
|
||||||
|
|
||||||
Mirror occurs around a local sketch axis rather than a global axis.
|
Mirror occurs around a local sketch axis rather than a global axis.
|
||||||
|
|
||||||
### Arguments
|
### Arguments
|
||||||
|
@ -65,7 +65,7 @@ layout: manual
|
|||||||
* [`line`](/docs/kcl-std/line)
|
* [`line`](/docs/kcl-std/line)
|
||||||
* [`loft`](/docs/kcl-std/loft)
|
* [`loft`](/docs/kcl-std/loft)
|
||||||
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
|
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
|
||||||
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
|
* [`patternTransform2d`](/docs/kcl-std/patternTransform2d)
|
||||||
* [`polygon`](/docs/kcl-std/polygon)
|
* [`polygon`](/docs/kcl-std/polygon)
|
||||||
* [`profileStart`](/docs/kcl-std/profileStart)
|
* [`profileStart`](/docs/kcl-std/profileStart)
|
||||||
* [`profileStartX`](/docs/kcl-std/profileStartX)
|
* [`profileStartX`](/docs/kcl-std/profileStartX)
|
||||||
@ -94,7 +94,7 @@ layout: manual
|
|||||||
* [`intersect`](/docs/kcl-std/intersect)
|
* [`intersect`](/docs/kcl-std/intersect)
|
||||||
* [`patternCircular3d`](/docs/kcl-std/patternCircular3d)
|
* [`patternCircular3d`](/docs/kcl-std/patternCircular3d)
|
||||||
* [`patternLinear3d`](/docs/kcl-std/patternLinear3d)
|
* [`patternLinear3d`](/docs/kcl-std/patternLinear3d)
|
||||||
* [`patternTransform`](/docs/kcl-std/functions/std-solid-patternTransform)
|
* [`patternTransform`](/docs/kcl-std/patternTransform)
|
||||||
* [`shell`](/docs/kcl-std/functions/std-solid-shell)
|
* [`shell`](/docs/kcl-std/functions/std-solid-shell)
|
||||||
* [`subtract`](/docs/kcl-std/subtract)
|
* [`subtract`](/docs/kcl-std/subtract)
|
||||||
* [`union`](/docs/kcl-std/union)
|
* [`union`](/docs/kcl-std/union)
|
||||||
|
@ -30,7 +30,7 @@ This module contains functions for creating and manipulating sketches, and makin
|
|||||||
* [`line`](/docs/kcl-std/line)
|
* [`line`](/docs/kcl-std/line)
|
||||||
* [`loft`](/docs/kcl-std/loft)
|
* [`loft`](/docs/kcl-std/loft)
|
||||||
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
|
* [`patternCircular2d`](/docs/kcl-std/patternCircular2d)
|
||||||
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
|
* [`patternTransform2d`](/docs/kcl-std/patternTransform2d)
|
||||||
* [`polygon`](/docs/kcl-std/polygon)
|
* [`polygon`](/docs/kcl-std/polygon)
|
||||||
* [`profileStart`](/docs/kcl-std/profileStart)
|
* [`profileStart`](/docs/kcl-std/profileStart)
|
||||||
* [`profileStartX`](/docs/kcl-std/profileStartX)
|
* [`profileStartX`](/docs/kcl-std/profileStartX)
|
||||||
|
@ -18,7 +18,7 @@ This module contains functions for modifying solids, e.g., by adding a fillet or
|
|||||||
* [`intersect`](/docs/kcl-std/intersect)
|
* [`intersect`](/docs/kcl-std/intersect)
|
||||||
* [`patternCircular3d`](/docs/kcl-std/patternCircular3d)
|
* [`patternCircular3d`](/docs/kcl-std/patternCircular3d)
|
||||||
* [`patternLinear3d`](/docs/kcl-std/patternLinear3d)
|
* [`patternLinear3d`](/docs/kcl-std/patternLinear3d)
|
||||||
* [`patternTransform`](/docs/kcl-std/functions/std-solid-patternTransform)
|
* [`patternTransform`](/docs/kcl-std/patternTransform)
|
||||||
* [`shell`](/docs/kcl-std/functions/std-solid-shell)
|
* [`shell`](/docs/kcl-std/functions/std-solid-shell)
|
||||||
* [`subtract`](/docs/kcl-std/subtract)
|
* [`subtract`](/docs/kcl-std/subtract)
|
||||||
* [`union`](/docs/kcl-std/union)
|
* [`union`](/docs/kcl-std/union)
|
||||||
|
@ -11,7 +11,7 @@ Contains frequently used constants, functions for interacting with the KittyCAD
|
|||||||
|
|
||||||
The standard library is organised into modules (listed below), but most things are always available in KCL programs.
|
The standard library is organised into modules (listed below), but most things are always available in KCL programs.
|
||||||
|
|
||||||
You might also want the [KCL language reference](/docs/kcl-lang) or the [KCL guide](https://zoo.dev/docs/kcl-book/intro.html).
|
You might also want the [KCL language reference](/docs/kcl-lang) or the [KCL guide]().
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ patternCircular2d(
|
|||||||
@sketchSet: [Sketch],
|
@sketchSet: [Sketch],
|
||||||
instances: number,
|
instances: number,
|
||||||
center: Point2d,
|
center: Point2d,
|
||||||
arcDegrees?: number,
|
arcDegrees: number,
|
||||||
rotateDuplicates?: bool,
|
rotateDuplicates: bool,
|
||||||
useOriginal?: bool,
|
useOriginal?: bool,
|
||||||
): [Sketch]
|
): [Sketch]
|
||||||
```
|
```
|
||||||
@ -27,8 +27,8 @@ patternCircular2d(
|
|||||||
| `sketchSet` | [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) | Which sketch(es) to pattern | Yes |
|
| `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 |
|
| `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 |
|
| `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 |
|
| `arcDegrees` | [`number`](/docs/kcl-std/types/std-types-number) | The arc angle (in degrees) to place the repetitions. Must be greater than 0. | Yes |
|
||||||
| `rotateDuplicates` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether or not to rotate the duplicates as they are copied. Defaults to true. | No |
|
| `rotateDuplicates` | [`bool`](/docs/kcl-std/types/std-types-bool) | Whether or not to rotate the duplicates as they are copied. | Yes |
|
||||||
| `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 |
|
| `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 |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
---
|
---
|
||||||
title: "patternTransform2d"
|
title: "patternTransform2d"
|
||||||
subtitle: "Function in std::sketch"
|
subtitle: "Function in std::sketch"
|
||||||
excerpt: "Just like `patternTransform`, but works on 2D sketches not 3D solids."
|
excerpt: "Just like patternTransform, but works on 2D sketches not 3D solids."
|
||||||
layout: manual
|
layout: manual
|
||||||
---
|
---
|
||||||
|
|
||||||
Just like `patternTransform`, but works on 2D sketches not 3D solids.
|
Just like patternTransform, but works on 2D sketches not 3D solids.
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
patternTransform2d(
|
patternTransform2d(
|
||||||
@sketches: [Sketch; 1+],
|
@sketches: [Sketch],
|
||||||
instances: number(_),
|
instances: number,
|
||||||
transform: fn(number(_)): { },
|
transform: FunctionSource,
|
||||||
useOriginal?: boolean,
|
useOriginal?: bool,
|
||||||
): [Sketch; 1+]
|
): [Sketch]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -22,14 +22,14 @@ patternTransform2d(
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketches` | [`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch) | The sketch(es) to duplicate. | Yes |
|
| `sketches` | [`[Sketch]`](/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 |
|
| `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 |
|
||||||
| `transform` | [`fn(number(_)): { }`](/docs/kcl-std/types/std-types-fn) | How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument `1`. This simplifies your math: the transform function can rely on id `0` being the original instance passed into the `patternTransform`. See the examples. | Yes |
|
| `transform` | `FunctionSource` | How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument `1`. This simplifies your math: the transform function can rely on id `0` being the original instance passed into the `patternTransform`. See the examples. | Yes |
|
||||||
| `useOriginal` | `boolean` | If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. | 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 |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
[`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch)
|
[`[Sketch]`](/docs/kcl-std/types/std-types-Sketch)
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
16168
docs/kcl-std/std.json
@ -235,48 +235,6 @@ extrude001 = extrude(sketch001, length = 5)`
|
|||||||
.first()
|
.first()
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('KCL errors with functions show hints for the entire backtrace', async ({
|
|
||||||
page,
|
|
||||||
homePage,
|
|
||||||
scene,
|
|
||||||
cmdBar,
|
|
||||||
editor,
|
|
||||||
toolbar,
|
|
||||||
}) => {
|
|
||||||
await homePage.goToModelingScene()
|
|
||||||
await scene.settled(cmdBar)
|
|
||||||
|
|
||||||
const code = `fn check(@x) {
|
|
||||||
return assert(x, isGreaterThan = 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn middle(@x) {
|
|
||||||
return check(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
middle(1)
|
|
||||||
middle(0)
|
|
||||||
`
|
|
||||||
await test.step('Set the code with a KCL error', async () => {
|
|
||||||
await toolbar.openPane('code')
|
|
||||||
await editor.replaceCode('', code)
|
|
||||||
})
|
|
||||||
// This shows all the diagnostics in a way that doesn't require the mouse
|
|
||||||
// pointer hovering over a coordinate, which would be brittle.
|
|
||||||
await test.step('Open CodeMirror diagnostics list', async () => {
|
|
||||||
// Ensure keyboard focus is in the editor.
|
|
||||||
await page.getByText('fn check(').click()
|
|
||||||
await page.keyboard.press('ControlOrMeta+Shift+M')
|
|
||||||
})
|
|
||||||
await expect(
|
|
||||||
page.getByText(`assert failed: Expected 0 to be greater than 0 but it wasn't
|
|
||||||
check()
|
|
||||||
middle()`)
|
|
||||||
).toBeVisible()
|
|
||||||
// There should be one hint inside middle() and one at the top level.
|
|
||||||
await expect(page.getByText('Part of the error backtrace')).toHaveCount(2)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test(
|
test(
|
||||||
|
@ -36,29 +36,27 @@ test.describe('Command bar tests', () => {
|
|||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
// Click the line of code for xLine.
|
// Click the line of code for xLine.
|
||||||
await page.getByText(`startProfile(at = [-10, -10])`).click()
|
await page.getByText(`close()`).click() // TODO remove this and reinstate // await topHorzSegmentClick()
|
||||||
|
|
||||||
// Wait for the selection to register (TODO: we need a definitive way to wait for this)
|
|
||||||
await page.waitForTimeout(200)
|
|
||||||
|
|
||||||
await toolbar.extrudeButton.click()
|
await toolbar.extrudeButton.click()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
currentArgKey: 'length',
|
currentArgKey: 'sketches',
|
||||||
currentArgValue: '5',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '1 profile',
|
Sketches: '',
|
||||||
Length: '',
|
Length: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'length',
|
highlightedHeaderArg: 'sketches',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '1 profile',
|
Sketches: '1 segment',
|
||||||
Length: '5',
|
Length: '5',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -288,7 +286,7 @@ test.describe('Command bar tests', () => {
|
|||||||
await cmdBar.cmdOptions.getByText('Extrude').click()
|
await cmdBar.cmdOptions.getByText('Extrude').click()
|
||||||
|
|
||||||
// Assert that we're on the selection step
|
// Assert that we're on the selection step
|
||||||
await expect(page.getByRole('button', { name: 'Profiles' })).toBeDisabled()
|
await expect(page.getByRole('button', { name: 'sketches' })).toBeDisabled()
|
||||||
// Select a face
|
// Select a face
|
||||||
await page.mouse.move(700, 200)
|
await page.mouse.move(700, 200)
|
||||||
await page.mouse.click(700, 200)
|
await page.mouse.click(700, 200)
|
||||||
@ -401,6 +399,7 @@ test.describe('Command bar tests', () => {
|
|||||||
sortBy: 'last-modified-desc',
|
sortBy: 'last-modified-desc',
|
||||||
})
|
})
|
||||||
await page.goto(page.url() + targetURL)
|
await page.goto(page.url() + targetURL)
|
||||||
|
expect(page.url()).toContain(targetURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Submit the command`, async () => {
|
await test.step(`Submit the command`, async () => {
|
||||||
@ -411,7 +410,7 @@ test.describe('Command bar tests', () => {
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Method: '',
|
Method: '',
|
||||||
Name: 'main.kcl',
|
Name: 'test',
|
||||||
Code: '1 line',
|
Code: '1 line',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'method',
|
highlightedHeaderArg: 'method',
|
||||||
@ -422,7 +421,7 @@ test.describe('Command bar tests', () => {
|
|||||||
commandName: 'Import file from URL',
|
commandName: 'Import file from URL',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Method: 'New project',
|
Method: 'New project',
|
||||||
Name: 'main.kcl',
|
Name: 'test',
|
||||||
Code: '1 line',
|
Code: '1 line',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -464,6 +463,7 @@ test.describe('Command bar tests', () => {
|
|||||||
sortBy: 'last-modified-desc',
|
sortBy: 'last-modified-desc',
|
||||||
})
|
})
|
||||||
await page.goto(page.url() + targetURL)
|
await page.goto(page.url() + targetURL)
|
||||||
|
expect(page.url()).toContain(targetURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Submit the command`, async () => {
|
await test.step(`Submit the command`, async () => {
|
||||||
@ -474,7 +474,7 @@ test.describe('Command bar tests', () => {
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Method: '',
|
Method: '',
|
||||||
Name: 'main.kcl',
|
Name: 'test',
|
||||||
Code: '1 line',
|
Code: '1 line',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'method',
|
highlightedHeaderArg: 'method',
|
||||||
@ -487,7 +487,7 @@ test.describe('Command bar tests', () => {
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Method: 'Existing project',
|
Method: 'Existing project',
|
||||||
Name: 'main.kcl',
|
Name: 'test',
|
||||||
ProjectName: '',
|
ProjectName: '',
|
||||||
Code: '1 line',
|
Code: '1 line',
|
||||||
},
|
},
|
||||||
@ -500,7 +500,7 @@ test.describe('Command bar tests', () => {
|
|||||||
headerArguments: {
|
headerArguments: {
|
||||||
Method: 'Existing project',
|
Method: 'Existing project',
|
||||||
ProjectName: 'testProjectDir',
|
ProjectName: 'testProjectDir',
|
||||||
Name: 'main.kcl',
|
Name: 'test',
|
||||||
Code: '1 line',
|
Code: '1 line',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -510,7 +510,7 @@ test.describe('Command bar tests', () => {
|
|||||||
await test.step(`Ensure we created the project and are in the modeling scene`, async () => {
|
await test.step(`Ensure we created the project and are in the modeling scene`, async () => {
|
||||||
await editor.expectEditor.toContain('extrusionDistance = 12')
|
await editor.expectEditor.toContain('extrusionDistance = 12')
|
||||||
await toolbar.openPane('files')
|
await toolbar.openPane('files')
|
||||||
await toolbar.expectFileTreeState(['main-1.kcl', 'main.kcl'])
|
await toolbar.expectFileTreeState(['main.kcl', 'test.kcl'])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -661,56 +661,4 @@ c = 3 + a`
|
|||||||
`a = 5b = a * amyParameter001 = ${newValue}c = 3 + a`
|
`a = 5b = a * amyParameter001 = ${newValue}c = 3 + a`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Command palette can be opened via query parameter', async ({
|
|
||||||
page,
|
|
||||||
homePage,
|
|
||||||
cmdBar,
|
|
||||||
}) => {
|
|
||||||
await page.goto(`${page.url()}/?cmd=app.theme&groupId=settings`)
|
|
||||||
await homePage.expectState({
|
|
||||||
projectCards: [],
|
|
||||||
sortBy: 'last-modified-desc',
|
|
||||||
})
|
|
||||||
await cmdBar.expectState({
|
|
||||||
stage: 'arguments',
|
|
||||||
commandName: 'Settings · app · theme',
|
|
||||||
currentArgKey: 'value',
|
|
||||||
currentArgValue: '',
|
|
||||||
headerArguments: {
|
|
||||||
Level: 'user',
|
|
||||||
Value: '',
|
|
||||||
},
|
|
||||||
highlightedHeaderArg: 'value',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test('Text-to-CAD command can be closed with escape while in prompt', async ({
|
|
||||||
page,
|
|
||||||
homePage,
|
|
||||||
cmdBar,
|
|
||||||
}) => {
|
|
||||||
await homePage.expectState({
|
|
||||||
projectCards: [],
|
|
||||||
sortBy: 'last-modified-desc',
|
|
||||||
})
|
|
||||||
await homePage.textToCadBtn.click()
|
|
||||||
await cmdBar.expectState({
|
|
||||||
stage: 'arguments',
|
|
||||||
commandName: 'Text-to-CAD Create',
|
|
||||||
currentArgKey: 'prompt',
|
|
||||||
currentArgValue: '',
|
|
||||||
headerArguments: {
|
|
||||||
Method: 'New project',
|
|
||||||
NewProjectName: 'untitled',
|
|
||||||
Prompt: '',
|
|
||||||
},
|
|
||||||
highlightedHeaderArg: 'prompt',
|
|
||||||
})
|
|
||||||
await page.keyboard.press('Escape')
|
|
||||||
await cmdBar.toBeClosed()
|
|
||||||
await cmdBar.expectState({
|
|
||||||
stage: 'commandBarClosed',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
@ -1131,15 +1131,14 @@ sketch001 = startSketchOn(XZ)
|
|||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await page.getByText('startProfile(at = [4.61, -14.01])').click()
|
await page.getByText('startProfile(at = [4.61, -14.01])').click()
|
||||||
// Wait for the selection to register (TODO: we need a definitive way to wait for this)
|
|
||||||
await page.waitForTimeout(200)
|
|
||||||
await toolbar.extrudeButton.click()
|
await toolbar.extrudeButton.click()
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'length',
|
currentArgKey: 'length',
|
||||||
currentArgValue: '5',
|
currentArgValue: '5',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '1 profile',
|
Sketches: '1 face',
|
||||||
Length: '',
|
Length: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'length',
|
highlightedHeaderArg: 'length',
|
||||||
@ -1149,7 +1148,7 @@ sketch001 = startSketchOn(XZ)
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '1 profile',
|
Sketches: '1 face',
|
||||||
Length: '5',
|
Length: '5',
|
||||||
},
|
},
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
@ -1355,9 +1354,7 @@ sketch001 = startSketchOn(XZ)
|
|||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
const projectLink = page.getByRole('link', { name: 'cube' })
|
const projectLink = page.getByRole('link', { name: 'cube' })
|
||||||
const gizmo = page.locator('[aria-label*=gizmo]')
|
const gizmo = page.locator('[aria-label*=gizmo]')
|
||||||
const resetCameraButton = page.getByRole('button', {
|
const resetCameraButton = page.getByRole('button', { name: 'Reset view' })
|
||||||
name: 'Reset view',
|
|
||||||
})
|
|
||||||
const locationToHaveColor = async (
|
const locationToHaveColor = async (
|
||||||
position: { x: number; y: number },
|
position: { x: number; y: number },
|
||||||
color: [number, number, number]
|
color: [number, number, number]
|
||||||
|
@ -238,26 +238,6 @@ test.describe('when using the file tree to', () => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
test(
|
|
||||||
`create new folders and that doesn't trigger a navigation`,
|
|
||||||
{ tag: ['@electron', '@macos', '@windows'] },
|
|
||||||
async ({ page, homePage, scene, toolbar, cmdBar }) => {
|
|
||||||
await homePage.goToModelingScene()
|
|
||||||
await scene.settled(cmdBar)
|
|
||||||
await toolbar.openPane('files')
|
|
||||||
const { createNewFolder } = await getUtils(page, test)
|
|
||||||
|
|
||||||
await createNewFolder('folder')
|
|
||||||
|
|
||||||
await createNewFolder('folder.kcl')
|
|
||||||
|
|
||||||
await test.step(`Postcondition: folders are created and we didn't navigate`, async () => {
|
|
||||||
await toolbar.expectFileTreeState(['folder', 'folder.kcl', 'main.kcl'])
|
|
||||||
await expect(toolbar.fileName).toHaveText('main.kcl')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'deleting all files recreates a default main.kcl with no code',
|
'deleting all files recreates a default main.kcl with no code',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
|
@ -105,19 +105,14 @@ export class CmdBarFixture {
|
|||||||
expectState = async (expected: CmdBarSerialised) => {
|
expectState = async (expected: CmdBarSerialised) => {
|
||||||
return expect.poll(() => this._serialiseCmdBar()).toEqual(expected)
|
return expect.poll(() => this._serialiseCmdBar()).toEqual(expected)
|
||||||
}
|
}
|
||||||
/**
|
/** The method will use buttons OR press enter randomly to progress the cmdbar,
|
||||||
* This method is used to progress the command bar to the next step, defaulting to clicking the next button.
|
* this could have unexpected results depending on what's focused
|
||||||
* Optionally, with the `shouldUseKeyboard` parameter, it will hit `Enter` to progress.
|
*
|
||||||
* * TODO: This method assumes the user has a valid input to the current stage,
|
* TODO: This method assumes the user has a valid input to the current stage,
|
||||||
* and assumes we are past the `pickCommand` step.
|
* and assumes we are past the `pickCommand` step.
|
||||||
*/
|
*/
|
||||||
progressCmdBar = async (shouldUseKeyboard = false) => {
|
progressCmdBar = async (shouldFuzzProgressMethod = true) => {
|
||||||
await this.page.waitForTimeout(2000)
|
await this.page.waitForTimeout(2000)
|
||||||
if (shouldUseKeyboard) {
|
|
||||||
await this.page.keyboard.press('Enter')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const arrowButton = this.page.getByRole('button', {
|
const arrowButton = this.page.getByRole('button', {
|
||||||
name: 'arrow right Continue',
|
name: 'arrow right Continue',
|
||||||
})
|
})
|
||||||
@ -151,7 +146,9 @@ export class CmdBarFixture {
|
|||||||
await this.cmdBarOpenBtn.click()
|
await this.cmdBarOpenBtn.click()
|
||||||
await expect(this.page.getByPlaceholder('Search commands')).toBeVisible()
|
await expect(this.page.getByPlaceholder('Search commands')).toBeVisible()
|
||||||
if (selectCmd === 'promptToEdit') {
|
if (selectCmd === 'promptToEdit') {
|
||||||
const promptEditCommand = this.selectOption({ name: 'Text-to-CAD Edit' })
|
const promptEditCommand = this.page.getByText(
|
||||||
|
'Use Zoo AI to edit your parts and code.'
|
||||||
|
)
|
||||||
await expect(promptEditCommand.first()).toBeVisible()
|
await expect(promptEditCommand.first()).toBeVisible()
|
||||||
await promptEditCommand.first().scrollIntoViewIfNeeded()
|
await promptEditCommand.first().scrollIntoViewIfNeeded()
|
||||||
await promptEditCommand.first().click()
|
await promptEditCommand.first().click()
|
||||||
@ -313,11 +310,6 @@ export class CmdBarFixture {
|
|||||||
await expect(this.cmdBarElement).toBeVisible({ timeout: 10_000 })
|
await expect(this.cmdBarElement).toBeVisible({ timeout: 10_000 })
|
||||||
}
|
}
|
||||||
|
|
||||||
async toBeClosed() {
|
|
||||||
// Check that the command bar is closed
|
|
||||||
await expect(this.cmdBarElement).not.toBeVisible({ timeout: 10_000 })
|
|
||||||
}
|
|
||||||
|
|
||||||
async expectArgValue(value: string) {
|
async expectArgValue(value: string) {
|
||||||
// Check the placeholder project name exists
|
// Check the placeholder project name exists
|
||||||
const actualArgument = await this.cmdBarElement
|
const actualArgument = await this.cmdBarElement
|
||||||
|
@ -26,7 +26,6 @@ export class HomePageFixture {
|
|||||||
sortByNameBtn!: Locator
|
sortByNameBtn!: Locator
|
||||||
appHeader!: Locator
|
appHeader!: Locator
|
||||||
tutorialBtn!: Locator
|
tutorialBtn!: Locator
|
||||||
textToCadBtn!: Locator
|
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page
|
this.page = page
|
||||||
@ -48,7 +47,6 @@ export class HomePageFixture {
|
|||||||
this.sortByNameBtn = this.page.getByTestId('home-sort-by-name')
|
this.sortByNameBtn = this.page.getByTestId('home-sort-by-name')
|
||||||
this.appHeader = this.page.getByTestId('app-header')
|
this.appHeader = this.page.getByTestId('app-header')
|
||||||
this.tutorialBtn = this.page.getByTestId('home-tutorial-button')
|
this.tutorialBtn = this.page.getByTestId('home-tutorial-button')
|
||||||
this.textToCadBtn = this.page.getByTestId('home-text-to-cad')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _serialiseSortBy = async (): Promise<
|
private _serialiseSortBy = async (): Promise<
|
||||||
@ -123,13 +121,11 @@ export class HomePageFixture {
|
|||||||
await projectCard.click()
|
await projectCard.click()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the project name in case caller has used the default and needs it */
|
goToModelingScene = async (name: string = 'testDefault') => {
|
||||||
goToModelingScene = async (name = 'testDefault') => {
|
|
||||||
// On web this is a no-op. There is no project view.
|
// On web this is a no-op. There is no project view.
|
||||||
if (process.env.PLATFORM === 'web') return ''
|
if (process.env.PLATFORM === 'web') return
|
||||||
|
|
||||||
await this.createAndGoToProject(name)
|
await this.createAndGoToProject(name)
|
||||||
return name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isNativeFileMenuCreated = async () => {
|
isNativeFileMenuCreated = async () => {
|
||||||
|
@ -61,7 +61,6 @@ class MyAPIReporter implements Reporter {
|
|||||||
const payload = {
|
const payload = {
|
||||||
// Required information
|
// Required information
|
||||||
project: 'https://github.com/KittyCAD/modeling-app',
|
project: 'https://github.com/KittyCAD/modeling-app',
|
||||||
suite: process.env.CI_SUITE || 'e2e',
|
|
||||||
branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
|
branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
|
||||||
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
|
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
|
||||||
test: test.titlePath().slice(2).join(' › '),
|
test: test.titlePath().slice(2).join(' › '),
|
||||||
|
@ -252,7 +252,7 @@ test.describe(
|
|||||||
tronApp,
|
tronApp,
|
||||||
'Edit.Modify with Zoo Text-To-CAD'
|
'Edit.Modify with Zoo Text-To-CAD'
|
||||||
)
|
)
|
||||||
await cmdBar.expectCommandName('Text-to-CAD Edit')
|
await cmdBar.expectCommandName('Prompt-to-edit')
|
||||||
})
|
})
|
||||||
await test.step('Modeling.Edit.Edit parameter', async () => {
|
await test.step('Modeling.Edit.Edit parameter', async () => {
|
||||||
await page.waitForTimeout(250)
|
await page.waitForTimeout(250)
|
||||||
@ -518,7 +518,7 @@ test.describe(
|
|||||||
'Design.Create with Zoo Text-To-CAD'
|
'Design.Create with Zoo Text-To-CAD'
|
||||||
)
|
)
|
||||||
await cmdBar.toBeOpened()
|
await cmdBar.toBeOpened()
|
||||||
await cmdBar.expectCommandName('Text-to-CAD Create')
|
await cmdBar.expectCommandName('Text to CAD')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Modeling.Design.Modify with Zoo Text-To-CAD', async () => {
|
await test.step('Modeling.Design.Modify with Zoo Text-To-CAD', async () => {
|
||||||
@ -528,7 +528,7 @@ test.describe(
|
|||||||
'Design.Modify with Zoo Text-To-CAD'
|
'Design.Modify with Zoo Text-To-CAD'
|
||||||
)
|
)
|
||||||
await cmdBar.toBeOpened()
|
await cmdBar.toBeOpened()
|
||||||
await cmdBar.expectCommandName('Text-to-CAD Edit')
|
await cmdBar.expectCommandName('Prompt-to-edit')
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Modeling.Help.KCL code samples', async () => {
|
await test.step('Modeling.Help.KCL code samples', async () => {
|
||||||
|
@ -74,11 +74,20 @@ test.describe('Point-and-click tests', () => {
|
|||||||
|
|
||||||
await test.step('do extrude flow and check extrude code is added to editor', async () => {
|
await test.step('do extrude flow and check extrude code is added to editor', async () => {
|
||||||
await toolbar.extrudeButton.click()
|
await toolbar.extrudeButton.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'sketches',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: { Sketches: '', Length: '' },
|
||||||
|
highlightedHeaderArg: 'sketches',
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'length',
|
currentArgKey: 'length',
|
||||||
currentArgValue: '5',
|
currentArgValue: '5',
|
||||||
headerArguments: { Profiles: '1 profile', Length: '' },
|
headerArguments: { Sketches: '1 face', Length: '' },
|
||||||
highlightedHeaderArg: 'length',
|
highlightedHeaderArg: 'length',
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
})
|
})
|
||||||
@ -89,7 +98,7 @@ test.describe('Point-and-click tests', () => {
|
|||||||
|
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: { Profiles: '1 profile', Length: '5' },
|
headerArguments: { Sketches: '1 face', Length: '5' },
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
@ -1625,15 +1634,15 @@ sketch002 = startSketchOn(plane001)
|
|||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'sketches',
|
currentArgKey: 'sketches',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: { Profiles: '' },
|
headerArguments: { Sketches: '' },
|
||||||
highlightedHeaderArg: 'Profiles',
|
highlightedHeaderArg: 'sketches',
|
||||||
commandName: 'Loft',
|
commandName: 'Loft',
|
||||||
})
|
})
|
||||||
await selectSketches()
|
await selectSketches()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: { Profiles: '2 profiles' },
|
headerArguments: { Sketches: '2 faces' },
|
||||||
commandName: 'Loft',
|
commandName: 'Loft',
|
||||||
})
|
})
|
||||||
await cmdBar.submit()
|
await cmdBar.submit()
|
||||||
@ -1645,9 +1654,18 @@ sketch002 = startSketchOn(plane001)
|
|||||||
|
|
||||||
await test.step(`Go through the command bar flow with preselected sketches`, async () => {
|
await test.step(`Go through the command bar flow with preselected sketches`, async () => {
|
||||||
await toolbar.loftButton.click()
|
await toolbar.loftButton.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'sketches',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: { Sketches: '' },
|
||||||
|
highlightedHeaderArg: 'sketches',
|
||||||
|
commandName: 'Loft',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: { Profiles: '2 profiles' },
|
headerArguments: { Sketches: '2 faces' },
|
||||||
commandName: 'Loft',
|
commandName: 'Loft',
|
||||||
})
|
})
|
||||||
await cmdBar.submit()
|
await cmdBar.submit()
|
||||||
@ -1812,10 +1830,10 @@ sketch002 = startSketchOn(XZ)
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Profiles: '',
|
Sketches: '',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'Profiles',
|
highlightedHeaderArg: 'sketches',
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
})
|
})
|
||||||
await clickOnSketch1()
|
await clickOnSketch1()
|
||||||
@ -1826,7 +1844,7 @@ sketch002 = startSketchOn(XZ)
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Profiles: '1 profile',
|
Sketches: '1 face',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'path',
|
highlightedHeaderArg: 'path',
|
||||||
@ -1839,7 +1857,7 @@ sketch002 = startSketchOn(XZ)
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Profiles: '1 profile',
|
Sketches: '1 face',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'path',
|
highlightedHeaderArg: 'path',
|
||||||
@ -1849,17 +1867,13 @@ sketch002 = startSketchOn(XZ)
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '1 profile',
|
Sketches: '1 face',
|
||||||
Path: '1 segment',
|
Path: '1 segment',
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
},
|
},
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
})
|
})
|
||||||
// Confirm we can submit from the review step with just `Enter`
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar(true)
|
|
||||||
await cmdBar.expectState({
|
|
||||||
stage: 'commandBarClosed',
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
|
||||||
@ -1954,10 +1968,10 @@ profile001 = ${circleCode}`
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Profiles: '',
|
Sketches: '',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'Profiles',
|
highlightedHeaderArg: 'sketches',
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
})
|
})
|
||||||
await editor.scrollToText(circleCode)
|
await editor.scrollToText(circleCode)
|
||||||
@ -1969,7 +1983,7 @@ profile001 = ${circleCode}`
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Profiles: '1 profile',
|
Sketches: '1 face',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'path',
|
highlightedHeaderArg: 'path',
|
||||||
@ -1983,7 +1997,7 @@ profile001 = ${circleCode}`
|
|||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
Profiles: '1 profile',
|
Sketches: '1 face',
|
||||||
Path: '',
|
Path: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'path',
|
highlightedHeaderArg: 'path',
|
||||||
@ -1993,13 +2007,13 @@ profile001 = ${circleCode}`
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '1 profile',
|
Sketches: '1 face',
|
||||||
Path: '1 helix',
|
Path: '1 helix',
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
},
|
},
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
})
|
})
|
||||||
await cmdBar.progressCmdBar(true)
|
await cmdBar.progressCmdBar()
|
||||||
await editor.expectEditor.toContain(sweepDeclaration)
|
await editor.expectEditor.toContain(sweepDeclaration)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -2092,6 +2106,18 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
await test.step(`Apply fillet to the preselected edge`, async () => {
|
await test.step(`Apply fillet to the preselected edge`, async () => {
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await toolbar.filletButton.click()
|
await toolbar.filletButton.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Fillet',
|
||||||
|
highlightedHeaderArg: 'selection',
|
||||||
|
currentArgKey: 'selection',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Selection: '',
|
||||||
|
Radius: '',
|
||||||
|
},
|
||||||
|
stage: 'arguments',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Fillet',
|
commandName: 'Fillet',
|
||||||
highlightedHeaderArg: 'radius',
|
highlightedHeaderArg: 'radius',
|
||||||
@ -2621,6 +2647,18 @@ extrude001 = extrude(profile001, length = 5)
|
|||||||
await test.step(`Apply fillet`, async () => {
|
await test.step(`Apply fillet`, async () => {
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await toolbar.filletButton.click()
|
await toolbar.filletButton.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Fillet',
|
||||||
|
highlightedHeaderArg: 'selection',
|
||||||
|
currentArgKey: 'selection',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Selection: '',
|
||||||
|
Radius: '',
|
||||||
|
},
|
||||||
|
stage: 'arguments',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Fillet',
|
commandName: 'Fillet',
|
||||||
highlightedHeaderArg: 'radius',
|
highlightedHeaderArg: 'radius',
|
||||||
@ -2726,6 +2764,19 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
await test.step(`Apply chamfer to the preselected edge`, async () => {
|
await test.step(`Apply chamfer to the preselected edge`, async () => {
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await toolbar.chamferButton.click()
|
await toolbar.chamferButton.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Chamfer',
|
||||||
|
highlightedHeaderArg: 'selection',
|
||||||
|
currentArgKey: 'selection',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Selection: '',
|
||||||
|
Length: '',
|
||||||
|
},
|
||||||
|
stage: 'arguments',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await page.waitForTimeout(1000)
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Chamfer',
|
commandName: 'Chamfer',
|
||||||
highlightedHeaderArg: 'length',
|
highlightedHeaderArg: 'length',
|
||||||
@ -3209,6 +3260,8 @@ extrude001 = extrude(sketch001, length = 30)
|
|||||||
await test.step(`Go through the command bar flow with a preselected face (cap)`, async () => {
|
await test.step(`Go through the command bar flow with a preselected face (cap)`, async () => {
|
||||||
await toolbar.shellButton.click()
|
await toolbar.shellButton.click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
@ -3638,17 +3691,16 @@ tag=$rectangleSegmentC002,
|
|||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// select line of code
|
// select line of code
|
||||||
const codeToSelection = `startProfile(at = [-66.77, 84.81])`
|
const codeToSelection = `segAng(rectangleSegmentA002) - 90,`
|
||||||
// revolve
|
// revolve
|
||||||
await editor.scrollToText(codeToSelection)
|
await editor.scrollToText(codeToSelection)
|
||||||
await page.getByText(codeToSelection).click()
|
await page.getByText(codeToSelection).click()
|
||||||
// Wait for the selection to register (TODO: we need a definitive way to wait for this)
|
|
||||||
await page.waitForTimeout(200)
|
|
||||||
await toolbar.revolveButton.click()
|
await toolbar.revolveButton.click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
|
||||||
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = X)`
|
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = X)`
|
||||||
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
|
||||||
@ -4577,12 +4629,24 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
|
|
||||||
await test.step('Go through command bar flow', async () => {
|
await test.step('Go through command bar flow', async () => {
|
||||||
await toolbar.extrudeButton.click()
|
await toolbar.extrudeButton.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'sketches',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Sketches: '',
|
||||||
|
Length: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'sketches',
|
||||||
|
commandName: 'Extrude',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'length',
|
currentArgKey: 'length',
|
||||||
currentArgValue: '5',
|
currentArgValue: '5',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '2 profiles',
|
Sketches: '2 faces',
|
||||||
Length: '',
|
Length: '',
|
||||||
},
|
},
|
||||||
highlightedHeaderArg: 'length',
|
highlightedHeaderArg: 'length',
|
||||||
@ -4593,7 +4657,7 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '2 profiles',
|
Sketches: '2 faces',
|
||||||
Length: '1',
|
Length: '1',
|
||||||
},
|
},
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
@ -4659,12 +4723,25 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
|
|
||||||
await test.step('Go through command bar flow', async () => {
|
await test.step('Go through command bar flow', async () => {
|
||||||
await toolbar.sweepButton.click()
|
await toolbar.sweepButton.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'sketches',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Sketches: '',
|
||||||
|
Path: '',
|
||||||
|
Sectional: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'sketches',
|
||||||
|
commandName: 'Sweep',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'path',
|
currentArgKey: 'path',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '2 profiles',
|
Sketches: '2 faces',
|
||||||
Path: '',
|
Path: '',
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
},
|
},
|
||||||
@ -4677,7 +4754,7 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '2 profiles',
|
Sketches: '2 faces',
|
||||||
Path: '1 segment',
|
Path: '1 segment',
|
||||||
Sectional: '',
|
Sectional: '',
|
||||||
},
|
},
|
||||||
@ -4743,12 +4820,25 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
await test.step('Go through command bar flow', async () => {
|
await test.step('Go through command bar flow', async () => {
|
||||||
await toolbar.closePane('code')
|
await toolbar.closePane('code')
|
||||||
await toolbar.revolveButton.click()
|
await toolbar.revolveButton.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
stage: 'arguments',
|
||||||
|
currentArgKey: 'sketches',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Sketches: '',
|
||||||
|
AxisOrEdge: '',
|
||||||
|
Angle: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'sketches',
|
||||||
|
commandName: 'Revolve',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'axisOrEdge',
|
currentArgKey: 'axisOrEdge',
|
||||||
currentArgValue: '',
|
currentArgValue: '',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '2 profiles',
|
Sketches: '2 faces',
|
||||||
AxisOrEdge: '',
|
AxisOrEdge: '',
|
||||||
Angle: '',
|
Angle: '',
|
||||||
},
|
},
|
||||||
@ -4764,7 +4854,7 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
currentArgKey: 'angle',
|
currentArgKey: 'angle',
|
||||||
currentArgValue: '360',
|
currentArgValue: '360',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '2 profiles',
|
Sketches: '2 faces',
|
||||||
AxisOrEdge: 'Edge',
|
AxisOrEdge: 'Edge',
|
||||||
Edge: '1 segment',
|
Edge: '1 segment',
|
||||||
Angle: '',
|
Angle: '',
|
||||||
@ -4777,7 +4867,7 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'review',
|
stage: 'review',
|
||||||
headerArguments: {
|
headerArguments: {
|
||||||
Profiles: '2 profiles',
|
Sketches: '2 faces',
|
||||||
AxisOrEdge: 'Edge',
|
AxisOrEdge: 'Edge',
|
||||||
Edge: '1 segment',
|
Edge: '1 segment',
|
||||||
Angle: '180',
|
Angle: '180',
|
||||||
|
@ -2064,59 +2064,3 @@ test(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
test(
|
|
||||||
'nested dir import works on windows',
|
|
||||||
{ tag: ['@electron', '@windows'] },
|
|
||||||
async ({ scene, cmdBar, context, page }, testInfo) => {
|
|
||||||
// Skip if on non-windows
|
|
||||||
if (process.platform !== 'win32') {
|
|
||||||
test.skip()
|
|
||||||
}
|
|
||||||
await context.folderSetupFn(async (dir) => {
|
|
||||||
const bracketDir = path.join(dir, 'bracket')
|
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
|
||||||
const nestedDir = path.join(bracketDir, 'nested')
|
|
||||||
await fsp.mkdir(nestedDir, { recursive: true })
|
|
||||||
|
|
||||||
await fsp.copyFile(
|
|
||||||
executorInputPath('cylinder-inches.kcl'),
|
|
||||||
path.join(nestedDir, 'main.kcl')
|
|
||||||
)
|
|
||||||
await fsp.writeFile(
|
|
||||||
path.join(bracketDir, 'main.kcl'),
|
|
||||||
`import 'nested\\main.kcl' as thing
|
|
||||||
|
|
||||||
thing`
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
|
||||||
const u = await getUtils(page)
|
|
||||||
|
|
||||||
const pointOnModel = { x: 630, y: 280 }
|
|
||||||
|
|
||||||
await test.step('Opening the bracket project should load the stream', async () => {
|
|
||||||
// expect to see the text bracket
|
|
||||||
await expect(page.getByText('bracket')).toBeVisible()
|
|
||||||
|
|
||||||
await page.getByText('bracket').click()
|
|
||||||
|
|
||||||
await scene.settled(cmdBar)
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole('button', { name: 'Start Sketch' })
|
|
||||||
).toBeEnabled({
|
|
||||||
timeout: 20_000,
|
|
||||||
})
|
|
||||||
|
|
||||||
// gray at this pixel means the stream has loaded in the most
|
|
||||||
// user way we can verify it (pixel color)
|
|
||||||
await expect
|
|
||||||
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), {
|
|
||||||
timeout: 10_000,
|
|
||||||
})
|
|
||||||
.toBeLessThan(15)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
@ -995,8 +995,8 @@ profile001 = startProfile(sketch001, at = [${roundOff(scale * 69.6)}, ${roundOff
|
|||||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||||
await u.closeDebugPanel()
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
// click profile in code
|
// click "line(end = [1.32, 0.38])"
|
||||||
await page.getByText(`startProfile(at = [-0.45, 0.87])`).click()
|
await page.getByText(`line(end = [1.32, 0.38])`).click()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeEnabled(
|
await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeEnabled(
|
||||||
{ timeout: 10_000 }
|
{ timeout: 10_000 }
|
||||||
@ -1014,13 +1014,14 @@ profile001 = startProfile(sketch001, at = [${roundOff(scale * 69.6)}, ${roundOff
|
|||||||
// click extrude
|
// click extrude
|
||||||
await toolbar.extrudeButton.click()
|
await toolbar.extrudeButton.click()
|
||||||
|
|
||||||
// sketch selection should already have been made.
|
// sketch selection should already have been made. "Sketches: 1 face" only show up when the selection has been made already
|
||||||
// otherwise the cmdbar would be waiting for a selection.
|
// otherwise the cmdbar would be waiting for a selection.
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
currentArgKey: 'length',
|
currentArgKey: 'length',
|
||||||
currentArgValue: '5',
|
currentArgValue: '5',
|
||||||
headerArguments: { Profiles: '1 profile', Length: '' },
|
headerArguments: { Sketches: '1 segment', Length: '' },
|
||||||
highlightedHeaderArg: 'length',
|
highlightedHeaderArg: 'length',
|
||||||
commandName: 'Extrude',
|
commandName: 'Extrude',
|
||||||
})
|
})
|
||||||
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 63 KiB |
@ -551,20 +551,17 @@ export async function getUtils(page: Page, test_?: typeof test) {
|
|||||||
|
|
||||||
createNewFile: async (name: string) => {
|
createNewFile: async (name: string) => {
|
||||||
return test?.step(`Create a file named ${name}`, async () => {
|
return test?.step(`Create a file named ${name}`, async () => {
|
||||||
|
// If the application is in the middle of connecting a stream
|
||||||
|
// then creating a new file won't work in the end.
|
||||||
|
await expect(
|
||||||
|
page.getByRole('button', { name: 'Start Sketch' })
|
||||||
|
).not.toBeDisabled()
|
||||||
await page.getByTestId('create-file-button').click()
|
await page.getByTestId('create-file-button').click()
|
||||||
await page.getByTestId('tree-input-field').fill(name)
|
await page.getByTestId('tree-input-field').fill(name)
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
createNewFolder: async (name: string) => {
|
|
||||||
return test?.step(`Create a folder named ${name}`, async () => {
|
|
||||||
await page.getByTestId('create-folder-button').click()
|
|
||||||
await page.getByTestId('tree-input-field').fill(name)
|
|
||||||
await page.keyboard.press('Enter')
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
cloneFile: async (name: string) => {
|
cloneFile: async (name: string) => {
|
||||||
return test?.step(`Cloning file '${name}'`, async () => {
|
return test?.step(`Cloning file '${name}'`, async () => {
|
||||||
await page
|
await page
|
||||||
|
@ -4,10 +4,9 @@ import type { Page } from '@playwright/test'
|
|||||||
|
|
||||||
import { createProject, getUtils } from '@e2e/playwright/test-utils'
|
import { createProject, getUtils } from '@e2e/playwright/test-utils'
|
||||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
|
||||||
|
|
||||||
test.describe('Text-to-CAD tests', () => {
|
test.describe('Text-to-CAD tests', () => {
|
||||||
test('basic lego happy case', async ({ page, homePage, cmdBar }) => {
|
test('basic lego happy case', async ({ page, homePage }) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
|
||||||
await test.step('Set up', async () => {
|
await test.step('Set up', async () => {
|
||||||
@ -16,11 +15,7 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
})
|
})
|
||||||
|
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(page, 'a 2x4 lego')
|
||||||
page,
|
|
||||||
'a 2x4 lego',
|
|
||||||
cmdBar
|
|
||||||
)
|
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -61,7 +56,6 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
test('success model, then ignore success toast, user can create new prompt from command bar', async ({
|
test('success model, then ignore success toast, user can create new prompt from command bar', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
cmdBar,
|
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
|
||||||
@ -70,11 +64,7 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
|
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(page, 'a 2x6 lego')
|
||||||
page,
|
|
||||||
'a 2x6 lego',
|
|
||||||
cmdBar
|
|
||||||
)
|
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -92,11 +82,7 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
await expect(successToastMessage).toBeVisible({ timeout: 15000 })
|
await expect(successToastMessage).toBeVisible({ timeout: 15000 })
|
||||||
|
|
||||||
// Can send a new prompt from the command bar.
|
// Can send a new prompt from the command bar.
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(page, 'a 2x4 lego')
|
||||||
page,
|
|
||||||
'a 2x4 lego',
|
|
||||||
cmdBar
|
|
||||||
)
|
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -114,7 +100,6 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
test('you can reject text-to-cad output and it does nothing', async ({
|
test('you can reject text-to-cad output and it does nothing', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
cmdBar,
|
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
|
||||||
@ -123,11 +108,7 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
|
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(page, 'a 2x4 lego')
|
||||||
page,
|
|
||||||
'a 2x4 lego',
|
|
||||||
cmdBar
|
|
||||||
)
|
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -160,7 +141,6 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
test('sending a bad prompt fails, can dismiss', async ({
|
test('sending a bad prompt fails, can dismiss', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
cmdBar,
|
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
|
||||||
@ -170,11 +150,7 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
|
|
||||||
const randomPrompt = `aslkdfja;` + Date.now() + `FFFFEIWJF`
|
const randomPrompt = `aslkdfja;` + Date.now() + `FFFFEIWJF`
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(page, randomPrompt)
|
||||||
page,
|
|
||||||
randomPrompt,
|
|
||||||
cmdBar
|
|
||||||
)
|
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -212,7 +188,6 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
test('sending a bad prompt fails, can start over from toast', async ({
|
test('sending a bad prompt fails, can start over from toast', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
cmdBar,
|
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
|
||||||
@ -222,7 +197,7 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
|
|
||||||
const badPrompt = 'akjsndladf lajbhflauweyfaaaljhr472iouafyvsssssss'
|
const badPrompt = 'akjsndladf lajbhflauweyfaaaljhr472iouafyvsssssss'
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(page, badPrompt, cmdBar)
|
await sendPromptFromCommandBarTriggeredByButton(page, badPrompt)
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -281,7 +256,6 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
test('sending a bad prompt fails, can ignore toast, can start over from command bar', async ({
|
test('sending a bad prompt fails, can ignore toast, can start over from command bar', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
cmdBar,
|
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
|
||||||
@ -291,7 +265,7 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
|
|
||||||
const badPrompt = 'akjsndladflajbhflauweyf15;'
|
const badPrompt = 'akjsndladflajbhflauweyf15;'
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(page, badPrompt, cmdBar)
|
await sendPromptFromCommandBarTriggeredByButton(page, badPrompt)
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -318,11 +292,7 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
await expect(page.getByText(`Text-to-CAD failed`)).toBeVisible()
|
await expect(page.getByText(`Text-to-CAD failed`)).toBeVisible()
|
||||||
|
|
||||||
// They should be able to try again from the command bar.
|
// They should be able to try again from the command bar.
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(page, 'a 2x4 lego')
|
||||||
page,
|
|
||||||
'a 2x4 lego',
|
|
||||||
cmdBar
|
|
||||||
)
|
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -340,40 +310,17 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
test('ensure you can shift+enter in the prompt box', async ({
|
test('ensure you can shift+enter in the prompt box', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
cmdBar,
|
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
const projectName = await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
|
|
||||||
const promptWithNewline = `a 2x4\nlego`
|
const promptWithNewline = `a 2x4\nlego`
|
||||||
|
|
||||||
await test.step('Get to the prompt step to test', async () => {
|
await page.getByTestId('text-to-cad').click()
|
||||||
await cmdBar.openCmdBar()
|
|
||||||
await cmdBar.selectOption({ name: 'Text-to-CAD Create' }).click()
|
|
||||||
|
|
||||||
await cmdBar.currentArgumentInput.fill('existing')
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
|
|
||||||
await cmdBar.currentArgumentInput.fill(projectName)
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
|
|
||||||
await cmdBar.expectState({
|
|
||||||
commandName: 'Text-to-CAD Create',
|
|
||||||
stage: 'arguments',
|
|
||||||
currentArgKey: 'prompt',
|
|
||||||
currentArgValue: '',
|
|
||||||
highlightedHeaderArg: 'prompt',
|
|
||||||
headerArguments: {
|
|
||||||
Method: 'Existing project',
|
|
||||||
ProjectName: projectName,
|
|
||||||
Prompt: '',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Type the prompt.
|
// Type the prompt.
|
||||||
await page.keyboard.type('a 2x4')
|
await page.keyboard.type('a 2x4')
|
||||||
@ -407,7 +354,6 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
test('can do many at once and get many prompts back, and interact with many', async ({
|
test('can do many at once and get many prompts back, and interact with many', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
cmdBar,
|
|
||||||
}) => {
|
}) => {
|
||||||
// Let this test run longer since we've seen it timeout.
|
// Let this test run longer since we've seen it timeout.
|
||||||
test.setTimeout(180_000)
|
test.setTimeout(180_000)
|
||||||
@ -419,23 +365,11 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
|
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(page, 'a 2x4 lego')
|
||||||
page,
|
|
||||||
'a 2x4 lego',
|
|
||||||
cmdBar
|
|
||||||
)
|
|
||||||
|
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(page, 'a 2x8 lego')
|
||||||
page,
|
|
||||||
'a 2x8 lego',
|
|
||||||
cmdBar
|
|
||||||
)
|
|
||||||
|
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(page, 'a 2x10 lego')
|
||||||
page,
|
|
||||||
'a 2x10 lego',
|
|
||||||
cmdBar
|
|
||||||
)
|
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
@ -506,7 +440,6 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
test('can do many at once with errors, clicking dismiss error does not dismiss all', async ({
|
test('can do many at once with errors, clicking dismiss error does not dismiss all', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
cmdBar,
|
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
|
|
||||||
@ -515,16 +448,11 @@ test.describe('Text-to-CAD tests', () => {
|
|||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await u.waitForPageLoad()
|
||||||
|
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(page, 'a 2x4 lego')
|
||||||
page,
|
|
||||||
'a 2x4 lego',
|
|
||||||
cmdBar
|
|
||||||
)
|
|
||||||
|
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(
|
||||||
page,
|
page,
|
||||||
'alkjsdnlajshdbfjlhsbdf a;askjdnf',
|
'alkjsdnlajshdbfjlhsbdf a;askjdnf'
|
||||||
cmdBar
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
@ -598,9 +526,7 @@ async function _sendPromptFromCommandBar(page: Page, promptStr: string) {
|
|||||||
const cmdSearchBar = page.getByPlaceholder('Search commands')
|
const cmdSearchBar = page.getByPlaceholder('Search commands')
|
||||||
await expect(cmdSearchBar).toBeVisible()
|
await expect(cmdSearchBar).toBeVisible()
|
||||||
|
|
||||||
const textToCadCommand = page.getByRole('option', {
|
const textToCadCommand = page.getByText('Use the Zoo Text-to-CAD API')
|
||||||
name: 'Text-to-CAD Create',
|
|
||||||
})
|
|
||||||
await expect(textToCadCommand.first()).toBeVisible()
|
await expect(textToCadCommand.first()).toBeVisible()
|
||||||
// Click the Text-to-CAD command
|
// Click the Text-to-CAD command
|
||||||
await textToCadCommand.first().scrollIntoViewIfNeeded()
|
await textToCadCommand.first().scrollIntoViewIfNeeded()
|
||||||
@ -618,67 +544,29 @@ async function _sendPromptFromCommandBar(page: Page, promptStr: string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendPromptFromCommandBarAndSetExistingProject(
|
async function sendPromptFromCommandBarTriggeredByButton(
|
||||||
page: Page,
|
page: Page,
|
||||||
promptStr: string,
|
promptStr: string
|
||||||
cmdBar: CmdBarFixture,
|
|
||||||
projectName = 'testDefault'
|
|
||||||
) {
|
) {
|
||||||
await page.waitForTimeout(1000)
|
await page.waitForTimeout(1000)
|
||||||
await test.step(`Send prompt from command bar: ${promptStr}`, async () => {
|
await test.step(`Send prompt from command bar: ${promptStr}`, async () => {
|
||||||
await cmdBar.openCmdBar()
|
await page.getByTestId('text-to-cad').click()
|
||||||
await cmdBar.selectOption({ name: 'Text-to-CAD Create' }).click()
|
|
||||||
|
|
||||||
await cmdBar.expectState({
|
// Enter the prompt.
|
||||||
commandName: 'Text-to-CAD Create',
|
const prompt = page.getByRole('textbox', { name: 'Prompt' })
|
||||||
stage: 'arguments',
|
await expect(prompt.first()).toBeVisible()
|
||||||
currentArgKey: 'method',
|
|
||||||
currentArgValue: '',
|
|
||||||
highlightedHeaderArg: 'method',
|
|
||||||
headerArguments: {
|
|
||||||
Method: '',
|
|
||||||
Prompt: '',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
await cmdBar.currentArgumentInput.fill('existing')
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
|
|
||||||
await cmdBar.expectState({
|
// Type the prompt.
|
||||||
commandName: 'Text-to-CAD Create',
|
await page.keyboard.type(promptStr)
|
||||||
stage: 'arguments',
|
await page.waitForTimeout(200)
|
||||||
currentArgKey: 'projectName',
|
await page.keyboard.press('Enter')
|
||||||
currentArgValue: '',
|
|
||||||
highlightedHeaderArg: 'projectName',
|
|
||||||
headerArguments: {
|
|
||||||
Method: 'Existing project',
|
|
||||||
ProjectName: '',
|
|
||||||
Prompt: '',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
await cmdBar.currentArgumentInput.fill(projectName)
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
|
|
||||||
await cmdBar.expectState({
|
|
||||||
commandName: 'Text-to-CAD Create',
|
|
||||||
stage: 'arguments',
|
|
||||||
currentArgKey: 'prompt',
|
|
||||||
currentArgValue: '',
|
|
||||||
highlightedHeaderArg: 'prompt',
|
|
||||||
headerArguments: {
|
|
||||||
Method: 'Existing project',
|
|
||||||
ProjectName: projectName,
|
|
||||||
Prompt: '',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
await cmdBar.currentArgumentInput.fill(promptStr)
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'Text-to-CAD functionality',
|
'Text-to-CAD functionality',
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page, cmdBar }, testInfo) => {
|
async ({ context, page }, testInfo) => {
|
||||||
const projectName = 'project-000'
|
const projectName = 'project-000'
|
||||||
const prompt = 'lego 2x4'
|
const prompt = 'lego 2x4'
|
||||||
const textToCadFileName = 'lego-2x4.kcl'
|
const textToCadFileName = 'lego-2x4.kcl'
|
||||||
@ -715,12 +603,7 @@ test(
|
|||||||
await openKclCodePanel()
|
await openKclCodePanel()
|
||||||
|
|
||||||
await test.step(`Test file creation`, async () => {
|
await test.step(`Test file creation`, async () => {
|
||||||
await sendPromptFromCommandBarAndSetExistingProject(
|
await sendPromptFromCommandBarTriggeredByButton(page, prompt)
|
||||||
page,
|
|
||||||
prompt,
|
|
||||||
cmdBar,
|
|
||||||
projectName
|
|
||||||
)
|
|
||||||
// File is considered created if it shows up in the Project Files pane
|
// File is considered created if it shows up in the Project Files pane
|
||||||
await expect(textToCadFileButton).toBeVisible({ timeout: 20_000 })
|
await expect(textToCadFileButton).toBeVisible({ timeout: 20_000 })
|
||||||
expect(fileExists()).toBeTruthy()
|
expect(fileExists()).toBeTruthy()
|
||||||
@ -890,12 +773,12 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
|||||||
)
|
)
|
||||||
await expect(page.getByTestId('app-header-file-name')).toBeVisible()
|
await expect(page.getByTestId('app-header-file-name')).toBeVisible()
|
||||||
await expect(page.getByTestId('app-header-file-name')).toContainText(
|
await expect(page.getByTestId('app-header-file-name')).toContainText(
|
||||||
'main.kcl'
|
'2x2x2-cube.kcl'
|
||||||
)
|
)
|
||||||
|
|
||||||
await u.openFilePanel()
|
await u.openFilePanel()
|
||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('file-tree-item').getByText('main.kcl')
|
page.getByTestId('file-tree-item').getByText('2x2x2-cube.kcl')
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -1030,7 +913,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
|||||||
)
|
)
|
||||||
await expect(page.getByTestId('app-header-file-name')).toBeVisible()
|
await expect(page.getByTestId('app-header-file-name')).toBeVisible()
|
||||||
await expect(page.getByTestId('app-header-file-name')).toContainText(
|
await expect(page.getByTestId('app-header-file-name')).toContainText(
|
||||||
'main.kcl'
|
'2x2x2-cube.kcl'
|
||||||
)
|
)
|
||||||
|
|
||||||
await page.getByRole('button', { name: 'Reject' }).click()
|
await page.getByRole('button', { name: 'Reject' }).click()
|
||||||
@ -1078,7 +961,7 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
|||||||
)
|
)
|
||||||
await expect(page.getByTestId('app-header-file-name')).toBeVisible()
|
await expect(page.getByTestId('app-header-file-name')).toBeVisible()
|
||||||
await expect(page.getByTestId('app-header-file-name')).toContainText(
|
await expect(page.getByTestId('app-header-file-name')).toContainText(
|
||||||
'main.kcl'
|
'2x2x2-cube.kcl'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -1330,14 +1213,18 @@ test.describe('Mocked Text-to-CAD API tests', { tag: ['@skipWin'] }, () => {
|
|||||||
)
|
)
|
||||||
await expect(page.getByTestId('app-header-file-name')).toBeVisible()
|
await expect(page.getByTestId('app-header-file-name')).toBeVisible()
|
||||||
await expect(page.getByTestId('app-header-file-name')).toContainText(
|
await expect(page.getByTestId('app-header-file-name')).toContainText(
|
||||||
'main.kcl'
|
'2x2x2-cube.kcl'
|
||||||
)
|
)
|
||||||
|
|
||||||
// Check file is created
|
// Check file is created
|
||||||
await u.openFilePanel()
|
await u.openFilePanel()
|
||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('file-tree-item').getByText('main.kcl')
|
page.getByTestId('file-tree-item').getByText('2x2x2-cube.kcl')
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByTestId('file-tree-item').getByText('main.kcl')
|
||||||
|
).not.toBeVisible()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -573,6 +573,7 @@ profile001 = startProfile(sketch002, at = [-12.34, 12.34])
|
|||||||
await expect(page.getByTestId('command-bar')).toBeVisible()
|
await expect(page.getByTestId('command-bar')).toBeVisible()
|
||||||
await page.waitForTimeout(100)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await expect(page.getByText('Confirm Extrude')).toBeVisible()
|
await expect(page.getByText('Confirm Extrude')).toBeVisible()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
|
@ -94,6 +94,7 @@
|
|||||||
"build:wasm:dev": "./scripts/build-wasm-dev.sh",
|
"build:wasm:dev": "./scripts/build-wasm-dev.sh",
|
||||||
"build:wasm:dev:windows": "powershell -ExecutionPolicy Bypass -File ./scripts/build-wasm-dev.ps1",
|
"build:wasm:dev:windows": "powershell -ExecutionPolicy Bypass -File ./scripts/build-wasm-dev.ps1",
|
||||||
"pretest": "npm run remove-importmeta",
|
"pretest": "npm run remove-importmeta",
|
||||||
|
"test:rust": "(cd rust && just test && just lint)",
|
||||||
"simpleserver": "npm run pretest && http-server ./public --cors -p 3000",
|
"simpleserver": "npm run pretest && http-server ./public --cors -p 3000",
|
||||||
"simpleserver:ci": "npm run pretest && http-server ./public --cors -p 3000 &",
|
"simpleserver:ci": "npm run pretest && http-server ./public --cors -p 3000 &",
|
||||||
"simpleserver:bg": "npm run pretest && http-server ./public --cors -p 3000 &",
|
"simpleserver:bg": "npm run pretest && http-server ./public --cors -p 3000 &",
|
||||||
@ -129,14 +130,15 @@
|
|||||||
"tronb:package:prod": "npm run tronb:vite:prod && electron-builder --config electron-builder.yml --publish always",
|
"tronb:package:prod": "npm run tronb:vite:prod && electron-builder --config electron-builder.yml --publish always",
|
||||||
"test-setup": "npm install && npm run build:wasm",
|
"test-setup": "npm install && npm run build:wasm",
|
||||||
"test": "vitest --mode development",
|
"test": "vitest --mode development",
|
||||||
"test:rust": "(cd rust && just test && just lint)",
|
|
||||||
"test:snapshots": "PLATFORM=web NODE_ENV=development playwright test --config=playwright.config.ts --grep=@snapshot --trace=on --shard=1/1",
|
"test:snapshots": "PLATFORM=web NODE_ENV=development playwright test --config=playwright.config.ts --grep=@snapshot --trace=on --shard=1/1",
|
||||||
"test:unit": "vitest run --mode development --exclude **/jest-component-unit-tests/*",
|
"test:unit": "vitest run --mode development --exclude **/kclSamples.test.ts --exclude **/jest-component-unit-tests/*",
|
||||||
"test:unit:components": "jest -c jest-component-unit-tests/jest.config.ts --rootDir jest-component-unit-tests/",
|
"test:unit:components": "jest -c jest-component-unit-tests/jest.config.ts --rootDir jest-component-unit-tests/",
|
||||||
|
"test:unit:kcl-samples": "vitest run --mode development ./src/lang/kclSamples.test.ts",
|
||||||
"test:playwright:electron": "playwright test --config=playwright.electron.config.ts --grep-invert=@snapshot",
|
"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": "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: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:unit:local": "npm run simpleserver:bg && npm run test:unit; kill-port 3000"
|
"test:unit:local": "npm run simpleserver:bg && npm run test:unit; kill-port 3000",
|
||||||
|
"test:unit:kcl-samples:local": "npm run simpleserver:bg && npm run test:unit:kcl-samples; kill-port 3000"
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
|
@ -37,8 +37,6 @@ When you submit a PR to add or modify KCL samples, images will be generated and
|
|||||||
[](bottle/main.kcl)
|
[](bottle/main.kcl)
|
||||||
#### [bracket](bracket/main.kcl) ([screenshot](screenshots/bracket.png))
|
#### [bracket](bracket/main.kcl) ([screenshot](screenshots/bracket.png))
|
||||||
[](bracket/main.kcl)
|
[](bracket/main.kcl)
|
||||||
#### [brake-rotor](brake-rotor/main.kcl) ([screenshot](screenshots/brake-rotor.png))
|
|
||||||
[](brake-rotor/main.kcl)
|
|
||||||
#### [car-wheel-assembly](car-wheel-assembly/main.kcl) ([screenshot](screenshots/car-wheel-assembly.png))
|
#### [car-wheel-assembly](car-wheel-assembly/main.kcl) ([screenshot](screenshots/car-wheel-assembly.png))
|
||||||
[](car-wheel-assembly/main.kcl)
|
[](car-wheel-assembly/main.kcl)
|
||||||
#### [cold-plate](cold-plate/main.kcl) ([screenshot](screenshots/cold-plate.png))
|
#### [cold-plate](cold-plate/main.kcl) ([screenshot](screenshots/cold-plate.png))
|
||||||
@ -51,16 +49,12 @@ When you submit a PR to add or modify KCL samples, images will be generated and
|
|||||||
[](countersunk-plate/main.kcl)
|
[](countersunk-plate/main.kcl)
|
||||||
#### [cpu-cooler](cpu-cooler/main.kcl) ([screenshot](screenshots/cpu-cooler.png))
|
#### [cpu-cooler](cpu-cooler/main.kcl) ([screenshot](screenshots/cpu-cooler.png))
|
||||||
[](cpu-cooler/main.kcl)
|
[](cpu-cooler/main.kcl)
|
||||||
#### [curtain-wall-anchor-plate](curtain-wall-anchor-plate/main.kcl) ([screenshot](screenshots/curtain-wall-anchor-plate.png))
|
|
||||||
[](curtain-wall-anchor-plate/main.kcl)
|
|
||||||
#### [cycloidal-gear](cycloidal-gear/main.kcl) ([screenshot](screenshots/cycloidal-gear.png))
|
#### [cycloidal-gear](cycloidal-gear/main.kcl) ([screenshot](screenshots/cycloidal-gear.png))
|
||||||
[](cycloidal-gear/main.kcl)
|
[](cycloidal-gear/main.kcl)
|
||||||
#### [dodecahedron](dodecahedron/main.kcl) ([screenshot](screenshots/dodecahedron.png))
|
#### [dodecahedron](dodecahedron/main.kcl) ([screenshot](screenshots/dodecahedron.png))
|
||||||
[](dodecahedron/main.kcl)
|
[](dodecahedron/main.kcl)
|
||||||
#### [enclosure](enclosure/main.kcl) ([screenshot](screenshots/enclosure.png))
|
#### [enclosure](enclosure/main.kcl) ([screenshot](screenshots/enclosure.png))
|
||||||
[](enclosure/main.kcl)
|
[](enclosure/main.kcl)
|
||||||
#### [engine-valve](engine-valve/main.kcl) ([screenshot](screenshots/engine-valve.png))
|
|
||||||
[](engine-valve/main.kcl)
|
|
||||||
#### [exhaust-manifold](exhaust-manifold/main.kcl) ([screenshot](screenshots/exhaust-manifold.png))
|
#### [exhaust-manifold](exhaust-manifold/main.kcl) ([screenshot](screenshots/exhaust-manifold.png))
|
||||||
[](exhaust-manifold/main.kcl)
|
[](exhaust-manifold/main.kcl)
|
||||||
#### [flange](flange/main.kcl) ([screenshot](screenshots/flange.png))
|
#### [flange](flange/main.kcl) ([screenshot](screenshots/flange.png))
|
||||||
@ -109,8 +103,6 @@ When you submit a PR to add or modify KCL samples, images will be generated and
|
|||||||
[](mounting-plate/main.kcl)
|
[](mounting-plate/main.kcl)
|
||||||
#### [multi-axis-robot](multi-axis-robot/main.kcl) ([screenshot](screenshots/multi-axis-robot.png))
|
#### [multi-axis-robot](multi-axis-robot/main.kcl) ([screenshot](screenshots/multi-axis-robot.png))
|
||||||
[](multi-axis-robot/main.kcl)
|
[](multi-axis-robot/main.kcl)
|
||||||
#### [pdu-faceplate](pdu-faceplate/main.kcl) ([screenshot](screenshots/pdu-faceplate.png))
|
|
||||||
[](pdu-faceplate/main.kcl)
|
|
||||||
#### [pillow-block-bearing](pillow-block-bearing/main.kcl) ([screenshot](screenshots/pillow-block-bearing.png))
|
#### [pillow-block-bearing](pillow-block-bearing/main.kcl) ([screenshot](screenshots/pillow-block-bearing.png))
|
||||||
[](pillow-block-bearing/main.kcl)
|
[](pillow-block-bearing/main.kcl)
|
||||||
#### [pipe](pipe/main.kcl) ([screenshot](screenshots/pipe.png))
|
#### [pipe](pipe/main.kcl) ([screenshot](screenshots/pipe.png))
|
||||||
@ -127,24 +119,16 @@ When you submit a PR to add or modify KCL samples, images will be generated and
|
|||||||
[](router-template-cross-bar/main.kcl)
|
[](router-template-cross-bar/main.kcl)
|
||||||
#### [router-template-slate](router-template-slate/main.kcl) ([screenshot](screenshots/router-template-slate.png))
|
#### [router-template-slate](router-template-slate/main.kcl) ([screenshot](screenshots/router-template-slate.png))
|
||||||
[](router-template-slate/main.kcl)
|
[](router-template-slate/main.kcl)
|
||||||
#### [sash-window](sash-window/main.kcl) ([screenshot](screenshots/sash-window.png))
|
|
||||||
[](sash-window/main.kcl)
|
|
||||||
#### [sheet-metal-bracket](sheet-metal-bracket/main.kcl) ([screenshot](screenshots/sheet-metal-bracket.png))
|
#### [sheet-metal-bracket](sheet-metal-bracket/main.kcl) ([screenshot](screenshots/sheet-metal-bracket.png))
|
||||||
[](sheet-metal-bracket/main.kcl)
|
[](sheet-metal-bracket/main.kcl)
|
||||||
#### [shepherds-hook-bolt](shepherds-hook-bolt/main.kcl) ([screenshot](screenshots/shepherds-hook-bolt.png))
|
|
||||||
[](shepherds-hook-bolt/main.kcl)
|
|
||||||
#### [socket-head-cap-screw](socket-head-cap-screw/main.kcl) ([screenshot](screenshots/socket-head-cap-screw.png))
|
#### [socket-head-cap-screw](socket-head-cap-screw/main.kcl) ([screenshot](screenshots/socket-head-cap-screw.png))
|
||||||
[](socket-head-cap-screw/main.kcl)
|
[](socket-head-cap-screw/main.kcl)
|
||||||
#### [spinning-highrise-tower](spinning-highrise-tower/main.kcl) ([screenshot](screenshots/spinning-highrise-tower.png))
|
|
||||||
[](spinning-highrise-tower/main.kcl)
|
|
||||||
#### [spur-gear](spur-gear/main.kcl) ([screenshot](screenshots/spur-gear.png))
|
#### [spur-gear](spur-gear/main.kcl) ([screenshot](screenshots/spur-gear.png))
|
||||||
[](spur-gear/main.kcl)
|
[](spur-gear/main.kcl)
|
||||||
#### [spur-reduction-gearset](spur-reduction-gearset/main.kcl) ([screenshot](screenshots/spur-reduction-gearset.png))
|
#### [spur-reduction-gearset](spur-reduction-gearset/main.kcl) ([screenshot](screenshots/spur-reduction-gearset.png))
|
||||||
[](spur-reduction-gearset/main.kcl)
|
[](spur-reduction-gearset/main.kcl)
|
||||||
#### [surgical-drill-guide](surgical-drill-guide/main.kcl) ([screenshot](screenshots/surgical-drill-guide.png))
|
#### [surgical-drill-guide](surgical-drill-guide/main.kcl) ([screenshot](screenshots/surgical-drill-guide.png))
|
||||||
[](surgical-drill-guide/main.kcl)
|
[](surgical-drill-guide/main.kcl)
|
||||||
#### [thermal-block-insert](thermal-block-insert/main.kcl) ([screenshot](screenshots/thermal-block-insert.png))
|
|
||||||
[](thermal-block-insert/main.kcl)
|
|
||||||
#### [tooling-nest-block](tooling-nest-block/main.kcl) ([screenshot](screenshots/tooling-nest-block.png))
|
#### [tooling-nest-block](tooling-nest-block/main.kcl) ([screenshot](screenshots/tooling-nest-block.png))
|
||||||
[](tooling-nest-block/main.kcl)
|
[](tooling-nest-block/main.kcl)
|
||||||
#### [utility-sink](utility-sink/main.kcl) ([screenshot](screenshots/utility-sink.png))
|
#### [utility-sink](utility-sink/main.kcl) ([screenshot](screenshots/utility-sink.png))
|
||||||
|
@ -1,179 +0,0 @@
|
|||||||
// A 320mm vented brake disc (rotor), with straight vanes, 30mm thick. The disc bell should accommodate 5 M12 wheel studs on a 114.3mm pitch circle diameter.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@settings(defaultLengthUnit = mm)
|
|
||||||
|
|
||||||
// Define parameters.
|
|
||||||
dDisc = 320
|
|
||||||
dPitchCircle = 114.3
|
|
||||||
dBore = 64
|
|
||||||
nStuds = 5
|
|
||||||
dStudDrilling = 12.5 // M12
|
|
||||||
hFrictionSurface = 60
|
|
||||||
tDiscHalf = 10
|
|
||||||
|
|
||||||
// Vent parameters.
|
|
||||||
tVent = 10
|
|
||||||
wVent = 6
|
|
||||||
rVentFillet = 2
|
|
||||||
nVentBosses = 36
|
|
||||||
|
|
||||||
// Drilling parameters.
|
|
||||||
dDrillDia = 6
|
|
||||||
aBase = 90
|
|
||||||
aSweep = 30
|
|
||||||
nArcs = 12
|
|
||||||
|
|
||||||
// Bell parameters.
|
|
||||||
aDraftBell = 5
|
|
||||||
tBell = 5 // Wall thickness.
|
|
||||||
hBellAboveDiscFace = 40
|
|
||||||
hBellSubflush = 4
|
|
||||||
wUndercut = 8
|
|
||||||
|
|
||||||
fn drillHole(activeSketch, t) {
|
|
||||||
// Sketch a vent hole at line parameter value t on an arc drawn across the disc surface.
|
|
||||||
rInner = dDisc / 2 - hFrictionSurface
|
|
||||||
rOuter = dDisc / 2
|
|
||||||
|
|
||||||
aStart = aBase
|
|
||||||
aEnd = aBase - aSweep
|
|
||||||
|
|
||||||
// Linear interpolation of radius.
|
|
||||||
rCurrent = rInner + t * (rOuter - rInner)
|
|
||||||
|
|
||||||
// Linear interpolation of angle.
|
|
||||||
aCurrent = aStart + t * (aEnd - aStart)
|
|
||||||
|
|
||||||
// Calculate position.
|
|
||||||
xCenter = rCurrent * cos(aCurrent)
|
|
||||||
yCenter = rCurrent * sin(aCurrent)
|
|
||||||
|
|
||||||
// Draw.
|
|
||||||
drillCircle = circle(activeSketch, center = [xCenter, yCenter], radius = dDrillDia / 2)
|
|
||||||
return drillCircle
|
|
||||||
}
|
|
||||||
|
|
||||||
fn createDiscHalf(plane, dDiscParam, hFrictionSurfaceParam, tDiscHalfParam) {
|
|
||||||
// Create a disc half with a vent hole pattern.
|
|
||||||
sketchFace = startSketchOn(plane)
|
|
||||||
profileFace = circle(sketchFace, center = [0, 0], radius = dDiscParam / 2)
|
|
||||||
|> subtract2d(tool = circle(sketchFace, center = [0, 0], radius = dDiscParam / 2 - hFrictionSurfaceParam))
|
|
||||||
|
|
||||||
// Create three circles at t = 0, 0.5, and 1
|
|
||||||
hole1 = drillHole(activeSketch = sketchFace, t = 0.2)
|
|
||||||
hole2 = drillHole(activeSketch = sketchFace, t = 0.5)
|
|
||||||
hole3 = drillHole(activeSketch = sketchFace, t = 0.8)
|
|
||||||
|
|
||||||
// Pattern and cut.
|
|
||||||
holes = patternCircular2d(
|
|
||||||
[hole1, hole2, hole3],
|
|
||||||
instances = nArcs,
|
|
||||||
center = [0, 0],
|
|
||||||
arcDegrees = 360,
|
|
||||||
rotateDuplicates = true,
|
|
||||||
)
|
|
||||||
profileDrilled = subtract2d(profileFace, tool = holes)
|
|
||||||
|
|
||||||
// Extrude.
|
|
||||||
discHalf = extrude(profileFace, length = tDiscHalfParam)
|
|
||||||
return discHalf
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Create inboard half.
|
|
||||||
discInboard = createDiscHalf(
|
|
||||||
plane = XY,
|
|
||||||
dDiscParam = dDisc,
|
|
||||||
hFrictionSurfaceParam = hFrictionSurface,
|
|
||||||
tDiscHalfParam = tDiscHalf,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create vents.
|
|
||||||
planeVent = offsetPlane(XY, offset = tDiscHalf)
|
|
||||||
sketchVent = startSketchOn(planeVent)
|
|
||||||
profileVent = startProfile(sketchVent, at = [-wVent, dDisc / 2])
|
|
||||||
|> angledLine(angle = 0, length = wVent, tag = $rectangleSegmentA001)
|
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = hFrictionSurface, tag = $seg02)
|
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $seg03)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg01)
|
|
||||||
|> close()
|
|
||||||
|
|
||||||
ventPad = extrude(profileVent, length = tVent)
|
|
||||||
|> fillet(
|
|
||||||
radius = rVentFillet,
|
|
||||||
tags = [
|
|
||||||
getCommonEdge(faces = [seg01, rectangleSegmentA001]),
|
|
||||||
getCommonEdge(faces = [seg02, rectangleSegmentA001]),
|
|
||||||
getCommonEdge(faces = [seg01, seg03]),
|
|
||||||
getCommonEdge(faces = [seg03, seg02])
|
|
||||||
],
|
|
||||||
)
|
|
||||||
ventSet = patternCircular3d(
|
|
||||||
ventPad,
|
|
||||||
instances = nVentBosses,
|
|
||||||
axis = [0, 0, 1],
|
|
||||||
center = [0, 0, tDiscHalf],
|
|
||||||
arcDegrees = 360,
|
|
||||||
rotateDuplicates = true,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create outboard half.
|
|
||||||
planeOutboard = offsetPlane(XY, offset = tDiscHalf + tVent)
|
|
||||||
discOutboard = createDiscHalf(
|
|
||||||
plane = planeOutboard,
|
|
||||||
dDiscParam = dDisc,
|
|
||||||
hFrictionSurfaceParam = hFrictionSurface,
|
|
||||||
tDiscHalfParam = tDiscHalf,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Now create bell.
|
|
||||||
rCenter = dDisc / 2 - hFrictionSurface - wUndercut
|
|
||||||
rBore = dBore / 2
|
|
||||||
lDraftExterior = hBellAboveDiscFace / tan(90 - aDraftBell)
|
|
||||||
lDraftInterior = (hBellAboveDiscFace - tBell) / tan(90 - aDraftBell)
|
|
||||||
|
|
||||||
// Inner and outer radius of outboard face of disc bell.
|
|
||||||
rOuter = rCenter - lDraftExterior - rBore
|
|
||||||
rInner = rOuter + lDraftExterior - (tBell + lDraftInterior)
|
|
||||||
|
|
||||||
sketchDiscBell = startSketchOn(-YZ)
|
|
||||||
bodyDiscBell = startProfile(
|
|
||||||
sketchDiscBell,
|
|
||||||
at = [
|
|
||||||
-dDisc / 2 + hFrictionSurface,
|
|
||||||
tDiscHalf * 2 + tVent
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> arc(
|
|
||||||
%,
|
|
||||||
angleStart = -180,
|
|
||||||
angleEnd = 0,
|
|
||||||
radius = wUndercut / 2,
|
|
||||||
)
|
|
||||||
|> line(end = [lDraftExterior, hBellAboveDiscFace])
|
|
||||||
|> xLine(length = rOuter, tag = $seg04)
|
|
||||||
|> yLine(length = -tBell)
|
|
||||||
|> xLine(length = -rInner)
|
|
||||||
|> line(end = [-lDraftInterior, -hBellAboveDiscFace])
|
|
||||||
|> line(end = [0, -2]) // Wall thickness.
|
|
||||||
|> xLine(length = -1 * (tBell + wUndercut))
|
|
||||||
|> close(%)
|
|
||||||
|> revolve(axis = Y)
|
|
||||||
|
|
||||||
// Drill lug holes.
|
|
||||||
sketchLugs = startSketchOn(bodyDiscBell, face = seg04)
|
|
||||||
profileStud = circle(sketchLugs, center = [0, dPitchCircle / 2], radius = dStudDrilling / 2)
|
|
||||||
|> patternCircular2d(
|
|
||||||
%,
|
|
||||||
instances = nStuds,
|
|
||||||
center = [0, 0],
|
|
||||||
arcDegrees = 360,
|
|
||||||
rotateDuplicates = true,
|
|
||||||
)
|
|
||||||
|
|
||||||
clearance = 2 // Some margin on negative extrude.
|
|
||||||
lugs = extrude(profileStud, length = -1 * (tBell + clearance))
|
|
@ -1,155 +0,0 @@
|
|||||||
// Curtain Wall Anchor Plate
|
|
||||||
// A structural steel L-plate used to anchor curtain wall systems to concrete slabs, with elongated holes for adjustability and bolts with nuts and base plates for secure fastening
|
|
||||||
|
|
||||||
// Set units in millimeters (mm)
|
|
||||||
@settings(defaultLengthUnit = mm, kclVersion = 1.0)
|
|
||||||
|
|
||||||
// Define parameters
|
|
||||||
slabPlateBaseLength = 300
|
|
||||||
slabPlateHookLength = 80
|
|
||||||
slabPlateWidth = 200
|
|
||||||
slabPlateThickness = 8
|
|
||||||
offsetSlabRail = 200
|
|
||||||
|
|
||||||
// Generate L-shaped anchor profile with base and hook flange
|
|
||||||
// Includes fillets at internal and external corners for strength and safety
|
|
||||||
fn lProfileFn(lengthBase, lengthHook, width, thickness) {
|
|
||||||
profilePlane = startSketchOn(offsetPlane(XZ, offset = -width / 2))
|
|
||||||
profileShape = startProfile(profilePlane, at = [0, 0])
|
|
||||||
|> yLine(length = lengthHook, tag = $hookOutside)
|
|
||||||
|> xLine(length = thickness)
|
|
||||||
|> yLine(length = thickness - lengthHook, tag = $hookInside)
|
|
||||||
|> xLine(length = lengthBase - thickness, tag = $baseInside)
|
|
||||||
|> yLine(length = -thickness)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $baseOutside)
|
|
||||||
|> close()
|
|
||||||
profileBody = extrude(profileShape, length = width)
|
|
||||||
|> fillet(
|
|
||||||
radius = thickness,
|
|
||||||
tags = [
|
|
||||||
getCommonEdge(faces = [baseInside, hookInside])
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> fillet(
|
|
||||||
radius = thickness * 2,
|
|
||||||
tags = [
|
|
||||||
getCommonEdge(faces = [baseOutside, hookOutside])
|
|
||||||
],
|
|
||||||
)
|
|
||||||
return profileBody
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a hexagonal shape used for bolt and nut heads
|
|
||||||
fn hexagonFn(plane, radius) {
|
|
||||||
shape = startProfile(plane, at = [-radius, 0])
|
|
||||||
|> angledLine(angle = 60, length = radius)
|
|
||||||
|> xLine(length = radius)
|
|
||||||
|> angledLine(angle = -60, length = radius)
|
|
||||||
|> angledLine(angle = -120, length = radius)
|
|
||||||
|> xLine(length = -radius)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
return shape
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build a bolt with a hexagonal head and cylindrical shaft
|
|
||||||
fn boltFn(diameter, length) {
|
|
||||||
boltHeadPlane = startSketchOn(XY)
|
|
||||||
boltHeadShape = hexagonFn(plane = boltHeadPlane, radius = diameter)
|
|
||||||
boltHeadBody = extrude(boltHeadShape, length = diameter * 0.7)
|
|
||||||
boltPlane = startSketchOn(boltHeadBody, face = START)
|
|
||||||
boltShape = circle(boltPlane, center = [0, 0], radius = diameter / 2)
|
|
||||||
boltBody = extrude(boltShape, length = length)
|
|
||||||
return boltBody
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct a bolt assembly with base plate and hex nut
|
|
||||||
// Assembles all parts for realistic anchor simulation
|
|
||||||
fn boltWithPlateAndNutFn(diameter, length, gap) {
|
|
||||||
plateSide = diameter * 3
|
|
||||||
plateplane = startSketchOn(offsetPlane(XY, offset = -gap))
|
|
||||||
plateShape = startProfile(plateplane, at = [-plateSide / 2, -plateSide / 2])
|
|
||||||
|> yLine(length = plateSide)
|
|
||||||
|> xLine(length = plateSide)
|
|
||||||
|> yLine(length = -plateSide)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
plateBody = extrude(plateShape, length = -diameter * 0.3)
|
|
||||||
nutPlane = startSketchOn(plateBody, face = START)
|
|
||||||
boltHeadShape = hexagonFn(plane = nutPlane, radius = 12)
|
|
||||||
boltHeadBody = extrude(boltHeadShape, length = diameter * 0.7)
|
|
||||||
boltBody = boltFn(diameter = diameter, length = gap + diameter + 3)
|
|
||||||
mergedBody = union([boltHeadBody, boltBody])
|
|
||||||
return mergedBody
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate the plate geometry with a vertical hook for slab attachment
|
|
||||||
slabPlate = lProfileFn(
|
|
||||||
lengthBase = slabPlateBaseLength,
|
|
||||||
lengthHook = slabPlateHookLength,
|
|
||||||
width = slabPlateWidth,
|
|
||||||
thickness = slabPlateThickness,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Define oblong holes for bolts, allowing positional adjustment
|
|
||||||
wideHoleWidth = 12
|
|
||||||
wideHoleLength = 60
|
|
||||||
wideHoleOffset = 30
|
|
||||||
|
|
||||||
// Two slots mirrored across the plate width
|
|
||||||
wideHolePlane = startSketchOn(XY)
|
|
||||||
wideHoleShape = startProfile(
|
|
||||||
wideHolePlane,
|
|
||||||
at = [
|
|
||||||
-(wideHoleLength - wideHoleWidth) / 2,
|
|
||||||
wideHoleWidth / 2
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> xLine(length = wideHoleLength - wideHoleWidth)
|
|
||||||
|> tangentialArc(endAbsolute = [
|
|
||||||
(wideHoleLength - wideHoleWidth) / 2,
|
|
||||||
-wideHoleWidth / 2
|
|
||||||
])
|
|
||||||
|> xLine(length = wideHoleWidth - wideHoleLength)
|
|
||||||
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = offsetSlabRail,
|
|
||||||
y = wideHoleOffset - (slabPlateWidth / 2),
|
|
||||||
z = -1,
|
|
||||||
)
|
|
||||||
wideHoleVoidLeft = extrude(wideHoleShape, length = slabPlateThickness + 2)
|
|
||||||
wideHoleVoidRight = clone(wideHoleVoidLeft)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = 0,
|
|
||||||
y = slabPlateWidth - (wideHoleOffset * 2),
|
|
||||||
z = 0,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Cut the holes into the anchor plate body
|
|
||||||
slabPlatePunchOne = subtract([slabPlate], tools = [wideHoleVoidLeft])
|
|
||||||
slabPlatePunchTwo = subtract([slabPlatePunchOne], tools = [wideHoleVoidRight])
|
|
||||||
|
|
||||||
// Add two bolt assemblies into the oblong slots
|
|
||||||
// Properly rotated and spaced to match anchor hole layout
|
|
||||||
slabPlateBolts = boltWithPlateAndNutFn(diameter = 10, length = 20, gap = slabPlateThickness + 5)
|
|
||||||
|> rotate(
|
|
||||||
%,
|
|
||||||
roll = 180,
|
|
||||||
pitch = 0,
|
|
||||||
yaw = 0,
|
|
||||||
)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = offsetSlabRail,
|
|
||||||
y = wideHoleOffset - (slabPlateWidth / 2),
|
|
||||||
z = 5,
|
|
||||||
)
|
|
||||||
|> patternLinear3d(
|
|
||||||
%,
|
|
||||||
instances = 2,
|
|
||||||
distance = slabPlateWidth - (wideHoleOffset * 2),
|
|
||||||
axis = [0, -1, 0],
|
|
||||||
)
|
|
@ -1,79 +0,0 @@
|
|||||||
// Engine Valve
|
|
||||||
// A mechanical valve used in internal combustion engines to control intake or exhaust flow
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@settings(defaultLengthUnit = mm, kclVersion = 1.0)
|
|
||||||
|
|
||||||
// Define parameters
|
|
||||||
valveDiameter = 30
|
|
||||||
valveLength = 120
|
|
||||||
valveHeadLength = valveDiameter * 1.0
|
|
||||||
valveHeadThickness = 3
|
|
||||||
stemDiameter = 6
|
|
||||||
stemHeadLength = 9
|
|
||||||
stemLength = valveLength - valveHeadLength - stemHeadLength
|
|
||||||
|
|
||||||
// Create the valve head
|
|
||||||
valveRadius = valveDiameter / 2
|
|
||||||
valveHeadPlane = startSketchOn(XZ)
|
|
||||||
valveHeadShape = startProfile(valveHeadPlane, at = [-0.01, valveHeadLength])
|
|
||||||
|> xLine(length = 0.01 - (stemDiameter / 2))
|
|
||||||
|> line(endAbsolute = [0.01 - (stemDiameter / 2), valveRadius])
|
|
||||||
|> tangentialArc(endAbsolute = [-0.8 * valveRadius, valveHeadThickness], tag = $seg01)
|
|
||||||
|> tangentialArc(endAbsolute = [-valveRadius, 0])
|
|
||||||
|> xLine(length = 0.3 * valveRadius)
|
|
||||||
|> arc(
|
|
||||||
interiorAbsolute = [
|
|
||||||
-0.34 * valveRadius,
|
|
||||||
0.08 * valveRadius
|
|
||||||
],
|
|
||||||
endAbsolute = [
|
|
||||||
-0.02 * valveRadius,
|
|
||||||
0.11 * valveRadius
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
valveHead = revolve(valveHeadShape, angle = 360, axis = Y)
|
|
||||||
|
|
||||||
// Create the valve stem
|
|
||||||
valveStemSketch = startSketchOn(offsetPlane(XY, offset = valveHeadLength))
|
|
||||||
|> circle(center = [0, 0], radius = stemDiameter / 2)
|
|
||||||
|> extrude(length = stemLength - valveHeadLength - stemHeadLength)
|
|
||||||
|
|
||||||
// Create the valve stem end
|
|
||||||
stepLength = stemHeadLength / 10
|
|
||||||
step1 = startSketchOn(valveStemSketch, face = END)
|
|
||||||
|> circle(%, center = [0, 0], radius = stemDiameter / 2 * 0.9)
|
|
||||||
|> extrude(%, length = stepLength * 2)
|
|
||||||
step2 = startSketchOn(step1, face = END)
|
|
||||||
|> circle(%, center = [0, 0], radius = stemDiameter / 2 * 0.8)
|
|
||||||
|> extrude(%, length = stepLength)
|
|
||||||
step3 = startSketchOn(step2, face = END)
|
|
||||||
|> circle(%, center = [0, 0], radius = stemDiameter / 2 * 0.9)
|
|
||||||
|> extrude(%, length = stepLength)
|
|
||||||
step4 = startSketchOn(step3, face = END)
|
|
||||||
|> circle(%, center = [0, 0], radius = stemDiameter / 2 * 0.8)
|
|
||||||
|> extrude(%, length = stepLength)
|
|
||||||
step5 = startSketchOn(step4, face = END)
|
|
||||||
|> circle(%, center = [0, 0], radius = stemDiameter / 2 * 0.9)
|
|
||||||
|> extrude(%, length = stepLength)
|
|
||||||
step6 = startSketchOn(step5, face = END)
|
|
||||||
|> circle(%, center = [0, 0], radius = stemDiameter / 2 * 0.8)
|
|
||||||
|> extrude(%, length = stepLength)
|
|
||||||
step7 = startSketchOn(step6, face = END)
|
|
||||||
|> circle(
|
|
||||||
%,
|
|
||||||
center = [0, 0],
|
|
||||||
radius = stemDiameter / 2 * 0.9,
|
|
||||||
tag = $seg02,
|
|
||||||
)
|
|
||||||
|> extrude(%, length = stepLength * 3, tagEnd = $capEnd001)
|
|
||||||
|> chamfer(
|
|
||||||
length = 0.5,
|
|
||||||
tags = [
|
|
||||||
getCommonEdge(faces = [seg02, capEnd001])
|
|
||||||
],
|
|
||||||
)
|
|
@ -74,16 +74,6 @@
|
|||||||
"main.kcl"
|
"main.kcl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"file": "main.kcl",
|
|
||||||
"pathFromProjectDirectoryToFirstFile": "brake-rotor/main.kcl",
|
|
||||||
"multipleFiles": false,
|
|
||||||
"title": "A 320mm vented brake disc (rotor), with straight vanes, 30mm thick. The disc bell should accommodate 5 M12 wheel studs on a 114.3mm pitch circle diameter.",
|
|
||||||
"description": "",
|
|
||||||
"files": [
|
|
||||||
"main.kcl"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "car-wheel-assembly/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "car-wheel-assembly/main.kcl",
|
||||||
@ -157,16 +147,6 @@
|
|||||||
"removable-sticker.kcl"
|
"removable-sticker.kcl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"file": "main.kcl",
|
|
||||||
"pathFromProjectDirectoryToFirstFile": "curtain-wall-anchor-plate/main.kcl",
|
|
||||||
"multipleFiles": false,
|
|
||||||
"title": "Curtain Wall Anchor Plate",
|
|
||||||
"description": "A structural steel L-plate used to anchor curtain wall systems to concrete slabs, with elongated holes for adjustability and bolts with nuts and base plates for secure fastening",
|
|
||||||
"files": [
|
|
||||||
"main.kcl"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "cycloidal-gear/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "cycloidal-gear/main.kcl",
|
||||||
@ -197,16 +177,6 @@
|
|||||||
"main.kcl"
|
"main.kcl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"file": "main.kcl",
|
|
||||||
"pathFromProjectDirectoryToFirstFile": "engine-valve/main.kcl",
|
|
||||||
"multipleFiles": false,
|
|
||||||
"title": "Engine Valve",
|
|
||||||
"description": "A mechanical valve used in internal combustion engines to control intake or exhaust flow",
|
|
||||||
"files": [
|
|
||||||
"main.kcl"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "exhaust-manifold/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "exhaust-manifold/main.kcl",
|
||||||
@ -452,16 +422,6 @@
|
|||||||
"robot-rotating-base.kcl"
|
"robot-rotating-base.kcl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"file": "main.kcl",
|
|
||||||
"pathFromProjectDirectoryToFirstFile": "pdu-faceplate/main.kcl",
|
|
||||||
"multipleFiles": false,
|
|
||||||
"title": "Power Distribution Unit (PDU) faceplate with European plug sockets and switch",
|
|
||||||
"description": "Designed for standard 19-inch rack systems with 1U height and 8 sockets",
|
|
||||||
"files": [
|
|
||||||
"main.kcl"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "pillow-block-bearing/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "pillow-block-bearing/main.kcl",
|
||||||
@ -552,16 +512,6 @@
|
|||||||
"main.kcl"
|
"main.kcl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"file": "main.kcl",
|
|
||||||
"pathFromProjectDirectoryToFirstFile": "sash-window/main.kcl",
|
|
||||||
"multipleFiles": false,
|
|
||||||
"title": "Sash Window",
|
|
||||||
"description": "A traditional wooden sash window with two vertically sliding panels and a central locking mechanism",
|
|
||||||
"files": [
|
|
||||||
"main.kcl"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "sheet-metal-bracket/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "sheet-metal-bracket/main.kcl",
|
||||||
@ -572,16 +522,6 @@
|
|||||||
"main.kcl"
|
"main.kcl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"file": "main.kcl",
|
|
||||||
"pathFromProjectDirectoryToFirstFile": "shepherds-hook-bolt/main.kcl",
|
|
||||||
"multipleFiles": false,
|
|
||||||
"title": "Shepherd’s Hook Bolt",
|
|
||||||
"description": "A bent bolt with a curved hook, typically used for hanging or anchoring loads. The threaded end allows secure attachment to surfaces or materials, while the curved hook resists pull-out under tension.",
|
|
||||||
"files": [
|
|
||||||
"main.kcl"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "socket-head-cap-screw/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "socket-head-cap-screw/main.kcl",
|
||||||
@ -592,16 +532,6 @@
|
|||||||
"main.kcl"
|
"main.kcl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"file": "main.kcl",
|
|
||||||
"pathFromProjectDirectoryToFirstFile": "spinning-highrise-tower/main.kcl",
|
|
||||||
"multipleFiles": false,
|
|
||||||
"title": "Spinning Highrise Tower",
|
|
||||||
"description": "A conceptual high-rise tower with a central core and rotating floor slabs, demonstrating dynamic form through vertical repetition and transformation",
|
|
||||||
"files": [
|
|
||||||
"main.kcl"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "spur-gear/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "spur-gear/main.kcl",
|
||||||
@ -632,16 +562,6 @@
|
|||||||
"main.kcl"
|
"main.kcl"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"file": "main.kcl",
|
|
||||||
"pathFromProjectDirectoryToFirstFile": "thermal-block-insert/main.kcl",
|
|
||||||
"multipleFiles": false,
|
|
||||||
"title": "Thermal Block Insert",
|
|
||||||
"description": "Interlocking insulation insert for masonry walls, designed with a tongue-and-groove profile for modular alignment and thermal efficiency",
|
|
||||||
"files": [
|
|
||||||
"main.kcl"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"file": "main.kcl",
|
"file": "main.kcl",
|
||||||
"pathFromProjectDirectoryToFirstFile": "tooling-nest-block/main.kcl",
|
"pathFromProjectDirectoryToFirstFile": "tooling-nest-block/main.kcl",
|
||||||
|
@ -1,240 +0,0 @@
|
|||||||
// Power Distribution Unit (PDU) faceplate with European plug sockets and switch
|
|
||||||
// Designed for standard 19-inch rack systems with 1U height and 8 sockets
|
|
||||||
|
|
||||||
// Set units in millimeters (mm)
|
|
||||||
@settings(defaultLengthUnit = mm, kclVersion = 1.0)
|
|
||||||
|
|
||||||
// Define the dimensions
|
|
||||||
// Width fits standard 19” rack, height is 1U, depth is variable
|
|
||||||
faceplateWidth = 482.6 // this is standardized to fit 19-inch racks)
|
|
||||||
faceplateHeight = 44.45 // usually 1U (44.45 mm), but can be 2U (88.9 mm) or more
|
|
||||||
faceplateDepth = 100 // varies by manufacturer, but commonly between 100 mm and 300 mm
|
|
||||||
|
|
||||||
|
|
||||||
// Define dimensions of side supports (width and thickness)
|
|
||||||
supportWidth = 50
|
|
||||||
supportThickness = 3
|
|
||||||
|
|
||||||
// Main body of the PDU faceplate with integrated rack mounting flanges
|
|
||||||
faceplateShape = startSketchOn(offsetPlane(XY, offset = -faceplateHeight / 2))
|
|
||||||
|> startProfile(%, at = [-faceplateWidth / 2 - supportWidth, 0])
|
|
||||||
|> yLine(length = supportThickness)
|
|
||||||
|> xLine(length = supportWidth)
|
|
||||||
|> yLine(length = faceplateDepth - supportThickness)
|
|
||||||
|> xLine(length = faceplateWidth)
|
|
||||||
|> yLine(length = supportThickness - faceplateDepth)
|
|
||||||
|> xLine(length = supportWidth)
|
|
||||||
|> yLine(length = -supportThickness)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg01)
|
|
||||||
|> close()
|
|
||||||
faceplateBody = extrude(faceplateShape, length = faceplateHeight)
|
|
||||||
faceplateFrontFace = startSketchOn(faceplateBody, face = seg01)
|
|
||||||
|
|
||||||
// Creates recessed volume within the faceplate for inserting modules
|
|
||||||
nestWall = 2
|
|
||||||
nestWidth = faceplateWidth - (nestWall * 2)
|
|
||||||
nestHeight = faceplateHeight - (nestWall * 2)
|
|
||||||
nestDepth = faceplateDepth - nestWall
|
|
||||||
nestShape = startProfile(faceplateFrontFace, at = [-nestWidth / 2, nestHeight / 2])
|
|
||||||
|> xLine(length = nestWidth)
|
|
||||||
|> yLine(length = -nestHeight)
|
|
||||||
|> xLine(length = -nestWidth)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
nestVoid = extrude(nestShape, length = -nestDepth)
|
|
||||||
|
|
||||||
// Spacer block on the left side, used to position components correctly
|
|
||||||
moduleHeight = nestHeight
|
|
||||||
moduleWidth = nestHeight
|
|
||||||
moduleDepth = nestHeight
|
|
||||||
|
|
||||||
leftSpacerWidth = moduleWidth * 1.5
|
|
||||||
leftSpacerPosition = leftSpacerWidth / 2 - (nestWidth / 2)
|
|
||||||
|
|
||||||
fn boxModuleFn(width) {
|
|
||||||
shape = startSketchOn(XZ)
|
|
||||||
|> startProfile(%, at = [-width / 2, moduleHeight / 2])
|
|
||||||
|> xLine(length = width)
|
|
||||||
|> yLine(length = -moduleHeight)
|
|
||||||
|> xLine(length = -width)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
body = extrude(shape, length = -moduleDepth)
|
|
||||||
return body
|
|
||||||
}
|
|
||||||
leftSpacerShape = boxModuleFn(width = leftSpacerWidth)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = leftSpacerPosition,
|
|
||||||
y = 0,
|
|
||||||
z = 0,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Module for power switch including front plate and red rocker button
|
|
||||||
switchPosition = leftSpacerPosition + leftSpacerWidth / 2 + moduleWidth / 2
|
|
||||||
switchWidth = moduleWidth
|
|
||||||
|
|
||||||
// Switch Body
|
|
||||||
switchBody = boxModuleFn(width = moduleWidth)
|
|
||||||
|
|
||||||
// Switch Plate
|
|
||||||
switchPlateWidth = 20
|
|
||||||
switchPlateHeight = 30
|
|
||||||
switchPlateThickness = 3
|
|
||||||
switchPlateShape = startSketchOn(switchBody, face = END)
|
|
||||||
|> startProfile(
|
|
||||||
%,
|
|
||||||
at = [
|
|
||||||
-switchPlateWidth / 2,
|
|
||||||
-switchPlateHeight / 2
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> yLine(length = switchPlateHeight)
|
|
||||||
|> xLine(length = switchPlateWidth)
|
|
||||||
|> yLine(length = -switchPlateHeight)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
switchPlateBody = extrude(switchPlateShape, length = switchPlateThickness)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = switchPosition,
|
|
||||||
y = 0,
|
|
||||||
z = 0,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Switch Button
|
|
||||||
switchButtonHeight = 26
|
|
||||||
switchButtonWidth = 15
|
|
||||||
switchButtonShape = startSketchOn(offsetPlane(-YZ, offset = -switchButtonWidth / 2))
|
|
||||||
|> startProfile(
|
|
||||||
%,
|
|
||||||
at = [
|
|
||||||
switchPlateThickness,
|
|
||||||
switchButtonHeight / 2
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> line(end = [3, -1])
|
|
||||||
|> arc(interiorAbsolute = [6, 0], endAbsolute = [12, -9])
|
|
||||||
|> line(endAbsolute = [
|
|
||||||
switchPlateThickness,
|
|
||||||
-switchButtonHeight / 2
|
|
||||||
])
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
switchButtonBody = extrude(switchButtonShape, length = switchButtonWidth)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = switchPosition,
|
|
||||||
y = 0,
|
|
||||||
z = 0,
|
|
||||||
)
|
|
||||||
|> appearance(%, color = "#ff0000")
|
|
||||||
|
|
||||||
// Spacer between switch and plug modules for layout alignment
|
|
||||||
secondSpacerWidth = moduleWidth / 2
|
|
||||||
secondSpacerPosition = switchPosition + switchWidth / 2 + secondSpacerWidth / 2
|
|
||||||
secondSpacerBody = boxModuleFn(width = secondSpacerWidth)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = secondSpacerPosition,
|
|
||||||
y = 0,
|
|
||||||
z = 0,
|
|
||||||
)
|
|
||||||
|
|
||||||
// European power plug modules with circular sockets and two-pin holes
|
|
||||||
// 8 identical sockets, each with grounding notch and dual-pin recesses
|
|
||||||
powerPlugWidth = moduleWidth
|
|
||||||
powerPlugCount = 8
|
|
||||||
powerPlugOveralWidth = powerPlugWidth * powerPlugCount
|
|
||||||
firstPowerPlugPosition = secondSpacerPosition + secondSpacerWidth / 2 + powerPlugWidth / 2
|
|
||||||
lastPowerPlugPosition = firstPowerPlugPosition + powerPlugWidth * (powerPlugCount - 1)
|
|
||||||
powerPlugBody = boxModuleFn(width = powerPlugWidth)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = firstPowerPlugPosition,
|
|
||||||
y = 0,
|
|
||||||
z = 0,
|
|
||||||
)
|
|
||||||
plugShape = startSketchOn(powerPlugBody, face = END)
|
|
||||||
|> circle(%, center = [0, 0], radius = 17)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = firstPowerPlugPosition,
|
|
||||||
y = 0,
|
|
||||||
z = 0,
|
|
||||||
)
|
|
||||||
plugBody = extrude(plugShape, length = -20)
|
|
||||||
plugHoleDistance = 20
|
|
||||||
plugHoleShape = startSketchOn(plugBody, face = START)
|
|
||||||
|> circle(%, center = [-plugHoleDistance / 2, 0], radius = 3)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = firstPowerPlugPosition,
|
|
||||||
y = 0,
|
|
||||||
z = 0,
|
|
||||||
)
|
|
||||||
|> patternLinear2d(
|
|
||||||
%,
|
|
||||||
instances = 2,
|
|
||||||
distance = plugHoleDistance,
|
|
||||||
axis = [1, 0],
|
|
||||||
)
|
|
||||||
plugHoleBody = extrude(plugHoleShape, length = -5)
|
|
||||||
|> patternLinear3d(
|
|
||||||
%,
|
|
||||||
instances = powerPlugCount,
|
|
||||||
distance = powerPlugWidth,
|
|
||||||
axis = [1, 0, 0],
|
|
||||||
)
|
|
||||||
|
|
||||||
// Rightmost spacer to fill in remaining horizontal space
|
|
||||||
rightSpacerWidth = nestWidth / 2 - lastPowerPlugPosition - (powerPlugWidth / 2)
|
|
||||||
rightSpacerPosition = lastPowerPlugPosition + powerPlugWidth / 2 + rightSpacerWidth / 2
|
|
||||||
rightSpacerBody = boxModuleFn(width = rightSpacerWidth)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = rightSpacerPosition,
|
|
||||||
y = 0,
|
|
||||||
z = 0,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Rack mounting holes on flanges, elongated for alignment flexibility
|
|
||||||
holeWidth = 25
|
|
||||||
holeDiameter = 5
|
|
||||||
holeStraightSegment = holeWidth - holeDiameter
|
|
||||||
holeVerticalDistance = faceplateHeight * 0.3
|
|
||||||
|
|
||||||
holeShapes = startProfile(
|
|
||||||
faceplateFrontFace,
|
|
||||||
at = [
|
|
||||||
-holeStraightSegment / 2,
|
|
||||||
holeDiameter / 2
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> xLine(length = holeStraightSegment)
|
|
||||||
|> tangentialArc(endAbsolute = [
|
|
||||||
holeStraightSegment / 2,
|
|
||||||
-holeDiameter / 2
|
|
||||||
])
|
|
||||||
|> xLine(length = -holeStraightSegment)
|
|
||||||
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = -faceplateWidth / 2 - (supportWidth / 2),
|
|
||||||
y = 0,
|
|
||||||
z = -holeVerticalDistance,
|
|
||||||
)
|
|
||||||
|> patternLinear2d(
|
|
||||||
%,
|
|
||||||
instances = 3,
|
|
||||||
distance = holeVerticalDistance,
|
|
||||||
axis = [0, 1],
|
|
||||||
)
|
|
||||||
|> patternLinear2d(
|
|
||||||
%,
|
|
||||||
instances = 2,
|
|
||||||
distance = faceplateWidth + supportWidth,
|
|
||||||
axis = [1, 0],
|
|
||||||
)
|
|
||||||
holeVoid = extrude(holeShapes, length = -supportThickness)
|
|
@ -1,214 +0,0 @@
|
|||||||
// Sash Window
|
|
||||||
// A traditional wooden sash window with two vertically sliding panels and a central locking mechanism
|
|
||||||
|
|
||||||
// Set units in millimeters (mm)
|
|
||||||
@settings(defaultLengthUnit = mm, kclVersion = 1.0)
|
|
||||||
|
|
||||||
// Window state: 0 for closed, 1 for open
|
|
||||||
windowState = 0
|
|
||||||
|
|
||||||
// Basic window dimensions
|
|
||||||
windowWidth = 500
|
|
||||||
windowHeight = 1000
|
|
||||||
|
|
||||||
// Frame thickness and depth
|
|
||||||
frameWidth = 30
|
|
||||||
frameDepth = 50
|
|
||||||
|
|
||||||
// Number of divisions per sash (horizontal and vertical)
|
|
||||||
sashOpeningCountHorizontal = 2
|
|
||||||
sashOpeningCountVertical = 1
|
|
||||||
|
|
||||||
// Derived dimensions
|
|
||||||
sashWidth = windowWidth - (frameWidth * 2)
|
|
||||||
sashHeight = (windowHeight - (frameWidth * 2)) / 2 + frameWidth / 2
|
|
||||||
sashDepth = frameDepth / 2 - 2
|
|
||||||
sashTravelDistance = sashHeight * windowState * 0.8
|
|
||||||
|
|
||||||
// Function to create panel with frame and openings
|
|
||||||
fn panelFn(plane, offset, width, height, depth, perimeter, divisionThickness, openingCountHorizontal, openingCountVertical) {
|
|
||||||
// Create panel base shape
|
|
||||||
panelPlane = startSketchOn(offsetPlane(XZ, offset = offset))
|
|
||||||
panelShape = startProfile(panelPlane, at = [-width / 2, -height / 2])
|
|
||||||
|> yLine(length = height)
|
|
||||||
|> xLine(length = width)
|
|
||||||
|> yLine(length = -height)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
panelBody = extrude(panelShape, length = depth)
|
|
||||||
|
|
||||||
// Create opening grid within the panel
|
|
||||||
voidAreaWidth = width - (perimeter * 2)
|
|
||||||
voidAreaHeight = height - (perimeter * 2)
|
|
||||||
|
|
||||||
divisionTotalThicknessHorizontal = divisionThickness * openingCountHorizontal - divisionThickness
|
|
||||||
divisionTotalThicknessVertical = divisionThickness * openingCountVertical - divisionThickness
|
|
||||||
voidWidth = (voidAreaWidth - divisionTotalThicknessHorizontal) / openingCountHorizontal
|
|
||||||
voidHeight = (voidAreaHeight - divisionTotalThicknessVertical) / openingCountVertical
|
|
||||||
|
|
||||||
voidStepHorizontal = voidWidth + divisionThickness
|
|
||||||
voidStepVertical = voidHeight + divisionThickness
|
|
||||||
voidPlane = startSketchOn(panelBody, face = END)
|
|
||||||
voidShape = startProfile(
|
|
||||||
voidPlane,
|
|
||||||
at = [
|
|
||||||
-voidAreaWidth / 2,
|
|
||||||
-voidAreaHeight / 2
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> yLine(length = voidHeight)
|
|
||||||
|> xLine(length = voidWidth)
|
|
||||||
|> yLine(length = -voidHeight)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
|> patternLinear2d(
|
|
||||||
%,
|
|
||||||
instances = openingCountHorizontal,
|
|
||||||
distance = voidStepHorizontal,
|
|
||||||
axis = [1, 0],
|
|
||||||
)
|
|
||||||
|> patternLinear2d(
|
|
||||||
%,
|
|
||||||
instances = openingCountVertical,
|
|
||||||
distance = voidStepVertical,
|
|
||||||
axis = [0, 1],
|
|
||||||
)
|
|
||||||
voidBody = extrude(voidShape, length = -depth)
|
|
||||||
|> appearance(color = "#a55e2c")
|
|
||||||
return panelBody
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create main window frame
|
|
||||||
frame = panelFn(
|
|
||||||
plane = XZ,
|
|
||||||
offset = -frameDepth / 2,
|
|
||||||
width = windowWidth,
|
|
||||||
height = windowHeight,
|
|
||||||
depth = frameDepth,
|
|
||||||
perimeter = frameWidth,
|
|
||||||
divisionThickness = 10,
|
|
||||||
openingCountHorizontal = 1,
|
|
||||||
openingCountVertical = 1,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create bottom sliding sash
|
|
||||||
bottomSash = panelFn(
|
|
||||||
plane = XZ,
|
|
||||||
offset = (frameDepth / 2 - sashDepth) / 2,
|
|
||||||
width = sashWidth,
|
|
||||||
height = sashHeight,
|
|
||||||
depth = sashDepth,
|
|
||||||
perimeter = frameWidth,
|
|
||||||
divisionThickness = 10,
|
|
||||||
openingCountHorizontal = sashOpeningCountHorizontal,
|
|
||||||
openingCountVertical = sashOpeningCountVertical,
|
|
||||||
)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = 0,
|
|
||||||
y = 0,
|
|
||||||
z = frameWidth / 2 - (sashHeight / 2),
|
|
||||||
)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = 0,
|
|
||||||
y = 0,
|
|
||||||
z = sashTravelDistance,
|
|
||||||
) // open / close
|
|
||||||
|
|
||||||
// Latch mechanism on bottom sash
|
|
||||||
// Create latch plate
|
|
||||||
latchPlateWidth = 13
|
|
||||||
latchPlateLength = 30
|
|
||||||
latchPlateThickness = 1
|
|
||||||
|
|
||||||
latchPlatePlane = startSketchOn(offsetPlane(XY, offset = frameWidth / 2))
|
|
||||||
latchPlateShape = startProfile(
|
|
||||||
latchPlatePlane,
|
|
||||||
at = [
|
|
||||||
-latchPlateLength / 2,
|
|
||||||
-latchPlateWidth / 2
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> yLine(length = latchPlateWidth)
|
|
||||||
|> xLine(length = latchPlateLength)
|
|
||||||
|> yLine(length = -latchPlateWidth)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
latchPlateBody = extrude(latchPlateShape, length = latchPlateThickness)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = 0,
|
|
||||||
y = -frameDepth / 4,
|
|
||||||
z = 0,
|
|
||||||
)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = 0,
|
|
||||||
y = 0,
|
|
||||||
z = sashTravelDistance,
|
|
||||||
) // open / close
|
|
||||||
|
|
||||||
// Create latch cylinder
|
|
||||||
latchCylinderHeight = 5
|
|
||||||
latchCylinderPlane = startSketchOn(offsetPlane(latchPlatePlane, offset = latchPlateThickness))
|
|
||||||
latchCylinderShape = startProfile(latchCylinderPlane, at = [40, -1])
|
|
||||||
|> xLine(length = -35)
|
|
||||||
|> arc(interiorAbsolute = [-5, 0], endAbsolute = [5, 1])
|
|
||||||
|> xLine(length = 35)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
latchCylinderBody = extrude(latchCylinderShape, length = latchCylinderHeight)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = 0,
|
|
||||||
y = -frameDepth / 4,
|
|
||||||
z = 0,
|
|
||||||
)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = 0,
|
|
||||||
y = 0,
|
|
||||||
z = sashTravelDistance,
|
|
||||||
) // open / close
|
|
||||||
|> rotate(
|
|
||||||
%,
|
|
||||||
roll = 0,
|
|
||||||
pitch = 0,
|
|
||||||
yaw = -90 * windowState,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create top fixed sash
|
|
||||||
topSash = panelFn(
|
|
||||||
plane = XZ,
|
|
||||||
offset = -(frameDepth / 2 - sashDepth) / 2 - sashDepth,
|
|
||||||
width = sashWidth,
|
|
||||||
height = sashHeight,
|
|
||||||
depth = sashDepth,
|
|
||||||
perimeter = frameWidth,
|
|
||||||
divisionThickness = 10,
|
|
||||||
openingCountHorizontal = sashOpeningCountHorizontal,
|
|
||||||
openingCountVertical = sashOpeningCountVertical,
|
|
||||||
)
|
|
||||||
|> translate(
|
|
||||||
%,
|
|
||||||
x = 0,
|
|
||||||
y = 0,
|
|
||||||
z = sashHeight / 2 - (frameWidth / 2),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create latch nut on the top sash
|
|
||||||
latchNutPlane = startSketchOn(XZ)
|
|
||||||
latchNutShape = startProfile(
|
|
||||||
latchNutPlane,
|
|
||||||
at = [
|
|
||||||
-latchPlateLength / 2,
|
|
||||||
-latchPlateWidth / 2
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> yLine(length = latchPlateWidth)
|
|
||||||
|> xLine(length = latchPlateLength)
|
|
||||||
|> yLine(length = -latchPlateWidth)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
latchNutPlateBody = extrude(latchNutShape, length = latchPlateThickness)
|
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 216 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
Before Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 178 KiB |
Before Width: | Height: | Size: 78 KiB |
@ -1,89 +0,0 @@
|
|||||||
// Shepherd’s Hook Bolt
|
|
||||||
// A bent bolt with a curved hook, typically used for hanging or anchoring loads. The threaded end allows secure attachment to surfaces or materials, while the curved hook resists pull-out under tension.
|
|
||||||
|
|
||||||
// Set units in millimeters (mm)
|
|
||||||
@settings(defaultLengthUnit = mm, kclVersion = 1.0)
|
|
||||||
|
|
||||||
// Define bolt geometry parameters
|
|
||||||
boltDiameter = 5
|
|
||||||
hookRadius = 12
|
|
||||||
shankLength = 5
|
|
||||||
threadedEndLength = 30
|
|
||||||
nutDistance = 20
|
|
||||||
hookStartAngle = 290
|
|
||||||
hookEndAngle = 150
|
|
||||||
|
|
||||||
approximatePitch = boltDiameter * 0.15
|
|
||||||
threadDepth = 0.6134 * approximatePitch
|
|
||||||
innerRadius = boltDiameter / 2 - threadDepth
|
|
||||||
boltNumberOfRevolutions = threadedEndLength / approximatePitch
|
|
||||||
|
|
||||||
// Helper values for computing geometry transitions between straight shaft and hook arc
|
|
||||||
hypotenuse = hookRadius / cos(hookStartAngle - 270)
|
|
||||||
side = sqrt(pow(hypotenuse, exp = 2) - pow(hookRadius, exp = 2))
|
|
||||||
shankOffset = hypotenuse + side
|
|
||||||
|
|
||||||
// Converts polar coordinates to cartesian points for drawing arcs
|
|
||||||
fn polarToCartesian(radius, angle) {
|
|
||||||
x = radius * cos(angle)
|
|
||||||
y = radius * sin(angle)
|
|
||||||
return [x, y]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the hook and shank profile path
|
|
||||||
// Includes straight segment and two connected arcs forming the hook
|
|
||||||
hookProfilePlane = startSketchOn(XZ)
|
|
||||||
hookProfileShape = startProfile(hookProfilePlane, at = [0, -shankOffset - shankLength])
|
|
||||||
|> line(endAbsolute = [0, -shankOffset])
|
|
||||||
|> tangentialArc(endAbsolute = polarToCartesian(radius = hookRadius, angle = hookStartAngle))
|
|
||||||
|> tangentialArc(endAbsolute = polarToCartesian(radius = hookRadius, angle = hookEndAngle), tag = $hook)
|
|
||||||
|
|
||||||
// Create the circular cross-section used for sweeping along the hook path
|
|
||||||
hookSectionPlane = offsetPlane(XY, offset = -shankOffset - shankLength)
|
|
||||||
hookSectionShape = circle(hookSectionPlane, center = [0, 0], radius = boltDiameter / 2)
|
|
||||||
|
|
||||||
// Sweep the section along the hook profile to form the main body of the hook bolt
|
|
||||||
hookBody = sweep(hookSectionShape, path = hookProfileShape, sectional = true)
|
|
||||||
|
|
||||||
// Add a cylindrical tip at the hook end
|
|
||||||
tipPlane = startSketchOn(hookBody, face = END)
|
|
||||||
tipShape = circle(
|
|
||||||
tipPlane,
|
|
||||||
center = [hookRadius, 0],
|
|
||||||
radius = boltDiameter / 2,
|
|
||||||
tag = $seg01,
|
|
||||||
)
|
|
||||||
tipBody = extrude(
|
|
||||||
tipShape,
|
|
||||||
length = hookRadius * 0.5,
|
|
||||||
tagStart = $startTag,
|
|
||||||
tagEnd = $capEnd001,
|
|
||||||
)
|
|
||||||
|> fillet(
|
|
||||||
radius = boltDiameter / 4,
|
|
||||||
tags = [
|
|
||||||
getCommonEdge(faces = [seg01, capEnd001])
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
// Create the threaded end of the bolt
|
|
||||||
|
|
||||||
// Construct the triangular profile for thread cutting
|
|
||||||
boltThreadSectionPlane = startSketchOn(XZ)
|
|
||||||
boltThreadSectionShapeForRevolve = startProfile(
|
|
||||||
boltThreadSectionPlane,
|
|
||||||
at = [
|
|
||||||
innerRadius,
|
|
||||||
-shankOffset - shankLength - threadedEndLength
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> line(end = [threadDepth, approximatePitch / 2])
|
|
||||||
|> line(end = [-threadDepth, approximatePitch / 2])
|
|
||||||
|> patternLinear2d(axis = [0, 1], instances = boltNumberOfRevolutions, distance = approximatePitch)
|
|
||||||
|> xLine(length = -innerRadius * 0.9)
|
|
||||||
|> yLine(length = -threadedEndLength)
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
|
|
||||||
// Create a revolved solid representing the thread geometry by repeating and revolving the profile around the shaft
|
|
||||||
boltThreadRevolve = revolve(boltThreadSectionShapeForRevolve, angle = 360, axis = Y)
|
|
@ -1,93 +0,0 @@
|
|||||||
// Spinning Highrise Tower
|
|
||||||
// A conceptual high-rise tower with a central core and rotating floor slabs, demonstrating dynamic form through vertical repetition and transformation
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@settings(defaultLengthUnit = m, kclVersion = 1.0)
|
|
||||||
|
|
||||||
// Define global parameters for floor geometry and building layout
|
|
||||||
floorCount = 17
|
|
||||||
floorHeight = 5
|
|
||||||
slabWidth = 30
|
|
||||||
slabThickness = 0.5
|
|
||||||
rotationAngleStep = 5
|
|
||||||
handrailHeight = 1.2
|
|
||||||
handrailThickness = 0.3
|
|
||||||
balconyDepth = 3
|
|
||||||
|
|
||||||
// Calculate facade and core geometry from parameters
|
|
||||||
facadeWidth = slabWidth - (balconyDepth * 2)
|
|
||||||
facadeHeight = floorHeight - slabThickness
|
|
||||||
coreHeight = floorCount * floorHeight - slabThickness
|
|
||||||
frameSide = 0.1
|
|
||||||
windowTargetWidth = 6
|
|
||||||
windowTargetCount = facadeWidth / windowTargetWidth
|
|
||||||
windowCount = round(windowTargetCount)
|
|
||||||
windowWidth = facadeWidth / windowCount
|
|
||||||
|
|
||||||
// Helper function: Creates a box from a center plane with given width and height
|
|
||||||
fn boxFn(plane, width, height) {
|
|
||||||
shape = startSketchOn(plane)
|
|
||||||
|> startProfile(%, at = [-width / 2, -width / 2])
|
|
||||||
|> line(%, end = [0, width])
|
|
||||||
|> line(%, end = [width, 0])
|
|
||||||
|> line(%, end = [0, -width])
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close(%)
|
|
||||||
body = extrude(shape, length = height)
|
|
||||||
return body
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function: Defines transformation (translation and rotation) for each floor
|
|
||||||
fn transformFn(@i) {
|
|
||||||
return {
|
|
||||||
translate = [0, 0, i * floorHeight],
|
|
||||||
rotation = { angle = rotationAngleStep * i }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create building base
|
|
||||||
baseThickness = 0.2
|
|
||||||
baseSlab = boxFn(plane = XY, width = slabWidth, height = -baseThickness)
|
|
||||||
|> appearance(%, color = "#dbd7d2")
|
|
||||||
|
|
||||||
// Create ground platform beneath the base
|
|
||||||
groundSize = 50
|
|
||||||
groundBody = boxFn(plane = offsetPlane(XY, offset = -baseThickness), width = groundSize, height = -5)
|
|
||||||
|> appearance(%, color = "#3a3631")
|
|
||||||
|
|
||||||
// Create a single slab with handrail height to be reused with pattern
|
|
||||||
slabAndHandrailGeometry = boxFn(plane = offsetPlane(XY, offset = floorHeight - slabThickness), width = slabWidth, height = slabThickness + handrailHeight)
|
|
||||||
slabVoidStart = -slabWidth / 2 + handrailThickness
|
|
||||||
slabVoidWidth = slabWidth - (handrailThickness * 2)
|
|
||||||
slabVoidShape = startSketchOn(slabAndHandrailGeometry, face = END)
|
|
||||||
|> startProfile(%, at = [slabVoidStart, slabVoidStart])
|
|
||||||
|> line(%, end = [0, slabVoidWidth])
|
|
||||||
|> line(%, end = [slabVoidWidth, 0])
|
|
||||||
|> line(%, end = [0, -slabVoidWidth])
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close(%)
|
|
||||||
|
|
||||||
// Generate and pattern slabs with voids across all floors
|
|
||||||
slabBody = extrude(slabVoidShape, length = -handrailHeight)
|
|
||||||
|> patternTransform(instances = floorCount, transform = transformFn)
|
|
||||||
|> appearance(%, color = "#dbd7d2")
|
|
||||||
|
|
||||||
// Create structural core of the tower
|
|
||||||
coreLength = 10
|
|
||||||
coreWidth = 8
|
|
||||||
core = startSketchOn(XY)
|
|
||||||
|> startProfile(%, at = [-coreLength / 2, -coreWidth / 2])
|
|
||||||
|> line(%, end = [0, coreWidth])
|
|
||||||
|> line(%, end = [coreLength, 0])
|
|
||||||
|> line(%, end = [-0.22, -coreWidth])
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
||||||
|> close(%)
|
|
||||||
|> extrude(%, length = coreHeight)
|
|
||||||
|
|
||||||
// Create facade panels for each floor
|
|
||||||
facadeStart = facadeWidth / 2
|
|
||||||
facadeGeometry = boxFn(plane = XY, width = facadeWidth, height = facadeHeight)
|
|
||||||
|> patternTransform(instances = floorCount, transform = transformFn)
|
|
||||||
|> appearance(%, color = "#151819")
|
|
@ -1,61 +0,0 @@
|
|||||||
// Thermal Block Insert
|
|
||||||
// Interlocking insulation insert for masonry walls, designed with a tongue-and-groove profile for modular alignment and thermal efficiency
|
|
||||||
|
|
||||||
// Set units in millimeters (mm)
|
|
||||||
@settings(defaultLengthUnit = mm, kclVersion = 1.0)
|
|
||||||
|
|
||||||
// Define overall dimensions of the insert block
|
|
||||||
insertLength = 400
|
|
||||||
insertHeight = 200
|
|
||||||
insertThickness = 50
|
|
||||||
|
|
||||||
// Define tongue-and-groove profile parameters for interlocking geometry
|
|
||||||
setbackFactor = 0.25 // spacing between tongues
|
|
||||||
tongueTargetCount = insertLength / 80
|
|
||||||
tongueCount = round(tongueTargetCount)
|
|
||||||
tongueLength = insertLength / (tongueCount * (1 + setbackFactor * 2) + 1)
|
|
||||||
tongueGap = tongueLength * setbackFactor * 2
|
|
||||||
tongueStep = tongueLength + tongueGap
|
|
||||||
tongueDepth = tongueLength * 0.5
|
|
||||||
tongueSetback = tongueLength * setbackFactor
|
|
||||||
|
|
||||||
// Function to create one side of the repeating tongue geometry along the block edge
|
|
||||||
fn tongueBlockFn() {
|
|
||||||
tongueSingleBlock = xLine(length = tongueLength)
|
|
||||||
|> line(end = [-tongueSetback, tongueDepth])
|
|
||||||
|> xLine(length = tongueLength)
|
|
||||||
|> line(end = [-tongueSetback, -tongueDepth])
|
|
||||||
|> patternLinear2d(
|
|
||||||
%,
|
|
||||||
instances = tongueCount,
|
|
||||||
distance = tongueStep,
|
|
||||||
axis = [1, 0],
|
|
||||||
)
|
|
||||||
|> xLine(length = tongueLength)
|
|
||||||
return tongueSingleBlock
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create top-side profile with tongues
|
|
||||||
tongueShape = startSketchOn(XY)
|
|
||||||
|> startProfile(%, at = [-insertLength / 2, insertThickness / 2])
|
|
||||||
|> tongueBlockFn()
|
|
||||||
|> yLine(length = -insertThickness / 2)
|
|
||||||
|> xLine(length = -insertLength)
|
|
||||||
|> close(%)
|
|
||||||
|
|
||||||
// Create bottom-side profile with grooves (inverse of tongue)
|
|
||||||
grooveShape = startSketchOn(XY)
|
|
||||||
|> startProfile(
|
|
||||||
%,
|
|
||||||
at = [
|
|
||||||
-insertLength / 2,
|
|
||||||
-insertThickness / 2 - tongueDepth
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|> tongueBlockFn()
|
|
||||||
|> yLine(length = insertThickness / 2 + tongueDepth)
|
|
||||||
|> xLine(length = -insertLength)
|
|
||||||
|> close(%)
|
|
||||||
|
|
||||||
// Extrude both tongue and groove profiles to form the final thermal insert block
|
|
||||||
insertShape = extrude([tongueShape, grooveShape], length = insertHeight)
|
|
123
rust/Cargo.lock
generated
@ -1815,7 +1815,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-bumper"
|
name = "kcl-bumper"
|
||||||
version = "0.1.75"
|
version = "0.1.73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@ -1826,7 +1826,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-derive-docs"
|
name = "kcl-derive-docs"
|
||||||
version = "0.1.75"
|
version = "0.1.73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -1845,9 +1845,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-directory-test-macro"
|
name = "kcl-directory-test-macro"
|
||||||
version = "0.1.75"
|
version = "0.1.73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"convert_case",
|
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
@ -1855,7 +1854,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-language-server"
|
name = "kcl-language-server"
|
||||||
version = "0.2.75"
|
version = "0.2.73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@ -1876,7 +1875,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-language-server-release"
|
name = "kcl-language-server-release"
|
||||||
version = "0.1.75"
|
version = "0.1.73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@ -1896,7 +1895,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.2.75"
|
version = "0.2.73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"approx 0.5.1",
|
"approx 0.5.1",
|
||||||
@ -1935,7 +1934,6 @@ dependencies = [
|
|||||||
"measurements",
|
"measurements",
|
||||||
"miette",
|
"miette",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"nalgebra-glm",
|
|
||||||
"parse-display 0.10.0",
|
"parse-display 0.10.0",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"pyo3",
|
"pyo3",
|
||||||
@ -1973,7 +1971,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-python-bindings"
|
name = "kcl-python-bindings"
|
||||||
version = "0.3.75"
|
version = "0.3.73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"kcl-lib",
|
"kcl-lib",
|
||||||
@ -1988,7 +1986,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-test-server"
|
name = "kcl-test-server"
|
||||||
version = "0.1.75"
|
version = "0.1.73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"hyper 0.14.32",
|
"hyper 0.14.32",
|
||||||
@ -2001,7 +1999,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-to-core"
|
name = "kcl-to-core"
|
||||||
version = "0.1.75"
|
version = "0.1.73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -2015,7 +2013,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-wasm-lib"
|
name = "kcl-wasm-lib"
|
||||||
version = "0.1.75"
|
version = "0.1.73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bson",
|
"bson",
|
||||||
@ -2255,16 +2253,6 @@ dependencies = [
|
|||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "matrixmultiply"
|
|
||||||
version = "0.3.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"rawpointer",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "measurements"
|
name = "measurements"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
@ -2385,33 +2373,6 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nalgebra"
|
|
||||||
version = "0.33.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "26aecdf64b707efd1310e3544d709c5c0ac61c13756046aaaba41be5c4f66a3b"
|
|
||||||
dependencies = [
|
|
||||||
"approx 0.5.1",
|
|
||||||
"matrixmultiply",
|
|
||||||
"num-complex",
|
|
||||||
"num-rational",
|
|
||||||
"num-traits 0.2.19",
|
|
||||||
"simba",
|
|
||||||
"typenum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nalgebra-glm"
|
|
||||||
version = "0.19.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e441f43bccdf40cb6bd4294321e6983c5bc7b9886112d19fd4c9813976b117e4"
|
|
||||||
dependencies = [
|
|
||||||
"approx 0.5.1",
|
|
||||||
"nalgebra",
|
|
||||||
"num-traits 0.2.19",
|
|
||||||
"simba",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "newline-converter"
|
name = "newline-converter"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -2451,15 +2412,6 @@ dependencies = [
|
|||||||
"num-traits 0.2.19",
|
"num-traits 0.2.19",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-complex"
|
|
||||||
version = "0.4.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits 0.2.19",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-conv"
|
name = "num-conv"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -2490,17 +2442,6 @@ dependencies = [
|
|||||||
"num-modular",
|
"num-modular",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-rational"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
|
||||||
dependencies = [
|
|
||||||
"num-bigint",
|
|
||||||
"num-integer",
|
|
||||||
"num-traits 0.2.19",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.1.43"
|
version = "0.1.43"
|
||||||
@ -2654,12 +2595,6 @@ dependencies = [
|
|||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "paste"
|
|
||||||
version = "1.0.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pbkdf2"
|
name = "pbkdf2"
|
||||||
version = "0.12.2"
|
version = "0.12.2"
|
||||||
@ -3158,12 +3093,6 @@ dependencies = [
|
|||||||
"getrandom 0.3.1",
|
"getrandom 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rawpointer"
|
|
||||||
version = "0.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
version = "1.10.0"
|
version = "1.10.0"
|
||||||
@ -3447,15 +3376,6 @@ version = "1.0.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "safe_arch"
|
|
||||||
version = "0.7.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
|
|
||||||
dependencies = [
|
|
||||||
"bytemuck",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@ -3711,19 +3631,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "simba"
|
|
||||||
version = "0.9.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa"
|
|
||||||
dependencies = [
|
|
||||||
"approx 0.5.1",
|
|
||||||
"num-complex",
|
|
||||||
"num-traits 0.2.19",
|
|
||||||
"paste",
|
|
||||||
"wide",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simd-adler32"
|
name = "simd-adler32"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
@ -4824,16 +4731,6 @@ dependencies = [
|
|||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wide"
|
|
||||||
version = "0.7.32"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "41b5576b9a81633f3e8df296ce0063042a73507636cbe956c61133dd7034ab22"
|
|
||||||
dependencies = [
|
|
||||||
"bytemuck",
|
|
||||||
"safe_arch",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "kcl-bumper"
|
name = "kcl-bumper"
|
||||||
version = "0.1.75"
|
version = "0.1.73"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://github.com/KittyCAD/modeling-api"
|
repository = "https://github.com/KittyCAD/modeling-api"
|
||||||
rust-version = "1.76"
|
rust-version = "1.76"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-derive-docs"
|
name = "kcl-derive-docs"
|
||||||
description = "A tool for generating documentation from Rust derive macros"
|
description = "A tool for generating documentation from Rust derive macros"
|
||||||
version = "0.1.75"
|
version = "0.1.73"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-directory-test-macro"
|
name = "kcl-directory-test-macro"
|
||||||
description = "A tool for generating tests from a directory of kcl files"
|
description = "A tool for generating tests from a directory of kcl files"
|
||||||
version = "0.1.75"
|
version = "0.1.73"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
@ -11,7 +11,6 @@ proc-macro = true
|
|||||||
bench = false
|
bench = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
convert_case = "0.8.0"
|
|
||||||
proc-macro2 = "1"
|
proc-macro2 = "1"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
syn = { version = "2.0.96", features = ["full"] }
|
syn = { version = "2.0.96", features = ["full"] }
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
use convert_case::Casing;
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use syn::{parse_macro_input, LitStr};
|
use syn::{parse_macro_input, LitStr};
|
||||||
|
|
||||||
/// A macro that generates test functions for each directory within a given path.
|
/// A macro that generates test functions for each directory within a given path.
|
||||||
/// To be included the test directory must have a main.kcl file.
|
|
||||||
/// This will also recursively search for directories within the given path.
|
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
@ -48,11 +45,7 @@ pub fn test_all_dirs(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
// Generate a test function for each directory
|
// Generate a test function for each directory
|
||||||
let test_fns = dirs.iter().map(|(dir_name, dir_path)| {
|
let test_fns = dirs.iter().map(|(dir_name, dir_path)| {
|
||||||
let relative_path = dir_path
|
let test_fn_name = format_ident!("{}_{}", fn_name, sanitize_dir_name(dir_name));
|
||||||
.strip_prefix(&path.to_string_lossy().to_string())
|
|
||||||
.unwrap()
|
|
||||||
.trim();
|
|
||||||
let test_fn_name = format_ident!("{}_{}", fn_name, sanitize_dir_name(relative_path));
|
|
||||||
let dir_name_str = dir_name.clone();
|
let dir_name_str = dir_name.clone();
|
||||||
let dir_path_str = dir_path.clone();
|
let dir_path_str = dir_path.clone();
|
||||||
|
|
||||||
@ -82,26 +75,16 @@ fn get_all_directories(path: &std::path::Path) -> Result<Vec<(String, String)>,
|
|||||||
|
|
||||||
for entry in fs::read_dir(path)? {
|
for entry in fs::read_dir(path)? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
let new_path = entry.path();
|
let path = entry.path();
|
||||||
|
|
||||||
if new_path.is_dir()
|
if path.is_dir() && !IGNORE_DIRS.contains(&path.file_name().and_then(|name| name.to_str()).unwrap_or("")) {
|
||||||
&& !IGNORE_DIRS.contains(&new_path.file_name().and_then(|name| name.to_str()).unwrap_or(""))
|
let dir_name = path
|
||||||
{
|
|
||||||
// Check if the directory contains a main.kcl file.
|
|
||||||
let main_kcl_path = new_path.join("main.kcl");
|
|
||||||
if !main_kcl_path.exists() {
|
|
||||||
// Recurse into the directory.
|
|
||||||
let sub_dirs = get_all_directories(&new_path)?;
|
|
||||||
dirs.extend(sub_dirs);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let dir_name = new_path
|
|
||||||
.file_name()
|
.file_name()
|
||||||
.and_then(|name| name.to_str())
|
.and_then(|name| name.to_str())
|
||||||
.unwrap_or("unknown")
|
.unwrap_or("unknown")
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
let dir_path = new_path.to_str().unwrap_or("unknown").to_string();
|
let dir_path = path.to_str().unwrap_or("unknown").to_string();
|
||||||
|
|
||||||
dirs.push((dir_name, dir_path));
|
dirs.push((dir_name, dir_path));
|
||||||
}
|
}
|
||||||
@ -112,9 +95,10 @@ fn get_all_directories(path: &std::path::Path) -> Result<Vec<(String, String)>,
|
|||||||
|
|
||||||
/// Sanitize directory name to create a valid Rust identifier
|
/// Sanitize directory name to create a valid Rust identifier
|
||||||
fn sanitize_dir_name(name: &str) -> String {
|
fn sanitize_dir_name(name: &str) -> String {
|
||||||
let binding = name
|
let name = name.replace(|c: char| !c.is_ascii_alphanumeric() && c != '_', "_");
|
||||||
.replace(|c: char| !c.is_ascii_alphanumeric() && c != '_', "_")
|
if name.chars().next().is_some_and(|c| c.is_numeric()) {
|
||||||
.replace("/", "_");
|
format!("d_{}", name)
|
||||||
let name = binding.trim_start_matches('_').to_string();
|
} else {
|
||||||
name.to_case(convert_case::Case::Snake)
|
name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-language-server-release"
|
name = "kcl-language-server-release"
|
||||||
version = "0.1.75"
|
version = "0.1.73"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||||
publish = false
|
publish = false
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
name = "kcl-language-server"
|
name = "kcl-language-server"
|
||||||
description = "A language server for KCL."
|
description = "A language server for KCL."
|
||||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||||
version = "0.2.75"
|
version = "0.2.73"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
description = "KittyCAD Language implementation and tools"
|
description = "KittyCAD Language implementation and tools"
|
||||||
version = "0.2.75"
|
version = "0.2.73"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/KittyCAD/modeling-app"
|
repository = "https://github.com/KittyCAD/modeling-app"
|
||||||
@ -50,7 +50,6 @@ lazy_static = { workspace = true }
|
|||||||
measurements = "0.11.0"
|
measurements = "0.11.0"
|
||||||
miette = { workspace = true }
|
miette = { workspace = true }
|
||||||
mime_guess = "2.0.5"
|
mime_guess = "2.0.5"
|
||||||
nalgebra-glm = "0.19.0"
|
|
||||||
parse-display = "0.10.0"
|
parse-display = "0.10.0"
|
||||||
pyo3 = { workspace = true, optional = true }
|
pyo3 = { workspace = true, optional = true }
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
//! Cache testing framework.
|
//! Cache testing framework.
|
||||||
|
|
||||||
#[cfg(feature = "artifact-graph")]
|
|
||||||
use kcl_lib::NodePathStep;
|
|
||||||
use kcl_lib::{bust_cache, ExecError, ExecOutcome};
|
use kcl_lib::{bust_cache, ExecError, ExecOutcome};
|
||||||
use kcmc::{each_cmd as mcmd, ModelingCmd};
|
use kcmc::{each_cmd as mcmd, ModelingCmd};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds as kcmc;
|
||||||
@ -332,40 +330,6 @@ extrude001 = extrude(profile001, length = 4)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "artifact-graph")]
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
|
||||||
async fn kcl_test_cache_add_offset_plane_computes_node_path() {
|
|
||||||
let code = r#"sketch001 = startSketchOn(XY)
|
|
||||||
profile001 = startProfile(sketch001, at = [0, 0])
|
|
||||||
"#;
|
|
||||||
let code_with_more = code.to_owned()
|
|
||||||
+ r#"plane001 = offsetPlane(XY, offset = 500)
|
|
||||||
"#;
|
|
||||||
|
|
||||||
let result = cache_test(
|
|
||||||
"add_offset_plane_preserves_artifact_commands",
|
|
||||||
vec![
|
|
||||||
Variation {
|
|
||||||
code,
|
|
||||||
other_files: vec![],
|
|
||||||
settings: &Default::default(),
|
|
||||||
},
|
|
||||||
Variation {
|
|
||||||
code: code_with_more.as_str(),
|
|
||||||
other_files: vec![],
|
|
||||||
settings: &Default::default(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let second = &result.last().unwrap().2;
|
|
||||||
|
|
||||||
let v = second.artifact_graph.values().collect::<Vec<_>>();
|
|
||||||
let path_step = &v[2].code_ref().unwrap().node_path.steps[0];
|
|
||||||
assert_eq!(*path_step, NodePathStep::ProgramBodyItem { index: 2 });
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn kcl_test_cache_empty_file_pop_cache_empty_file_planes_work() {
|
async fn kcl_test_cache_empty_file_pop_cache_empty_file_planes_work() {
|
||||||
// Get the current working directory.
|
// Get the current working directory.
|
||||||
|