Compare commits
1 Commits
kcl-60
...
franknoiro
| Author | SHA1 | Date | |
|---|---|---|---|
| a1a4fb9481 |
2
.github/workflows/build-apps.yml
vendored
2
.github/workflows/build-apps.yml
vendored
@ -378,7 +378,7 @@ jobs:
|
||||
NOTES: ${{ needs.prepare-files.outputs.notes }}
|
||||
PUB_DATE: ${{ github.event.repository.updated_at }}
|
||||
WEBSITE_DIR: ${{ env.IS_NIGHTLY == 'true' && 'dl.zoo.dev/releases/modeling-app/nightly' || 'dl.zoo.dev/releases/modeling-app' }}
|
||||
URL_CODED_NAME: ${{ env.IS_NIGHTLY == 'true' && 'Zoo%20Design%20Studio%20%28Nightly%29' || 'Zoo%20Design%20Studio' }}
|
||||
URL_CODED_NAME: ${{ env.IS_NIGHTLY == 'true' && 'Zoo%20Modeling%20App%20%28Nightly%29' || 'Zoo%20Modeling%20App' }}
|
||||
run: |
|
||||
RELEASE_DIR=https://${WEBSITE_DIR}
|
||||
jq --null-input \
|
||||
|
||||
55
.github/workflows/nix.yml
vendored
55
.github/workflows/nix.yml
vendored
@ -1,55 +0,0 @@
|
||||
name: Test Nix Flake
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
nix-flake-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
|
||||
- name: nix flake check for all platforms
|
||||
run: |
|
||||
nix flake check --all-systems
|
||||
|
||||
nix-build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
|
||||
- name: nix build . for x86_64-linux
|
||||
run: nix build .
|
||||
|
||||
nix-build-macos:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
|
||||
- name: nix build . for x86_64-darwin
|
||||
run: nix build .
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -26,7 +26,6 @@ yarn-error.log*
|
||||
.idea
|
||||
.vscode
|
||||
.helix
|
||||
result
|
||||
|
||||
# rust
|
||||
rust/target
|
||||
|
||||
File diff suppressed because one or more lines are too long
80
docs/kcl/import.md
Normal file
80
docs/kcl/import.md
Normal file
File diff suppressed because one or more lines are too long
@ -77,7 +77,6 @@ layout: manual
|
||||
* [`helix`](kcl/std-helix)
|
||||
* [`hole`](kcl/hole)
|
||||
* [`hollow`](kcl/hollow)
|
||||
* [`intersect`](kcl/intersect)
|
||||
* [`lastSegX`](kcl/lastSegX)
|
||||
* [`lastSegY`](kcl/lastSegY)
|
||||
* [`legAngX`](kcl/legAngX)
|
||||
@ -124,7 +123,6 @@ layout: manual
|
||||
* [`sqrt`](kcl/sqrt)
|
||||
* [`startProfileAt`](kcl/startProfileAt)
|
||||
* [`startSketchOn`](kcl/startSketchOn)
|
||||
* [`subtract`](kcl/subtract)
|
||||
* [`sweep`](kcl/sweep)
|
||||
* [`tangentToEnd`](kcl/tangentToEnd)
|
||||
* [`tangentialArc`](kcl/tangentialArc)
|
||||
@ -133,7 +131,6 @@ layout: manual
|
||||
* [`toDegrees`](kcl/toDegrees)
|
||||
* [`toRadians`](kcl/toRadians)
|
||||
* [`translate`](kcl/translate)
|
||||
* [`union`](kcl/union)
|
||||
* [`xLine`](kcl/xLine)
|
||||
* [`yLine`](kcl/yLine)
|
||||
* **std::math**
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
8389
docs/kcl/std.json
8389
docs/kcl/std.json
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -252,7 +252,7 @@ Data for an imported geometry.
|
||||
|
||||
| Property | Type | Description | Required |
|
||||
|----------|------|-------------|----------|
|
||||
| `type` |enum: `ImportedGeometry`| | No |
|
||||
| `type` |enum: [`ImportedGeometry`](/docs/kcl/types/ImportedGeometry)| | No |
|
||||
| `id` |[`string`](/docs/kcl/types/string)| The ID of the imported geometry. | No |
|
||||
| `value` |`[` [`string`](/docs/kcl/types/string) `]`| The original file paths. | No |
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1144,7 +1144,7 @@ sketch001 = startSketchOn(XZ)
|
||||
)
|
||||
|
||||
test(
|
||||
`Can import a local OBJ file`,
|
||||
`Can use the import stdlib function on a local OBJ file`,
|
||||
{ tag: '@electron' },
|
||||
async ({ page, context }, testInfo) => {
|
||||
test.fixme(orRunWhenFullSuiteEnabled())
|
||||
@ -1194,7 +1194,7 @@ sketch001 = startSketchOn(XZ)
|
||||
.toBeLessThan(15)
|
||||
})
|
||||
await test.step(`Write the import function line`, async () => {
|
||||
await u.codeLocator.fill(`import 'cube.obj'\ncube`)
|
||||
await u.codeLocator.fill(`import('cube.obj')`)
|
||||
await page.waitForTimeout(800)
|
||||
})
|
||||
await test.step(`Reset the camera before checking`, async () => {
|
||||
|
||||
@ -99,6 +99,7 @@ export class HomePageFixture {
|
||||
createAndGoToProject = async (projectTitle = 'untitled') => {
|
||||
await this.projectsLoaded()
|
||||
await this.projectButtonNew.click()
|
||||
await this.projectTextName.click()
|
||||
await this.projectTextName.fill(projectTitle)
|
||||
await this.projectButtonContinue.click()
|
||||
}
|
||||
|
||||
@ -233,7 +233,7 @@ export class SceneFixture {
|
||||
settled = async (cmdBar: CmdBarFixture) => {
|
||||
const u = await getUtils(this.page)
|
||||
|
||||
await expect(this.startEditSketchBtn).not.toBeDisabled({ timeout: 15_000 })
|
||||
await expect(this.startEditSketchBtn).not.toBeDisabled()
|
||||
await expect(this.startEditSketchBtn).toBeVisible()
|
||||
|
||||
await cmdBar.openCmdBar()
|
||||
|
||||
@ -68,10 +68,13 @@ test.describe('edit with AI example snapshots', () => {
|
||||
body1CapCoords.x,
|
||||
body1CapCoords.y
|
||||
)
|
||||
const yellow: [number, number, number] = [179, 179, 131]
|
||||
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
|
||||
|
||||
await test.step('wait for scene to load select body and check selection came through', async () => {
|
||||
await scene.expectPixelColor([134, 134, 134], body1CapCoords, 15)
|
||||
await clickBody1Cap()
|
||||
await scene.expectPixelColor(yellow, body1CapCoords, 20)
|
||||
await editor.expectState({
|
||||
highlightedCode: '',
|
||||
activeLines: ['|>startProfileAt([-73.64,-42.89],%)'],
|
||||
|
||||
@ -51,7 +51,6 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
|
||||
page,
|
||||
scene,
|
||||
}) => {
|
||||
test.fixme(orRunWhenFullSuiteEnabled())
|
||||
await context.addInitScript((file) => {
|
||||
localStorage.setItem('persistCode', file)
|
||||
}, file)
|
||||
@ -260,7 +259,6 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
|
||||
page,
|
||||
scene,
|
||||
}) => {
|
||||
test.fixme(orRunWhenFullSuiteEnabled())
|
||||
const body1CapCoords = { x: 571, y: 311 }
|
||||
const body2WallCoords = { x: 620, y: 152 }
|
||||
const [clickBody1Cap] = scene.makeMouseHelpers(
|
||||
|
||||
@ -588,7 +588,6 @@ test(
|
||||
'Draft circle should look right',
|
||||
{ tag: '@snapshot' },
|
||||
async ({ page, context, cmdBar, scene }) => {
|
||||
test.fixme(orRunWhenFullSuiteEnabled())
|
||||
const u = await getUtils(page)
|
||||
await page.setViewportSize({ width: 1200, height: 500 })
|
||||
const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
import { createProject } from '@e2e/playwright/test-utils'
|
||||
import { test } from '@e2e/playwright/zoo-test'
|
||||
|
||||
test.describe('Stress test', () => {
|
||||
test('Create project and load stress test', async ({
|
||||
cmdBar,
|
||||
scene,
|
||||
page,
|
||||
}, testInfo) => {
|
||||
const projectName = 'stress-test-project'
|
||||
// Create and load project
|
||||
await createProject({ name: projectName, page })
|
||||
await scene.settled(cmdBar)
|
||||
})
|
||||
})
|
||||
@ -1336,7 +1336,7 @@ part001 = startSketchOn(XZ)
|
||||
const isObj = lineOfInterest.includes('{ angle = 3,')
|
||||
test(`${lineOfInterest}${isObj ? '-[obj-input]' : ''}${
|
||||
doesHaveTagOutsideSketch ? '-[tagOutsideSketch]' : ''
|
||||
}`, async ({ page, editor, homePage }) => {
|
||||
}`, async ({ page, editor, scene, cmdBar, homePage }) => {
|
||||
await page.addInitScript(
|
||||
async ({ lineToBeDeleted, extraLine }) => {
|
||||
localStorage.setItem(
|
||||
@ -1359,7 +1359,7 @@ part001 = startSketchOn(XZ)
|
||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
await u.waitForPageLoad()
|
||||
await scene.settled(cmdBar)
|
||||
await page.waitForTimeout(1000)
|
||||
|
||||
await expect
|
||||
@ -1401,7 +1401,17 @@ part001 = startSketchOn(XZ)
|
||||
]
|
||||
|
||||
await page.mouse.move(hoverPos.x + x, hoverPos.y + y)
|
||||
await page.mouse.move(hoverPos.x, hoverPos.y, { steps: 5 })
|
||||
await wiggleMove(
|
||||
page,
|
||||
hoverPos.x,
|
||||
hoverPos.y,
|
||||
20,
|
||||
Math.sqrt(x * x + y * y),
|
||||
ang,
|
||||
10,
|
||||
5,
|
||||
`[data-overlay-toolbar-index="0"]`
|
||||
)
|
||||
|
||||
await editor.expectEditor.toContain(lineOfInterest, {
|
||||
shouldNormalise: true,
|
||||
@ -1414,7 +1424,17 @@ part001 = startSketchOn(XZ)
|
||||
await page.getByText('Cancel').click()
|
||||
|
||||
await page.mouse.move(hoverPos.x + x, hoverPos.y + y)
|
||||
await page.mouse.move(hoverPos.x, hoverPos.y, { steps: 5 })
|
||||
await wiggleMove(
|
||||
page,
|
||||
hoverPos.x,
|
||||
hoverPos.y,
|
||||
20,
|
||||
Math.sqrt(x * x + y * y),
|
||||
ang,
|
||||
10,
|
||||
5,
|
||||
`[data-overlay-toolbar-index="0"]`
|
||||
)
|
||||
|
||||
await editor.expectEditor.toContain(lineOfInterest, {
|
||||
shouldNormalise: true,
|
||||
|
||||
77
flake.lock
generated
77
flake.lock
generated
@ -1,56 +1,6 @@
|
||||
{
|
||||
"nodes": {
|
||||
"naersk": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1743800763,
|
||||
"narHash": "sha256-YFKV+fxEpMgP5VsUcM6Il28lI0NlpM7+oB1XxbBAYCw=",
|
||||
"owner": "nix-community",
|
||||
"repo": "naersk",
|
||||
"rev": "ed0232117731a4c19d3ee93aa0c382a8fe754b01",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "naersk",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1744157173,
|
||||
"narHash": "sha256-bWSjxDwq7iVePrhmA7tY2dyMWHuNJo8knkO4y+q4ZkY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6a39c6e495eefabc935d8ddf66aa45d85b85fa3f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1744157173,
|
||||
"narHash": "sha256-bWSjxDwq7iVePrhmA7tY2dyMWHuNJo8knkO4y+q4ZkY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6a39c6e495eefabc935d8ddf66aa45d85b85fa3f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1736320768,
|
||||
"narHash": "sha256-nIYdTAiKIGnFNugbomgBJR+Xv5F1ZQU+HfaBqJKroC0=",
|
||||
@ -66,23 +16,38 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1728538411,
|
||||
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"naersk": "naersk",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-overlay": "rust-overlay"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1744338850,
|
||||
"narHash": "sha256-pwMIVmsb8fjjT92n5XFDqCsplcX70qVMMT7NulumPXs=",
|
||||
"lastModified": 1736476219,
|
||||
"narHash": "sha256-+qyv3QqdZCdZ3cSO/cbpEY6tntyYjfe1bB12mdpNFaY=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "5e64aecc018e6f775572609e7d7485fdba6985a7",
|
||||
"rev": "de30cc5963da22e9742bbbbb9a3344570ed237b9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
136
flake.nix
136
flake.nix
@ -1,96 +1,84 @@
|
||||
{
|
||||
description = "zoo.dev modeling-app";
|
||||
description = "modeling-app development environment";
|
||||
|
||||
# Flake inputs
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
rust-overlay.url = "github:oxalica/rust-overlay";
|
||||
naersk.url = "github:nix-community/naersk";
|
||||
rust-overlay.url = "github:oxalica/rust-overlay"; # A helper for Rust + Nix
|
||||
};
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
rust-overlay,
|
||||
naersk,
|
||||
}: let
|
||||
overlays = [
|
||||
(import rust-overlay)
|
||||
(self: super: {
|
||||
rustToolchain = super.rust-bin.stable.latest.default.override {
|
||||
targets = ["wasm32-unknown-unknown"];
|
||||
extensions = ["rustfmt" "llvm-tools-preview" "rust-src"];
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
allSystems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
"x86_64-darwin"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
|
||||
forAllSystems = f:
|
||||
nixpkgs.lib.genAttrs allSystems (system:
|
||||
f {
|
||||
pkgs = import nixpkgs {
|
||||
inherit overlays system;
|
||||
# Flake outputs
|
||||
outputs = { self, nixpkgs, rust-overlay }:
|
||||
let
|
||||
# Overlays enable you to customize the Nixpkgs attribute set
|
||||
overlays = [
|
||||
# Makes a `rust-bin` attribute available in Nixpkgs
|
||||
(import rust-overlay)
|
||||
# Provides a `rustToolchain` attribute for Nixpkgs that we can use to
|
||||
# create a Rust environment
|
||||
(self: super: {
|
||||
rustToolchain = super. rust-bin.stable.latest.default.override {
|
||||
targets = [ "wasm32-unknown-unknown" ];
|
||||
extensions = [ "rustfmt" "llvm-tools-preview" "rust-src" ];
|
||||
};
|
||||
system = system;
|
||||
});
|
||||
in {
|
||||
devShells = forAllSystems ({pkgs, ...}: {
|
||||
default = pkgs.mkShell {
|
||||
packages =
|
||||
(with pkgs; [
|
||||
})
|
||||
(self: super: {
|
||||
cargo-llvm-cov = super.cargo-llvm-cov.overrideAttrs(oa: {
|
||||
doCheck = false; doInstallCheck = false;
|
||||
});
|
||||
})
|
||||
];
|
||||
|
||||
# Systems supported
|
||||
allSystems = [
|
||||
"x86_64-linux" # 64-bit Intel/AMD Linux
|
||||
"aarch64-linux" # 64-bit ARM Linux
|
||||
"x86_64-darwin" # 64-bit Intel macOS
|
||||
"aarch64-darwin" # 64-bit ARM macOS
|
||||
];
|
||||
|
||||
# Helper to provide system-specific attributes
|
||||
forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f {
|
||||
pkgs = import nixpkgs { inherit overlays system; config.allowBroken = true; };
|
||||
});
|
||||
|
||||
in
|
||||
{
|
||||
# Development environment output
|
||||
devShells = forAllSystems ({ pkgs }: {
|
||||
default = pkgs.mkShell {
|
||||
# The Nix packages provided in the environment
|
||||
packages = (with pkgs; [
|
||||
# The package provided by our custom overlay. Includes cargo, Clippy, cargo-fmt,
|
||||
# rustdoc, rustfmt, and other tools.
|
||||
rustToolchain
|
||||
|
||||
cargo-llvm-cov
|
||||
cargo-nextest
|
||||
|
||||
just
|
||||
postgresql.lib
|
||||
openssl
|
||||
pkg-config
|
||||
|
||||
nodejs_22
|
||||
yarn
|
||||
|
||||
electron
|
||||
playwright-driver.browsers
|
||||
wasm-pack
|
||||
python3Full
|
||||
])
|
||||
++ pkgs.lib.optionals pkgs.stdenv.isDarwin (with pkgs; [
|
||||
]) ++ pkgs.lib.optionals pkgs.stdenv.isDarwin (with pkgs; [
|
||||
libiconv
|
||||
darwin.apple_sdk.frameworks.Security
|
||||
]);
|
||||
|
||||
TARGET_CC = "${pkgs.stdenv.cc}/bin/${pkgs.stdenv.cc.targetPrefix}cc";
|
||||
LIBCLANG_PATH = "${pkgs.libclang.lib}/lib";
|
||||
ELECTRON_OVERRIDE_DIST_PATH = "${pkgs.electron}/bin/";
|
||||
PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = true;
|
||||
PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH = "${pkgs.playwright-driver.browsers}/chromium-1091/chrome-linux/chrome";
|
||||
PLAYWRIGHT_BROWSERS_PATH = "${pkgs.playwright-driver.browsers}";
|
||||
NODE_ENV = "development";
|
||||
};
|
||||
});
|
||||
|
||||
packages = forAllSystems ({
|
||||
pkgs,
|
||||
system,
|
||||
}: let
|
||||
naersk-lib = pkgs.callPackage naersk {
|
||||
cargo = pkgs.rustToolchain;
|
||||
rustc = pkgs.rustToolchain;
|
||||
};
|
||||
in {
|
||||
kcl-language-server = naersk-lib.buildPackage {
|
||||
pname = "kcl-language-server";
|
||||
version = "0.1.0";
|
||||
release = true;
|
||||
|
||||
src = ./rust;
|
||||
|
||||
cargoBuildOptions = opt: opt ++ ["-p" "kcl-language-server"];
|
||||
buildInputs = [pkgs.openssl pkgs.pkg-config];
|
||||
};
|
||||
default = self.packages.${system}.kcl-language-server;
|
||||
});
|
||||
};
|
||||
TARGET_CC = "${pkgs.stdenv.cc}/bin/${pkgs.stdenv.cc.targetPrefix}cc";
|
||||
LIBCLANG_PATH = "${pkgs.libclang.lib}/lib";
|
||||
ELECTRON_OVERRIDE_DIST_PATH = "${pkgs.electron}/bin/";
|
||||
PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = true;
|
||||
PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH = "${pkgs.playwright-driver.browsers}/chromium-1091/chrome-linux/chrome";
|
||||
PLAYWRIGHT_BROWSERS_PATH = "${pkgs.playwright-driver.browsers}";
|
||||
NODE_ENV = "development";
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@ -389,13 +389,6 @@ export class LanguageServerPlugin implements PluginValue {
|
||||
}
|
||||
|
||||
if (insertText && insertTextFormat === 2) {
|
||||
// We end with ${} so you can jump to the end of the snippet.
|
||||
// After the last argument.
|
||||
// This is not standard from the lsp so we add it here.
|
||||
if (insertText.endsWith(')')) {
|
||||
// We have a function its safe to insert the ${} at the end.
|
||||
insertText = insertText + '${}'
|
||||
}
|
||||
return snippetCompletion(insertText, completion)
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 58 KiB |
24
rust/Cargo.lock
generated
24
rust/Cargo.lock
generated
@ -1780,7 +1780,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-bumper"
|
||||
version = "0.1.60"
|
||||
version = "0.1.58"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1791,7 +1791,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-derive-docs"
|
||||
version = "0.1.60"
|
||||
version = "0.1.58"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"anyhow",
|
||||
@ -1810,7 +1810,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-directory-test-macro"
|
||||
version = "0.1.60"
|
||||
version = "0.1.58"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1819,7 +1819,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-language-server"
|
||||
version = "0.2.60"
|
||||
version = "0.2.58"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1840,7 +1840,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-language-server-release"
|
||||
version = "0.1.60"
|
||||
version = "0.1.58"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@ -1860,7 +1860,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.2.60"
|
||||
version = "0.2.58"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx 0.5.1",
|
||||
@ -1928,7 +1928,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-python-bindings"
|
||||
version = "0.3.60"
|
||||
version = "0.3.58"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"kcl-lib",
|
||||
@ -1943,7 +1943,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-test-server"
|
||||
version = "0.1.60"
|
||||
version = "0.1.58"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hyper 0.14.32",
|
||||
@ -1956,7 +1956,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-to-core"
|
||||
version = "0.1.60"
|
||||
version = "0.1.58"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1970,7 +1970,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-wasm-lib"
|
||||
version = "0.1.60"
|
||||
version = "0.1.58"
|
||||
dependencies = [
|
||||
"bson",
|
||||
"console_error_panic_hook",
|
||||
@ -2033,9 +2033,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kittycad-modeling-cmds"
|
||||
version = "0.2.113"
|
||||
version = "0.2.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa1c927569925425a1b03711617c384a30cb7554394e8a6a01266910b22421de"
|
||||
checksum = "58f5fbcfb0fe3384592829cd1a5109aa45fb6a3ffc5ff2d164d2fd528ffd4641"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
|
||||
@ -36,7 +36,7 @@ dashmap = { version = "6.1.0" }
|
||||
http = "1"
|
||||
indexmap = "2.7.0"
|
||||
kittycad = { version = "0.3.36", default-features = false, features = ["js", "requests"] }
|
||||
kittycad-modeling-cmds = { version = "0.2.113", features = ["ts-rs", "websocket"] }
|
||||
kittycad-modeling-cmds = { version = "0.2.108", features = ["ts-rs", "websocket"] }
|
||||
lazy_static = "1.5.0"
|
||||
miette = "7.5.0"
|
||||
pyo3 = { version = "0.24.0" }
|
||||
|
||||
@ -13,7 +13,6 @@ redo-kcl-stdlib-docs-no-imgs:
|
||||
# Then run the stdlib docs generation
|
||||
redo-kcl-stdlib-docs:
|
||||
TWENTY_TWENTY=overwrite {{cnr}} -p kcl-lib --no-fail-fast -- kcl_test_example
|
||||
TWENTY_TWENTY=overwrite {{cnr}} --workspace --no-fail-fast docs::kcl_doc::test::test_examples
|
||||
EXPECTORATE=overwrite {{cnr}} -p kcl-lib --no-fail-fast -- docs::gen_std_tests::test_generate_stdlib
|
||||
|
||||
# Copy a test KCL file from executor tests into a new simulation test.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
|
||||
[package]
|
||||
name = "kcl-bumper"
|
||||
version = "0.1.60"
|
||||
version = "0.1.58"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/KittyCAD/modeling-api"
|
||||
rust-version = "1.76"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-derive-docs"
|
||||
description = "A tool for generating documentation from Rust derive macros"
|
||||
version = "0.1.60"
|
||||
version = "0.1.58"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-directory-test-macro"
|
||||
description = "A tool for generating tests from a directory of kcl files"
|
||||
version = "0.1.60"
|
||||
version = "0.1.58"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "kcl-language-server-release"
|
||||
version = "0.1.60"
|
||||
version = "0.1.58"
|
||||
edition = "2021"
|
||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||
publish = false
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
name = "kcl-language-server"
|
||||
description = "A language server for KCL."
|
||||
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
|
||||
version = "0.2.60"
|
||||
version = "0.2.58"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@ -9,10 +9,7 @@ export async function createClient(
|
||||
serverOptions: lc.ServerOptions
|
||||
): Promise<lc.LanguageClient> {
|
||||
const clientOptions: lc.LanguageClientOptions = {
|
||||
documentSelector: [
|
||||
{ scheme: 'file', language: 'kcl' },
|
||||
{ scheme: 'untitled', language: 'kcl' },
|
||||
],
|
||||
documentSelector: [{ scheme: 'file', language: 'kcl' }],
|
||||
initializationOptions,
|
||||
traceOutputChannel,
|
||||
outputChannel,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "kcl-lib"
|
||||
description = "KittyCAD Language implementation and tools"
|
||||
version = "0.2.60"
|
||||
version = "0.2.58"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
@ -103,7 +103,7 @@ tokio-tungstenite = { version = "0.24.0", features = [
|
||||
tower-lsp = { workspace = true, features = ["proposed", "default"] }
|
||||
|
||||
[features]
|
||||
default = ["cli", "engine"]
|
||||
default = ["engine"]
|
||||
cli = ["dep:clap", "kittycad/clap"]
|
||||
dhat-heap = ["dep:dhat"]
|
||||
# For the lsp server, when run with stdout for rpc we want to disable println.
|
||||
|
||||
@ -444,11 +444,12 @@ impl FnData {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
pub(super) fn to_autocomplete_snippet(&self) -> String {
|
||||
if self.name == "loft" {
|
||||
return "loft([${0:sketch000}, ${1:sketch001}])".to_owned();
|
||||
return "loft([${0:sketch000}, ${1:sketch001}])${}".to_owned();
|
||||
} else if self.name == "hole" {
|
||||
return "hole(${0:holeSketch}, ${1:%})".to_owned();
|
||||
return "hole(${0:holeSketch}, ${1:%})${}".to_owned();
|
||||
}
|
||||
let mut args = Vec::new();
|
||||
let mut index = 0;
|
||||
@ -458,7 +459,9 @@ impl FnData {
|
||||
args.push(arg_str);
|
||||
}
|
||||
}
|
||||
format!("{}({})", self.preferred_name, args.join(", "))
|
||||
// We end with ${} so you can jump to the end of the snippet.
|
||||
// After the last argument.
|
||||
format!("{}({})${{}}", self.preferred_name, args.join(", "))
|
||||
}
|
||||
|
||||
fn to_signature_help(&self) -> SignatureHelp {
|
||||
|
||||
@ -498,17 +498,12 @@ pub trait StdLibFn: std::fmt::Debug + Send + Sync {
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn to_autocomplete_snippet(&self) -> Result<String> {
|
||||
if self.name() == "loft" {
|
||||
return Ok("loft([${0:sketch000}, ${1:sketch001}])".to_string());
|
||||
} else if self.name() == "union" {
|
||||
return Ok("union([${0:extrude001}, ${1:extrude002}])".to_string());
|
||||
} else if self.name() == "subtract" {
|
||||
return Ok("subtract([${0:extrude001}], tools = [${1:extrude002}])".to_string());
|
||||
} else if self.name() == "intersect" {
|
||||
return Ok("intersect([${0:extrude001}, ${1:extrude002}])".to_string());
|
||||
return Ok("loft([${0:sketch000}, ${1:sketch001}])${}".to_string());
|
||||
} else if self.name() == "hole" {
|
||||
return Ok("hole(${0:holeSketch}, ${1:%})".to_string());
|
||||
return Ok("hole(${0:holeSketch}, ${1:%})${}".to_string());
|
||||
}
|
||||
let in_keyword_fn = self.keyword_arguments();
|
||||
let mut args = Vec::new();
|
||||
@ -519,7 +514,9 @@ pub trait StdLibFn: std::fmt::Debug + Send + Sync {
|
||||
args.push(arg_str);
|
||||
}
|
||||
}
|
||||
Ok(format!("{}({})", self.name(), args.join(", ")))
|
||||
// We end with ${} so you can jump to the end of the snippet.
|
||||
// After the last argument.
|
||||
Ok(format!("{}({})${{}}", self.name(), args.join(", ")))
|
||||
}
|
||||
|
||||
fn to_signature_help(&self) -> SignatureHelp {
|
||||
@ -893,26 +890,29 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_line() {
|
||||
let line_fn: Box<dyn StdLibFn> = Box::new(crate::std::sketch::Line);
|
||||
let snippet = line_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(snippet, r#"line(${0:%}, end = [${1:3.14}, ${2:3.14}])"#);
|
||||
assert_eq!(snippet, r#"line(${0:%}, end = [${1:3.14}, ${2:3.14}])${}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_extrude() {
|
||||
let extrude_fn: Box<dyn StdLibFn> = Box::new(crate::std::extrude::Extrude);
|
||||
let snippet = extrude_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(snippet, r#"extrude(${0:%}, length = ${1:3.14})"#);
|
||||
assert_eq!(snippet, r#"extrude(${0:%}, length = ${1:3.14})${}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_fillet() {
|
||||
let fillet_fn: Box<dyn StdLibFn> = Box::new(crate::std::fillet::Fillet);
|
||||
let snippet = fillet_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(
|
||||
snippet,
|
||||
r#"fillet(${0:%}, radius = ${1:3.14}, tags = [${2:"tag_or_edge_fn"}])"#
|
||||
r#"fillet(${0:%}, radius = ${1:3.14}, tags = [${2:"tag_or_edge_fn"}])${}"#
|
||||
);
|
||||
}
|
||||
|
||||
@ -920,17 +920,18 @@ mod tests {
|
||||
fn get_autocomplete_snippet_start_sketch_on() {
|
||||
let start_sketch_on_fn: Box<dyn StdLibFn> = Box::new(crate::std::sketch::StartSketchOn);
|
||||
let snippet = start_sketch_on_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(snippet, r#"startSketchOn(${0:"XY"})"#);
|
||||
assert_eq!(snippet, r#"startSketchOn(${0:"XY"})${}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_pattern_circular_3d() {
|
||||
// We test this one specifically because it has ints and floats and strings.
|
||||
let pattern_fn: Box<dyn StdLibFn> = Box::new(crate::std::patterns::PatternCircular3D);
|
||||
let snippet = pattern_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(
|
||||
snippet,
|
||||
r#"patternCircular3d(${0:%}, instances = ${1:10}, axis = [${2:3.14}, ${3:3.14}, ${4:3.14}], center = [${5:3.14}, ${6:3.14}, ${7:3.14}], arcDegrees = ${8:3.14}, rotateDuplicates = ${9:false})"#
|
||||
r#"patternCircular3d(${0:%}, instances = ${1:10}, axis = [${2:3.14}, ${3:3.14}, ${4:3.14}], center = [${5:3.14}, ${6:3.14}, ${7:3.14}], arcDegrees = ${8:3.14}, rotateDuplicates = ${9:false})${}"#
|
||||
);
|
||||
}
|
||||
|
||||
@ -941,10 +942,11 @@ mod tests {
|
||||
panic!();
|
||||
};
|
||||
let snippet = revolve_fn.to_autocomplete_snippet();
|
||||
assert_eq!(snippet, r#"revolve(axis = ${0:X})"#);
|
||||
assert_eq!(snippet, r#"revolve(axis = ${0:X})${}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_circle() {
|
||||
let data = kcl_doc::walk_prelude();
|
||||
let DocData::Fn(circle_fn) = data.into_iter().find(|d| d.name() == "circle").unwrap() else {
|
||||
@ -953,11 +955,12 @@ mod tests {
|
||||
let snippet = circle_fn.to_autocomplete_snippet();
|
||||
assert_eq!(
|
||||
snippet,
|
||||
r#"circle(center = [${0:3.14}, ${1:3.14}], radius = ${2:3.14})"#
|
||||
r#"circle(center = [${0:3.14}, ${1:3.14}], radius = ${2:3.14})${}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_arc() {
|
||||
let arc_fn: Box<dyn StdLibFn> = Box::new(crate::std::sketch::Arc);
|
||||
let snippet = arc_fn.to_autocomplete_snippet().unwrap();
|
||||
@ -967,7 +970,7 @@ mod tests {
|
||||
angleStart = ${0:3.14},
|
||||
angleEnd = ${1:3.14},
|
||||
radius = ${2:3.14},
|
||||
}, ${3:%})"#
|
||||
}, ${3:%})${}"#
|
||||
);
|
||||
}
|
||||
|
||||
@ -975,16 +978,17 @@ mod tests {
|
||||
fn get_autocomplete_snippet_map() {
|
||||
let map_fn: Box<dyn StdLibFn> = Box::new(crate::std::array::Map);
|
||||
let snippet = map_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(snippet, r#"map(${0:[0..9]})"#);
|
||||
assert_eq!(snippet, r#"map(${0:[0..9]})${}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_pattern_linear_2d() {
|
||||
let pattern_fn: Box<dyn StdLibFn> = Box::new(crate::std::patterns::PatternLinear2D);
|
||||
let snippet = pattern_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(
|
||||
snippet,
|
||||
r#"patternLinear2d(${0:%}, instances = ${1:10}, distance = ${2:3.14}, axis = [${3:3.14}, ${4:3.14}])"#
|
||||
r#"patternLinear2d(${0:%}, instances = ${1:10}, distance = ${2:3.14}, axis = [${3:3.14}, ${4:3.14}])${}"#
|
||||
);
|
||||
}
|
||||
|
||||
@ -994,32 +998,36 @@ mod tests {
|
||||
let snippet = appearance_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(
|
||||
snippet,
|
||||
r#"appearance(${0:%}, color = ${1:"#.to_owned() + "\"#" + r#"ff0000"})"#
|
||||
r#"appearance(${0:%}, color = ${1:"#.to_owned() + "\"#" + r#"ff0000"})${}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_loft() {
|
||||
let loft_fn: Box<dyn StdLibFn> = Box::new(crate::std::loft::Loft);
|
||||
let snippet = loft_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(snippet, r#"loft([${0:sketch000}, ${1:sketch001}])"#);
|
||||
assert_eq!(snippet, r#"loft([${0:sketch000}, ${1:sketch001}])${}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_sweep() {
|
||||
let sweep_fn: Box<dyn StdLibFn> = Box::new(crate::std::sweep::Sweep);
|
||||
let snippet = sweep_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(snippet, r#"sweep(${0:%}, path = ${1:sketch000})"#);
|
||||
assert_eq!(snippet, r#"sweep(${0:%}, path = ${1:sketch000})${}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_hole() {
|
||||
let hole_fn: Box<dyn StdLibFn> = Box::new(crate::std::sketch::Hole);
|
||||
let snippet = hole_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(snippet, r#"hole(${0:holeSketch}, ${1:%})"#);
|
||||
assert_eq!(snippet, r#"hole(${0:holeSketch}, ${1:%})${}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_helix() {
|
||||
let data = kcl_doc::walk_prelude();
|
||||
let DocData::Fn(helix_fn) = data.into_iter().find(|d| d.name() == "helix").unwrap() else {
|
||||
@ -1028,32 +1036,36 @@ mod tests {
|
||||
let snippet = helix_fn.to_autocomplete_snippet();
|
||||
assert_eq!(
|
||||
snippet,
|
||||
r#"helix(revolutions = ${0:3.14}, angleStart = ${1:3.14}, radius = ${2:3.14}, axis = ${3:X}, length = ${4:3.14})"#
|
||||
r#"helix(revolutions = ${0:3.14}, angleStart = ${1:3.14}, radius = ${2:3.14}, axis = ${3:X}, length = ${4:3.14})${}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_union() {
|
||||
let union_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Union);
|
||||
let snippet = union_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(snippet, r#"union([${0:extrude001}, ${1:extrude002}])"#);
|
||||
assert_eq!(snippet, r#"union(${0:%})${}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_subtract() {
|
||||
let subtract_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Subtract);
|
||||
let snippet = subtract_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(snippet, r#"subtract([${0:extrude001}], tools = [${1:extrude002}])"#);
|
||||
assert_eq!(snippet, r#"subtract(${0:%}, tools = ${1:%})${}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_intersect() {
|
||||
let intersect_fn: Box<dyn StdLibFn> = Box::new(crate::std::csg::Intersect);
|
||||
let snippet = intersect_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(snippet, r#"intersect([${0:extrude001}, ${1:extrude002}])"#);
|
||||
assert_eq!(snippet, r#"intersect(${0:%})${}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_get_common_edge() {
|
||||
let get_common_edge_fn: Box<dyn StdLibFn> = Box::new(crate::std::edge::GetCommonEdge);
|
||||
let snippet = get_common_edge_fn.to_autocomplete_snippet().unwrap();
|
||||
@ -1061,34 +1073,40 @@ mod tests {
|
||||
snippet,
|
||||
r#"getCommonEdge(faces = [{
|
||||
value = ${0:"string"},
|
||||
}])"#
|
||||
}])${}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_scale() {
|
||||
let scale_fn: Box<dyn StdLibFn> = Box::new(crate::std::transform::Scale);
|
||||
let snippet = scale_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(snippet, r#"scale(${0:%}, x = ${1:3.14}, y = ${2:3.14}, z = ${3:3.14})"#);
|
||||
assert_eq!(
|
||||
snippet,
|
||||
r#"scale(${0:%}, x = ${1:3.14}, y = ${2:3.14}, z = ${3:3.14})${}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_translate() {
|
||||
let translate_fn: Box<dyn StdLibFn> = Box::new(crate::std::transform::Translate);
|
||||
let snippet = translate_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(
|
||||
snippet,
|
||||
r#"translate(${0:%}, x = ${1:3.14}, y = ${2:3.14}, z = ${3:3.14})"#
|
||||
r#"translate(${0:%}, x = ${1:3.14}, y = ${2:3.14}, z = ${3:3.14})${}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::literal_string_with_formatting_args)]
|
||||
fn get_autocomplete_snippet_rotate() {
|
||||
let rotate_fn: Box<dyn StdLibFn> = Box::new(crate::std::transform::Rotate);
|
||||
let snippet = rotate_fn.to_autocomplete_snippet().unwrap();
|
||||
assert_eq!(
|
||||
snippet,
|
||||
r#"rotate(${0:%}, roll = ${1:3.14}, pitch = ${2:3.14}, yaw = ${3:3.14})"#
|
||||
r#"rotate(${0:%}, roll = ${1:3.14}, pitch = ${2:3.14}, yaw = ${3:3.14})${}"#
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ pub(crate) const SETTINGS_UNIT_ANGLE: &str = "defaultAngleUnit";
|
||||
pub(super) const NO_PRELUDE: &str = "no_std";
|
||||
|
||||
pub(super) const IMPORT_FORMAT: &str = "format";
|
||||
pub(super) const IMPORT_FORMAT_VALUES: [&str; 9] = ["fbx", "gltf", "glb", "obj", "ply", "sldprt", "stp", "step", "stl"];
|
||||
pub(super) const IMPORT_COORDS: &str = "coords";
|
||||
pub(super) const IMPORT_COORDS_VALUES: [(&str, &System); 3] =
|
||||
[("zoo", KITTYCAD), ("opengl", OPENGL), ("vulkan", VULKAN)];
|
||||
|
||||
@ -115,30 +115,6 @@ impl CodeRef {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
|
||||
#[ts(export_to = "Artifact.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CompositeSolid {
|
||||
pub id: ArtifactId,
|
||||
pub sub_type: CompositeSolidSubType,
|
||||
/// Constituent solids of the composite solid.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub solid_ids: Vec<ArtifactId>,
|
||||
/// Tool solids used for asymmetric operations like subtract.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub tool_ids: Vec<ArtifactId>,
|
||||
pub code_ref: CodeRef,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, ts_rs::TS)]
|
||||
#[ts(export_to = "Artifact.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum CompositeSolidSubType {
|
||||
Intersect,
|
||||
Subtract,
|
||||
Union,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
|
||||
#[ts(export_to = "Artifact.ts")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -342,7 +318,6 @@ pub struct Helix {
|
||||
#[ts(export_to = "Artifact.ts")]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
pub enum Artifact {
|
||||
CompositeSolid(CompositeSolid),
|
||||
Plane(Plane),
|
||||
Path(Path),
|
||||
Segment(Segment),
|
||||
@ -361,7 +336,6 @@ pub enum Artifact {
|
||||
impl Artifact {
|
||||
pub(crate) fn id(&self) -> ArtifactId {
|
||||
match self {
|
||||
Artifact::CompositeSolid(a) => a.id,
|
||||
Artifact::Plane(a) => a.id,
|
||||
Artifact::Path(a) => a.id,
|
||||
Artifact::Segment(a) => a.id,
|
||||
@ -381,7 +355,6 @@ impl Artifact {
|
||||
#[expect(dead_code)]
|
||||
pub(crate) fn code_ref(&self) -> Option<&CodeRef> {
|
||||
match self {
|
||||
Artifact::CompositeSolid(a) => Some(&a.code_ref),
|
||||
Artifact::Plane(a) => Some(&a.code_ref),
|
||||
Artifact::Path(a) => Some(&a.code_ref),
|
||||
Artifact::Segment(a) => Some(&a.code_ref),
|
||||
@ -402,7 +375,6 @@ impl Artifact {
|
||||
/// type, return the new artifact which should be used as a replacement.
|
||||
fn merge(&mut self, new: Artifact) -> Option<Artifact> {
|
||||
match self {
|
||||
Artifact::CompositeSolid(a) => a.merge(new),
|
||||
Artifact::Plane(a) => a.merge(new),
|
||||
Artifact::Path(a) => a.merge(new),
|
||||
Artifact::Segment(a) => a.merge(new),
|
||||
@ -420,18 +392,6 @@ impl Artifact {
|
||||
}
|
||||
}
|
||||
|
||||
impl CompositeSolid {
|
||||
fn merge(&mut self, new: Artifact) -> Option<Artifact> {
|
||||
let Artifact::CompositeSolid(new) = new else {
|
||||
return Some(new);
|
||||
};
|
||||
merge_ids(&mut self.solid_ids, new.solid_ids);
|
||||
merge_ids(&mut self.tool_ids, new.tool_ids);
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Plane {
|
||||
fn merge(&mut self, new: Artifact) -> Option<Artifact> {
|
||||
let Artifact::Plane(new) = new else {
|
||||
@ -1087,85 +1047,6 @@ fn artifacts_to_update(
|
||||
// the helix here, but it's not useful right now.
|
||||
return Ok(return_arr);
|
||||
}
|
||||
ModelingCmd::BooleanIntersection(_) | ModelingCmd::BooleanSubtract(_) | ModelingCmd::BooleanUnion(_) => {
|
||||
let (sub_type, solid_ids, tool_ids) = match cmd {
|
||||
ModelingCmd::BooleanIntersection(intersection) => {
|
||||
let solid_ids = intersection
|
||||
.solid_ids
|
||||
.iter()
|
||||
.copied()
|
||||
.map(ArtifactId::new)
|
||||
.collect::<Vec<_>>();
|
||||
(CompositeSolidSubType::Intersect, solid_ids, Vec::new())
|
||||
}
|
||||
ModelingCmd::BooleanSubtract(subtract) => {
|
||||
let solid_ids = subtract
|
||||
.target_ids
|
||||
.iter()
|
||||
.copied()
|
||||
.map(ArtifactId::new)
|
||||
.collect::<Vec<_>>();
|
||||
let tool_ids = subtract
|
||||
.tool_ids
|
||||
.iter()
|
||||
.copied()
|
||||
.map(ArtifactId::new)
|
||||
.collect::<Vec<_>>();
|
||||
(CompositeSolidSubType::Subtract, solid_ids, tool_ids)
|
||||
}
|
||||
ModelingCmd::BooleanUnion(union) => {
|
||||
let solid_ids = union.solid_ids.iter().copied().map(ArtifactId::new).collect::<Vec<_>>();
|
||||
(CompositeSolidSubType::Union, solid_ids, Vec::new())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let mut new_solid_ids = vec![id];
|
||||
|
||||
match response {
|
||||
OkModelingCmdResponse::BooleanIntersection(intersection) => intersection
|
||||
.extra_solid_ids
|
||||
.iter()
|
||||
.copied()
|
||||
.map(ArtifactId::new)
|
||||
.for_each(|id| new_solid_ids.push(id)),
|
||||
OkModelingCmdResponse::BooleanSubtract(subtract) => subtract
|
||||
.extra_solid_ids
|
||||
.iter()
|
||||
.copied()
|
||||
.map(ArtifactId::new)
|
||||
.for_each(|id| new_solid_ids.push(id)),
|
||||
OkModelingCmdResponse::BooleanUnion(union) => union
|
||||
.extra_solid_ids
|
||||
.iter()
|
||||
.copied()
|
||||
.map(ArtifactId::new)
|
||||
.for_each(|id| new_solid_ids.push(id)),
|
||||
_ => {}
|
||||
}
|
||||
let return_arr = new_solid_ids
|
||||
.into_iter()
|
||||
// Extra solid IDs may include the command's ID. Make sure we
|
||||
// don't create a duplicate.
|
||||
.filter(|solid_id| *solid_id != id)
|
||||
.map(|solid_id| {
|
||||
Artifact::CompositeSolid(CompositeSolid {
|
||||
id: solid_id,
|
||||
sub_type,
|
||||
solid_ids: solid_ids.clone(),
|
||||
tool_ids: tool_ids.clone(),
|
||||
code_ref: CodeRef {
|
||||
range,
|
||||
path_to_node: path_to_node.clone(),
|
||||
},
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// TODO: Should we add the reverse graph edges?
|
||||
|
||||
return Ok(return_arr);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
||||
@ -67,11 +67,6 @@ impl Artifact {
|
||||
/// the graph. This should be disjoint with `child_ids`.
|
||||
pub(crate) fn back_edges(&self) -> Vec<ArtifactId> {
|
||||
match self {
|
||||
Artifact::CompositeSolid(a) => {
|
||||
let mut ids = a.solid_ids.clone();
|
||||
ids.extend(a.tool_ids.iter());
|
||||
ids
|
||||
}
|
||||
Artifact::Plane(_) => Vec::new(),
|
||||
Artifact::Path(a) => vec![a.plane_id],
|
||||
Artifact::Segment(a) => vec![a.path_id],
|
||||
@ -92,11 +87,6 @@ impl Artifact {
|
||||
/// the graph.
|
||||
pub(crate) fn child_ids(&self) -> Vec<ArtifactId> {
|
||||
match self {
|
||||
Artifact::CompositeSolid(_) => {
|
||||
// Note: Don't include these since they're parents: solid_ids,
|
||||
// tool_ids.
|
||||
Vec::new()
|
||||
}
|
||||
Artifact::Plane(a) => a.path_ids.clone(),
|
||||
Artifact::Path(a) => {
|
||||
// Note: Don't include these since they're parents: plane_id.
|
||||
@ -223,7 +213,6 @@ impl ArtifactGraph {
|
||||
let id = artifact.id();
|
||||
|
||||
let grouped = match artifact {
|
||||
Artifact::CompositeSolid(_) => false,
|
||||
Artifact::Plane(_) => false,
|
||||
Artifact::Path(_) => {
|
||||
groups.entry(id).or_insert_with(Vec::new).push(id);
|
||||
@ -289,15 +278,6 @@ impl ArtifactGraph {
|
||||
}
|
||||
|
||||
match artifact {
|
||||
Artifact::CompositeSolid(composite_solid) => {
|
||||
writeln!(
|
||||
output,
|
||||
"{prefix}{}[\"CompositeSolid {:?}<br>{:?}\"]",
|
||||
id,
|
||||
composite_solid.sub_type,
|
||||
code_ref_display(&composite_solid.code_ref)
|
||||
)?;
|
||||
}
|
||||
Artifact::Plane(plane) => {
|
||||
writeln!(
|
||||
output,
|
||||
|
||||
@ -939,40 +939,25 @@ impl Node<BinaryExpression> {
|
||||
if self.operator == BinaryOperator::Add || self.operator == BinaryOperator::Or {
|
||||
if let (KclValue::Solid { value: left }, KclValue::Solid { value: right }) = (&left_value, &right_value) {
|
||||
let args = crate::std::Args::new(Default::default(), self.into(), ctx.clone(), None);
|
||||
let result = crate::std::csg::inner_union(
|
||||
vec![*left.clone(), *right.clone()],
|
||||
Default::default(),
|
||||
exec_state,
|
||||
args,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
crate::std::csg::inner_union(vec![*left.clone(), *right.clone()], exec_state, args).await?;
|
||||
return Ok(result.into());
|
||||
}
|
||||
} else if self.operator == BinaryOperator::Sub {
|
||||
// Check if we have solids.
|
||||
if let (KclValue::Solid { value: left }, KclValue::Solid { value: right }) = (&left_value, &right_value) {
|
||||
let args = crate::std::Args::new(Default::default(), self.into(), ctx.clone(), None);
|
||||
let result = crate::std::csg::inner_subtract(
|
||||
vec![*left.clone()],
|
||||
vec![*right.clone()],
|
||||
Default::default(),
|
||||
exec_state,
|
||||
args,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
crate::std::csg::inner_subtract(vec![*left.clone()], vec![*right.clone()], exec_state, args)
|
||||
.await?;
|
||||
return Ok(result.into());
|
||||
}
|
||||
} else if self.operator == BinaryOperator::And {
|
||||
// Check if we have solids.
|
||||
if let (KclValue::Solid { value: left }, KclValue::Solid { value: right }) = (&left_value, &right_value) {
|
||||
let args = crate::std::Args::new(Default::default(), self.into(), ctx.clone(), None);
|
||||
let result = crate::std::csg::inner_intersect(
|
||||
vec![*left.clone(), *right.clone()],
|
||||
Default::default(),
|
||||
exec_state,
|
||||
args,
|
||||
)
|
||||
.await?;
|
||||
let result =
|
||||
crate::std::csg::inner_intersect(vec![*left.clone(), *right.clone()], exec_state, args).await?;
|
||||
return Ok(result.into());
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,7 +173,7 @@ pub(super) fn format_from_annotations(
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
message: format!(
|
||||
"Unknown format for import, expected one of: {}",
|
||||
crate::IMPORT_FILE_EXTENSIONS.join(", ")
|
||||
annotations::IMPORT_FORMAT_VALUES.join(", ")
|
||||
),
|
||||
source_ranges: vec![p.as_source_range()],
|
||||
})
|
||||
|
||||
@ -11,7 +11,9 @@ pub use cache::{bust_cache, clear_mem_cache};
|
||||
pub use cad_op::Operation;
|
||||
pub use geometry::*;
|
||||
pub use id_generator::IdGenerator;
|
||||
pub(crate) use import::PreImportedGeometry;
|
||||
pub(crate) use import::{
|
||||
import_foreign, send_to_engine as send_import_to_engine, PreImportedGeometry, ZOO_COORD_SYSTEM,
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
pub use kcl_value::{KclObjectFields, KclValue};
|
||||
use kcmc::{
|
||||
|
||||
@ -131,36 +131,11 @@ pub mod pretty {
|
||||
pub use crate::{parsing::token::NumericSuffix, unparser::format_number};
|
||||
}
|
||||
|
||||
#[cfg(feature = "cli")]
|
||||
use clap::ValueEnum;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::log::{log, logln};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
|
||||
pub static ref IMPORT_FILE_EXTENSIONS: Vec<String> = {
|
||||
let mut import_file_extensions = vec!["stp".to_string(), "glb".to_string(), "fbxb".to_string()];
|
||||
#[cfg(feature = "cli")]
|
||||
let named_extensions = kittycad::types::FileImportFormat::value_variants()
|
||||
.iter()
|
||||
.map(|x| format!("{}", x))
|
||||
.collect::<Vec<String>>();
|
||||
#[cfg(not(feature = "cli"))]
|
||||
let named_extensions = vec![]; // We don't really need this outside of the CLI.
|
||||
// Add all the default import formats.
|
||||
import_file_extensions.extend_from_slice(&named_extensions);
|
||||
import_file_extensions
|
||||
};
|
||||
|
||||
pub static ref RELEVANT_FILE_EXTENSIONS: Vec<String> = {
|
||||
let mut relevant_extensions = IMPORT_FILE_EXTENSIONS.clone();
|
||||
relevant_extensions.push("kcl".to_string());
|
||||
relevant_extensions
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Program {
|
||||
#[serde(flatten)]
|
||||
|
||||
@ -3418,148 +3418,3 @@ async fn kcl_test_kcl_lsp_multi_file_error() {
|
||||
|
||||
server.executor_ctx().await.clone().unwrap().close().await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_kcl_lsp_on_hover_untitled_file_scheme() {
|
||||
let server = kcl_lsp_server(true).await.unwrap();
|
||||
|
||||
// Send open file.
|
||||
server
|
||||
.did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
|
||||
text_document: tower_lsp::lsp_types::TextDocumentItem {
|
||||
uri: "untitled:Untitled-1".try_into().unwrap(),
|
||||
language_id: "kcl".to_string(),
|
||||
version: 1,
|
||||
text: r#"startSketchOn(XY)
|
||||
foo = 42
|
||||
foo
|
||||
|
||||
fn bar(x: string): string {
|
||||
return x
|
||||
}
|
||||
|
||||
bar("an arg")
|
||||
|
||||
startSketchOn(XY)
|
||||
|> startProfileAt([0, 0], %)
|
||||
|> line(end = [10, 0])
|
||||
|> line(end = [0, 10])
|
||||
"#
|
||||
.to_string(),
|
||||
},
|
||||
})
|
||||
.await;
|
||||
|
||||
// Std lib call
|
||||
let hover = server
|
||||
.hover(tower_lsp::lsp_types::HoverParams {
|
||||
text_document_position_params: tower_lsp::lsp_types::TextDocumentPositionParams {
|
||||
text_document: tower_lsp::lsp_types::TextDocumentIdentifier {
|
||||
uri: "untitled:Untitled-1".try_into().unwrap(),
|
||||
},
|
||||
position: tower_lsp::lsp_types::Position { line: 0, character: 2 },
|
||||
},
|
||||
work_done_progress_params: Default::default(),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
match hover.unwrap().contents {
|
||||
tower_lsp::lsp_types::HoverContents::Markup(tower_lsp::lsp_types::MarkupContent { value, .. }) => {
|
||||
assert!(value.contains("startSketchOn"));
|
||||
assert!(value.contains(": SketchSurface"));
|
||||
assert!(value.contains("Start a new 2-dimensional sketch on a specific"));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
// Variable use
|
||||
let hover = server
|
||||
.hover(tower_lsp::lsp_types::HoverParams {
|
||||
text_document_position_params: tower_lsp::lsp_types::TextDocumentPositionParams {
|
||||
text_document: tower_lsp::lsp_types::TextDocumentIdentifier {
|
||||
uri: "untitled:Untitled-1".try_into().unwrap(),
|
||||
},
|
||||
position: tower_lsp::lsp_types::Position { line: 2, character: 1 },
|
||||
},
|
||||
work_done_progress_params: Default::default(),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
match hover.unwrap().contents {
|
||||
tower_lsp::lsp_types::HoverContents::Markup(tower_lsp::lsp_types::MarkupContent { value, .. }) => {
|
||||
assert!(value.contains("foo: number = 42"));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
// User-defined function call.
|
||||
let hover = server
|
||||
.hover(tower_lsp::lsp_types::HoverParams {
|
||||
text_document_position_params: tower_lsp::lsp_types::TextDocumentPositionParams {
|
||||
text_document: tower_lsp::lsp_types::TextDocumentIdentifier {
|
||||
uri: "untitled:Untitled-1".try_into().unwrap(),
|
||||
},
|
||||
position: tower_lsp::lsp_types::Position { line: 8, character: 1 },
|
||||
},
|
||||
work_done_progress_params: Default::default(),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
match hover.unwrap().contents {
|
||||
tower_lsp::lsp_types::HoverContents::Markup(tower_lsp::lsp_types::MarkupContent { value, .. }) => {
|
||||
assert!(value.contains("bar(x: string): string"));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
// Variable inside a function
|
||||
let hover = server
|
||||
.hover(tower_lsp::lsp_types::HoverParams {
|
||||
text_document_position_params: tower_lsp::lsp_types::TextDocumentPositionParams {
|
||||
text_document: tower_lsp::lsp_types::TextDocumentIdentifier {
|
||||
uri: "untitled:Untitled-1".try_into().unwrap(),
|
||||
},
|
||||
position: tower_lsp::lsp_types::Position { line: 5, character: 9 },
|
||||
},
|
||||
work_done_progress_params: Default::default(),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
match hover.unwrap().contents {
|
||||
tower_lsp::lsp_types::HoverContents::Markup(tower_lsp::lsp_types::MarkupContent { value, .. }) => {
|
||||
assert!(value.contains("x: string"));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
// std function KwArg
|
||||
let hover = server
|
||||
.hover(tower_lsp::lsp_types::HoverParams {
|
||||
text_document_position_params: tower_lsp::lsp_types::TextDocumentPositionParams {
|
||||
text_document: tower_lsp::lsp_types::TextDocumentIdentifier {
|
||||
uri: "untitled:Untitled-1".try_into().unwrap(),
|
||||
},
|
||||
position: tower_lsp::lsp_types::Position {
|
||||
line: 12,
|
||||
character: 11,
|
||||
},
|
||||
},
|
||||
work_done_progress_params: Default::default(),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
match hover.unwrap().contents {
|
||||
tower_lsp::lsp_types::HoverContents::Markup(tower_lsp::lsp_types::MarkupContent { value, .. }) => {
|
||||
assert!(value.contains("end?: [number]"));
|
||||
assert!(value.contains("How far away (along the X and Y axes) should this line go?"));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
server.executor_ctx().await.clone().unwrap().close().await;
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ use crate::{
|
||||
token::{Token, TokenSlice, TokenType},
|
||||
PIPE_OPERATOR, PIPE_SUBSTITUTION_OPERATOR,
|
||||
},
|
||||
SourceRange, IMPORT_FILE_EXTENSIONS,
|
||||
SourceRange,
|
||||
};
|
||||
|
||||
thread_local! {
|
||||
@ -1803,6 +1803,11 @@ fn import_stmt(i: &mut TokenSlice) -> PResult<BoxNode<ImportStatement>> {
|
||||
end = alias.end;
|
||||
*selector_alias = Some(alias);
|
||||
}
|
||||
|
||||
ParseContext::warn(CompilationError::err(
|
||||
SourceRange::new(start, path.end, path.module_id),
|
||||
"Importing a whole module is experimental, likely to be buggy, and likely to change",
|
||||
));
|
||||
}
|
||||
|
||||
let path_string = match path.inner.value {
|
||||
@ -1838,6 +1843,8 @@ fn import_stmt(i: &mut TokenSlice) -> PResult<BoxNode<ImportStatement>> {
|
||||
))
|
||||
}
|
||||
|
||||
const FOREIGN_IMPORT_EXTENSIONS: [&str; 8] = ["fbx", "gltf", "glb", "obj", "ply", "sldprt", "step", "stl"];
|
||||
|
||||
/// Validates the path string in an `import` statement.
|
||||
///
|
||||
/// `var_name` is `true` if the path will be used as a variable name.
|
||||
@ -1902,11 +1909,12 @@ fn validate_path_string(path_string: String, var_name: bool, path_range: SourceR
|
||||
|
||||
ImportPath::Std { path: segments }
|
||||
} else if path_string.contains('.') {
|
||||
let extn = std::path::Path::new(&path_string).extension().unwrap_or_default();
|
||||
if !IMPORT_FILE_EXTENSIONS.contains(&extn.to_string_lossy().to_string()) {
|
||||
// TODO should allow other extensions if there is a format attribute.
|
||||
let extn = &path_string[path_string.rfind('.').unwrap() + 1..];
|
||||
if !FOREIGN_IMPORT_EXTENSIONS.contains(&extn) {
|
||||
ParseContext::warn(CompilationError::err(
|
||||
path_range,
|
||||
format!("unsupported import path format. KCL files can be imported from the current project, CAD files with the following formats are supported: {}", IMPORT_FILE_EXTENSIONS.join(", ")),
|
||||
format!("unsupported import path format. KCL files can be imported from the current project, CAD files with the following formats are supported: {}", FOREIGN_IMPORT_EXTENSIONS.join(", ")),
|
||||
))
|
||||
}
|
||||
ImportPath::Foreign { path: path_string }
|
||||
@ -1914,7 +1922,7 @@ fn validate_path_string(path_string: String, var_name: bool, path_range: SourceR
|
||||
return Err(ErrMode::Cut(
|
||||
CompilationError::fatal(
|
||||
path_range,
|
||||
format!("unsupported import path format. KCL files can be imported from the current project, CAD files with the following formats are supported: {}", IMPORT_FILE_EXTENSIONS.join(", ")),
|
||||
format!("unsupported import path format. KCL files can be imported from the current project, CAD files with the following formats are supported: {}", FOREIGN_IMPORT_EXTENSIONS.join(", ")),
|
||||
)
|
||||
.into(),
|
||||
));
|
||||
@ -4490,9 +4498,21 @@ export fn cos(num: number(rad)): number(_) {}"#;
|
||||
|
||||
#[test]
|
||||
fn warn_import() {
|
||||
let some_program_string = r#"import "foo.bad""#;
|
||||
let some_program_string = r#"import "foo.kcl""#;
|
||||
let (_, errs) = assert_no_err(some_program_string);
|
||||
assert_eq!(errs.len(), 1, "{errs:#?}");
|
||||
|
||||
let some_program_string = r#"import "foo.obj""#;
|
||||
let (_, errs) = assert_no_err(some_program_string);
|
||||
assert_eq!(errs.len(), 1, "{errs:#?}");
|
||||
|
||||
let some_program_string = r#"import "foo.sldprt""#;
|
||||
let (_, errs) = assert_no_err(some_program_string);
|
||||
assert_eq!(errs.len(), 1, "{errs:#?}");
|
||||
|
||||
let some_program_string = r#"import "foo.bad""#;
|
||||
let (_, errs) = assert_no_err(some_program_string);
|
||||
assert_eq!(errs.len(), 2, "{errs:#?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -664,6 +664,10 @@ impl Args {
|
||||
FromArgs::from_args(self, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn get_import_data(&self) -> Result<(String, Option<crate::std::import::ImportFormat>), KclError> {
|
||||
FromArgs::from_args(self, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn get_sketch_data_and_optional_tag(
|
||||
&self,
|
||||
) -> Result<(super::sketch::SketchData, Option<FaceTag>), KclError> {
|
||||
@ -1073,6 +1077,35 @@ macro_rules! let_field_of {
|
||||
};
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for crate::std::import::ImportFormat {
|
||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||
let obj = arg.as_object()?;
|
||||
let_field_of!(obj, typ "format");
|
||||
match typ {
|
||||
"fbx" => Some(Self::Fbx {}),
|
||||
"gltf" => Some(Self::Gltf {}),
|
||||
"sldprt" => Some(Self::Sldprt {}),
|
||||
"step" => Some(Self::Step {}),
|
||||
"stl" => {
|
||||
let_field_of!(obj, coords?);
|
||||
let_field_of!(obj, units);
|
||||
Some(Self::Stl { coords, units })
|
||||
}
|
||||
"obj" => {
|
||||
let_field_of!(obj, coords?);
|
||||
let_field_of!(obj, units);
|
||||
Some(Self::Obj { coords, units })
|
||||
}
|
||||
"ply" => {
|
||||
let_field_of!(obj, coords?);
|
||||
let_field_of!(obj, units);
|
||||
Some(Self::Ply { coords, units })
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for super::sketch::AngledLineThatIntersectsData {
|
||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||
let obj = arg.as_object()?;
|
||||
|
||||
@ -2,13 +2,6 @@
|
||||
|
||||
use anyhow::Result;
|
||||
use kcl_derive_docs::stdlib;
|
||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, ModelingCmd};
|
||||
use kittycad_modeling_cmds::{
|
||||
self as kcmc,
|
||||
ok_response::OkModelingCmdResponse,
|
||||
output::{BooleanIntersection, BooleanSubtract, BooleanUnion},
|
||||
websocket::OkWebSocketResponseData,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
errors::{KclError, KclErrorDetails},
|
||||
@ -16,13 +9,10 @@ use crate::{
|
||||
std::Args,
|
||||
};
|
||||
|
||||
use super::DEFAULT_TOLERANCE;
|
||||
|
||||
/// Union two or more solids into a single solid.
|
||||
pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solids: Vec<Solid> =
|
||||
args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::Union(vec![RuntimeType::solids()]), exec_state)?;
|
||||
let tolerance = args.get_kw_arg_opt("tolerance")?;
|
||||
|
||||
if solids.len() < 2 {
|
||||
return Err(KclError::UndefinedValue(KclErrorDetails {
|
||||
@ -31,7 +21,7 @@ pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
}));
|
||||
}
|
||||
|
||||
let solids = inner_union(solids, tolerance, exec_state, args).await?;
|
||||
let solids = inner_union(solids, exec_state, args).await?;
|
||||
Ok(solids.into())
|
||||
}
|
||||
|
||||
@ -40,19 +30,18 @@ pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
/// ```no_run
|
||||
/// // Union two cubes using the stdlib functions.
|
||||
///
|
||||
/// fn cube(center, size) {
|
||||
/// fn cube(center) {
|
||||
/// return startSketchOn('XY')
|
||||
/// |> startProfileAt([center[0] - size, center[1] - size], %)
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
|
||||
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
|
||||
/// |> startProfileAt([center[0] - 10, center[1] - 10], %)
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] - 10])
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] + 10])
|
||||
/// |> line(endAbsolute = [center[0] - 10, center[1] + 10])
|
||||
/// |> close()
|
||||
/// |> extrude(length = 10)
|
||||
/// }
|
||||
///
|
||||
/// part001 = cube([0, 0], 10)
|
||||
/// part002 = cube([7, 3], 5)
|
||||
/// |> translate(z = 1)
|
||||
/// part001 = cube([0, 0])
|
||||
/// part002 = cube([20, 10])
|
||||
///
|
||||
/// unionedPart = union([part001, part002])
|
||||
/// ```
|
||||
@ -62,19 +51,18 @@ pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
/// // NOTE: This will not work when using codemods through the UI.
|
||||
/// // Codemods will generate the stdlib function call instead.
|
||||
///
|
||||
/// fn cube(center, size) {
|
||||
/// fn cube(center) {
|
||||
/// return startSketchOn('XY')
|
||||
/// |> startProfileAt([center[0] - size, center[1] - size], %)
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
|
||||
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
|
||||
/// |> startProfileAt([center[0] - 10, center[1] - 10], %)
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] - 10])
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] + 10])
|
||||
/// |> line(endAbsolute = [center[0] - 10, center[1] + 10])
|
||||
/// |> close()
|
||||
/// |> extrude(length = 10)
|
||||
/// }
|
||||
///
|
||||
/// part001 = cube([0, 0], 10)
|
||||
/// part002 = cube([7, 3], 5)
|
||||
/// |> translate(z = 1)
|
||||
/// part001 = cube([0, 0])
|
||||
/// part002 = cube([20, 10])
|
||||
///
|
||||
/// // This is the equivalent of: union([part001, part002])
|
||||
/// unionedPart = part001 + part002
|
||||
@ -85,19 +73,18 @@ pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
/// // NOTE: This will not work when using codemods through the UI.
|
||||
/// // Codemods will generate the stdlib function call instead.
|
||||
///
|
||||
/// fn cube(center, size) {
|
||||
/// fn cube(center) {
|
||||
/// return startSketchOn('XY')
|
||||
/// |> startProfileAt([center[0] - size, center[1] - size], %)
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
|
||||
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
|
||||
/// |> startProfileAt([center[0] - 10, center[1] - 10], %)
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] - 10])
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] + 10])
|
||||
/// |> line(endAbsolute = [center[0] - 10, center[1] + 10])
|
||||
/// |> close()
|
||||
/// |> extrude(length = 10)
|
||||
/// }
|
||||
///
|
||||
/// part001 = cube([0, 0], 10)
|
||||
/// part002 = cube([7, 3], 5)
|
||||
/// |> translate(z = 1)
|
||||
/// part001 = cube([0, 0])
|
||||
/// part002 = cube([20, 10])
|
||||
///
|
||||
/// // This is the equivalent of: union([part001, part002])
|
||||
/// // Programmers will understand `|` as a union operation, but mechanical engineers
|
||||
@ -109,64 +96,31 @@ pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
||||
feature_tree_operation = true,
|
||||
keywords = true,
|
||||
unlabeled_first = true,
|
||||
deprecated = true,
|
||||
args = {
|
||||
solids = {docs = "The solids to union."},
|
||||
tolerance = {docs = "The tolerance to use for the union operation."},
|
||||
}
|
||||
}]
|
||||
pub(crate) async fn inner_union(
|
||||
solids: Vec<Solid>,
|
||||
tolerance: Option<f64>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Vec<Solid>, KclError> {
|
||||
let solid_out_id = exec_state.next_uuid();
|
||||
|
||||
let mut solid = solids[0].clone();
|
||||
solid.id = solid_out_id;
|
||||
let mut new_solids = vec![solid.clone()];
|
||||
|
||||
if args.ctx.no_engine_commands().await {
|
||||
return Ok(new_solids);
|
||||
}
|
||||
|
||||
// Flush the fillets for the solids.
|
||||
args.flush_batch_for_solids(exec_state, &solids).await?;
|
||||
|
||||
let result = args
|
||||
.send_modeling_cmd(
|
||||
solid_out_id,
|
||||
ModelingCmd::from(mcmd::BooleanUnion {
|
||||
solid_ids: solids.iter().map(|s| s.id).collect(),
|
||||
tolerance: LengthUnit(tolerance.unwrap_or(DEFAULT_TOLERANCE)),
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
// TODO: call the engine union operation.
|
||||
// TODO: figure out all the shit after for the faces etc.
|
||||
|
||||
let OkWebSocketResponseData::Modeling {
|
||||
modeling_response: OkModelingCmdResponse::BooleanUnion(BooleanUnion { extra_solid_ids }),
|
||||
} = result
|
||||
else {
|
||||
return Err(KclError::Internal(KclErrorDetails {
|
||||
message: "Failed to get the result of the union operation.".to_string(),
|
||||
source_ranges: vec![args.source_range],
|
||||
}));
|
||||
};
|
||||
|
||||
// If we have more solids, set those as well.
|
||||
if !extra_solid_ids.is_empty() {
|
||||
solid.id = extra_solid_ids[0];
|
||||
new_solids.push(solid.clone());
|
||||
}
|
||||
|
||||
Ok(new_solids)
|
||||
// For now just return the first solid.
|
||||
// Til we have a proper implementation.
|
||||
Ok(vec![solids[0].clone()])
|
||||
}
|
||||
|
||||
/// Intersect returns the shared volume between multiple solids, preserving only
|
||||
/// overlapping regions.
|
||||
pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solids: Vec<Solid> = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let tolerance = args.get_kw_arg_opt("tolerance")?;
|
||||
|
||||
if solids.len() < 2 {
|
||||
return Err(KclError::UndefinedValue(KclErrorDetails {
|
||||
@ -175,7 +129,7 @@ pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValu
|
||||
}));
|
||||
}
|
||||
|
||||
let solids = inner_intersect(solids, tolerance, exec_state, args).await?;
|
||||
let solids = inner_intersect(solids, exec_state, args).await?;
|
||||
Ok(solids.into())
|
||||
}
|
||||
|
||||
@ -190,19 +144,18 @@ pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValu
|
||||
/// ```no_run
|
||||
/// // Intersect two cubes using the stdlib functions.
|
||||
///
|
||||
/// fn cube(center, size) {
|
||||
/// fn cube(center) {
|
||||
/// return startSketchOn('XY')
|
||||
/// |> startProfileAt([center[0] - size, center[1] - size], %)
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
|
||||
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
|
||||
/// |> startProfileAt([center[0] - 10, center[1] - 10], %)
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] - 10])
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] + 10])
|
||||
/// |> line(endAbsolute = [center[0] - 10, center[1] + 10])
|
||||
/// |> close()
|
||||
/// |> extrude(length = 10)
|
||||
/// }
|
||||
///
|
||||
/// part001 = cube([0, 0], 10)
|
||||
/// part002 = cube([7, 3], 5)
|
||||
/// |> translate(z = 1)
|
||||
/// part001 = cube([0, 0])
|
||||
/// part002 = cube([8, 8])
|
||||
///
|
||||
/// intersectedPart = intersect([part001, part002])
|
||||
/// ```
|
||||
@ -212,19 +165,18 @@ pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValu
|
||||
/// // NOTE: This will not work when using codemods through the UI.
|
||||
/// // Codemods will generate the stdlib function call instead.
|
||||
///
|
||||
/// fn cube(center, size) {
|
||||
/// fn cube(center) {
|
||||
/// return startSketchOn('XY')
|
||||
/// |> startProfileAt([center[0] - size, center[1] - size], %)
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
|
||||
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
|
||||
/// |> startProfileAt([center[0] - 10, center[1] - 10], %)
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] - 10])
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] + 10])
|
||||
/// |> line(endAbsolute = [center[0] - 10, center[1] + 10])
|
||||
/// |> close()
|
||||
/// |> extrude(length = 10)
|
||||
/// }
|
||||
///
|
||||
/// part001 = cube([0, 0], 10)
|
||||
/// part002 = cube([7, 3], 5)
|
||||
/// |> translate(z = 1)
|
||||
/// part001 = cube([0, 0])
|
||||
/// part002 = cube([8, 8])
|
||||
///
|
||||
/// // This is the equivalent of: intersect([part001, part002])
|
||||
/// intersectedPart = part001 & part002
|
||||
@ -234,57 +186,25 @@ pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValu
|
||||
feature_tree_operation = true,
|
||||
keywords = true,
|
||||
unlabeled_first = true,
|
||||
deprecated = true,
|
||||
args = {
|
||||
solids = {docs = "The solids to intersect."},
|
||||
tolerance = {docs = "The tolerance to use for the intersection operation."},
|
||||
}
|
||||
}]
|
||||
pub(crate) async fn inner_intersect(
|
||||
solids: Vec<Solid>,
|
||||
tolerance: Option<f64>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Vec<Solid>, KclError> {
|
||||
let solid_out_id = exec_state.next_uuid();
|
||||
|
||||
let mut solid = solids[0].clone();
|
||||
solid.id = solid_out_id;
|
||||
let mut new_solids = vec![solid.clone()];
|
||||
|
||||
if args.ctx.no_engine_commands().await {
|
||||
return Ok(new_solids);
|
||||
}
|
||||
|
||||
// Flush the fillets for the solids.
|
||||
args.flush_batch_for_solids(exec_state, &solids).await?;
|
||||
|
||||
let result = args
|
||||
.send_modeling_cmd(
|
||||
solid_out_id,
|
||||
ModelingCmd::from(mcmd::BooleanIntersection {
|
||||
solid_ids: solids.iter().map(|s| s.id).collect(),
|
||||
tolerance: LengthUnit(tolerance.unwrap_or(DEFAULT_TOLERANCE)),
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
// TODO: call the engine union operation.
|
||||
// TODO: figure out all the shit after for the faces etc.
|
||||
|
||||
let OkWebSocketResponseData::Modeling {
|
||||
modeling_response: OkModelingCmdResponse::BooleanIntersection(BooleanIntersection { extra_solid_ids }),
|
||||
} = result
|
||||
else {
|
||||
return Err(KclError::Internal(KclErrorDetails {
|
||||
message: "Failed to get the result of the intersection operation.".to_string(),
|
||||
source_ranges: vec![args.source_range],
|
||||
}));
|
||||
};
|
||||
|
||||
// If we have more solids, set those as well.
|
||||
if !extra_solid_ids.is_empty() {
|
||||
solid.id = extra_solid_ids[0];
|
||||
new_solids.push(solid.clone());
|
||||
}
|
||||
|
||||
Ok(new_solids)
|
||||
// For now just return the first solid.
|
||||
// Til we have a proper implementation.
|
||||
Ok(vec![solids[0].clone()])
|
||||
}
|
||||
|
||||
/// Subtract removes tool solids from base solids, leaving the remaining material.
|
||||
@ -292,23 +212,7 @@ pub async fn subtract(exec_state: &mut ExecState, args: Args) -> Result<KclValue
|
||||
let solids: Vec<Solid> = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let tools: Vec<Solid> = args.get_kw_arg_typed("tools", &RuntimeType::solids(), exec_state)?;
|
||||
|
||||
if solids.len() > 1 {
|
||||
return Err(KclError::UndefinedValue(KclErrorDetails {
|
||||
message: "Only one solid is allowed for a subtract operation, currently.".to_string(),
|
||||
source_ranges: vec![args.source_range],
|
||||
}));
|
||||
}
|
||||
|
||||
if tools.len() > 1 {
|
||||
return Err(KclError::UndefinedValue(KclErrorDetails {
|
||||
message: "Only one tool is allowed for a subtract operation, currently.".to_string(),
|
||||
source_ranges: vec![args.source_range],
|
||||
}));
|
||||
}
|
||||
|
||||
let tolerance = args.get_kw_arg_opt("tolerance")?;
|
||||
|
||||
let solids = inner_subtract(solids, tools, tolerance, exec_state, args).await?;
|
||||
let solids = inner_subtract(solids, tools, exec_state, args).await?;
|
||||
Ok(solids.into())
|
||||
}
|
||||
|
||||
@ -323,19 +227,20 @@ pub async fn subtract(exec_state: &mut ExecState, args: Args) -> Result<KclValue
|
||||
/// ```no_run
|
||||
/// // Subtract a cylinder from a cube using the stdlib functions.
|
||||
///
|
||||
/// fn cube(center, size) {
|
||||
/// fn cube(center) {
|
||||
/// return startSketchOn('XY')
|
||||
/// |> startProfileAt([center[0] - size, center[1] - size], %)
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
|
||||
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
|
||||
/// |> startProfileAt([center[0] - 10, center[1] - 10], %)
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] - 10])
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] + 10])
|
||||
/// |> line(endAbsolute = [center[0] - 10, center[1] + 10])
|
||||
/// |> close()
|
||||
/// |> extrude(length = 10)
|
||||
/// }
|
||||
///
|
||||
/// part001 = cube([0, 0], 10)
|
||||
/// part002 = cube([7, 3], 5)
|
||||
/// |> translate(z = 1)
|
||||
/// part001 = cube([0, 0])
|
||||
/// part002 = startSketchOn('XY')
|
||||
/// |> circle(center = [0, 0], radius = 2)
|
||||
/// |> extrude(length = 10)
|
||||
///
|
||||
/// subtractedPart = subtract([part001], tools=[part002])
|
||||
/// ```
|
||||
@ -345,19 +250,20 @@ pub async fn subtract(exec_state: &mut ExecState, args: Args) -> Result<KclValue
|
||||
/// // NOTE: This will not work when using codemods through the UI.
|
||||
/// // Codemods will generate the stdlib function call instead.
|
||||
///
|
||||
/// fn cube(center, size) {
|
||||
/// fn cube(center) {
|
||||
/// return startSketchOn('XY')
|
||||
/// |> startProfileAt([center[0] - size, center[1] - size], %)
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] - size])
|
||||
/// |> line(endAbsolute = [center[0] + size, center[1] + size])
|
||||
/// |> line(endAbsolute = [center[0] - size, center[1] + size])
|
||||
/// |> startProfileAt([center[0] - 10, center[1] - 10], %)
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] - 10])
|
||||
/// |> line(endAbsolute = [center[0] + 10, center[1] + 10])
|
||||
/// |> line(endAbsolute = [center[0] - 10, center[1] + 10])
|
||||
/// |> close()
|
||||
/// |> extrude(length = 10)
|
||||
/// }
|
||||
///
|
||||
/// part001 = cube([0, 0], 10)
|
||||
/// part002 = cube([7, 3], 5)
|
||||
/// |> translate(z = 1)
|
||||
/// part001 = cube([0, 0])
|
||||
/// part002 = startSketchOn('XY')
|
||||
/// |> circle(center = [0, 0], radius = 2)
|
||||
/// |> extrude(length = 10)
|
||||
///
|
||||
/// // This is the equivalent of: subtract([part001], tools=[part002])
|
||||
/// subtractedPart = part001 - part002
|
||||
@ -367,59 +273,26 @@ pub async fn subtract(exec_state: &mut ExecState, args: Args) -> Result<KclValue
|
||||
feature_tree_operation = true,
|
||||
keywords = true,
|
||||
unlabeled_first = true,
|
||||
deprecated = true,
|
||||
args = {
|
||||
solids = {docs = "The solids to use as the base to subtract from."},
|
||||
tools = {docs = "The solids to subtract."},
|
||||
tolerance = {docs = "The tolerance to use for the subtraction operation."},
|
||||
}
|
||||
}]
|
||||
pub(crate) async fn inner_subtract(
|
||||
solids: Vec<Solid>,
|
||||
tools: Vec<Solid>,
|
||||
tolerance: Option<f64>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Vec<Solid>, KclError> {
|
||||
let solid_out_id = exec_state.next_uuid();
|
||||
|
||||
let mut solid = solids[0].clone();
|
||||
solid.id = solid_out_id;
|
||||
let mut new_solids = vec![solid.clone()];
|
||||
|
||||
if args.ctx.no_engine_commands().await {
|
||||
return Ok(new_solids);
|
||||
}
|
||||
|
||||
// Flush the fillets for the solids and the tools.
|
||||
let combined_solids = solids.iter().chain(tools.iter()).cloned().collect::<Vec<Solid>>();
|
||||
args.flush_batch_for_solids(exec_state, &combined_solids).await?;
|
||||
|
||||
let result = args
|
||||
.send_modeling_cmd(
|
||||
solid_out_id,
|
||||
ModelingCmd::from(mcmd::BooleanSubtract {
|
||||
target_ids: solids.iter().map(|s| s.id).collect(),
|
||||
tool_ids: tools.iter().map(|s| s.id).collect(),
|
||||
tolerance: LengthUnit(tolerance.unwrap_or(DEFAULT_TOLERANCE)),
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
// TODO: call the engine union operation.
|
||||
// TODO: figure out all the shit after for the faces etc.
|
||||
|
||||
let OkWebSocketResponseData::Modeling {
|
||||
modeling_response: OkModelingCmdResponse::BooleanSubtract(BooleanSubtract { extra_solid_ids }),
|
||||
} = result
|
||||
else {
|
||||
return Err(KclError::Internal(KclErrorDetails {
|
||||
message: "Failed to get the result of the subtract operation.".to_string(),
|
||||
source_ranges: vec![args.source_range],
|
||||
}));
|
||||
};
|
||||
|
||||
// If we have more solids, set those as well.
|
||||
if !extra_solid_ids.is_empty() {
|
||||
solid.id = extra_solid_ids[0];
|
||||
new_solids.push(solid.clone());
|
||||
}
|
||||
|
||||
Ok(new_solids)
|
||||
// For now just return the first solid.
|
||||
// Til we have a proper implementation.
|
||||
Ok(vec![solids[0].clone()])
|
||||
}
|
||||
|
||||
@ -10,7 +10,6 @@ use kcmc::{
|
||||
ok_response::OkModelingCmdResponse,
|
||||
output::ExtrusionFaceInfo,
|
||||
shared::ExtrusionFaceCapType,
|
||||
shared::Opposite,
|
||||
websocket::{ModelingCmdReq, OkWebSocketResponseData},
|
||||
ModelingCmd,
|
||||
};
|
||||
@ -31,22 +30,10 @@ use crate::{
|
||||
pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let sketches = args.get_unlabeled_kw_arg_typed("sketches", &RuntimeType::sketches(), exec_state)?;
|
||||
let length = args.get_kw_arg("length")?;
|
||||
let symmetric = args.get_kw_arg_opt("symmetric")?;
|
||||
let bidirectional_length = args.get_kw_arg_opt("bidirectionalLength")?;
|
||||
let tag_start = args.get_kw_arg_opt("tagStart")?;
|
||||
let tag_end = args.get_kw_arg_opt("tagEnd")?;
|
||||
|
||||
let result = inner_extrude(
|
||||
sketches,
|
||||
length,
|
||||
symmetric,
|
||||
bidirectional_length,
|
||||
tag_start,
|
||||
tag_end,
|
||||
exec_state,
|
||||
args,
|
||||
)
|
||||
.await?;
|
||||
let result = inner_extrude(sketches, length, tag_start, tag_end, exec_state, args).await?;
|
||||
|
||||
Ok(result.into())
|
||||
}
|
||||
@ -100,50 +87,6 @@ pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
///
|
||||
/// example = extrude(exampleSketch, length = 10)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// exampleSketch = startSketchOn('XZ')
|
||||
/// |> startProfileAt([-10, 0], %)
|
||||
/// |> arc({
|
||||
/// angleStart = 120,
|
||||
/// angleEnd = -60,
|
||||
/// radius = 5,
|
||||
/// }, %)
|
||||
/// |> line(end = [10, 0])
|
||||
/// |> line(end = [5, 0])
|
||||
/// |> bezierCurve({
|
||||
/// control1 = [-3, 0],
|
||||
/// control2 = [2, 10],
|
||||
/// to = [-5, 10],
|
||||
/// }, %)
|
||||
/// |> line(end = [-4, 10])
|
||||
/// |> line(end = [-5, -2])
|
||||
/// |> close()
|
||||
///
|
||||
/// example = extrude(exampleSketch, length = 20, symmetric = true)
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// exampleSketch = startSketchOn('XZ')
|
||||
/// |> startProfileAt([-10, 0], %)
|
||||
/// |> arc({
|
||||
/// angleStart = 120,
|
||||
/// angleEnd = -60,
|
||||
/// radius = 5,
|
||||
/// }, %)
|
||||
/// |> line(end = [10, 0])
|
||||
/// |> line(end = [5, 0])
|
||||
/// |> bezierCurve({
|
||||
/// control1 = [-3, 0],
|
||||
/// control2 = [2, 10],
|
||||
/// to = [-5, 10],
|
||||
/// }, %)
|
||||
/// |> line(end = [-4, 10])
|
||||
/// |> line(end = [-5, -2])
|
||||
/// |> close()
|
||||
///
|
||||
/// example = extrude(exampleSketch, length = 10, bidirectionalLength = 50)
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "extrude",
|
||||
feature_tree_operation = true,
|
||||
@ -152,9 +95,6 @@ pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
args = {
|
||||
sketches = { docs = "Which sketch or sketches should be extruded"},
|
||||
length = { docs = "How far to extrude the given sketches"},
|
||||
symmetric = { docs = "If true, the extrusion will happen symmetrically around the sketch. Otherwise, the
|
||||
extrusion will happen on only one side of the sketch." },
|
||||
bidirectional_length = { docs = "If specified, will also extrude in the opposite direction to 'distance' to the specified distance. If 'symmetric' is true, this value is ignored."},
|
||||
tag_start = { docs = "A named tag for the face at the start of the extrusion, i.e. the original sketch" },
|
||||
tag_end = { docs = "A named tag for the face at the end of the extrusion, i.e. the new face created by extruding the original sketch" },
|
||||
}
|
||||
@ -163,8 +103,6 @@ pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
async fn inner_extrude(
|
||||
sketches: Vec<Sketch>,
|
||||
length: f64,
|
||||
symmetric: Option<bool>,
|
||||
bidirectional_length: Option<f64>,
|
||||
tag_start: Option<TagNode>,
|
||||
tag_end: Option<TagNode>,
|
||||
exec_state: &mut ExecState,
|
||||
@ -172,25 +110,6 @@ async fn inner_extrude(
|
||||
) -> Result<Vec<Solid>, KclError> {
|
||||
// Extrude the element(s).
|
||||
let mut solids = Vec::new();
|
||||
|
||||
if symmetric.unwrap_or(false) && bidirectional_length.is_some() {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
source_ranges: vec![args.source_range],
|
||||
message: "You cannot give both `symmetric` and `bidirectional` params, you have to choose one or the other"
|
||||
.to_owned(),
|
||||
}));
|
||||
}
|
||||
|
||||
let bidirection = bidirectional_length.map(LengthUnit);
|
||||
|
||||
let opposite = match (symmetric, bidirection) {
|
||||
(Some(true), _) => Opposite::Symmetric,
|
||||
(None, None) => Opposite::None,
|
||||
(Some(false), None) => Opposite::None,
|
||||
(None, Some(length)) => Opposite::Other(length),
|
||||
(Some(false), Some(length)) => Opposite::Other(length),
|
||||
};
|
||||
|
||||
for sketch in &sketches {
|
||||
let id = exec_state.next_uuid();
|
||||
args.batch_modeling_cmds(&sketch.build_sketch_mode_cmds(
|
||||
@ -201,7 +120,6 @@ async fn inner_extrude(
|
||||
target: sketch.id.into(),
|
||||
distance: LengthUnit(length),
|
||||
faces: Default::default(),
|
||||
opposite: opposite.clone(),
|
||||
}),
|
||||
},
|
||||
))
|
||||
|
||||
181
rust/kcl-lib/src/std/import.rs
Normal file
181
rust/kcl-lib/src/std/import.rs
Normal file
@ -0,0 +1,181 @@
|
||||
//! Standard library functions involved in importing files.
|
||||
|
||||
use anyhow::Result;
|
||||
use kcl_derive_docs::stdlib;
|
||||
use kcmc::{coord::System, format::InputFormat3d, units::UnitLength};
|
||||
use kittycad_modeling_cmds as kcmc;
|
||||
|
||||
use crate::{
|
||||
errors::{KclError, KclErrorDetails},
|
||||
execution::{import_foreign, send_import_to_engine, ExecState, ImportedGeometry, KclValue, ZOO_COORD_SYSTEM},
|
||||
std::Args,
|
||||
};
|
||||
|
||||
/// Import format specifier
|
||||
#[derive(serde :: Serialize, serde :: Deserialize, PartialEq, Debug, Clone, schemars :: JsonSchema)]
|
||||
#[cfg_attr(feature = "tabled", derive(tabled::Tabled))]
|
||||
#[serde(tag = "format")]
|
||||
pub enum ImportFormat {
|
||||
/// Autodesk Filmbox (FBX) format
|
||||
#[serde(rename = "fbx")]
|
||||
Fbx {},
|
||||
/// Binary glTF 2.0. We refer to this as glTF since that is how our customers refer to
|
||||
/// it, but this can also import binary glTF (glb).
|
||||
#[serde(rename = "gltf")]
|
||||
Gltf {},
|
||||
/// Wavefront OBJ format.
|
||||
#[serde(rename = "obj")]
|
||||
Obj {
|
||||
/// Co-ordinate system of input data.
|
||||
/// Defaults to the [KittyCAD co-ordinate system.
|
||||
coords: Option<System>,
|
||||
/// The units of the input data. This is very important for correct scaling and when
|
||||
/// calculating physics properties like mass, etc.
|
||||
/// Defaults to millimeters.
|
||||
units: UnitLength,
|
||||
},
|
||||
/// The PLY Polygon File Format.
|
||||
#[serde(rename = "ply")]
|
||||
Ply {
|
||||
/// Co-ordinate system of input data.
|
||||
/// Defaults to the [KittyCAD co-ordinate system.
|
||||
coords: Option<System>,
|
||||
/// The units of the input data. This is very important for correct scaling and when
|
||||
/// calculating physics properties like mass, etc.
|
||||
/// Defaults to millimeters.
|
||||
units: UnitLength,
|
||||
},
|
||||
/// SolidWorks part (SLDPRT) format.
|
||||
#[serde(rename = "sldprt")]
|
||||
Sldprt {},
|
||||
/// ISO 10303-21 (STEP) format.
|
||||
#[serde(rename = "step")]
|
||||
Step {},
|
||||
/// *ST**ereo**L**ithography format.
|
||||
#[serde(rename = "stl")]
|
||||
Stl {
|
||||
/// Co-ordinate system of input data.
|
||||
/// Defaults to the [KittyCAD co-ordinate system.
|
||||
coords: Option<System>,
|
||||
/// The units of the input data. This is very important for correct scaling and when
|
||||
/// calculating physics properties like mass, etc.
|
||||
/// Defaults to millimeters.
|
||||
units: UnitLength,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<ImportFormat> for InputFormat3d {
|
||||
fn from(format: ImportFormat) -> Self {
|
||||
match format {
|
||||
ImportFormat::Fbx {} => InputFormat3d::Fbx(Default::default()),
|
||||
ImportFormat::Gltf {} => InputFormat3d::Gltf(Default::default()),
|
||||
ImportFormat::Obj { coords, units } => InputFormat3d::Obj(kcmc::format::obj::import::Options {
|
||||
coords: coords.unwrap_or(ZOO_COORD_SYSTEM),
|
||||
units,
|
||||
}),
|
||||
ImportFormat::Ply { coords, units } => InputFormat3d::Ply(kcmc::format::ply::import::Options {
|
||||
coords: coords.unwrap_or(ZOO_COORD_SYSTEM),
|
||||
units,
|
||||
}),
|
||||
ImportFormat::Sldprt {} => InputFormat3d::Sldprt(kcmc::format::sldprt::import::Options {
|
||||
split_closed_faces: false,
|
||||
}),
|
||||
ImportFormat::Step {} => InputFormat3d::Step(kcmc::format::step::import::Options {
|
||||
split_closed_faces: false,
|
||||
}),
|
||||
ImportFormat::Stl { coords, units } => InputFormat3d::Stl(kcmc::format::stl::import::Options {
|
||||
coords: coords.unwrap_or(ZOO_COORD_SYSTEM),
|
||||
units,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Import a CAD file.
|
||||
/// For formats lacking unit data (STL, OBJ, PLY), the default import unit is millimeters.
|
||||
/// Otherwise you can specify the unit by passing in the options parameter.
|
||||
/// If you import a gltf file, we will try to find the bin file and import it as well.
|
||||
///
|
||||
/// Import paths are relative to the current project directory. This only works in the desktop app
|
||||
/// not in browser.
|
||||
pub async fn import(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let (file_path, options): (String, Option<ImportFormat>) = args.get_import_data()?;
|
||||
|
||||
let imported_geometry = inner_import(file_path, options, exec_state, args).await?;
|
||||
Ok(KclValue::ImportedGeometry(imported_geometry))
|
||||
}
|
||||
|
||||
/// Import a CAD file.
|
||||
///
|
||||
/// **DEPRECATED** Prefer to use import statements.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// ```no_run
|
||||
/// model = import("tests/inputs/cube.obj")
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// model = import("tests/inputs/cube.obj", {format: "obj", units: "m"})
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// model = import("tests/inputs/cube.gltf")
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// model = import("tests/inputs/cube.sldprt")
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// model = import("tests/inputs/cube.step")
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// import height, buildSketch from 'common.kcl'
|
||||
///
|
||||
/// plane = 'XZ'
|
||||
/// margin = 2
|
||||
/// s1 = buildSketch(plane, [0, 0])
|
||||
/// s2 = buildSketch(plane, [0, height() + margin])
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "import",
|
||||
feature_tree_operation = true,
|
||||
deprecated = true,
|
||||
tags = [],
|
||||
}]
|
||||
async fn inner_import(
|
||||
file_path: String,
|
||||
options: Option<ImportFormat>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<ImportedGeometry, KclError> {
|
||||
if file_path.is_empty() {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: "No file path was provided.".to_string(),
|
||||
source_ranges: vec![args.source_range],
|
||||
}));
|
||||
}
|
||||
|
||||
let format = options.map(InputFormat3d::from);
|
||||
send_import_to_engine(
|
||||
import_foreign(
|
||||
std::path::Path::new(&file_path),
|
||||
format,
|
||||
exec_state,
|
||||
&args.ctx,
|
||||
args.source_range,
|
||||
)
|
||||
.await?,
|
||||
&args.ctx,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@ -12,6 +12,7 @@ pub mod edge;
|
||||
pub mod extrude;
|
||||
pub mod fillet;
|
||||
pub mod helix;
|
||||
pub mod import;
|
||||
pub mod loft;
|
||||
pub mod math;
|
||||
pub mod mirror;
|
||||
@ -110,6 +111,7 @@ lazy_static! {
|
||||
Box::new(crate::std::sweep::Sweep),
|
||||
Box::new(crate::std::loft::Loft),
|
||||
Box::new(crate::std::planes::OffsetPlane),
|
||||
Box::new(crate::std::import::Import),
|
||||
Box::new(crate::std::math::Acos),
|
||||
Box::new(crate::std::math::Asin),
|
||||
Box::new(crate::std::math::Atan),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! Standard library revolution surfaces.
|
||||
|
||||
use anyhow::Result;
|
||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, shared::Opposite, ModelingCmd};
|
||||
use kcmc::{each_cmd as mcmd, length_unit::LengthUnit, shared::Angle, ModelingCmd};
|
||||
use kittycad_modeling_cmds::{self as kcmc, shared::Point3d};
|
||||
|
||||
use super::DEFAULT_TOLERANCE;
|
||||
@ -30,22 +30,8 @@ pub async fn revolve(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
||||
let tolerance = args.get_kw_arg_opt("tolerance")?;
|
||||
let tag_start = args.get_kw_arg_opt("tagStart")?;
|
||||
let tag_end = args.get_kw_arg_opt("tagEnd")?;
|
||||
let symmetric = args.get_kw_arg_opt("symmetric")?;
|
||||
let bidirectional_angle = args.get_kw_arg_opt("bidirectionalAngle")?;
|
||||
|
||||
let value = inner_revolve(
|
||||
sketches,
|
||||
axis,
|
||||
angle,
|
||||
tolerance,
|
||||
tag_start,
|
||||
tag_end,
|
||||
symmetric,
|
||||
bidirectional_angle,
|
||||
exec_state,
|
||||
args,
|
||||
)
|
||||
.await?;
|
||||
let value = inner_revolve(sketches, axis, angle, tolerance, tag_start, tag_end, exec_state, args).await?;
|
||||
Ok(value.into())
|
||||
}
|
||||
|
||||
@ -57,8 +43,6 @@ async fn inner_revolve(
|
||||
tolerance: Option<f64>,
|
||||
tag_start: Option<TagNode>,
|
||||
tag_end: Option<TagNode>,
|
||||
symmetric: Option<bool>,
|
||||
bidirectional_angle: Option<f64>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Vec<Solid>, KclError> {
|
||||
@ -74,54 +58,8 @@ async fn inner_revolve(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(bidirectional_angle) = bidirectional_angle {
|
||||
// Return an error if the angle is zero.
|
||||
// We don't use validate() here because we want to return a specific error message that is
|
||||
// nice and we use the other data in the docs, so we still need use the derive above for the json schema.
|
||||
if !(-360.0..=360.0).contains(&bidirectional_angle) || bidirectional_angle == 0.0 {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: format!(
|
||||
"Expected bidirectional angle to be between -360 and 360 and not 0, found `{}`",
|
||||
bidirectional_angle
|
||||
),
|
||||
source_ranges: vec![args.source_range],
|
||||
}));
|
||||
}
|
||||
|
||||
if let Some(angle) = angle {
|
||||
let ang = angle.signum() * bidirectional_angle + angle;
|
||||
if !(-360.0..=360.0).contains(&ang) {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
message: format!(
|
||||
"Combined angle and bidirectional must be between -360 and 360, found '{}'",
|
||||
ang
|
||||
),
|
||||
source_ranges: vec![args.source_range],
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if symmetric.unwrap_or(false) && bidirectional_angle.is_some() {
|
||||
return Err(KclError::Semantic(KclErrorDetails {
|
||||
source_ranges: vec![args.source_range],
|
||||
message: "You cannot give both `symmetric` and `bidirectional` params, you have to choose one or the other"
|
||||
.to_owned(),
|
||||
}));
|
||||
}
|
||||
|
||||
let angle = Angle::from_degrees(angle.unwrap_or(360.0));
|
||||
|
||||
let bidirectional_angle = bidirectional_angle.map(Angle::from_degrees);
|
||||
|
||||
let opposite = match (symmetric, bidirectional_angle) {
|
||||
(Some(true), _) => Opposite::Symmetric,
|
||||
(None, None) => Opposite::None,
|
||||
(Some(false), None) => Opposite::None,
|
||||
(None, Some(angle)) => Opposite::Other(angle),
|
||||
(Some(false), Some(angle)) => Opposite::Other(angle),
|
||||
};
|
||||
|
||||
let mut solids = Vec::new();
|
||||
for sketch in &sketches {
|
||||
let id = exec_state.next_uuid();
|
||||
@ -145,7 +83,6 @@ async fn inner_revolve(
|
||||
},
|
||||
tolerance: LengthUnit(tolerance.unwrap_or(DEFAULT_TOLERANCE)),
|
||||
axis_is_2d: true,
|
||||
opposite: opposite.clone(),
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
@ -159,7 +96,6 @@ async fn inner_revolve(
|
||||
target: sketch.id.into(),
|
||||
edge_id,
|
||||
tolerance: LengthUnit(tolerance.unwrap_or(DEFAULT_TOLERANCE)),
|
||||
opposite: opposite.clone(),
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
#[cfg(feature = "cli")]
|
||||
use clap::ValueEnum;
|
||||
|
||||
use crate::parsing::{
|
||||
ast::types::{
|
||||
Annotation, ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem,
|
||||
@ -192,7 +195,7 @@ impl Node<Annotation> {
|
||||
result.push_str(&indentation);
|
||||
result.push_str(comment);
|
||||
}
|
||||
if !result.ends_with("\n\n") && result != "\n" {
|
||||
if !comment.ends_with("*/") && !result.ends_with("\n\n") && result != "\n" {
|
||||
result.push('\n');
|
||||
}
|
||||
}
|
||||
@ -864,6 +867,29 @@ impl Parameter {
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
|
||||
pub static ref IMPORT_FILE_EXTENSIONS: Vec<String> = {
|
||||
let mut import_file_extensions = vec!["stp".to_string(), "glb".to_string(), "fbxb".to_string()];
|
||||
#[cfg(feature = "cli")]
|
||||
let named_extensions = kittycad::types::FileImportFormat::value_variants()
|
||||
.iter()
|
||||
.map(|x| format!("{}", x))
|
||||
.collect::<Vec<String>>();
|
||||
#[cfg(not(feature = "cli"))]
|
||||
let named_extensions = vec![]; // We don't really need this outside of the CLI.
|
||||
// Add all the default import formats.
|
||||
import_file_extensions.extend_from_slice(&named_extensions);
|
||||
import_file_extensions
|
||||
};
|
||||
|
||||
pub static ref RELEVANT_EXTENSIONS: Vec<String> = {
|
||||
let mut relevant_extensions = IMPORT_FILE_EXTENSIONS.clone();
|
||||
relevant_extensions.push("kcl".to_string());
|
||||
relevant_extensions
|
||||
};
|
||||
}
|
||||
|
||||
/// Collect all the kcl (and other relevant) files in a directory, recursively.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[async_recursion::async_recursion]
|
||||
@ -883,7 +909,7 @@ pub async fn walk_dir(dir: &std::path::PathBuf) -> Result<Vec<std::path::PathBuf
|
||||
files.extend(walk_dir(&path).await?);
|
||||
} else if path
|
||||
.extension()
|
||||
.is_some_and(|ext| crate::RELEVANT_FILE_EXTENSIONS.contains(&ext.to_string_lossy().to_string()))
|
||||
.is_some_and(|ext| RELEVANT_EXTENSIONS.contains(&ext.to_string_lossy().to_string()))
|
||||
{
|
||||
files.push(path);
|
||||
}
|
||||
@ -1022,20 +1048,6 @@ bar = 0
|
||||
assert_eq!(output, input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recast_annotations_with_block_comment() {
|
||||
let input = r#"/* Start comment
|
||||
|
||||
sdfsdfsdfs */
|
||||
@settings(defaultLengthUnit = in)
|
||||
|
||||
foo = 42
|
||||
"#;
|
||||
let program = crate::parsing::top_level_parse(input).unwrap();
|
||||
let output = program.recast(&Default::default(), 0);
|
||||
assert_eq!(output, input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_recast_if_else_if_same() {
|
||||
let input = r#"b = if false {
|
||||
|
||||
@ -585,32 +585,6 @@ export fn helix(
|
||||
/// |> circle(center = [-10, 10], radius = 4)
|
||||
/// |> revolve(angle = 90, axis = revolveAxis)
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// // Symmetrically revolve around a path.
|
||||
///
|
||||
/// profile001 = startSketchOn(XY)
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(end = [0, 20], tag = $revolveAxis)
|
||||
/// |> line(end = [20, 0])
|
||||
///
|
||||
/// sketch001 = startSketchOn(XY)
|
||||
/// |> circle(center = [-10, 10], radius = 4)
|
||||
/// |> revolve(angle = 90, axis = revolveAxis, symmetric = true)
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// // Bidirectional revolve around a path.
|
||||
///
|
||||
/// profile001 = startSketchOn(XY)
|
||||
/// |> startProfileAt([0, 0], %)
|
||||
/// |> line(end = [0, 20], tag = $revolveAxis)
|
||||
/// |> line(end = [20, 0])
|
||||
///
|
||||
/// sketch001 = startSketchOn(XY)
|
||||
/// |> circle(center = [-10, 10], radius = 4)
|
||||
/// |> revolve(angle = 90, axis = revolveAxis, bidirectionalAngle = 50)
|
||||
/// ```
|
||||
@(impl = std_rust)
|
||||
export fn revolve(
|
||||
/// The sketch or set of sketches that should be revolved
|
||||
@ -621,10 +595,6 @@ export fn revolve(
|
||||
angle?: number(deg),
|
||||
/// Tolerance for the revolve operation.
|
||||
tolerance?: number(mm),
|
||||
/// If true, the extrusion will happen symmetrically around the sketch. Otherwise, the extrusion will happen on only one side of the sketch.
|
||||
symmetric?: bool,
|
||||
/// If specified, will also revolve in the opposite direction to 'angle' to the specified angle. If 'symmetric' is true, this value is ignored.
|
||||
bidirectionalAngle?: number(deg),
|
||||
/// A named tag for the face at the start of the revolve, i.e. the original sketch.
|
||||
tagStart?: tag,
|
||||
/// A named tag for the face at the end of the revolve.
|
||||
|
||||
@ -213,8 +213,7 @@ description: Artifact commands angled_line.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 4.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -196,8 +196,7 @@ description: Artifact commands artifact_graph_example_code1.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -433,8 +432,7 @@ description: Artifact commands artifact_graph_example_code1.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 5.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -179,8 +179,7 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 6.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -384,8 +383,7 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 5.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -589,8 +587,7 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 4.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -794,8 +791,7 @@ description: Artifact commands artifact_graph_sketch_on_face_etc.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 3.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -212,8 +212,7 @@ description: Artifact commands assembly_mixed_units_cubes.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 5.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -495,8 +494,7 @@ description: Artifact commands assembly_mixed_units_cubes.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 5.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -179,8 +179,7 @@ description: Artifact commands basic_fillet_cube_close_opposite.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -179,8 +179,7 @@ description: Artifact commands basic_fillet_cube_end.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -179,8 +179,7 @@ description: Artifact commands basic_fillet_cube_next_adjacent.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -179,8 +179,7 @@ description: Artifact commands basic_fillet_cube_previous_adjacent.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -179,8 +179,7 @@ description: Artifact commands basic_fillet_cube_start.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -162,8 +162,7 @@ description: Artifact commands big_number_angle_to_match_length_x.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -162,8 +162,7 @@ description: Artifact commands big_number_angle_to_match_length_y.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 44 KiB |
@ -153,8 +153,7 @@ description: Artifact commands circle_three_point.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -179,8 +179,7 @@ description: Artifact commands circular_pattern3d_a_pattern.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 1.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -179,8 +179,7 @@ description: Artifact commands crazy_multi_profile.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 20.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -744,8 +743,7 @@ description: Artifact commands crazy_multi_profile.kcl
|
||||
"unit": "degrees",
|
||||
"value": 45.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -844,8 +842,7 @@ description: Artifact commands crazy_multi_profile.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 4.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1456,8 +1453,7 @@ description: Artifact commands crazy_multi_profile.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 2.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1575,8 +1571,7 @@ description: Artifact commands crazy_multi_profile.kcl
|
||||
"unit": "degrees",
|
||||
"value": 45.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -196,8 +196,7 @@ description: Artifact commands cube.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 40.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -196,8 +196,7 @@ description: Artifact commands cube_with_error.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 40.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -306,8 +306,7 @@ description: Artifact commands fillet-and-shell.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 8.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -715,8 +714,7 @@ description: Artifact commands fillet-and-shell.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 4.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1044,8 +1042,7 @@ description: Artifact commands fillet-and-shell.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 4.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1373,8 +1370,7 @@ description: Artifact commands fillet-and-shell.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 4.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1702,8 +1698,7 @@ description: Artifact commands fillet-and-shell.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 4.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -255,8 +255,7 @@ description: Artifact commands flush_batch_on_end.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 1.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -179,8 +179,7 @@ description: Artifact commands function_sketch.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 3.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -179,8 +179,7 @@ description: Artifact commands function_sketch_with_position.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 3.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -153,8 +153,7 @@ description: Artifact commands helix_ccw.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -766,8 +766,7 @@ description: Artifact commands i_shape.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 3.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -169,8 +169,7 @@ description: Artifact commands import_whole.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -178,9 +178,8 @@ description: Artifact commands intersect_cubes.kcl
|
||||
"command": {
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 20.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"distance": 10.0,
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -342,7 +341,7 @@ description: Artifact commands intersect_cubes.kcl
|
||||
"type": "move_path_pen",
|
||||
"path": "[uuid]",
|
||||
"to": {
|
||||
"x": 2.0,
|
||||
"x": -2.0,
|
||||
"y": -2.0,
|
||||
"z": 0.0
|
||||
}
|
||||
@ -364,7 +363,7 @@ description: Artifact commands intersect_cubes.kcl
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": 12.0,
|
||||
"x": 18.0,
|
||||
"y": -2.0,
|
||||
"z": 0.0
|
||||
},
|
||||
@ -381,8 +380,8 @@ description: Artifact commands intersect_cubes.kcl
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": 12.0,
|
||||
"y": 8.0,
|
||||
"x": 18.0,
|
||||
"y": 18.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": false
|
||||
@ -398,8 +397,8 @@ description: Artifact commands intersect_cubes.kcl
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": 2.0,
|
||||
"y": 8.0,
|
||||
"x": -2.0,
|
||||
"y": 18.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": false
|
||||
@ -437,8 +436,7 @@ description: Artifact commands intersect_cubes.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 10.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -544,41 +542,5 @@ description: Artifact commands intersect_cubes.kcl
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "set_object_transform",
|
||||
"object_id": "[uuid]",
|
||||
"transforms": [
|
||||
{
|
||||
"translate": {
|
||||
"property": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"set": false,
|
||||
"is_local": true
|
||||
},
|
||||
"rotate_rpy": null,
|
||||
"rotate_angle_axis": null,
|
||||
"scale": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "boolean_intersection",
|
||||
"solid_ids": [
|
||||
"[uuid]",
|
||||
"[uuid]"
|
||||
],
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph path2 [Path]
|
||||
2["Path<br>[58, 113, 0]"]
|
||||
3["Segment<br>[121, 177, 0]"]
|
||||
4["Segment<br>[185, 241, 0]"]
|
||||
5["Segment<br>[249, 305, 0]"]
|
||||
6["Segment<br>[313, 320, 0]"]
|
||||
2["Path<br>[52, 103, 0]"]
|
||||
3["Segment<br>[111, 163, 0]"]
|
||||
4["Segment<br>[171, 223, 0]"]
|
||||
5["Segment<br>[231, 283, 0]"]
|
||||
6["Segment<br>[291, 298, 0]"]
|
||||
7[Solid2d]
|
||||
end
|
||||
subgraph path24 [Path]
|
||||
24["Path<br>[58, 113, 0]"]
|
||||
25["Segment<br>[121, 177, 0]"]
|
||||
26["Segment<br>[185, 241, 0]"]
|
||||
27["Segment<br>[249, 305, 0]"]
|
||||
28["Segment<br>[313, 320, 0]"]
|
||||
24["Path<br>[52, 103, 0]"]
|
||||
25["Segment<br>[111, 163, 0]"]
|
||||
26["Segment<br>[171, 223, 0]"]
|
||||
27["Segment<br>[231, 283, 0]"]
|
||||
28["Segment<br>[291, 298, 0]"]
|
||||
29[Solid2d]
|
||||
end
|
||||
1["Plane<br>[33, 50, 0]"]
|
||||
8["Sweep Extrusion<br>[328, 354, 0]"]
|
||||
1["Plane<br>[27, 44, 0]"]
|
||||
8["Sweep Extrusion<br>[306, 326, 0]"]
|
||||
9[Wall]
|
||||
10[Wall]
|
||||
11[Wall]
|
||||
@ -32,8 +32,8 @@ flowchart LR
|
||||
20["SweepEdge Adjacent"]
|
||||
21["SweepEdge Opposite"]
|
||||
22["SweepEdge Adjacent"]
|
||||
23["Plane<br>[33, 50, 0]"]
|
||||
30["Sweep Extrusion<br>[328, 354, 0]"]
|
||||
23["Plane<br>[27, 44, 0]"]
|
||||
30["Sweep Extrusion<br>[306, 326, 0]"]
|
||||
31[Wall]
|
||||
32[Wall]
|
||||
33[Wall]
|
||||
@ -48,7 +48,6 @@ flowchart LR
|
||||
42["SweepEdge Adjacent"]
|
||||
43["SweepEdge Opposite"]
|
||||
44["SweepEdge Adjacent"]
|
||||
45["CompositeSolid Intersect<br>[448, 477, 0]"]
|
||||
1 --- 2
|
||||
2 --- 3
|
||||
2 --- 4
|
||||
@ -115,6 +114,4 @@ flowchart LR
|
||||
30 --- 42
|
||||
30 --- 43
|
||||
30 --- 44
|
||||
2 <--x 45
|
||||
24 <--x 45
|
||||
```
|
||||
|
||||
@ -101,20 +101,16 @@ description: Result of parsing intersect_cubes.kcl
|
||||
},
|
||||
"operator": "-",
|
||||
"right": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "size",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"raw": "10",
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "BinaryExpression",
|
||||
@ -153,20 +149,16 @@ description: Result of parsing intersect_cubes.kcl
|
||||
},
|
||||
"operator": "-",
|
||||
"right": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "size",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"raw": "10",
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "BinaryExpression",
|
||||
@ -254,20 +246,16 @@ description: Result of parsing intersect_cubes.kcl
|
||||
},
|
||||
"operator": "+",
|
||||
"right": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "size",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"raw": "10",
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "BinaryExpression",
|
||||
@ -306,20 +294,16 @@ description: Result of parsing intersect_cubes.kcl
|
||||
},
|
||||
"operator": "-",
|
||||
"right": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "size",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"raw": "10",
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "BinaryExpression",
|
||||
@ -402,20 +386,16 @@ description: Result of parsing intersect_cubes.kcl
|
||||
},
|
||||
"operator": "+",
|
||||
"right": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "size",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"raw": "10",
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "BinaryExpression",
|
||||
@ -454,20 +434,16 @@ description: Result of parsing intersect_cubes.kcl
|
||||
},
|
||||
"operator": "+",
|
||||
"right": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "size",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"raw": "10",
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "BinaryExpression",
|
||||
@ -550,20 +526,16 @@ description: Result of parsing intersect_cubes.kcl
|
||||
},
|
||||
"operator": "-",
|
||||
"right": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "size",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"raw": "10",
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "BinaryExpression",
|
||||
@ -602,20 +574,16 @@ description: Result of parsing intersect_cubes.kcl
|
||||
},
|
||||
"operator": "+",
|
||||
"right": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "size",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"raw": "10",
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "BinaryExpression",
|
||||
@ -688,38 +656,14 @@ description: Result of parsing intersect_cubes.kcl
|
||||
"arg": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"left": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"raw": "2",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 2.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
"operator": "*",
|
||||
"right": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "size",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"raw": "10",
|
||||
"start": 0,
|
||||
"type": "BinaryExpression",
|
||||
"type": "BinaryExpression"
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
@ -775,16 +719,6 @@ description: Result of parsing intersect_cubes.kcl
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Parameter",
|
||||
"identifier": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "size",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
}
|
||||
}
|
||||
],
|
||||
"start": 0,
|
||||
@ -846,18 +780,6 @@ description: Result of parsing intersect_cubes.kcl
|
||||
"start": 0,
|
||||
"type": "ArrayExpression",
|
||||
"type": "ArrayExpression"
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"raw": "10",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 10.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
@ -903,129 +825,61 @@ description: Result of parsing intersect_cubes.kcl
|
||||
"type": "Identifier"
|
||||
},
|
||||
"init": {
|
||||
"body": [
|
||||
"arguments": [
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"commentStart": 0,
|
||||
"elements": [
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"raw": "7",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 7.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"raw": "3",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 3.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"end": 0,
|
||||
"start": 0,
|
||||
"type": "ArrayExpression",
|
||||
"type": "ArrayExpression"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"elements": [
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"raw": "5",
|
||||
"raw": "8",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 5.0,
|
||||
"value": 8.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"raw": "8",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 8.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "cube",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"start": 0,
|
||||
"type": "CallExpression",
|
||||
"type": "CallExpression"
|
||||
},
|
||||
{
|
||||
"arguments": [
|
||||
{
|
||||
"type": "LabeledArg",
|
||||
"label": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "z",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"arg": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"raw": "1",
|
||||
"start": 0,
|
||||
"type": "Literal",
|
||||
"type": "Literal",
|
||||
"value": {
|
||||
"value": 1.0,
|
||||
"suffix": "None"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "translate",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"start": 0,
|
||||
"type": "CallExpressionKw",
|
||||
"type": "CallExpressionKw",
|
||||
"unlabeled": null
|
||||
"type": "ArrayExpression",
|
||||
"type": "ArrayExpression"
|
||||
}
|
||||
],
|
||||
"callee": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "cube",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name"
|
||||
},
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"start": 0,
|
||||
"type": "PipeExpression",
|
||||
"type": "PipeExpression"
|
||||
"type": "CallExpression",
|
||||
"type": "CallExpression"
|
||||
},
|
||||
"start": 0,
|
||||
"type": "VariableDeclarator"
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
fn cube(center, size) {
|
||||
fn cube(center) {
|
||||
return startSketchOn(XY)
|
||||
|> startProfileAt([center[0] - size, center[1] - size], %)
|
||||
|> line(endAbsolute = [center[0] + size, center[1] - size])
|
||||
|> line(endAbsolute = [center[0] + size, center[1] + size])
|
||||
|> line(endAbsolute = [center[0] - size, center[1] + size])
|
||||
|> startProfileAt([center[0] - 10, center[1] - 10], %)
|
||||
|> line(endAbsolute = [center[0] + 10, center[1] - 10])
|
||||
|> line(endAbsolute = [center[0] + 10, center[1] + 10])
|
||||
|> line(endAbsolute = [center[0] - 10, center[1] + 10])
|
||||
|> close()
|
||||
|> extrude(length = 2 * size)
|
||||
|> extrude(length = 10)
|
||||
}
|
||||
|
||||
part001 = cube([0, 0], 10)
|
||||
part002 = cube([7, 3], 5)
|
||||
|> translate(z = 1)
|
||||
part001 = cube([0, 0])
|
||||
part002 = cube([8, 8])
|
||||
|
||||
fullPart = intersect([part001, part002])
|
||||
|
||||
@ -10,7 +10,7 @@ description: Operations executed intersect_cubes.kcl
|
||||
"name": "cube",
|
||||
"functionSourceRange": [
|
||||
7,
|
||||
356,
|
||||
328,
|
||||
0
|
||||
],
|
||||
"unlabeledArg": null,
|
||||
@ -38,7 +38,7 @@ description: Operations executed intersect_cubes.kcl
|
||||
"length": {
|
||||
"value": {
|
||||
"type": "Number",
|
||||
"value": 20.0,
|
||||
"value": 10.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
@ -75,7 +75,7 @@ description: Operations executed intersect_cubes.kcl
|
||||
"name": "cube",
|
||||
"functionSourceRange": [
|
||||
7,
|
||||
356,
|
||||
328,
|
||||
0
|
||||
],
|
||||
"unlabeledArg": null,
|
||||
|
||||
@ -7,365 +7,182 @@ description: Variables in memory after executing intersect_cubes.kcl
|
||||
"type": "Function"
|
||||
},
|
||||
"fullPart": {
|
||||
"type": "HomArray",
|
||||
"value": [
|
||||
{
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": [
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": [
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
}
|
||||
],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
"sourceRange": []
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
}
|
||||
],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
10.0,
|
||||
-10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
10.0,
|
||||
-10.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
10.0,
|
||||
10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
10.0,
|
||||
10.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-10.0,
|
||||
10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
-10.0,
|
||||
10.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
"from": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"on": {
|
||||
"type": "plane",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": "XY",
|
||||
"origin": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"xAxis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"yAxis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"zAxis": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"to": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"artifactId": "[uuid]",
|
||||
"originalId": "[uuid]",
|
||||
"tag": null,
|
||||
"to": [
|
||||
10.0,
|
||||
-10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"height": 20.0,
|
||||
"startCapId": "[uuid]",
|
||||
"endCapId": "[uuid]",
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
10.0,
|
||||
-10.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
10.0,
|
||||
10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
10.0,
|
||||
10.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-10.0,
|
||||
10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
-10.0,
|
||||
10.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"on": {
|
||||
"type": "plane",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": "XY",
|
||||
"origin": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"xAxis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"yAxis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"zAxis": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"to": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"artifactId": "[uuid]",
|
||||
"originalId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": [
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
},
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudePlane"
|
||||
}
|
||||
],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
10.0,
|
||||
-10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
10.0,
|
||||
-10.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
10.0,
|
||||
10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
10.0,
|
||||
10.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-10.0,
|
||||
10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
-10.0,
|
||||
10.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"on": {
|
||||
"type": "plane",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": "XY",
|
||||
"origin": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"xAxis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"yAxis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"zAxis": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"to": [
|
||||
-10.0,
|
||||
-10.0
|
||||
],
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"artifactId": "[uuid]",
|
||||
"originalId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"height": 20.0,
|
||||
"startCapId": "[uuid]",
|
||||
"endCapId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
"height": 10.0,
|
||||
"startCapId": "[uuid]",
|
||||
"endCapId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"part001": {
|
||||
"type": "Solid",
|
||||
@ -537,7 +354,7 @@ description: Variables in memory after executing intersect_cubes.kcl
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"height": 20.0,
|
||||
"height": 10.0,
|
||||
"startCapId": "[uuid]",
|
||||
"endCapId": "[uuid]",
|
||||
"units": {
|
||||
@ -591,12 +408,12 @@ description: Variables in memory after executing intersect_cubes.kcl
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
2.0,
|
||||
-2.0,
|
||||
-2.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
12.0,
|
||||
18.0,
|
||||
-2.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
@ -610,13 +427,13 @@ description: Variables in memory after executing intersect_cubes.kcl
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
12.0,
|
||||
18.0,
|
||||
-2.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
12.0,
|
||||
8.0
|
||||
18.0,
|
||||
18.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
@ -629,13 +446,13 @@ description: Variables in memory after executing intersect_cubes.kcl
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
12.0,
|
||||
8.0
|
||||
18.0,
|
||||
18.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
2.0,
|
||||
8.0
|
||||
-2.0,
|
||||
18.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
@ -648,12 +465,12 @@ description: Variables in memory after executing intersect_cubes.kcl
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
2.0,
|
||||
8.0
|
||||
-2.0,
|
||||
18.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
2.0,
|
||||
-2.0,
|
||||
-2.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
@ -693,11 +510,11 @@ description: Variables in memory after executing intersect_cubes.kcl
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
2.0,
|
||||
-2.0,
|
||||
-2.0
|
||||
],
|
||||
"to": [
|
||||
2.0,
|
||||
-2.0,
|
||||
-2.0
|
||||
],
|
||||
"units": {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 67 KiB |
@ -2,18 +2,17 @@
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Result of unparsing intersect_cubes.kcl
|
||||
---
|
||||
fn cube(center, size) {
|
||||
fn cube(center) {
|
||||
return startSketchOn(XY)
|
||||
|> startProfileAt([center[0] - size, center[1] - size], %)
|
||||
|> line(endAbsolute = [center[0] + size, center[1] - size])
|
||||
|> line(endAbsolute = [center[0] + size, center[1] + size])
|
||||
|> line(endAbsolute = [center[0] - size, center[1] + size])
|
||||
|> startProfileAt([center[0] - 10, center[1] - 10], %)
|
||||
|> line(endAbsolute = [center[0] + 10, center[1] - 10])
|
||||
|> line(endAbsolute = [center[0] + 10, center[1] + 10])
|
||||
|> line(endAbsolute = [center[0] - 10, center[1] + 10])
|
||||
|> close()
|
||||
|> extrude(length = 2 * size)
|
||||
|> extrude(length = 10)
|
||||
}
|
||||
|
||||
part001 = cube([0, 0], 10)
|
||||
part002 = cube([7, 3], 5)
|
||||
|> translate(z = 1)
|
||||
part001 = cube([0, 0])
|
||||
part002 = cube([8, 8])
|
||||
|
||||
fullPart = intersect([part001, part002])
|
||||
|
||||
@ -1478,8 +1478,7 @@ description: Artifact commands 80-20-rail.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 48.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -269,8 +269,7 @@ description: Artifact commands ball-bearing.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.313,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -459,8 +458,7 @@ description: Artifact commands ball-bearing.kcl
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -697,8 +695,7 @@ description: Artifact commands ball-bearing.kcl
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -941,8 +938,7 @@ description: Artifact commands ball-bearing.kcl
|
||||
"unit": "degrees",
|
||||
"value": 36.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1235,8 +1231,7 @@ description: Artifact commands ball-bearing.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.313,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -476,8 +476,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 2.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1343,8 +1342,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -2.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2250,8 +2248,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 2.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3092,8 +3089,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -2.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3999,8 +3995,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 2.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4841,8 +4836,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -2.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5553,8 +5547,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 56.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5920,8 +5913,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 56.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6352,8 +6344,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 60.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6523,8 +6514,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 60.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6694,8 +6684,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 60.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7097,8 +7086,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 60.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7268,8 +7256,7 @@ description: Artifact commands bench.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 60.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -230,8 +230,7 @@ description: Artifact commands bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 6.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -701,8 +700,7 @@ description: Artifact commands bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.361324026261472,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -768,8 +766,7 @@ description: Artifact commands bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.361324026261472,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -835,8 +832,7 @@ description: Artifact commands bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.361324026261472,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -902,8 +898,7 @@ description: Artifact commands bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.361324026261472,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1081,8 +1076,7 @@ description: Artifact commands bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.45132402626147194,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1148,8 +1142,7 @@ description: Artifact commands bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.45132402626147194,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -169,8 +169,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.25,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -325,8 +324,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -485,8 +483,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.75,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -552,8 +549,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.75,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -619,8 +615,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.75,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -686,8 +681,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.75,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -753,8 +747,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.75,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -977,8 +970,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1116,8 +1108,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.25,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1276,8 +1267,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.25,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1343,8 +1333,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.25,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1410,8 +1399,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.25,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1477,8 +1465,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.25,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1544,8 +1531,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.25,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1704,8 +1690,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1771,8 +1756,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1838,8 +1822,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1905,8 +1888,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1972,8 +1954,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2039,8 +2020,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2106,8 +2086,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2173,8 +2152,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2240,8 +2218,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2307,8 +2284,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2374,8 +2350,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2441,8 +2416,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2508,8 +2482,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2575,8 +2548,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2642,8 +2614,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2709,8 +2680,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2912,8 +2882,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.125,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3039,8 +3008,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.125,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3166,8 +3134,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.125,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3293,8 +3260,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.125,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3420,8 +3386,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.125,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3683,8 +3648,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.125,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3810,8 +3774,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.125,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3937,8 +3900,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.125,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4064,8 +4026,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.125,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4191,8 +4152,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.125,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4730,8 +4690,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.475,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4979,8 +4938,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.95,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5159,8 +5117,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.95,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5226,8 +5183,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.95,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5293,8 +5249,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.95,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5360,8 +5315,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.95,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5427,8 +5381,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.95,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5587,8 +5540,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.475,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5654,8 +5606,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.475,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5721,8 +5672,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.475,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5788,8 +5738,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.475,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5855,8 +5804,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.475,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6163,8 +6111,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6456,8 +6403,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6761,8 +6707,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.95,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7179,8 +7124,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.95,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7898,8 +7842,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -8674,8 +8617,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -9291,8 +9233,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"unit": "degrees",
|
||||
"value": -70.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -10017,8 +9958,7 @@ description: Artifact commands car-wheel-assembly.kcl
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -413,8 +413,7 @@ description: Artifact commands color-cube.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 1.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -680,8 +679,7 @@ description: Artifact commands color-cube.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 1.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -947,8 +945,7 @@ description: Artifact commands color-cube.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 1.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1214,8 +1211,7 @@ description: Artifact commands color-cube.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 1.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1481,8 +1477,7 @@ description: Artifact commands color-cube.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 1.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1748,8 +1743,7 @@ description: Artifact commands color-cube.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 1.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -382,8 +382,7 @@ description: Artifact commands dodecahedron.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 5.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -533,8 +532,7 @@ description: Artifact commands dodecahedron.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 5.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -462,8 +462,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 834.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -593,8 +592,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 834.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -724,8 +722,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 834.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -855,8 +852,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 834.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -986,8 +982,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 834.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1117,8 +1112,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 834.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1248,8 +1242,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 834.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1379,8 +1372,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 834.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1857,8 +1849,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1988,8 +1979,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2119,8 +2109,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2250,8 +2239,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2381,8 +2369,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2512,8 +2499,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2802,8 +2788,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2933,8 +2918,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3411,8 +3395,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 671.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3542,8 +3525,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 671.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3673,8 +3655,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 671.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3804,8 +3785,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 671.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3935,8 +3915,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 671.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4066,8 +4045,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 671.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4395,8 +4373,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4526,8 +4503,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4816,8 +4792,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4947,8 +4922,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -13.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5236,8 +5210,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -2.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5518,8 +5491,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 200.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5645,8 +5617,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 200.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -5927,8 +5898,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -200.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6054,8 +6024,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -200.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6499,8 +6468,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 667.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6630,8 +6598,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 667.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6761,8 +6728,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 667.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -6892,8 +6858,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 667.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7023,8 +6988,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 667.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7154,8 +7118,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 667.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7444,8 +7407,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 667.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -7575,8 +7537,7 @@ description: Artifact commands dual-basin-utility-sink.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 667.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -204,8 +204,7 @@ description: Artifact commands enclosure.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 70.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -631,8 +630,7 @@ description: Artifact commands enclosure.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 67.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -917,8 +915,7 @@ description: Artifact commands enclosure.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 67.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1203,8 +1200,7 @@ description: Artifact commands enclosure.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 67.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1489,8 +1485,7 @@ description: Artifact commands enclosure.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 67.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2100,8 +2095,7 @@ description: Artifact commands enclosure.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 3.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2870,8 +2864,7 @@ description: Artifact commands enclosure.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 3.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -2728,8 +2728,7 @@ description: Artifact commands exhaust-manifold.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.125,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -355,8 +355,7 @@ description: Artifact commands flange.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.625,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -574,8 +573,7 @@ description: Artifact commands flange.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.1279999999999999,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -713,8 +711,7 @@ description: Artifact commands flange.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.06,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -852,8 +849,7 @@ description: Artifact commands flange.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.813,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -255,8 +255,7 @@ description: Artifact commands focusrite-scarlett-mounting-bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 88.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -727,8 +726,7 @@ description: Artifact commands focusrite-scarlett-mounting-bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -4.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1183,8 +1181,7 @@ description: Artifact commands focusrite-scarlett-mounting-bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -4.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1528,8 +1525,7 @@ description: Artifact commands focusrite-scarlett-mounting-bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 104.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1766,8 +1762,7 @@ description: Artifact commands focusrite-scarlett-mounting-bracket.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 104.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -620,8 +620,7 @@ description: Artifact commands food-service-spatula.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 3.5,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1223,8 +1222,7 @@ description: Artifact commands food-service-spatula.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 15.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1678,8 +1676,7 @@ description: Artifact commands food-service-spatula.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -150.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1999,8 +1996,7 @@ description: Artifact commands food-service-spatula.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -30.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -202,8 +202,7 @@ description: Artifact commands french-press.kcl
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -722,8 +721,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.75,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1229,8 +1227,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1423,8 +1420,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1530,8 +1526,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1637,8 +1632,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1924,8 +1918,7 @@ description: Artifact commands french-press.kcl
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2280,8 +2273,7 @@ description: Artifact commands french-press.kcl
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2673,8 +2665,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2853,8 +2844,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2920,8 +2910,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2987,8 +2976,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3054,8 +3042,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3121,8 +3108,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3188,8 +3174,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3255,8 +3240,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3322,8 +3306,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3482,8 +3465,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3549,8 +3531,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3616,8 +3597,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3683,8 +3663,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.05,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -3855,8 +3834,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 7.32,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4142,8 +4120,7 @@ description: Artifact commands french-press.kcl
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"tolerance": 0.0000001,
|
||||
"opposite": "None"
|
||||
"tolerance": 0.0000001
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -4620,8 +4597,7 @@ description: Artifact commands french-press.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": -0.65,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -187,8 +187,7 @@ description: Artifact commands gear-rack.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 5.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -513,8 +512,7 @@ description: Artifact commands gear-rack.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 5.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2660,8 +2658,7 @@ description: Artifact commands gear-rack.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 5.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -2918,8 +2915,7 @@ description: Artifact commands gear-rack.kcl
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 5.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
"faces": null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user