Compare commits

..

4 Commits

Author SHA1 Message Date
10c51896be Merge branch 'main' into safe-reset-scene 2025-04-02 15:20:24 -07:00
34f05b3cf2 updates
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-02 09:57:06 -07:00
3c89ac8421 Update src/components/CommandBar/CommandBarSelectionInput.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-04-02 09:57:06 -07:00
d3f788050c safe reset scene w cache
Signed-off-by: Jess Frazelle <github@jessfraz.com>

fmt

Signed-off-by: Jess Frazelle <github@jessfraz.com>

get the outcome data back out

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fmt

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

remove deferrer

Signed-off-by: Jess Frazelle <github@jessfraz.com>

move the artifact graph to kclmanager, dont defer

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

cleanup xstate stuffs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fmt

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fix tsc

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-02 09:57:04 -07:00
455 changed files with 77362 additions and 56547 deletions

View File

@ -1,5 +1,5 @@
name: Bug Report
description: File a bug report for the Zoo Design Studio
description: File a bug report for the Zoo Modeling App
title: "[BUG]: "
labels: ["bug"]
assignees: []
@ -70,7 +70,7 @@ body:
id: version
attributes:
label: Version
description: "The version of the Zoo Design Studio you're using."
description: "The version of the Zoo Modeling App you're using."
placeholder: "example: v0.15.0. You can find this in the settings."
validations:
required: true

View File

@ -241,7 +241,7 @@ jobs:
- uses: actions/upload-artifact@v4
with:
name: out-arm64-${{ matrix.platform }}
# first two will pick both Zoo Design Studio-$VERSION-arm64-win.exe and Zoo Design Studio-$VERSION-win.exe
# first two will pick both Zoo Modeling App-$VERSION-arm64-win.exe and Zoo Modeling App-$VERSION-win.exe
path: |
out/*-${{ env.VERSION_NO_V }}-win.*
out/*-${{ env.VERSION_NO_V }}-arm64-win.*

View File

@ -281,7 +281,7 @@ jobs:
os:
- "runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64"
- namespace-profile-macos-8-cores
- windows-latest-8-cores
- windows-latest
shardIndex: [1, 2, 3, 4]
shardTotal: [4]
# Disable macos and windows tests on hourly e2e tests since we only care
@ -292,7 +292,7 @@ jobs:
exclude:
- os: namespace-profile-macos-8-cores
isScheduled: true
- os: windows-latest-8-cores
- os: windows-latest
isScheduled: true
# TODO: add ref here for main and latest release tag
runs-on: ${{ matrix.os }}
@ -370,8 +370,8 @@ jobs:
with:
shell: bash
command: .github/ci-cd-scripts/playwright-electron.sh ${{matrix.shardIndex}} ${{matrix.shardTotal}} ${{ env.OS_NAME }}
timeout_minutes: 30
max_attempts: 9
timeout_minutes: 45
max_attempts: 15
env:
FAIL_ON_CONSOLE_ERRORS: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}

View File

@ -1,27 +1,27 @@
# Setting Up Zoo Design Studio
# Setting Up Zoo Modeling App
Compared to other CAD software, getting Zoo Design Studio up and running is quick and straightforward across platforms. It's about 100MB to download and is quick to install.
Compared to other CAD software, getting Zoo Modeling App up and running is quick and straightforward across platforms. It's about 100MB to download and is quick to install.
## Windows
1. Download the [Zoo Design Studio installer](https://zoo.dev/modeling-app/download) for Windows and for your processor type.
1. Download the [Zoo Modeling App installer](https://zoo.dev/modeling-app/download) for Windows and for your processor type.
2. Once downloaded, run the installer `Zoo Design Studio-{version}-{arch}-win.exe` which should take a few seconds.
2. Once downloaded, run the installer `Zoo Modeling App-{version}-{arch}-win.exe` which should take a few seconds.
3. The installation happens at `C:\Program Files\Zoo Design Studio`. A shortcut in the start menu is also created so you can run the app easily by clicking on it.
3. The installation happens at `C:\Program Files\Zoo Modeling App`. A shortcut in the start menu is also created so you can run the app easily by clicking on it.
## macOS
1. Download the [Zoo Design Studio installer](https://zoo.dev/modeling-app/download) for macOS and for your processor type.
1. Download the [Zoo Modeling App installer](https://zoo.dev/modeling-app/download) for macOS and for your processor type.
2. Once downloaded, open the disk image `Zoo Design Studio-{version}-{arch}-mac.dmg` and drag the applications to your `Applications` directory.
2. Once downloaded, open the disk image `Zoo Modeling App-{version}-{arch}-mac.dmg` and drag the applications to your `Applications` directory.
3. You can then open your `Applications` directory and double-click on `Zoo Design Studio` to open.
3. You can then open your `Applications` directory and double-click on `Zoo Modeling App` to open.
## Linux
1. Download the [Zoo Design Studio installer](https://zoo.dev/modeling-app/download) for Linux and for your processor type.
1. Download the [Zoo Modeling App installer](https://zoo.dev/modeling-app/download) for Linux and for your processor type.
2. Install the dependencies needed to run the [AppImage format](https://appimage.org/).
- On Ubuntu, install the FUSE library with these commands in a terminal.
@ -30,7 +30,7 @@ Compared to other CAD software, getting Zoo Design Studio up and running is quic
sudo apt install libfuse2
```
- Optionally, follow [these steps](https://github.com/probonopd/go-appimage/blob/master/src/appimaged/README.md#initial-setup) to install `appimaged`. It is a daemon that makes interacting with AppImage files more seamless.
- Once installed, copy the downloaded `Zoo Design Studio-{version}-{arch}-linux.AppImage` to the directory of your choice, for instance `~/Applications`.
- Once installed, copy the downloaded `Zoo Modeling App-{version}-{arch}-linux.AppImage` to the directory of your choice, for instance `~/Applications`.
- `appimaged` should automatically find it and make it executable. If not, run:
```bash

View File

@ -87,7 +87,7 @@ lint: install ## Lint the code
###############################################################################
# RUN
TARGET ?= desktop
TARGET ?= web
.PHONY: run
run: run-$(TARGET)
@ -103,9 +103,9 @@ run-desktop: install build-desktop ## Start the desktop app
###############################################################################
# TEST
E2E_GREP ?=
E2E_WORKERS ?=
E2E_WORKERS ?= 1
E2E_FAILURES ?= 1
E2E_GREP ?= ""
.PHONY: test
test: test-unit test-e2e
@ -121,19 +121,11 @@ test-e2e: test-e2e-$(TARGET)
.PHONY: test-e2e-web
test-e2e-web: install build-web ## Run the web e2e tests
@ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
ifdef E2E_GREP
yarn chrome:test --headed --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES)
else
yarn chrome:test --headed --workers='100%'
endif
yarn chrome:test --headed --workers=$(E2E_WORKERS) --max-failures=$(E2E_FAILURES) --grep=$(E2E_GREP)
.PHONY: test-e2e-desktop
test-e2e-desktop: install build-desktop ## Run the desktop e2e tests
ifdef E2E_GREP
yarn test:playwright:electron --grep="$(E2E_GREP)" --max-failures=$(E2E_FAILURES)
else
yarn test:playwright:electron --workers='100%'
endif
yarn test:playwright:electron --workers=$(E2E_WORKERS) --max-failures=$(E2E_FAILURES) --grep="$(E2E_GREP)"
###############################################################################
# CLEAN

View File

@ -1,17 +1,17 @@
![Zoo Design Studio](/public/zma-logomark-outlined.png)
![Zoo Modeling App](/public/zma-logomark-outlined.png)
## Zoo Design Studio
## Zoo Modeling App
download at [zoo.dev/modeling-app/download](https://zoo.dev/modeling-app/download)
A CAD application from the future, brought to you by the [Zoo team](https://zoo.dev).
Design Studio is our take on what a modern modelling experience can be. It is applying several lessons learned in the decades since most major CAD tools came into existence:
Modeling App is our take on what a modern modelling experience can be. It is applying several lessons learned in the decades since most major CAD tools came into existence:
- All artifacts—including parts and assemblies—should be represented as human-readable code. At the end of the day, your CAD project should be "plain text"
- This makes version control—which is a solved problem in software engineering—trivial for CAD
- All GUI (or point-and-click) interactions should be actions performed on this code representation under the hood
- This unlocks a hybrid approach to modeling. Whether you point-and-click as you always have or you write your own KCL code, you are performing the same action in Design Studio
- This unlocks a hybrid approach to modeling. Whether you point-and-click as you always have or you write your own KCL code, you are performing the same action in Modeling App
- Everything graphics _has_ to be built for the GPU
- Most CAD applications have had to retrofit support for GPUs, but our geometry engine is made for GPUs (primarily Nvidia's Vulkan), getting the order of magnitude rendering performance boost with it
- Make the resource-intensive pieces of an application auto-scaling
@ -19,9 +19,9 @@ Design Studio is our take on what a modern modelling experience can be. It is ap
We are excited about what a small team of people could build in a short time with our API. We welcome you to try our API, build your own applications, or contribute to ours!
Design Studio is a _hybrid_ user interface for CAD modeling. You can point-and-click to design parts (and soon assemblies), but everything you make is really just [`kcl` code](https://github.com/KittyCAD/kcl-experiments) under the hood. All of your CAD models can be checked into source control such as GitHub and responsibly versioned, rolled back, and more.
Modeling App is a _hybrid_ user interface for CAD modeling. You can point-and-click to design parts (and soon assemblies), but everything you make is really just [`kcl` code](https://github.com/KittyCAD/kcl-experiments) under the hood. All of your CAD models can be checked into source control such as GitHub and responsibly versioned, rolled back, and more.
The 3D view in Design Studio is just a video stream from our hosted geometry engine. The app sends new modeling commands to the engine via WebSockets, which returns back video frames of the view within the engine.
The 3D view in Modeling App is just a video stream from our hosted geometry engine. The app sends new modeling commands to the engine via WebSockets, which returns back video frames of the view within the engine.
## Tools
@ -198,13 +198,13 @@ If the prompt doesn't show up, start the app in command line to grab the electro
```
# Windows (PowerShell)
& 'C:\Program Files\Zoo Design Studio\Zoo Design Studio.exe'
& 'C:\Program Files\Zoo Modeling App\Zoo Modeling App.exe'
# macOS
/Applications/Zoo\ Modeling\ App.app/Contents/MacOS/Zoo\ Modeling\ App
# Linux
./Zoo Design Studio-{version}-{arch}-linux.AppImage
./Zoo Modeling App-{version}-{arch}-linux.AppImage
```
#### 4. Publish the release

View File

@ -54,7 +54,7 @@ example = extrude(exampleSketch, length = 5)
// Add color to a revolved solid.
sketch001 = startSketchOn(XY)
|> circle(center = [15, 0], radius = 5)
|> revolve(angle = 360, axis = Y)
|> revolve(angle = 360, axis = 'y')
|> appearance(color = '#ff0000', metalness = 90, roughness = 90)
```

View File

@ -9,12 +9,9 @@ layout: manual
### `std`
- [`X`](/docs/kcl/consts/std-X)
- [`XY`](/docs/kcl/consts/std-XY)
- [`XZ`](/docs/kcl/consts/std-XZ)
- [`Y`](/docs/kcl/consts/std-Y)
- [`YZ`](/docs/kcl/consts/std-YZ)
- [`Z`](/docs/kcl/consts/std-Z)
### `std::math`

View File

@ -1,15 +0,0 @@
---
title: "std::X"
excerpt: ""
layout: manual
---
```js
std::X
```

View File

@ -1,15 +0,0 @@
---
title: "std::Y"
excerpt: ""
layout: manual
---
```js
std::Y
```

View File

@ -1,15 +0,0 @@
---
title: "std::Z"
excerpt: ""
layout: manual
---
```js
std::Z
```

127
docs/kcl/helix.md Normal file

File diff suppressed because one or more lines are too long

View File

@ -12,7 +12,7 @@ Import a CAD file.
For formats lacking unit data (such as STL, OBJ, or PLY files), the default unit of measurement is millimeters. Alternatively you may specify the unit by passing your desired measurement unit in the options parameter. When importing a GLTF file, the bin file will be imported as well. Import paths are relative to the current project directory.
Note: The import command currently only works when using the native Design Studio.
Note: The import command currently only works when using the native Modeling App.
```js
import(

View File

@ -1,6 +1,6 @@
---
title: "KCL Standard Library"
excerpt: "Documentation for the KCL standard library for the Zoo Design Studio."
excerpt: "Documentation for the KCL standard library for the Zoo Modeling App."
layout: manual
---
@ -22,9 +22,6 @@ layout: manual
* [`string`](kcl/types/string)
* [`tag`](kcl/types/tag)
* **std**
* [`Axis2d`](kcl/types/Axis2d)
* [`Axis3d`](kcl/types/Axis3d)
* [`Edge`](kcl/types/Edge)
* [`Face`](kcl/types/Face)
* [`Helix`](kcl/types/Helix)
* [`Plane`](kcl/types/Plane)
@ -32,12 +29,9 @@ layout: manual
* [`Point3d`](kcl/types/Point3d)
* [`Sketch`](kcl/types/Sketch)
* [`Solid`](kcl/types/Solid)
* [`X`](kcl/consts/std-X)
* [`XY`](kcl/consts/std-XY)
* [`XZ`](kcl/consts/std-XZ)
* [`Y`](kcl/consts/std-Y)
* [`YZ`](kcl/consts/std-YZ)
* [`Z`](kcl/consts/std-Z)
* [`abs`](kcl/abs)
* [`acos`](kcl/acos)
* [`angleToMatchLengthX`](kcl/angleToMatchLengthX)
@ -74,7 +68,7 @@ layout: manual
* [`getNextAdjacentEdge`](kcl/getNextAdjacentEdge)
* [`getOppositeEdge`](kcl/getOppositeEdge)
* [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge)
* [`helix`](kcl/std-helix)
* [`helix`](kcl/helix)
* [`hole`](kcl/hole)
* [`hollow`](kcl/hollow)
* [`inch`](kcl/inch)
@ -93,6 +87,7 @@ layout: manual
* [`map`](kcl/map)
* [`max`](kcl/max)
* [`min`](kcl/min)
* [`mirror2d`](kcl/mirror2d)
* [`mm`](kcl/mm)
* [`offsetPlane`](kcl/offsetPlane)
* [`patternCircular2d`](kcl/patternCircular2d)
@ -111,7 +106,7 @@ layout: manual
* [`push`](kcl/push)
* [`reduce`](kcl/reduce)
* [`rem`](kcl/rem)
* [`revolve`](kcl/std-revolve)
* [`revolve`](kcl/revolve)
* [`rotate`](kcl/rotate)
* [`round`](kcl/round)
* [`scale`](kcl/scale)
@ -147,7 +142,6 @@ layout: manual
* [`tan`](kcl/std-math-tan)
* **std::sketch**
* [`circle`](kcl/std-sketch-circle)
* [`mirror2d`](kcl/std-sketch-mirror2d)
* **std::turns**
* [`turns::HALF_TURN`](kcl/consts/std-turns-HALF_TURN)
* [`turns::QUARTER_TURN`](kcl/consts/std-turns-QUARTER_TURN)

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
---
title: "KCL Known Issues"
excerpt: "Known issues with the KCL standard library for the Zoo Design Studio."
excerpt: "Known issues with the KCL standard library for the Zoo Modeling App."
layout: manual
---

104
docs/kcl/mirror2d.md Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
---
title: "KCL Modules"
excerpt: "Documentation of modules for the KCL language for the Zoo Design Studio."
excerpt: "Documentation of modules for the KCL language for the Zoo Modeling App."
layout: manual
---
@ -95,7 +95,7 @@ import "tests/inputs/cube.obj"
When importing a GLTF file, the bin file will be imported as well.
Import paths are relative to the current project directory. Imports currently only work when
using the native Design Studio, not in the browser.
using the native Modeling App, not in the browser.
### Supported values

237
docs/kcl/revolve.md Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,12 +1,12 @@
---
title: "KCL Settings"
excerpt: "Documentation of settings for the KCL language and Zoo Design Studio."
excerpt: "Documentation of settings for the KCL language and Zoo Modeling App."
layout: manual
---
# KCL Settings
There are three levels of settings available in the KittyCAD Design Studiolication:
There are three levels of settings available in the KittyCAD modeling application:
1. [User Settings](/docs/kcl/settings/user): Global settings that apply to all projects, stored in `user.toml`
2. [Project Settings](/docs/kcl/settings/project): Settings specific to a project, stored in `project.toml`
@ -14,7 +14,7 @@ There are three levels of settings available in the KittyCAD Design Studiolicati
## Configuration Files
The KittyCAD Design Studio uses TOML files for configuration:
The KittyCAD modeling app uses TOML files for configuration:
* **User Settings**: `user.toml` - See [complete documentation](/docs/kcl/settings/user)
* **Project Settings**: `project.toml` - See [complete documentation](/docs/kcl/settings/project)

View File

@ -35,7 +35,7 @@ base_unit = "in"
#### app
The settings for the Design Studio.
The settings for the modeling app.
**Default:** None

View File

@ -37,7 +37,7 @@ text_wrapping = false
#### app
The settings for the Design Studio.
The settings for the modeling app.
**Default:** None

View File

@ -146,7 +146,7 @@ exampleSketch = startSketchOn(XY)
|> line(end = [-2, 0])
|> close()
example = revolve(exampleSketch, axis = Y, angle = 180)
example = revolve(exampleSketch, axis = 'y', angle = 180)
exampleSketch002 = startSketchOn(example, 'end')
|> startProfileAt([4.5, -5], %)
@ -177,7 +177,7 @@ exampleSketch = startSketchOn(XY)
example = revolve(
exampleSketch,
axis = Y,
axis = 'y',
angle = 180,
tagEnd = $end01,
)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -74,7 +74,7 @@ helixPath = helix(
revolutions = 4,
length = 10,
radius = 5,
axis = Z,
axis = 'Z',
)
// Create a spring by sweeping around the helix path.

View File

@ -1,6 +1,6 @@
---
title: "KCL Types"
excerpt: "Documentation of types for the KCL standard library for the Zoo Design Studio."
excerpt: "Documentation of types for the KCL standard library for the Zoo Modeling App."
layout: manual
---

View File

@ -1,12 +0,0 @@
---
title: "std::Axis2d"
excerpt: "An infinite line in 2d space."
layout: manual
---
An infinite line in 2d space.

View File

@ -1,12 +0,0 @@
---
title: "std::Axis3d"
excerpt: "An infinite line in 3d space."
layout: manual
---
An infinite line in 3d space.

View File

@ -1,12 +0,0 @@
---
title: "std::Edge"
excerpt: "The edge of a solid."
layout: manual
---
The edge of a solid.

File diff suppressed because one or more lines are too long

View File

@ -32,44 +32,57 @@ test(
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await test.step('on open of project', async () => {
// Open the project
const projectName = page.getByText(`bracket`)
await expect(projectName).toBeVisible()
await projectName.click()
await scene.waitForExecutionDone()
await page.waitForTimeout(1_000) // wait for panel buttons to be available
page.on('console', console.log)
// Expect zero errors in gutter
await test.step('on open of project', async () => {
await expect(page.getByText(`bracket`)).toBeVisible()
// open the project
await page.getByText(`bracket`).click()
// expect zero errors in guter
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// Click the export button
// export the model
const exportButton = page.getByTestId('export-pane-button')
await expect(exportButton).toBeVisible()
await exportButton.click()
await page.waitForTimeout(1_000) // wait for export options to be available
// Select the first format option
// Wait for the model to finish loading
const modelStateIndicator = page.getByTestId(
'model-state-indicator-execution-done'
)
await expect(modelStateIndicator).toBeVisible({ timeout: 60000 })
const gltfOption = page.getByText('glTF')
const exportFileName = `main.gltf` // source file is named `main.kcl`
const submitButton = page.getByText('Confirm Export')
const exportingToastMessage = page.getByText(`Exporting...`)
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
// The open file's name is `main.kcl`, so the export file name should be `main.gltf`
const exportFileName = `main.gltf`
// Click the export button
await exportButton.click()
await expect(gltfOption).toBeVisible()
await expect(page.getByText('STL')).toBeVisible()
await page.keyboard.press('Enter')
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await page.waitForTimeout(500)
await page.keyboard.press('Enter')
// Find the toast.
// Look out for the toast message
const exportingToastMessage = page.getByText(`Exporting...`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
await expect(exportingToastMessage).toBeVisible()
await expect(alreadyExportingToastMessage).not.toBeVisible()
// Expect it to succeed
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
// Expect it to succeed.
await expect(errorToastMessage).not.toBeVisible()
await expect(engineErrorToastMessage).not.toBeVisible()
@ -77,7 +90,6 @@ test(
await expect(successToastMessage).toBeVisible()
await expect(exportingToastMessage).not.toBeVisible()
// Check for the exported file
const firstFileFullPath = path.resolve(
getPlaywrightDownloadDir(tronApp.projectDirName),
exportFileName
@ -104,53 +116,60 @@ test(
const u = await getUtils(page)
await u.openFilePanel()
// Click on the other file
const otherKclButton = page.getByRole('button', { name: 'other.kcl' })
// Click the file
await otherKclButton.click()
// Close the file pane
await u.closeFilePanel()
await scene.waitForExecutionDone()
await page.waitForTimeout(1_000) // wait for panel buttons to be available
// Expect zero errors in gutter
// FIXME: await scene.waitForExecutionDone() does not work. The modeling indicator stays in -receive-reliable and not execution done
await page.waitForTimeout(10000)
// expect zero errors in guter
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// Click the export button
// export the model
const exportButton = page.getByTestId('export-pane-button')
await expect(exportButton).toBeVisible()
await exportButton.click()
await page.waitForTimeout(1_000) // wait for export options to be available
// Select the first format option
const gltfOption = page.getByText('glTF')
const exportFileName = `other.gltf` // source file is named `other.kcl`
const submitButton = page.getByText('Confirm Export')
const exportingToastMessage = page.getByText(`Exporting...`)
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
// The open file's name is `other.kcl`, so the export file name should be `other.gltf`
const exportFileName = `other.gltf`
// Click the export button
await exportButton.click()
await expect(gltfOption).toBeVisible()
await expect(page.getByText('STL')).toBeVisible()
await page.keyboard.press('Enter')
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await page.waitForTimeout(500)
await page.keyboard.press('Enter')
// Find the toast.
// Look out for the toast message
const exportingToastMessage = page.getByText(`Exporting...`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
await expect(exportingToastMessage).toBeVisible()
await expect(alreadyExportingToastMessage).not.toBeVisible()
// Expect it to succeed
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
await expect(errorToastMessage).not.toBeVisible()
await expect(engineErrorToastMessage).not.toBeVisible()
const successToastMessage = page.getByText(`Exported successfully`)
await expect(successToastMessage).toBeVisible()
await expect(exportingToastMessage).not.toBeVisible()
await test.step('Check the success toast message shows and nothing else', async () =>
Promise.all([
expect(alreadyExportingToastMessage).not.toBeVisible(),
expect(errorToastMessage).not.toBeVisible(),
expect(engineErrorToastMessage).not.toBeVisible(),
expect(successToastMessage).toBeVisible(),
expect(exportingToastMessage).not.toBeVisible(),
]))
// Check for the exported file=
const secondFileFullPath = path.resolve(
getPlaywrightDownloadDir(tronApp.projectDirName),
exportFileName

View File

@ -1274,79 +1274,4 @@ sketch001 = startSketchOn(XZ)
await middleMousePan(800, 200, 900, 300)
})
})
test('Can select lines on the main axis', async ({
page,
homePage,
toolbar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([100.00, 100.0], sketch001)
|> yLine(length = -100.0)
|> xLine(length = 200.0)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()`
)
})
const width = 1200
const height = 800
const viewportSize = { width, height }
await page.setBodyDimensions(viewportSize)
await homePage.goToModelingScene()
const u = await getUtils(page)
await u.waitForPageLoad()
await toolbar.editSketch(0)
await page.waitForTimeout(1000)
// Click on the bottom segment that lies on the x axis
await page.mouse.click(width * 0.85, height / 2)
await page.waitForTimeout(1000)
// Verify segment is selected (you can check for visual indicators or state)
const element = page.locator('[data-overlay-index="1"]')
await expect(element).toHaveAttribute('data-overlay-visible', 'true')
})
test(`Only show axis planes when there are no errors`, async ({
page,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn(XZ)
profile001 = circle(sketch001, center = [-100.0, -100.0], radius = 50.0)
sketch002 = startSketchOn(XZ)
profile002 = circle(sketch002, center = [-100.0, 100.0], radius = 50.0)
extrude001 = extrude(profile002, length = 0)` // length = 0 is causing the error
)
})
const viewportSize = { width: 1200, height: 800 }
await page.setBodyDimensions(viewportSize)
await homePage.goToModelingScene()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await scene.expectPixelColor(
TEST_COLORS.DARK_MODE_BKGD,
// This is a position where the blue part of the axis plane is visible if its rendered
{ x: viewportSize.width * 0.75, y: viewportSize.height * 0.2 },
15
)
})
})

View File

@ -22,7 +22,7 @@ sketch001 = startSketchOn(XZ)
|> angledLine([-45, length001], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
revolve001 = revolve(sketch001, axis = X)
revolve001 = revolve(sketch001, axis = "X")
triangle()
|> extrude(length = 30)
plane001 = offsetPlane(XY, offset = 10)
@ -127,7 +127,7 @@ test.describe('Feature Tree pane', () => {
await testViewSource({
operationName: 'Revolve',
operationIndex: 0,
expectedActiveLine: 'revolve001 = revolve(sketch001, axis = X)',
expectedActiveLine: 'revolve001 = revolve(sketch001, axis = "X")',
})
await testViewSource({
operationName: 'Triangle',

View File

@ -177,25 +177,6 @@ export class ElectronZoo {
this.context = this.electron.context()
await this.context.tracing.start({ screenshots: true, snapshots: true })
// We need to patch this because addInitScript will bind too late in our
// electron tests, never running. We need to call reload() after each call
// to guarantee it runs.
const oldContextAddInitScript = this.context.addInitScript
this.context.addInitScript = async function (a, b) {
// @ts-ignore pretty sure way out of tsc's type checking capabilities.
// This code works perfectly fine.
await oldContextAddInitScript.apply(this, [a, b])
await that.page.reload()
}
const oldPageAddInitScript = this.page.addInitScript
this.page.addInitScript = async function (a: any, b: any) {
// @ts-ignore pretty sure way out of tsc's type checking capabilities.
// This code works perfectly fine.
await oldPageAddInitScript.apply(this, [a, b])
await that.page.reload()
}
}
await this.context.tracing.startChunk()
@ -238,6 +219,26 @@ export class ElectronZoo {
}))
}
// We need to patch this because addInitScript will bind too late in our
// electron tests, never running. We need to call reload() after each call
// to guarantee it runs.
const oldContextAddInitScript = this.context.addInitScript
this.context.addInitScript = async function (a, b) {
// @ts-ignore pretty sure way out of tsc's type checking capabilities.
// This code works perfectly fine.
await oldContextAddInitScript.apply(this, [a, b])
await that.page.reload()
}
// No idea why we mix and match page and context's addInitScript but we do
const oldPageAddInitScript = this.page.addInitScript
this.page.addInitScript = async function (a: any, b: any) {
// @ts-ignore pretty sure way out of tsc's type checking capabilities.
// This code works perfectly fine.
await oldPageAddInitScript.apply(this, [a, b])
await that.page.reload()
}
if (!this.firstUrl) {
await this.page.getByText('Your Projects').count()
this.firstUrl = this.page.url()

View File

@ -96,7 +96,7 @@ export class HomePageFixture {
await expect(this.projectSection).not.toHaveText('Loading your Projects...')
}
createAndGoToProject = async (projectTitle = 'untitled') => {
createAndGoToProject = async (projectTitle = 'project-$nnn') => {
await this.projectsLoaded()
await this.projectButtonNew.click()
await this.projectTextName.click()

View File

@ -1,120 +0,0 @@
import { expect, test } from '@e2e/playwright/zoo-test'
import * as fsp from 'fs/promises'
import path from 'path'
test.describe('Import UI tests', () => {
test('shows toast when trying to sketch on imported face', async ({
context,
page,
homePage,
toolbar,
scene,
editor,
}) => {
await context.folderSetupFn(async (dir) => {
const projectDir = path.join(dir, 'import-test')
await fsp.mkdir(projectDir, { recursive: true })
// Create the imported file
await fsp.writeFile(
path.join(projectDir, 'toBeImported.kcl'),
`sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([281.54, 305.81], sketch001)
|> angledLine([0, 123.43], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
85.99
], %)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude(profile001, length = 100)`
)
// Create the main file that imports
await fsp.writeFile(
path.join(projectDir, 'main.kcl'),
`import "toBeImported.kcl" as importedCube
importedCube
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([-134.53, -56.17], sketch001)
|> angledLine([0, 79.05], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
76.28
], %)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %, $seg01)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|> close()
extrude001 = extrude(profile001, length = 100)
sketch003 = startSketchOn(extrude001, seg02)
sketch002 = startSketchOn(extrude001, seg01)`
)
})
await homePage.openProject('import-test')
await scene.waitForExecutionDone()
await scene.moveCameraTo(
{
x: -114,
y: -897,
z: 475,
},
{
x: -114,
y: -51,
z: 83,
}
)
const [_, hoverOverNonImport] = scene.makeMouseHelpers(611, 364)
const [importedFaceClick, hoverOverImported] = scene.makeMouseHelpers(
940,
150
)
await test.step('check code highlight works for code define in the file being edited', async () => {
await hoverOverNonImport()
await editor.expectState({
highlightedCode: 'startProfileAt([-134.53,-56.17],sketch001)',
diagnostics: [],
activeLines: ['import"toBeImported.kcl"asimportedCube'],
})
})
await test.step('check code does nothing when geometry is defined in an import', async () => {
await hoverOverImported()
await editor.expectState({
highlightedCode: '',
diagnostics: [],
activeLines: ['import"toBeImported.kcl"asimportedCube'],
})
})
await test.step('check the user is warned when sketching on a imported face', async () => {
// Start sketch mode
await toolbar.startSketchPlaneSelection()
// Click on a face from the imported model
// await new Promise(() => {})
await importedFaceClick()
// Verify toast appears with correct content
await expect(page.getByText('This face is from an import')).toBeVisible()
await expect(
page.locator('.font-mono').getByText('toBeImported.kcl')
).toBeVisible()
await expect(
page.getByText('Please select this from the files pane to edit')
).toBeVisible()
})
})
})

View File

@ -1,7 +0,0 @@
export const throwError = (message: string): never => {
throw new Error(message)
}
export const throwTronAppMissing = () => {
throwError('tronApp is missing')
}

File diff suppressed because it is too large Load Diff

View File

@ -42,10 +42,10 @@ test.describe('Onboarding tests', () => {
await homePage.goToModelingScene()
// Test that the onboarding pane loaded
await expect(page.getByText('Welcome to Design Studio! This')).toBeVisible()
await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible()
// Test that the onboarding pane loaded
await expect(page.getByText('Welcome to Design Studio! This')).toBeVisible()
await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible()
// *and* that the code is shown in the editor
await expect(page.locator('.cm-content')).toContainText('// Shelf Bracket')
@ -86,7 +86,7 @@ test.describe('Onboarding tests', () => {
await test.step(`Ensure we see the onboarding stuff`, async () => {
// Test that the onboarding pane loaded
await expect(
page.getByText('Welcome to Design Studio! This')
page.getByText('Welcome to Modeling App! This')
).toBeVisible()
// *and* that the code is shown in the editor
@ -147,7 +147,7 @@ test.describe('Onboarding tests', () => {
await nextButton.click()
// Ensure we see the introduction and that the code has been reset
await expect(page.getByText('Welcome to Design Studio!')).toBeVisible()
await expect(page.getByText('Welcome to Modeling App!')).toBeVisible()
await expect(page.locator('.cm-content')).toContainText('// Shelf Bracket')
// There used to be old code here that checked if we stored the reset
@ -188,7 +188,7 @@ test.describe('Onboarding tests', () => {
await homePage.goToModelingScene()
// Test that the onboarding pane loaded
await expect(page.getByText('Welcome to Design Studio! This')).toBeVisible()
await expect(page.getByText('Welcome to Modeling App! This')).toBeVisible()
const nextButton = page.getByTestId('onboarding-next')
const prevButton = page.getByTestId('onboarding-prev')
@ -494,7 +494,7 @@ test('Restarting onboarding on desktop takes one attempt', async ({
const tutorialProjectIndicator = page
.getByTestId('project-sidebar-toggle')
.filter({ hasText: 'Tutorial Project 00' })
const tutorialModalText = page.getByText('Welcome to Design Studio!')
const tutorialModalText = page.getByText('Welcome to Modeling App!')
const tutorialDismissButton = page.getByRole('button', { name: 'Dismiss' })
const userMenuButton = page.getByTestId('user-sidebar-toggle')
const userMenuSettingsButton = page.getByRole('button', {

View File

@ -1084,8 +1084,8 @@ openSketch = startSketchOn(XY)
}) => {
// One dumb hardcoded screen pixel value
const testPoint = { x: 620, y: 257 }
const expectedOutput = `helix001 = helix( axis = X, radius = 5, length = 5, revolutions = 1, angleStart = 360, ccw = false,)`
const expectedLine = `axis=X,`
const expectedOutput = `helix001 = helix( axis = 'X', radius = 5, length = 5, revolutions = 1, angleStart = 360, ccw = false,)`
const expectedLine = `axis='X',`
await homePage.goToModelingScene()
@ -1217,7 +1217,7 @@ openSketch = startSketchOn(XY)
cmdBar,
}) => {
page.on('console', console.log)
const initialCode = `sketch001 = startSketchOn(XZ)
const initialCode = `sketch001 = startSketchOn('XZ')
profile001 = startProfileAt([0, 0], sketch001)
|> yLine(length = 100)
|> line(endAbsolute = [100, 0])
@ -3474,7 +3474,7 @@ segAng(rectangleSegmentA002),
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()
// Edit flow

View File

@ -828,7 +828,7 @@ test.describe(`Project management commands`, () => {
const commandButton = page.getByRole('button', { name: 'Commands' })
const commandOption = page.getByRole('option', { name: 'rename project' })
const projectNameOption = page.getByRole('option', { name: projectName })
const projectRenamedName = `untitled`
const projectRenamedName = `project-000`
// const projectMenuButton = page.getByTestId('project-sidebar-toggle')
const commandContinueButton = page.getByRole('button', {
name: 'Continue',
@ -941,7 +941,7 @@ test.describe(`Project management commands`, () => {
const commandButton = page.getByRole('button', { name: 'Commands' })
const commandOption = page.getByRole('option', { name: 'rename project' })
const projectNameOption = page.getByRole('option', { name: projectName })
const projectRenamedName = `untitled`
const projectRenamedName = `project-000`
const commandContinueButton = page.getByRole('button', {
name: 'Continue',
})
@ -1139,7 +1139,7 @@ test(`Create a few projects using the default project name`, async ({
await test.step(`Create project ${i}`, async () => {
await homePage.expectState({
projectCards: Array.from({ length: i }, (_, i) => ({
title: i === 0 ? 'untitled' : `untitled-${i}`,
title: `project-${i.toString().padStart(3, '0')}`,
fileCount: 1,
})).toReversed(),
sortBy: 'last-modified-desc',
@ -1323,9 +1323,9 @@ test(
})
await test.step('Check we can still create a project', async () => {
await createProject({ name: 'new-project', page, returnHome: true })
await createProject({ name: 'project-000', page, returnHome: true })
await expect(
page.getByTestId('project-link').filter({ hasText: 'new-project' })
page.getByTestId('project-link').filter({ hasText: 'project-000' })
).toBeVisible()
})
}

View File

@ -684,7 +684,7 @@ sketch001 = startSketchOn(XZ)
|> line(end = [12.73, -0.09])
|> tangentialArcTo([24.95, -5.38], %)
|> close()
|> revolve(axis = X)`
|> revolve(axis = "X")`
)
})
@ -771,7 +771,7 @@ sketch001 = startSketchOn(XZ)
|> tangentialArcTo([24.95, -5.38], %)
|> line(end = [1.97, 2.06])
|> close()
|> revolve(axis = X)`,
|> revolve(axis = "X")`,
{ shouldNormalise: true }
)
})
@ -1223,7 +1223,7 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
|> xLine(endAbsolute = 0 + .001)
|> yLine(endAbsolute = 0)
|> close()
|> revolve(axis = Y)
|> revolve(axis = "Y")
return lugSketch
}

View File

@ -351,7 +351,7 @@ const extrudeDefaultPlane = async (
},
},
project: {
default_project_name: 'untitled',
default_project_name: 'project-$nnn',
},
text_editor: {
text_wrapping: true,

View File

@ -23,7 +23,7 @@ export const TEST_SETTINGS: DeepPartial<Settings> = {
camera_projection: 'perspective',
},
project: {
default_project_name: 'untitled',
default_project_name: 'project-$nnn',
directory: '',
},
text_editor: {
@ -80,8 +80,7 @@ export const TEST_SETTINGS_CORRUPTED = {
},
} satisfies Partial<SaveSettingsPayload>
export const TEST_CODE_GIZMO = `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
export const TEST_CODE_GIZMO = `part001 = startSketchOn(XZ)
|> startProfileAt([20, 0], %)
|> line(end = [7.13, 4 + 0])
|> angledLine({ angle: 3 + 0, length: 3.14 + 0 }, %)

View File

@ -8,37 +8,37 @@ test.describe('Testing Gizmo', { tag: ['@skipWin'] }, () => {
const cases = [
{
testDescription: 'top view',
clickPosition: { x: 951, y: 385 },
clickPosition: { x: 951, y: 347 },
expectedCameraPosition: { x: 800, y: -152, z: 4886.02 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'bottom view',
clickPosition: { x: 951, y: 429 },
clickPosition: { x: 951, y: 391 },
expectedCameraPosition: { x: 800, y: -152, z: -4834.02 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'right view',
clickPosition: { x: 929, y: 417 },
clickPosition: { x: 929, y: 379 },
expectedCameraPosition: { x: 5660.02, y: -152, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'left view',
clickPosition: { x: 974, y: 397 },
clickPosition: { x: 974, y: 359 },
expectedCameraPosition: { x: -4060.02, y: -152, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'back view',
clickPosition: { x: 967, y: 421 },
clickPosition: { x: 967, y: 383 },
expectedCameraPosition: { x: 800, y: 4708.02, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'front view',
clickPosition: { x: 935, y: 393 },
clickPosition: { x: 935, y: 355 },
expectedCameraPosition: { x: 800, y: -5012.02, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},

View File

@ -2,11 +2,7 @@ import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Test toggling perspective', () => {
test('via command palette and toggle', async ({
page,
homePage,
toolbar,
}) => {
test('via command palette and toggle', async ({ page, homePage }) => {
test.fixme(orRunWhenFullSuiteEnabled())
const u = await getUtils(page)
@ -18,7 +14,7 @@ test.describe('Test toggling perspective', () => {
y: screenHeight * 0.2,
}
const backgroundColor: [number, number, number] = [29, 29, 29]
const xzPlaneColor: [number, number, number] = [72, 55, 96]
const xzPlaneColor: [number, number, number] = [82, 55, 96]
const locationToHaveColor = async (color: [number, number, number]) => {
return u.getGreatestPixDiff(checkedScreenLocation, color)
}
@ -30,29 +26,9 @@ test.describe('Test toggling perspective', () => {
const commandToast = page.getByText(
`Set camera projection to "orthographic"`
)
const checkSettingValue = async () => {
const settingsButton = page.getByRole('link', {
name: 'Settings',
exact: false,
})
let settingValue: string | null = null
await test.step(`Check the setting value`, async () => {
await settingsButton.click()
const userTab = page.getByRole('radio', { name: 'User' })
await userTab.click()
await expect(userTab).toBeChecked()
const setting = page.locator('#cameraProjection').first()
await expect(setting).toBeAttached()
await setting.scrollIntoViewIfNeeded()
settingValue = await setting.getByRole('combobox').inputValue()
await page.getByTestId('settings-close-button').click()
})
return settingValue
}
const projectionToggle = page.getByRole('switch', {
name: 'Camera projection: ',
})
await test.step('Setup', async () => {
await page.setBodyDimensions({ width: screenWidth, height: screenHeight })
@ -63,8 +39,8 @@ test.describe('Test toggling perspective', () => {
timeout: 5000,
message: 'This spot should have the background color',
})
.toBeLessThan(30)
expect(await checkSettingValue()).toBe('perspective')
.toBeLessThan(15)
await expect(projectionToggle).toHaveAttribute('aria-checked', 'true')
})
// Extremely wild note: flicking between ortho and persp actually changes
@ -83,22 +59,33 @@ test.describe('Test toggling perspective', () => {
timeout: 5000,
message: 'This spot should have the XZ plane color',
})
.toBeLessThan(30)
expect(await checkSettingValue()).toBe('orthographic')
.toBeLessThan(15)
await expect(projectionToggle).toHaveAttribute('aria-checked', 'false')
})
await test.step(`Refresh the page and ensure the stream is loaded in ortho`, async () => {
await page.reload()
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
await page.waitForTimeout(1000)
await u.closeKclCodePanel()
await expect
.poll(async () => locationToHaveColor(xzPlaneColor), {
timeout: 5000,
message: 'This spot should have the XZ plane color',
})
.toBeLessThan(30)
.toBeLessThan(15)
await expect(commandToast).not.toBeVisible()
expect(await checkSettingValue()).toBe('orthographic')
await expect(projectionToggle).toHaveAttribute('aria-checked', 'false')
})
await test.step(`Switch to perspective via toggle`, async () => {
await projectionToggle.click()
await expect(projectionToggle).toHaveAttribute('aria-checked', 'true')
await expect
.poll(async () => locationToHaveColor(backgroundColor), {
timeout: 5000,
message: 'This spot should have the background color',
})
.toBeLessThan(15)
})
})
})

View File

@ -8,8 +8,8 @@ import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing in-app sample loading', () => {
/**
* Note this test implicitly depends on the KCL sample "parametric-bearing-pillow-block",
* its title, and its units settings. https://github.com/KittyCAD/kcl-samples/blob/main/parametric-bearing-pillow-block/main.kcl
* Note this test implicitly depends on the KCL sample "a-parametric-bearing-pillow-block",
* its title, and its units settings. https://github.com/KittyCAD/kcl-samples/blob/main/a-parametric-bearing-pillow-block/main.kcl
*/
test('Web: should overwrite current code, cannot create new file', async ({
editor,
@ -29,8 +29,8 @@ test.describe('Testing in-app sample loading', () => {
// Locators and constants
const newSample = {
file: 'parametric-bearing-pillow-block' + FILE_EXT,
title: 'Parametric Bearing Pillow Block',
file: 'a-parametric-bearing-pillow-block' + FILE_EXT,
title: 'A Parametric Bearing Pillow Block',
}
const commandBarButton = page.getByRole('button', { name: 'Commands' })
const samplesCommandOption = page.getByRole('option', {
@ -72,7 +72,7 @@ test.describe('Testing in-app sample loading', () => {
/**
* Note this test implicitly depends on the KCL samples:
* "parametric-bearing-pillow-block": https://github.com/KittyCAD/kcl-samples/blob/main/parametric-bearing-pillow-block/main.kcl
* "a-parametric-bearing-pillow-block": https://github.com/KittyCAD/kcl-samples/blob/main/a-parametric-bearing-pillow-block/main.kcl
* "gear-rack": https://github.com/KittyCAD/kcl-samples/blob/main/gear-rack/main.kcl
*/
test(
@ -90,8 +90,8 @@ test.describe('Testing in-app sample loading', () => {
// Locators and constants
const sampleOne = {
file: 'parametric-bearing-pillow-block' + FILE_EXT,
title: 'Parametric Bearing Pillow Block',
file: 'a-parametric-bearing-pillow-block' + FILE_EXT,
title: 'A Parametric Bearing Pillow Block',
}
const sampleTwo = {
file: 'gear-rack' + FILE_EXT,

View File

@ -324,7 +324,7 @@ part009 = startSketchOn(XY)
|> line(end = [0, pipeLength])
|> angledLineToX({ angle = 60, to = pipeLargeDia }, %)
|> close()
rev = revolve(part009, axis = Y)
rev = revolve(part009, axis = 'y')
sketch006 = startSketchOn(XY)
profile001 = circle(
sketch006,
@ -381,7 +381,7 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
await page.waitForTimeout(200)
await expect(u.codeLocator).not.toContainText(
`rev = revolve(part009, axis: Y)`
`rev = revolve(part009, axis: 'y')`
)
// FIXME (commented section below), this test would select a wall that had a sketch on it, and delete the underlying extrude

View File

@ -57,7 +57,7 @@ test.describe('Testing settings', () => {
expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo')
expect(storedSettings.settings?.project?.directory).toBe('')
expect(storedSettings.settings?.project?.default_project_name).toBe(
'untitled'
'project-$nnn'
)
})

View File

@ -4,7 +4,6 @@ directories:
buildResources: assets
files:
- .vite/**
- "!node_modules/win-ca/pem/**"
mac:
category: public.app-category.developer-tools
artifactName: "${productName}-${version}-${arch}-${os}.${ext}"

View File

@ -22,7 +22,7 @@
data-domain="app.zoo.dev"
src="https://plausible.corp.zoo.dev/js/script.tagged-events.js"
></script>
<title>Zoo Design Studio</title>
<title>Zoo Modeling App</title>
</head>
<body class="body-bg">
<noscript>You need to enable JavaScript to run this app.</noscript>

View File

@ -2,13 +2,13 @@
"name": "zoo-modeling-app",
"version": "0.0.0",
"private": true,
"productName": "Zoo Design Studio",
"productName": "Zoo Modeling App",
"author": {
"name": "Zoo Corporation",
"email": "info@zoo.dev",
"url": "https://zoo.dev"
},
"description": "Zoo Design Studio",
"description": "Zoo Modeling App",
"main": ".vite/build/main.js",
"license": "MIT",
"dependencies": {
@ -26,7 +26,7 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.19",
"@headlessui/tailwindcss": "^0.2.2",
"@kittycad/lib": "2.0.26",
"@kittycad/lib": "2.0.25",
"@lezer/highlight": "^1.2.1",
"@lezer/lr": "^1.4.1",
"@react-hook/resize-observer": "^2.0.1",
@ -66,7 +66,6 @@
"vscode-languageserver-protocol": "^3.17.5",
"vscode-uri": "^3.1.0",
"web-vitals": "^3.5.2",
"win-ca": "^3.5.1",
"xstate": "^5.19.2",
"yargs": "^17.7.2"
},
@ -234,7 +233,7 @@
"ts-node": "^10.0.0",
"typescript": "^5.8.2",
"typescript-eslint": "^8.26.1",
"vite": "^5.4.17",
"vite": "^5.4.12",
"vite-plugin-package-version": "^1.1.0",
"vite-plugin-top-level-await": "^1.5.0",
"vite-tsconfig-paths": "^4.3.2",

View File

@ -683,9 +683,9 @@ vite-tsconfig-paths@^4.3.2:
tsconfck "^3.0.3"
vite@^5.0.0:
version "5.4.17"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.17.tgz#4bf61dd4cdbf64b0d6661f5dba76954cc81d5082"
integrity sha512-5+VqZryDj4wgCs55o9Lp+p8GE78TLVg0lasCH5xFZ4jacZjtqZa6JUw9/p0WeAojaOfncSM6v77InkFPGnvPvg==
version "5.4.14"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.14.tgz#ff8255edb02134df180dcfca1916c37a6abe8408"
integrity sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==
dependencies:
esbuild "^0.21.3"
postcss "^8.4.43"

View File

@ -1,29 +1,10 @@
import { defineConfig, devices } from '@playwright/test'
import os from 'os'
const platform = os.platform() // 'linux' (Ubuntu), 'darwin' (macOS), 'win32' (Windows)
let workers: number | string
if (process.env.E2E_WORKERS) {
workers = process.env.E2E_WORKERS.includes('%')
? process.env.E2E_WORKERS
: parseInt(process.env.E2E_WORKERS)
} else if (!process.env.CI) {
workers = 1 // Local dev: keep things simple and deterministic by default
} else {
// On CI: adjust based on OS
switch (platform) {
case 'linux':
workers = '100%' // CI Linux runners are generally beefier
break
case 'darwin':
case 'win32':
default:
workers = '75%' // Slightly conservative for GUI-based OSes
break
}
}
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
@ -38,8 +19,8 @@ export default defineConfig({
forbidOnly: !!process.env.CI,
/* Do not retry */
retries: process.env.CI ? 0 : 0,
/* Use all available CPU cores */
workers: workers,
/* Different amount of parallelism on CI and local. */
workers: process.env.CI ? 1 : 4,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: [
[process.env.CI ? 'dot' : 'list'],

View File

@ -1,29 +1,5 @@
import { defineConfig, devices } from '@playwright/test'
import os from 'os'
const platform = os.platform() // 'linux' (Ubuntu), 'darwin' (macOS), 'win32' (Windows)
let workers: number | string
if (process.env.E2E_WORKERS) {
workers = process.env.E2E_WORKERS.includes('%')
? process.env.E2E_WORKERS
: parseInt(process.env.E2E_WORKERS)
} else if (!process.env.CI) {
workers = 1 // Local dev: keep things simple and deterministic by default
} else {
// On CI: adjust based on OS
switch (platform) {
case 'linux':
workers = '50%' // CI Linux runners are generally beefier
break
case 'darwin':
case 'win32':
default:
workers = '25%' // Lower concurrency for heavier Electron processes
break
}
}
import { platform } from 'os'
/**
* See https://playwright.dev/docs/test-configuration.
@ -38,8 +14,8 @@ export default defineConfig({
forbidOnly: true,
/* Do not retry */
retries: 0,
/* Use all available CPU cores */
workers: workers,
/* Different amount of parallelism on CI and local. */
workers: platform() === 'win32' ? 1 : 2,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: [
['dot'],

View File

@ -31,7 +31,7 @@ data = {
{modified_release_body}
'''),
"username": "Design Studio Release Updates",
"username": "Modeling App Release Updates",
"avatar_url": "https://raw.githubusercontent.com/KittyCAD/modeling-app/main/public/discord-avatar.png"
}

View File

@ -4,9 +4,9 @@
First off, thank you so much for your interest in being a part of the closed Alpha program! We are thrilled to have others use our product and see what you build with it (and truthfully, how you break it too).
### Zoo Design Studio (ZMA)
### Zoo Modeling App (ZMA)
What we are introducing to you is our Zoo Design Studio (ZMA). ZMA is a CAD application that expresses a hybrid style of traditional CAD interface along with a code-CAD interface. ZMA is a great way for us to test our own APIs as well as inspire others to develop their own applications.
What we are introducing to you is our Zoo Modeling App (ZMA). ZMA is a CAD application that expresses a hybrid style of traditional CAD interface along with a code-CAD interface. ZMA is a great way for us to test our own APIs as well as inspire others to develop their own applications.
### Why Code?

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Create a function to make the 80-20 rail
// Define function
fn rail8020(originStart, railHeight, railLength) {
// Sketch side 1 of profile
sketch001 = startSketchOn(-XZ)

View File

@ -25,6 +25,8 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
---
#### [80-20-rail](80-20-rail/main.kcl) ([screenshot](screenshots/80-20-rail.png))
[![80-20-rail](screenshots/80-20-rail.png)](80-20-rail/main.kcl)
#### [a-parametric-bearing-pillow-block](a-parametric-bearing-pillow-block/main.kcl) ([screenshot](screenshots/a-parametric-bearing-pillow-block.png))
[![a-parametric-bearing-pillow-block](screenshots/a-parametric-bearing-pillow-block.png)](a-parametric-bearing-pillow-block/main.kcl)
#### [ball-bearing](ball-bearing/main.kcl) ([screenshot](screenshots/ball-bearing.png))
[![ball-bearing](screenshots/ball-bearing.png)](ball-bearing/main.kcl)
#### [bench](bench/main.kcl) ([screenshot](screenshots/bench.png))
@ -81,8 +83,6 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
[![mounting-plate](screenshots/mounting-plate.png)](mounting-plate/main.kcl)
#### [multi-axis-robot](multi-axis-robot/main.kcl) ([screenshot](screenshots/multi-axis-robot.png))
[![multi-axis-robot](screenshots/multi-axis-robot.png)](multi-axis-robot/main.kcl)
#### [parametric-bearing-pillow-block](parametric-bearing-pillow-block/main.kcl) ([screenshot](screenshots/parametric-bearing-pillow-block.png))
[![parametric-bearing-pillow-block](screenshots/parametric-bearing-pillow-block.png)](parametric-bearing-pillow-block/main.kcl)
#### [pipe](pipe/main.kcl) ([screenshot](screenshots/pipe.png))
[![pipe](screenshots/pipe.png)](pipe/main.kcl)
#### [pipe-flange-assembly](pipe-flange-assembly/main.kcl) ([screenshot](screenshots/pipe-flange-assembly.png))

View File

@ -1,10 +1,10 @@
// Parametric Bearing Pillow Block
// A Parametric Bearing Pillow Block
// A bearing pillow block, also known as a plummer block or pillow block bearing, is a pedestal used to provide support for a rotating shaft with the help of compatible bearings and various accessories. Housing a bearing, the pillow block provides a secure and stable foundation that allows the shaft to rotate smoothly within its machinery setup. These components are essential in a wide range of mechanical systems and machinery, playing a key role in reducing friction and supporting radial and axial loads.
// Set units
@settings(defaultLengthUnit = in)
// Define parameters
// Define constants such as length, width, height, counter-bore depth and diameter, bearing diameter, hole location padding, and more
length = 6
width = 4
height = 1
@ -14,15 +14,15 @@ holeDia = .375
padding = 1.5
bearingDia = 3
// Sketch the block body
body = startSketchOn(XY)
// (Needs to be updated). Sketch the block and extrude up to where the counterbore diameter starts.
extrude001 = startSketchOn(XY)
|> startProfileAt([-width / 2, -length / 2], %)
|> line(endAbsolute = [width / 2, -length / 2])
|> line(endAbsolute = [width / 2, length / 2])
|> line(endAbsolute = [-width / 2, length / 2])
|> close()
|> extrude(length = height)
counterBoreHoles = startSketchOn(body, 'end')
extrude002 = startSketchOn(extrude001, 'end')
|> circle(
center = [
-(width / 2 - (padding / 2)),
@ -34,7 +34,7 @@ counterBoreHoles = startSketchOn(body, 'end')
|> patternLinear2d(instances = 2, distance = width - padding, axis = [1, 0])
|> extrude(%, length = -cbDepth)
boltHoles = startSketchOn(body, 'start')
extrude003 = startSketchOn(extrude001, 'start')
|> circle(
center = [
-(width / 2 - (padding / 2)),
@ -46,6 +46,6 @@ boltHoles = startSketchOn(body, 'start')
|> patternLinear2d(instances = 2, distance = width - padding, axis = [1, 0])
|> extrude(length = -height + cbDepth)
centerHole = startSketchOn(body, 'end')
extrude004 = startSketchOn(extrude001, 'end')
|> circle(center = [0, 0], radius = bearingDia / 2)
|> extrude(length = -height)

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define parameters
// Define constants like ball diameter, inside diamter, overhange length, and thickness
outsideDiameter = 1.625
sphereDia = 0.25
shaftDia = 0.75
@ -35,7 +35,7 @@ ballsSketch = startSketchOn(XY)
|> close()
// Revolve the ball to make a sphere and pattern around the inside wall
balls = revolve(ballsSketch, axis = X)
balls = revolve(ballsSketch, axis = "X")
|> patternCircular3d(
arcDegrees = 360,
axis = [0, 0, 1],
@ -60,7 +60,7 @@ chainSketch = startSketchOn(XY)
|> close()
// Revolve the chain sketch
chainHead = revolve(chainSketch, axis = X)
chainHead = revolve(chainSketch, axis = "X")
|> patternCircular3d(
arcDegrees = 360,
axis = [0, 0, 1],
@ -80,7 +80,7 @@ linkSketch = startSketchOn(XZ)
)
// Revolve the link sketch
linkRevolve = revolve(linkSketch, axis = Y, angle = 360 / nBalls)
linkRevolve = revolve(linkSketch, axis = 'Y', angle = 360 / nBalls)
|> patternCircular3d(
arcDegrees = 360,
axis = [0, 0, 1],
@ -95,3 +95,5 @@ outsideWallSketch = startSketchOn(offsetPlane(XY, offset = -overallThickness / 2
|> hole(circle(center = [0, 0], radius = shaftDia / 2 + wallThickness + sphereDia), %)
outsideWall = extrude(outsideWallSketch, length = overallThickness)
// https://www.mcmaster.com/60355K185/

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parameters
import caliperTolerance, caliperPadLength, caliperThickness, caliperOuterEdgeRadius, caliperInnerEdgeRadius, rotorDiameter, rotorTotalThickness, yAxisOffset from "parameters.kcl"
// Import Constants
import caliperTolerance, caliperPadLength, caliperThickness, caliperOuterEdgeRadius, caliperInnerEdgeRadius, rotorDiameter, rotorTotalThickness, yAxisOffset from "globals.kcl"
// Sketch the brake caliper profile
brakeCaliperSketch = startSketchOn(XY)
@ -80,5 +80,5 @@ brakeCaliperSketch = startSketchOn(XY)
|> close()
// Revolve the brake caliper sketch
revolve(brakeCaliperSketch, axis = Y, angle = -70)
revolve(brakeCaliperSketch, axis = "Y", angle = -70)
|> appearance(color = "#c82d2d", metalness = 90, roughness = 90)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parameters
import rotorDiameter, rotorInnerDiameter, rotorSinglePlateThickness, rotorInnerDiameterThickness, lugHolePatternDia, lugSpacing, rotorTotalThickness, spacerPatternDiameter, spacerDiameter, spacerLength, spacerCount, wheelDiameter, lugCount, yAxisOffset, drillAndSlotCount from "parameters.kcl"
// Import Constants
import rotorDiameter, rotorInnerDiameter, rotorSinglePlateThickness, rotorInnerDiameterThickness, lugHolePatternDia, lugSpacing, rotorTotalThickness, spacerPatternDiameter, spacerDiameter, spacerLength, spacerCount, wheelDiameter, lugCount, yAxisOffset, drillAndSlotCount from "globals.kcl"
rotorSketch = startSketchOn(XZ)
|> circle(center = [0, 0], radius = rotorDiameter / 2)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parameters
import tireInnerDiameter, tireOuterDiameter, tireDepth, bendRadius, tireTreadWidth, tireTreadDepth, tireTreadOffset from "parameters.kcl"
// Import Constants
import tireInnerDiameter, tireOuterDiameter, tireDepth, bendRadius, tireTreadWidth, tireTreadDepth, tireTreadOffset from "globals.kcl"
// Create the sketch of the tire
tireSketch = startSketchOn(XY)
@ -41,5 +41,5 @@ tireSketch = startSketchOn(XY)
|> close()
// Revolve the sketch to create the tire
revolve(tireSketch, axis = Y)
revolve(tireSketch, axis = "Y")
|> appearance(color = "#0f0f0f", roughness = 80)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parameters
import lugCount, lugSpacing, offset, backSpacing, wheelWidth, wheelDiameter, spokeCount, spokeGap, spokeAngle, spokeThickness from "parameters.kcl"
// Import Constants
import lugCount, lugSpacing, offset, backSpacing, wheelWidth, wheelDiameter, spokeCount, spokeGap, spokeAngle, spokeThickness from "globals.kcl"
// Create the wheel center
lugBase = startSketchOn(XZ)
@ -54,7 +54,7 @@ wheelCenterInner = startSketchOn(XY)
|> yLine(endAbsolute = 0)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(axis = Y)
|> revolve(axis = 'y')
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
wheelCenterOuter = startSketchOn(XY)
@ -68,7 +68,7 @@ wheelCenterOuter = startSketchOn(XY)
|> yLine(endAbsolute = -wheelWidth / 20)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(axis = Y)
|> revolve(axis = 'y')
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)
// Write a function that defines the spoke geometry, patterns and extrudes it
@ -173,5 +173,5 @@ startSketchOn(XY)
|> xLine(length = wheelWidth * 0.03)
|> yLine(length = wheelWidth * 0.05)
|> close()
|> revolve(axis = Y)
|> revolve(axis = 'y')
|> appearance(color = "#ffffff", metalness = 0, roughness = 0)

View File

@ -1,9 +1,9 @@
// Car wheel assembly parameters
// Car wheel assembly global constants
// Set units
@settings(defaultLengthUnit = in)
// Car wheel
// Car Wheel
export lugCount = 5
export lugSpacing = 114.3 * mm()
export offset = -35 * mm()
@ -22,7 +22,7 @@ export lugThreadDiameter = lugDiameter / 2 * .85
export lugLength = 30 * mm()
export lugThreadDepth = lugLength - (12.7 * mm())
// Car rotor
// Car Rotor
export rotorDiameter = 12
export rotorInnerDiameter = 6
export rotorSinglePlateThickness = 0.25
@ -36,7 +36,7 @@ export spacerCount = 16
export yAxisOffset = 0.5
export drillAndSlotCount = 5
// Car tire
// Car Tire
export tireInnerDiameter = 19
export tireOuterDiameter = 24
export tireDepth = 11.02
@ -45,7 +45,7 @@ export tireTreadWidth = 0.39
export tireTreadDepth = 0.39
export tireTreadOffset = 3.15
// Brake caliper
// Brake Caliper
export caliperTolerance = 0.050
export caliperPadLength = 1.6
export caliperThickness = 0.39

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parameters
import lugDiameter, lugHeadLength, lugThreadDiameter, lugLength, lugThreadDepth, lugSpacing from "parameters.kcl"
// Import Constants
import lugDiameter, lugHeadLength, lugThreadDiameter, lugLength, lugThreadDepth, lugSpacing from "globals.kcl"
customPlane = {
plane = {
@ -32,7 +32,7 @@ fn lug(plane, length, diameter) {
|> xLine(endAbsolute = lugThreadDiameter)
|> yLine(endAbsolute = 0)
|> close()
|> revolve(axis = Y)
|> revolve(axis = "Y")
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
return lugSketch
}

View File

@ -4,24 +4,16 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parts
import "car-wheel.kcl" as carWheel
import "car-rotor.kcl" as carRotor
import "brake-caliper.kcl" as brakeCaliper
import "lug-nut.kcl" as lugNut
import "car-tire.kcl" as carTire
import lugCount from "globals.kcl"
// Import parameters
import * from "parameters.kcl"
// Place the car rotor
carRotor
|> translate(x = 0, y = 0.5, z = 0)
// Place the car wheel
carWheel
// Place the lug nuts
lugNut
|> patternCircular3d(
arcDegrees = 360,
@ -30,10 +22,6 @@ lugNut
instances = lugCount,
rotateDuplicates = false,
)
// Place the brake caliper
brakeCaliper
|> translate(x = 0, y = 0.5, z = 0)
// Place the car tire
carTire

View File

@ -1,10 +1,10 @@
// Color Cube
// This is a color cube centered about the origin. It is used to help determine orientation in the scene.
// Set units
// Set unit
@settings(defaultLengthUnit = mm)
// Parameters referenced in drawRectangle
// Globals referenced in drawRectangle
size = 100
halfSize = size / 2
extrudeLength = 1.0

View File

@ -1,10 +1,9 @@
// Cycloidal Gear
// A cycloidal gear is a gear with a continuous, curved tooth profile. They are used in watchmaking and high precision robotics actuation
// Set units
// Set Units
@settings(defaultLengthUnit = in)
// Create a function for the cycloidal gear
fn cycloidalGear(gearPitch, gearHeight, holeDiameter, helixAngle) {
// Create a function to draw the gear profile as a sketch. Rotate each profile about the gear's axis by an helix angle proportional to the total gear height
fn gearSketch(gHeight) {
@ -45,5 +44,4 @@ fn cycloidalGear(gearPitch, gearHeight, holeDiameter, helixAngle) {
return gearLoft
}
// Call the cycloidal gear function
cycloidalGear(.3, 1.5, 0.297, -80)

View File

@ -9,19 +9,19 @@
circR = 25
// Calculated parameters
// Thickness of the dodecahedron
// thickness of the dodecahedron
wallThickness = circR * 0.2
// Angle between faces in radians
// angle between faces in radians
dihedral = acos(-(sqrt(5) / 5))
// Inscribed radius
// inscribed radius
inscR = circR / 15 * sqrt(75 + 30 * sqrt(5))
// Pentagon edge length
// pentagon edge length
edgeL = 4 * circR / (sqrt(3) * (1 + sqrt(5)))
// Pentagon radius
// pentagon radius
pentR = edgeL / 2 / sin(toRadians(36))
// Define a plane for the bottom angled face
@ -69,7 +69,7 @@ bottomBowl = patternCircular3d(
rotateDuplicates = true,
)
// Pattern the bottom to create the top face
// pattern the bottom to create the top face
patternCircular3d(
bottom,
instances = 2,
@ -79,7 +79,7 @@ patternCircular3d(
rotateDuplicates = true,
)
// Pattern the bottom angled faces to create the top
// pattern the bottom angled faces to create the top
patternCircular3d(
bottomBowl,
instances = 2,

View File

@ -1,10 +1,10 @@
// Dual-Basin Utility Sink
// A stainless steel sink unit with dual rectangular basins and six under-counter storage compartments.
// Set units
// set units
@settings(defaultLengthUnit = mm)
// Define parameters
// globals
tableHeight = 850
tableWidth = 3400
tableDepth = 400

View File

@ -4,7 +4,6 @@
// Set units
@settings(defaultLengthUnit = mm)
// Define parameters
length = 175
width = 125
height = 70

View File

@ -1,10 +1,10 @@
// Exhaust Manifold
// A welded exhaust header for an inline 4-cylinder engine
// Set units
// Set Units
@settings(defaultLengthUnit = in)
// Define parameters
// Define Constants
primaryTubeDiameter = 1.625
wallThickness = 0.080
plateHeight = 0.125

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define parameters
// Define constants
mountingHoleDia = .625
baseDia = 4.625
pipeDia = 1.25

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = mm)
// define parameters
// define constants in mm
radius = 6.0
width = 144.0
length = 80.0
@ -15,7 +15,7 @@ tabLength = 25
tabWidth = 12
tabThk = 4
// Define a rectangular shape func
// define a rectangular shape func
fn rectShape(pos, w, l) {
rr = startSketchOn('xy')
|> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
@ -26,7 +26,7 @@ fn rectShape(pos, w, l) {
return rr
}
// Define the bracket plane
// define the bracket plane
bracketPlane = {
plane = {
origin = { x = 0, y = length / 2 + thk, z = 0 },
@ -36,7 +36,7 @@ bracketPlane = {
}
}
// Build the bracket sketch around the body
// build the bracket sketch around the body
fn bracketSketch(w, d, t) {
s = startSketchOn(bracketPlane)
|> startProfileAt([-w / 2 - t, d + t], %)
@ -51,7 +51,7 @@ fn bracketSketch(w, d, t) {
return s
}
// Build the body of the bracket
// build the body of the bracket
bs = bracketSketch(width, depth, thk)
bracketBody = bs
|> extrude(length = length + 2 * thk)
@ -65,7 +65,7 @@ bracketBody = bs
],
)
// Define the tab plane
// define the tab plane
tabPlane = {
plane = {
origin = { x = 0, y = 0, z = depth + thk },
@ -75,7 +75,7 @@ tabPlane = {
}
}
// Build the tabs of the mounting bracket (right side)
// build the tabs of the mounting bracket (right side)
tabsR = startSketchOn(tabPlane)
|> startProfileAt([width / 2 + thk, length / 2 + thk], %)
|> line(end = [tabWidth, -tabLength / 3], tag = $edge11)
@ -99,7 +99,7 @@ tabsR = startSketchOn(tabPlane)
)
|> patternLinear3d(axis = [0, -1, 0], instances = 2, distance = length + 2 * thk - (tabLength * 4 / 3))
// Build the tabs of the mounting bracket (left side)
// build the tabs of the mounting bracket (left side)
tabsL = startSketchOn(tabPlane)
|> startProfileAt([-width / 2 - thk, length / 2 + thk], %)
|> line(end = [-tabWidth, -tabLength / 3], tag = $edge21)
@ -123,7 +123,7 @@ tabsL = startSketchOn(tabPlane)
)
|> patternLinear3d(axis = [0, -1, 0], instances = 2, distance = length + 2 * thk - (tabLength * 4 / 3))
// Define a plane for retention bumps
// define a plane for retention bumps
retPlane = {
plane = {
origin = { x = -width / 2 + 20, y = 0, z = 0 },
@ -133,7 +133,7 @@ retPlane = {
}
}
// Build the retention bump in the front
// build the retention bump in the front
retFront = startSketchOn(retPlane)
|> startProfileAt([-length / 2 - thk, 0], %)
|> line(end = [0, thk])
@ -141,7 +141,7 @@ retFront = startSketchOn(retPlane)
|> close()
|> extrude(length = width - 40)
// Build the retention bump in the back
// build the retention bump in the back
retBack = startSketchOn(retPlane)
|> startProfileAt([length / 2 + thk, 0], %)
|> line(end = [0, thk])

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = mm)
// Define parameters
// Define constants in millimeters (mm)
flipperThickness = 3.5
flipperLength = 70.0
handleWidth = 15.0
@ -16,7 +16,7 @@ gripHeight = 20.0
gripFilletRadius = 3.0
gripSlotWidth = 8.0
// Function for drawing slots on a sketch given the start and end points as well as a width
// function for drawing slots on a sketch given the start and end points as well as a width
fn slot(sketch1, start, end, width) {
angle = if start[0] == end[0] {
if end[1] > start[1] {
@ -43,10 +43,10 @@ fn slot(sketch1, start, end, width) {
return slotSketch
}
// Create a sketch on the "XY" plane
// create a sketch on the "XY" plane
sketch000 = startSketchOn(XY)
// Create a profile of the flipper
// create a profile of the flipper
flipperProfile = startProfileAt([-flipperLength, -32.0], sketch000)
|> line(end = [flipperLength, 2.0])
|> yLine(length = 60.0, tag = $backEdge)
@ -58,25 +58,25 @@ flipperProfile = startProfileAt([-flipperLength, -32.0], sketch000)
}, %)
|> close()
// Create a profile of the middle
// create a profile of the middle
slotProfile000 = slot(sketch000, [-25, 0], [-55, 0], flipperSlotWidth)
// Create a profile of the top slot
// create a profile of the top slot
slotProfile001 = slot(sketch000, [-25, 18], [-55, 19], flipperSlotWidth)
// Create a profile of the bottom slot
// create a profile of the bottom slot
slotProfile002 = slot(sketch000, [-25, -18], [-55, -19], flipperSlotWidth)
// Create a profile with slots for the spatula
// create a profile with slots for the spatula
spatulaProfile = flipperProfile
|> hole(slotProfile000, %)
|> hole(slotProfile001, %)
|> hole(slotProfile002, %)
// Extrude the profile to create the spatula flipper
// extrude the profile to create the spatula flipper
flipper = extrude(spatulaProfile, length = flipperThickness)
// Fillet the edges of the flipper
// fillet the edges of the flipper
fillet(
flipper,
radius = flipperFilletRadius,
@ -86,10 +86,10 @@ fillet(
],
)
// Create a sketch on the "XZ" plane offset by half the thickness
// create a sketch on the "XZ" plane offset by half the thickness
sketch001 = startSketchOn(offsetPlane(XZ, offset = -handleWidth / 2))
// Create a profile of the spatula handle
// create a profile of the spatula handle
handleProfile = startProfileAt([0.0, flipperThickness], sketch001)
|> line(end = [31.819805, 31.819805], tag = $handleBottomEdge)
|> line(end = [140.953893, 51.303021])
@ -99,10 +99,10 @@ handleProfile = startProfileAt([0.0, flipperThickness], sketch001)
|> xLine(length = 7.071068)
|> close()
// Create an extrusion extrude001
// create an extrusion extrude001
handle = extrude(handleProfile, length = handleWidth)
// Fillet the bend of the spatula handle
// fillet the bend of the spatula handle
fillet(
handle,
radius = 4,
@ -112,7 +112,7 @@ fillet(
],
)
// Define a plane which is at the end of the handle
// define a plane which is at the end of the handle
handlePlane = {
plane = {
origin = [208.593833, 0.0, 75.921946],
@ -122,10 +122,10 @@ handlePlane = {
}
}
// Create a sketch on the handle plane
// create a sketch on the handle plane
sketch002 = startSketchOn(handlePlane)
// Create a profile of the grip
// create a profile of the grip
gripProfile = startProfileAt([-26.806746, -10.0], sketch002)
|> xLine(length = gripWidth - (2 * gripFilletRadius))
|> arc({
@ -153,14 +153,14 @@ gripProfile = startProfileAt([-26.806746, -10.0], sketch002)
}, %)
|> close()
// Extrude the grip profile to create the grip
// extrude the grip profile to create the grip
grip = extrude(gripProfile, length = -gripLength)
// Create a sketch on the grip for the hole
// create a sketch on the grip for the hole
sketch003 = startSketchOn(grip, gripEdgeTop)
// Create a profile for the grip hole
// create a profile for the grip hole
gripHoleProfile = slot(sketch003, [0, 200], [0, 210], gripSlotWidth)
// Cut a hole in the grip
// cut a hole in the grip
extrude(gripHoleProfile, length = -gripWidth - 20)

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define parameters
// Define constants
carafeDiameter = 4.41
carafeHeight = 7.32
handleThickness = 0.65
@ -23,7 +23,7 @@ sketch001 = startSketchOn(XZ)
], %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(angle = 360, axis = Y)
|> revolve(angle = 360, axis = 'Y')
// Create an angled plane to sketch the supports
plane001 = {
@ -132,7 +132,7 @@ sketch005 = startSketchOn(XZ)
|> xLine(endAbsolute = 0.15)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(axis = Y)
|> revolve(axis = 'y')
// Plunger and stem
sketch006 = startSketchOn(XZ)
@ -145,7 +145,7 @@ sketch006 = startSketchOn(XZ)
|> tangentialArc({ radius = 0.6, offset = -90 }, %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(axis = Y)
|> revolve(axis = 'y')
// Spiral plate
sketch007 = startSketchOn(offsetPlane(XY, offset = 1.12))
@ -201,7 +201,7 @@ sketch011 = startSketchOn(XZ)
}, %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> revolve(axis = Y)
|> revolve(axis = 'y')
// Draw and extrude handle
sketch012 = startSketchOn(offsetPlane(XZ, offset = handleThickness / 2))

View File

@ -1,10 +1,10 @@
// 100mm Gear Rack
// A flat bar or rail that is engraved with teeth along its length. These teeth are designed to mesh with the teeth of a gear, known as a pinion. When the pinion, a small cylindrical gear, rotates, its teeth engage with the teeth on the rack, causing the rack to move linearly. Conversely, linear motion applied to the rack will cause the pinion to rotate.
// Set units
// Set Units
@settings(defaultLengthUnit = mm)
// Define parameters
// Define constants
length = 100
pitchHeight = 11.5
width = 5

View File

@ -1,10 +1,10 @@
// Spur Gear
// A rotating machine part having cut teeth or, in the case of a cogwheel, inserted teeth (called cogs), which mesh with another toothed part to transmit torque. Geared devices can change the speed, torque, and direction of a power source. The two elements that define a gear are its circular shape and the teeth that are integrated into its outer edge, which are designed to fit into the teeth of another gear.
// Set units
// Set Units
@settings(defaultLengthUnit = in)
// Define parameters
// Define constants
nTeeth = 21
module = 0.5
pitchDiameter = module * nTeeth

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define parameters
// Define constants
binLength = 42.0
cornerRadius = 4.0
firstStep = 0.7
@ -21,7 +21,7 @@ countBinLength = 3
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
height = firstStep + secondStep + thirdStep
// Define a function which builds the profile of the baseplate bin
// define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -33,10 +33,10 @@ fn face(plane) {
return faceSketch
}
// Extrude a single side of the bin
// extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius)), length = binLength - (cornerRadius * 2))
// Create the other sides of the bin by using a circular pattern
// create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -46,16 +46,18 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// Define an axis axis000
// define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
custom = {
axis = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
}
}
// Create a single corner of the bin
// create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius)), angle = -90, axis = axis000)
// Create the corners of the bin
// create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -65,7 +67,7 @@ corners = patternCircular3d(
rotateDuplicates = true,
)
// Create the baseplate by patterning sides
// create the baseplate by patterning sides
basePlateSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -74,7 +76,7 @@ basePlateSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// Create the corners of the baseplate by patterning the corners
// create the corners of the baseplate by patterning the corners
basePlateCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],
@ -83,7 +85,7 @@ basePlateCorners = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// Create the center cutout for the magnet profile
// create the center cutout for the magnet profile
fn magnetCenterCutout(plane) {
magnetSketch = startSketchOn(plane)
|> startProfileAt([
@ -126,7 +128,7 @@ fn magnetCenterCutout(plane) {
return magnetSketch
}
// Create the outside profile of the magnets
// create the outside profile of the magnets
fn magnetBase(plane) {
magnetBaseSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -138,7 +140,7 @@ fn magnetBase(plane) {
return magnetBaseSketch
}
// Create sketch profile sketch000Profile002
// create sketch profile sketch000Profile002
magnetsSketch = startSketchOn(XY)
|> circle(center = [cornerRadius * 2, cornerRadius * 2], radius = magOuterDiam / 2)
|> patternCircular2d(
@ -148,14 +150,14 @@ magnetsSketch = startSketchOn(XY)
rotateDuplicates = true,
)
// Create a profile with holes for the magnets
// create a profile with holes for the magnets
magnetProfile = magnetBase(XY)
|> hole(magnetsSketch, %)
// Create an extrusion of the magnet cutout with holes
// create an extrusion of the magnet cutout with holes
magnetHolesExtrude = extrude(magnetProfile, length = -magDepth)
// Add a fillet to the extrusion
// add a fillet to the extrusion
magnetHolesExtrudeFillets = fillet(
magnetHolesExtrude,
radius = cornerRadius,
@ -167,13 +169,13 @@ magnetHolesExtrudeFillets = fillet(
],
)
// Create a profile without the holes for the magnets
// create a profile without the holes for the magnets
magnetProfileNoMagnets = magnetBase(offsetPlane(XY, offset = -magDepth))
// Create an extrusion of the magnet cutout without holes
// create an extrusion of the magnet cutout without holes
magnetCutoutExtrude = extrude(magnetProfileNoMagnets, length = -magDepth)
// Add a fillet to the extrusion
// add a fillet to the extrusion
magnetCutoutExtrudeFillets = fillet(
magnetCutoutExtrude,
radius = cornerRadius,
@ -185,7 +187,7 @@ magnetCutoutExtrudeFillets = fillet(
],
)
// Pattern the magnet cutouts with holes
// pattern the magnet cutouts with holes
patternLinear3d(
magnetHolesExtrudeFillets,
axis = [1.0, 0.0, 0.0],
@ -194,7 +196,7 @@ patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// Pattern the magnet cutouts without holes
// pattern the magnet cutouts without holes
patternLinear3d(
magnetCutoutExtrudeFillets,
axis = [1.0, 0.0, 0.0],

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define parameters
// Define constants
binLength = 42.0
cornerRadius = 4.0
firstStep = 0.7
@ -18,7 +18,7 @@ countBinLength = 3
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
height = firstStep + secondStep + thirdStep
// Define a function which builds the profile of the baseplate bin
// define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -30,10 +30,10 @@ fn face(plane) {
return faceSketch
}
// Extrude a single side of the bin
// extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius)), length = binLength - (cornerRadius * 2))
// Create the other sides of the bin by using a circular pattern
// create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -43,16 +43,18 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// Define an axis axis000
// define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
custom = {
axis = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
}
}
// Create a single corner of the bin
// create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius)), angle = -90, axis = axis000)
// Create the corners of the bin
// create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -62,7 +64,7 @@ corners = patternCircular3d(
rotateDuplicates = true,
)
// Create the baseplate by patterning sides
// create the baseplate by patterning sides
basePlateSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -71,7 +73,7 @@ basePlateSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// Create the corners of the baseplate by patterning the corners
// create the corners of the baseplate by patterning the corners
basePlateCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define parameters
// Define constants
binLength = 41.5
binHeight = 7.0
binBaseLength = 2.95
@ -33,7 +33,7 @@ countBinHeight = 1
height = firstStep + secondStep + thirdStep
lipHeight = lipStep1 + lipStep2 + lipStep3 + lipStep4 + lipStep5
// Define a function which builds the profile of the baseplate bin
// define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([binBaseLength + binTol, 0], %)
@ -46,10 +46,10 @@ fn face(plane) {
return faceSketch
}
// Extrude a single side of the bin
// extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius + binTol)), length = binLength - (cornerRadius * 2))
// Create the other sides of the bin by using a circular pattern
// create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -63,19 +63,21 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// Define an axis axis000
// define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [
cornerRadius + binTol,
cornerRadius + binTol
]
custom = {
axis = [0.0, 1.0],
origin = [
cornerRadius + binTol,
cornerRadius + binTol
]
}
}
// Create a single corner of the bin
// create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius + binTol)), angle = -90, axis = axis000)
// Create the corners of the bin
// create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -128,7 +130,7 @@ magCutout000 = startSketchOn(singleBinFill, "start")
)
|> extrude(length = -magDepth)
// Create the baseplate by patterning sides
// create the baseplate by patterning sides
binSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -137,7 +139,7 @@ binSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// Create the corners of the baseplate by patterning the corners
// create the corners of the baseplate by patterning the corners
binCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],
@ -146,7 +148,7 @@ binCorners = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// Create the fill of the bin by patterning the corners
// create the fill of the bin by patterning the corners
binFill = patternLinear3d(
singleBinFill,
axis = [1.0, 0.0, 0.0],
@ -155,6 +157,7 @@ binFill = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
//
binTop = startSketchOn(offsetPlane(XY, offset = height))
|> startProfileAt([0, 0], %)
|> xLine(length = (binLength + 2 * binTol) * countBinWidth, tag = $line010)
@ -173,7 +176,7 @@ binTop = startSketchOn(offsetPlane(XY, offset = height))
)
|> shell(faces = ["end"], thickness = binThk)
// Define a function which builds the profile of the baseplate bin
// define a function which builds the profile of the baseplate bin
fn lipFace(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -233,13 +236,13 @@ plane002 = {
}
}
// Extrude a single side of the lip of the bin
// extrude a single side of the lip of the bin
lipSingleLength = extrude(lipFace(plane000), length = binLength * countBinWidth - (2 * cornerRadius) + 2 * binTol * countBinWidth)
// Extrude a single side of the lip of the bin
// extrude a single side of the lip of the bin
lipSingleWidth = extrude(lipFace(plane001), length = binLength * countBinLength - (2 * cornerRadius) + 2 * binTol * countBinLength)
// Create the other sides of the lips by using a circular pattern
// create the other sides of the lips by using a circular pattern
lipLengths = patternCircular3d(
lipSingleLength,
arcDegrees = 360,
@ -253,7 +256,7 @@ lipLengths = patternCircular3d(
rotateDuplicates = true,
)
// Create the other sides of the lips by using a circular pattern
// create the other sides of the lips by using a circular pattern
lipWidths = patternCircular3d(
lipSingleWidth,
arcDegrees = 360,
@ -267,19 +270,21 @@ lipWidths = patternCircular3d(
rotateDuplicates = true,
)
// Define an axis axis000
// define an axis axis000
axis001 = {
direction = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
custom = {
axis = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
}
}
// Create a single corner of the bin
// create a single corner of the bin
lipSingleLengthCorner = revolve(lipFace(plane000), angle = -90, axis = axis001)
// Create a single corner of the bin
// create a single corner of the bin
lipSingleWidthCorner = revolve(lipFace(plane002), angle = 90, axis = axis001)
// Create the corners of the bin
// create the corners of the bin
lipCorners000 = patternCircular3d(
lipSingleLengthCorner,
arcDegrees = 360,
@ -293,7 +298,7 @@ lipCorners000 = patternCircular3d(
rotateDuplicates = true,
)
// Create the corners of the bin
// create the corners of the bin
lipCorners001 = patternCircular3d(
lipSingleWidthCorner,
arcDegrees = 360,

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define parameters
// Define constants
binLength = 41.5
binHeight = 7.0
binBaseLength = 2.95
@ -26,7 +26,7 @@ countBinHeight = 2
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
height = firstStep + secondStep + thirdStep
// Define a function which builds the profile of the baseplate bin
// define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([binBaseLength + binTol, 0], %)
@ -39,10 +39,10 @@ fn face(plane) {
return faceSketch
}
// Extrude a single side of the bin
// extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius + binTol)), length = binLength - (cornerRadius * 2))
// Create the other sides of the bin by using a circular pattern
// create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -56,19 +56,21 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// Define an axis axis000
// define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [
cornerRadius + binTol,
cornerRadius + binTol
]
custom = {
axis = [0.0, 1.0],
origin = [
cornerRadius + binTol,
cornerRadius + binTol
]
}
}
// Create a single corner of the bin
// create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius + binTol)), angle = -90, axis = axis000)
// Create the corners of the bin
// create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -121,7 +123,7 @@ magCutout000 = startSketchOn(singleBinFill, "start")
)
|> extrude(length = -magDepth)
// Create the baseplate by patterning sides
// create the baseplate by patterning sides
binSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -130,7 +132,7 @@ binSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// Create the corners of the baseplate by patterning the corners
// create the corners of the baseplate by patterning the corners
binCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],
@ -139,7 +141,7 @@ binCorners = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// Create the fill of the bin by patterning the corners
// create the fill of the bin by patterning the corners
binFill = patternLinear3d(
singleBinFill,
axis = [1.0, 0.0, 0.0],
@ -148,7 +150,7 @@ binFill = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// Create the top of the bin
// create the top of the bin
binTop = startSketchOn(offsetPlane(XY, offset = height))
|> startProfileAt([0, 0], %)
|> xLine(length = (binLength + 2 * binTol) * countBinWidth, tag = $line010)

View File

@ -1,10 +1,10 @@
// Hex Nut
// Hex nut
// A hex nut is a type of fastener with a threaded hole and a hexagonal outer shape, used in a wide variety of applications to secure parts together. The hexagonal shape allows for a greater torque to be applied with wrenches or tools, making it one of the most common nut types in hardware.
// Set Units
@settings(defaultLengthUnit = in)
// Define parameters (5/16" - 24 thread size)
// Define constants (5/16" - 24 thread size)
wallToWallLength = 0.5
thickness = 0.266
diameter = 0.3125

View File

@ -1,10 +1,10 @@
// I-beam
// A structural metal beam with an I shaped cross section. Often used in construction and architecture
// Set units
// Set Units
@settings(defaultLengthUnit = in)
// Define parameters
// Define Beam Dimensions
beamLength = 6 * ft()
beamHeight = 4
flangeWidth = 2.663
@ -13,13 +13,13 @@ webThickness = 0.193
rootRadius = 0.457
// Sketch a quadrant of the beam cross section, then mirror for symmetry across each axis. Extrude to the appropriate length
iBeam = startSketchOn(-XZ)
sketch001 = startSketchOn(-XZ)
|> startProfileAt([0, beamHeight / 2], %)
|> xLine(length = flangeWidth / 2)
|> yLine(length = -flangeThickness)
|> xLine(endAbsolute = webThickness / 2 + rootRadius)
|> tangentialArc({ radius = rootRadius, offset = 90 }, %)
|> yLine(endAbsolute = 0)
|> mirror2d(axis = X)
|> mirror2d(axis = Y)
|> mirror2d({ axis = 'X' }, %)
|> mirror2d({ axis = 'Y' }, %)
|> extrude(length = beamLength)

View File

@ -1,10 +1,10 @@
// Zoo Keyboard
// A custom keyboard with Zoo brand lettering
// Set units
// Set Units
@settings(defaultLengthUnit = in)
// Define parameters
// Define constants
baseColor = "#0f0f0f"
highlightColor1 = "#b0b0b0"
highlightColor2 = "#23af93"

View File

@ -1,7 +1,7 @@
// Kitt
// The beloved KittyCAD mascot in a voxelized style.
// Pixel box function
// pixel box function
fn pixelBox(kitExtrude, extrudeTag, positionY, positionZ, width, height, depth) {
pixelBoxBody = startSketchOn(kitExtrude, extrudeTag)
|> startProfileAt([positionY, positionZ], %)

View File

@ -4,8 +4,8 @@
// Set Units
@settings(defaultLengthUnit = in)
// Define parameters
lbumps = 3 // number of bumps long
// Define constants
lbumps = 4 // number of bumps long
wbumps = 2 // number of bumps wide
pitch = 8.0
clearance = 0.1

View File

@ -1,19 +1,19 @@
// Makeup Mirror
// A circular vanity mirror mounted on a swiveling arm with pivot joints, used for personal grooming.
// Set units
// Settings
@settings(defaultLengthUnit = mm)
// Hinge parameters
// hinge
hingeRadius = 8
hingeHeight = hingeRadius * 3
hingeGap = 0.5
// Arm parameters
// arm
armLength = 170
armRadius = 5
// Mirror parameters
// mirror
mirrorRadius = 170 / 2
mirrorThickness = 10
archToMirrorGap = 5
@ -21,7 +21,7 @@ archThickness = 1
archRadius = mirrorRadius + archToMirrorGap
// Geometry
// Add a function to create the hinge
// hinge
fn hingeFn(x, y, z) {
hingeBody = startSketchOn(offsetPlane(XY, offset = z))
|> circle(center = [x, y], radius = hingeRadius)
@ -39,7 +39,7 @@ hingePartB3 = hingeFn(armLength, 0, hingeHeight * 2 + hingeGap * 2)
hingePartC2 = hingeFn(armLength, -armLength, hingeHeight * 2 + hingeGap * 2)
hingePartC3 = hingeFn(armLength, -armLength, hingeHeight * 3 + hingeGap * 3)
// Add a function to create the arm
// arm
fn armFn(plane, offset, altitude) {
armBody = startSketchOn(plane)
|> circle(center = [offset, altitude], radius = armRadius)
@ -50,7 +50,7 @@ fn armFn(plane, offset, altitude) {
armPartA = armFn(YZ, 0, hingeHeight * 1.5 + hingeGap)
armPartB = armFn(XZ, armLength, hingeHeight * 2.5 + hingeGap * 2)
// Add a function to create the mirror
// mirror
fn mirrorFn(plane, offsetX, offsetY, altitude, radius, tiefe, gestellR, gestellD) {
armPlane = startSketchOn( offsetPlane(plane, offset = offsetY - (tiefe / 2)))
armBody = circle(armPlane, center = [offsetX, altitude], radius = radius)

View File

@ -6,6 +6,13 @@
"title": "80/20 Rail",
"description": "An 80/20 extruded aluminum linear rail. T-slot profile adjustable by profile height, rail length, and origin position"
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "a-parametric-bearing-pillow-block/main.kcl",
"multipleFiles": false,
"title": "A Parametric Bearing Pillow Block",
"description": "A bearing pillow block, also known as a plummer block or pillow block bearing, is a pedestal used to provide support for a rotating shaft with the help of compatible bearings and various accessories. Housing a bearing, the pillow block provides a secure and stable foundation that allows the shaft to rotate smoothly within its machinery setup. These components are essential in a wide range of mechanical systems and machinery, playing a key role in reducing friction and supporting radial and axial loads."
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "ball-bearing/main.kcl",
@ -150,7 +157,7 @@
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "hex-nut/main.kcl",
"multipleFiles": false,
"title": "Hex Nut",
"title": "Hex nut",
"description": "A hex nut is a type of fastener with a threaded hole and a hexagonal outer shape, used in a wide variety of applications to secure parts together. The hexagonal shape allows for a greater torque to be applied with wrenches or tools, making it one of the most common nut types in hardware."
},
{
@ -202,19 +209,12 @@
"title": "Robot Arm",
"description": "A 4 axis robotic arm for industrial use. These machines can be used for assembly, packaging, organization of goods, and quality inspection processes"
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "parametric-bearing-pillow-block/main.kcl",
"multipleFiles": false,
"title": "Parametric Bearing Pillow Block",
"description": "A bearing pillow block, also known as a plummer block or pillow block bearing, is a pedestal used to provide support for a rotating shaft with the help of compatible bearings and various accessories. Housing a bearing, the pillow block provides a secure and stable foundation that allows the shaft to rotate smoothly within its machinery setup. These components are essential in a wide range of mechanical systems and machinery, playing a key role in reducing friction and supporting radial and axial loads."
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "pipe/main.kcl",
"multipleFiles": false,
"title": "Pipe",
"description": "Piping for the pipe flange assembly"
"description": "A tubular section or hollow cylinder, usually but not necessarily of circular cross-section, used mainly to convey substances that can flow."
},
{
"file": "main.kcl",
@ -248,7 +248,7 @@
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "router-template-slate/main.kcl",
"multipleFiles": false,
"title": "Router Template for a Slate",
"title": "Router template for a slate",
"description": "A guide for routing a slate for a cross bar."
},
{

View File

@ -1,10 +1,10 @@
// Mounting Plate
// A flat piece of material, often metal or plastic, that serves as a support or base for attaching, securing, or mounting various types of equipment, devices, or components.
// Set units
// Set Units
@settings(defaultLengthUnit = in)
// Define parameters
// Define constants
plateLength = 10
plateWidth = 6
filletRadius = 0.5

View File

@ -4,7 +4,6 @@
// Set Units
@settings(defaultLengthUnit = in)
// Import parts
import "robot-arm-base.kcl" as robotArmBase
import "robot-rotating-base.kcl" as rotatingBase
import "robot-arm-j2.kcl" as j2RobotArm

View File

@ -1,23 +1,25 @@
// Pipe
// Piping for the pipe flange assembly
// piping for the pipe flange assembly
// Set units
// set units
@settings(defaultLengthUnit = in)
// Import parameters
import pipeInnerDiameter, pipeOuterDiameter, pipeLength from "parameters.kcl"
// import constants
import pipeInnerDiameter, pipeOuterDiameter, pipeLength from "globals.kcl"
// Create a function to make the pipe. Export
// create a function to make the pipe
export fn pipe() {
// Create the pipe base
// create the pipe base
pipeBase = startSketchOn(XZ)
|> circle(%, center = [0, 0], radius = pipeOuterDiameter / 2)
|> extrude(%, length = pipeLength)
// Extrude a hole through the length of the pipe
// extrude a hole through the length of the pipe
pipe = startSketchOn(pipeBase, 'end')
|> circle(center = [0, 0], radius = pipeInnerDiameter / 2)
|> extrude(%, length = -pipeLength)
|> appearance(color = "#a24ed0")
return pipe
}
// https://www.mcmaster.com/1120T74/

View File

@ -1,15 +1,15 @@
// Flange
// Flange used for mating two pipes together in the pipe flange assembly.
// 68095k348 flange
// flange used for mating two pipes together in the pipe flange assembly.
// Set units
// set units
@settings(defaultLengthUnit = in)
// Import parameters
import pipeDiameter, mountingHoleDiameter, mountingHolePlacementDiameter, flangeDiameter, flangeTotalThickness, flangeBackHeight, flangeFrontHeight, flangeBaseThickness, flangeBackDiameter, flangeFrontDiameter from "parameters.kcl"
// import constants
import pipeDiameter, mountingHoleDiameter, mountingHolePlacementDiameter, flangeDiameter, flangeTotalThickness, flangeBackHeight, flangeFrontHeight, flangeBaseThickness, flangeBackDiameter, flangeFrontDiameter from "globals.kcl"
// Create a function to create the flange. We must create a function since we are using multiple flanges.
// create a function to create the flange
export fn flange() {
// Sketch the mounting hole pattern
// sketch the mounting hole pattern
mountingHoles = startSketchOn(XY)
|> circle(%, center = [0, mountingHolePlacementDiameter / 2], radius = mountingHoleDiameter / 2)
|> patternCircular2d(
@ -20,13 +20,13 @@ export fn flange() {
rotateDuplicates = false,
)
// Create the flange base
// create the flange base
flangeBase = startSketchOn(XY)
|> circle(%, center = [0, 0], radius = flangeDiameter / 2)
|> hole(mountingHoles, %)
|> extrude(%, length = flangeBaseThickness)
// Create both the raised portions on the front and back of the flange base
// create both the raised portions on the front and back of the flange base
flangeBack = startSketchOn(flangeBase, 'start')
|> circle(%, center = [0, 0], radius = flangeBackDiameter / 2)
|> extrude(%, length = flangeBackHeight)
@ -34,7 +34,7 @@ export fn flange() {
|> circle(%, center = [0, 0], radius = flangeFrontDiameter / 2)
|> extrude(%, length = flangeFrontHeight)
// Create the circular cut in the center for the pipe
// create the circular cut in the center for the pipe
pipeCut = startSketchOn(flangeFront, 'end')
|> circle(%, center = [0, 0], radius = pipeDiameter / 2)
|> extrude(%, length = -flangeTotalThickness)
@ -42,3 +42,5 @@ export fn flange() {
return pipeCut
}
// https://www.mcmaster.com/68095K348/

View File

@ -1,13 +1,13 @@
// Socket Head Cap Screw
// 91251A404 Socket Head Cap Screw
// screw for mating the flanges together in the pipe flange assembly
// Set units
// set units
@settings(defaultLengthUnit = in)
// Import parameters
import boltDiameter, boltLength, boltHeadLength, boltHeadDiameter, boltHexDrive, boltHexFlatLength, boltThreadLength from "parameters.kcl"
// import constants
import boltDiameter, boltLength, boltHeadLength, boltHeadDiameter, boltHexDrive, boltHexFlatLength, boltThreadLength from "globals.kcl"
// Create a function to make a the bolt
// create a function to make a the bolt
export fn bolt() {
// Create the head of the cap screw
boltHead = startSketchOn(XZ)
@ -52,3 +52,5 @@ export fn bolt() {
return boltBody
}
// https://www.mcmaster.com/91251a404/

Some files were not shown because too many files have changed in this diff Show More