Compare commits

...

5 Commits

Author SHA1 Message Date
6d50278d34 bump kcl friends (#6272)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-10 19:01:30 -07:00
35844842de Bump modeling api & pull thru csg endpoints (#6245)
* csg-upts

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

* base

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

* do the id shit

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

* tried to run

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

* csg-upts

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

* use bens samples

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

* use bens samples

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

* gen std

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

* gen std

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

* updates

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

* updates

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

* fix;

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-10 18:30:57 -07:00
843e772094 Franknoirot/adhoc/improve e2e (#6265)
* fix: increasing timeout to reduce failures..?

* fix: removing debugging code

* Remove unnecessary pixel color check

* Only close the command palette on disconnection events

This code closes the palette on *any* network event, including it
getting established. This made tests like "Create a few projects using
the default project name" unreliable.

Also adds a block comment about how we should do something more
sophisticated than bail out in the future.

* Show a toast to explain why the user just lost their command flow

* Remove unnecessary click in test. `fill` focuses already

* Oop don't spam this disconnection toast if the palette isn't open

Honoring exhausting hook dependency checks

* Skip circle snapshot test, it's being weird

* Disable the export button if engine connection is unavailable

* Refactor useDemoCode to hopefully be more reliable

* allow weak connections to receive demo code

* revert Refactor useDemoCode to hopefully be more reliable
Commit:
2625c14783 [2625c1478]

---------

Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jace Browning <jacebrowning@gmail.com>
Co-authored-by: Andrew Varga <grizzly33@gmail.com>
2025-04-11 00:08:39 +00:00
9d0518dfeb Fix URL encoded names after rename to Zoo Design Studio (#6269) 2025-04-10 17:20:37 -04:00
d33d399c31 Repetitive structs removed for import file extensions (#6211)
* get rid of repetitive structs

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

fmt

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

get rid of more

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

add more

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

updates

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

fix

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

updates

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

await the shit

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

updates

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

put it at the root

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

* updates

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

* fix;es

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

* fixes

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

* fix

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

* kcl-language-server flake

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

* updates

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-10 13:57:12 -07:00
75 changed files with 7165 additions and 1213 deletions

View File

@ -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%20Modeling%20App%20%28Nightly%29' || 'Zoo%20Modeling%20App' }}
URL_CODED_NAME: ${{ env.IS_NIGHTLY == 'true' && 'Zoo%20Design%20Studio%20%28Nightly%29' || 'Zoo%20Design%20Studio' }}
run: |
RELEASE_DIR=https://${WEBSITE_DIR}
jq --null-input \

1
.gitignore vendored
View File

@ -26,6 +26,7 @@ yarn-error.log*
.idea
.vscode
.helix
result
# rust
rust/target

View File

@ -77,6 +77,7 @@ layout: manual
* [`helix`](kcl/std-helix)
* [`hole`](kcl/hole)
* [`hollow`](kcl/hollow)
* [`intersect`](kcl/intersect)
* [`lastSegX`](kcl/lastSegX)
* [`lastSegY`](kcl/lastSegY)
* [`legAngX`](kcl/legAngX)
@ -123,6 +124,7 @@ layout: manual
* [`sqrt`](kcl/sqrt)
* [`startProfileAt`](kcl/startProfileAt)
* [`startSketchOn`](kcl/startSketchOn)
* [`subtract`](kcl/subtract)
* [`sweep`](kcl/sweep)
* [`tangentToEnd`](kcl/tangentToEnd)
* [`tangentialArc`](kcl/tangentialArc)
@ -131,6 +133,7 @@ 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 it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -99,7 +99,6 @@ 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()
}

View File

@ -233,7 +233,7 @@ export class SceneFixture {
settled = async (cmdBar: CmdBarFixture) => {
const u = await getUtils(this.page)
await expect(this.startEditSketchBtn).not.toBeDisabled()
await expect(this.startEditSketchBtn).not.toBeDisabled({ timeout: 15_000 })
await expect(this.startEditSketchBtn).toBeVisible()
await cmdBar.openCmdBar()

View File

@ -68,12 +68,10 @@ 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 clickBody1Cap()
await scene.expectPixelColor(yellow, body1CapCoords, 20)
await editor.expectState({
highlightedCode: '',
activeLines: ['|>startProfileAt([-73.64,-42.89],%)'],

View File

@ -588,6 +588,7 @@ 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

View File

@ -0,0 +1,15 @@
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)
})
})

41
flake.lock generated
View File

@ -1,6 +1,40 @@
{
"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": 1744096231,
"narHash": "sha256-kUfx3FKU1Etnua3EaKvpeuXs7zoFiAcli1gBwkPvGSs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b2b0718004cc9a5bca610326de0a82e6ea75920b",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1736320768,
"narHash": "sha256-nIYdTAiKIGnFNugbomgBJR+Xv5F1ZQU+HfaBqJKroC0=",
@ -16,7 +50,7 @@
"type": "github"
}
},
"nixpkgs_2": {
"nixpkgs_3": {
"locked": {
"lastModified": 1728538411,
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
@ -34,13 +68,14 @@
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"naersk": "naersk",
"nixpkgs": "nixpkgs_2",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": "nixpkgs_2"
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1736476219,

142
flake.nix
View File

@ -1,84 +1,104 @@
{
description = "modeling-app development environment";
description = "zoo.dev modeling-app";
# Flake inputs
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
rust-overlay.url = "github:oxalica/rust-overlay"; # A helper for Rust + Nix
rust-overlay.url = "github:oxalica/rust-overlay";
naersk.url = "github:nix-community/naersk";
};
# 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" ];
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"];
};
})
(self: super: {
cargo-llvm-cov = super.cargo-llvm-cov.overrideAttrs (oa: {
doCheck = false;
doInstallCheck = false;
});
})
];
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;
config.allowBroken = true;
};
})
(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.
system = system;
});
in {
devShells = forAllSystems ({pkgs, ...}: {
default = pkgs.mkShell {
packages =
(with pkgs; [
rustToolchain
cargo-llvm-cov
cargo-nextest
just
postgresql.lib
openssl
pkg-config
nodejs_22
yarn
electron
playwright-driver.browsers
]) ++ pkgs.lib.optionals pkgs.stdenv.isDarwin (with pkgs; [
wasm-pack
python3Full
])
++ 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";
};
});
};
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;
});
};
}

24
rust/Cargo.lock generated
View File

@ -1780,7 +1780,7 @@ dependencies = [
[[package]]
name = "kcl-bumper"
version = "0.1.58"
version = "0.1.59"
dependencies = [
"anyhow",
"clap",
@ -1791,7 +1791,7 @@ dependencies = [
[[package]]
name = "kcl-derive-docs"
version = "0.1.58"
version = "0.1.59"
dependencies = [
"Inflector",
"anyhow",
@ -1810,7 +1810,7 @@ dependencies = [
[[package]]
name = "kcl-directory-test-macro"
version = "0.1.58"
version = "0.1.59"
dependencies = [
"proc-macro2",
"quote",
@ -1819,7 +1819,7 @@ dependencies = [
[[package]]
name = "kcl-language-server"
version = "0.2.58"
version = "0.2.59"
dependencies = [
"anyhow",
"clap",
@ -1840,7 +1840,7 @@ dependencies = [
[[package]]
name = "kcl-language-server-release"
version = "0.1.58"
version = "0.1.59"
dependencies = [
"anyhow",
"clap",
@ -1860,7 +1860,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.2.58"
version = "0.2.59"
dependencies = [
"anyhow",
"approx 0.5.1",
@ -1928,7 +1928,7 @@ dependencies = [
[[package]]
name = "kcl-python-bindings"
version = "0.3.58"
version = "0.3.59"
dependencies = [
"anyhow",
"kcl-lib",
@ -1943,7 +1943,7 @@ dependencies = [
[[package]]
name = "kcl-test-server"
version = "0.1.58"
version = "0.1.59"
dependencies = [
"anyhow",
"hyper 0.14.32",
@ -1956,7 +1956,7 @@ dependencies = [
[[package]]
name = "kcl-to-core"
version = "0.1.58"
version = "0.1.59"
dependencies = [
"anyhow",
"async-trait",
@ -1970,7 +1970,7 @@ dependencies = [
[[package]]
name = "kcl-wasm-lib"
version = "0.1.58"
version = "0.1.59"
dependencies = [
"bson",
"console_error_panic_hook",
@ -2033,9 +2033,9 @@ dependencies = [
[[package]]
name = "kittycad-modeling-cmds"
version = "0.2.110"
version = "0.2.112"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdfd16800a12a2eaefff53958bd871875c246e669274269f7caefc25d19641ad"
checksum = "08f06b4eb4e98ded7cda21586347baeb8055c4898f609f55f7c544cfed2b229c"
dependencies = [
"anyhow",
"chrono",

View File

@ -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.110", features = ["ts-rs", "websocket"] }
kittycad-modeling-cmds = { version = "0.2.112", features = ["ts-rs", "websocket"] }
lazy_static = "1.5.0"
miette = "7.5.0"
pyo3 = { version = "0.24.0" }

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-bumper"
version = "0.1.58"
version = "0.1.59"
edition = "2021"
repository = "https://github.com/KittyCAD/modeling-api"
rust-version = "1.76"

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-derive-docs"
description = "A tool for generating documentation from Rust derive macros"
version = "0.1.58"
version = "0.1.59"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -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.58"
version = "0.1.59"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -1,6 +1,6 @@
[package]
name = "kcl-language-server-release"
version = "0.1.58"
version = "0.1.59"
edition = "2021"
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
publish = false

View File

@ -2,7 +2,7 @@
name = "kcl-language-server"
description = "A language server for KCL."
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
version = "0.2.58"
version = "0.2.59"
edition = "2021"
license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-lib"
description = "KittyCAD Language implementation and tools"
version = "0.2.58"
version = "0.2.59"
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 = ["engine"]
default = ["cli", "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.

View File

@ -20,7 +20,6 @@ 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)];

View File

@ -939,25 +939,40 @@ 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()], exec_state, args).await?;
let result = crate::std::csg::inner_union(
vec![*left.clone(), *right.clone()],
Default::default(),
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()], exec_state, args)
.await?;
let result = crate::std::csg::inner_subtract(
vec![*left.clone()],
vec![*right.clone()],
Default::default(),
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()], exec_state, args).await?;
let result = crate::std::csg::inner_intersect(
vec![*left.clone(), *right.clone()],
Default::default(),
exec_state,
args,
)
.await?;
return Ok(result.into());
}
}

View File

@ -173,7 +173,7 @@ pub(super) fn format_from_annotations(
KclError::Semantic(KclErrorDetails {
message: format!(
"Unknown format for import, expected one of: {}",
annotations::IMPORT_FORMAT_VALUES.join(", ")
crate::IMPORT_FILE_EXTENSIONS.join(", ")
),
source_ranges: vec![p.as_source_range()],
})

View File

@ -131,11 +131,36 @@ 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)]

View File

@ -35,7 +35,7 @@ use crate::{
token::{Token, TokenSlice, TokenType},
PIPE_OPERATOR, PIPE_SUBSTITUTION_OPERATOR,
},
SourceRange,
SourceRange, IMPORT_FILE_EXTENSIONS,
};
thread_local! {
@ -1843,8 +1843,6 @@ 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.
@ -1909,12 +1907,11 @@ fn validate_path_string(path_string: String, var_name: bool, path_range: SourceR
ImportPath::Std { path: segments }
} else if path_string.contains('.') {
// 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) {
let extn = std::path::Path::new(&path_string).extension().unwrap_or_default();
if !IMPORT_FILE_EXTENSIONS.contains(&extn.to_string_lossy().to_string()) {
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: {}", FOREIGN_IMPORT_EXTENSIONS.join(", ")),
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(", ")),
))
}
ImportPath::Foreign { path: path_string }
@ -1922,7 +1919,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: {}", FOREIGN_IMPORT_EXTENSIONS.join(", ")),
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(", ")),
)
.into(),
));

View File

@ -2,6 +2,13 @@
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},
@ -9,10 +16,13 @@ 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 {
@ -21,7 +31,7 @@ pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
}));
}
let solids = inner_union(solids, exec_state, args).await?;
let solids = inner_union(solids, tolerance, exec_state, args).await?;
Ok(solids.into())
}
@ -30,18 +40,19 @@ 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) {
/// fn cube(center, size) {
/// return startSketchOn('XY')
/// |> 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])
/// |> 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])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0])
/// part002 = cube([20, 10])
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// |> translate(z = 1)
///
/// unionedPart = union([part001, part002])
/// ```
@ -51,18 +62,19 @@ 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) {
/// fn cube(center, size) {
/// return startSketchOn('XY')
/// |> 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])
/// |> 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])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0])
/// part002 = cube([20, 10])
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// |> translate(z = 1)
///
/// // This is the equivalent of: union([part001, part002])
/// unionedPart = part001 + part002
@ -73,18 +85,19 @@ 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) {
/// fn cube(center, size) {
/// return startSketchOn('XY')
/// |> 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])
/// |> 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])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0])
/// part002 = cube([20, 10])
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// |> translate(z = 1)
///
/// // This is the equivalent of: union([part001, part002])
/// // Programmers will understand `|` as a union operation, but mechanical engineers
@ -96,31 +109,64 @@ 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?;
// TODO: call the engine union operation.
// TODO: figure out all the shit after for the faces etc.
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?;
// For now just return the first solid.
// Til we have a proper implementation.
Ok(vec![solids[0].clone()])
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)
}
/// 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 {
@ -129,7 +175,7 @@ pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValu
}));
}
let solids = inner_intersect(solids, exec_state, args).await?;
let solids = inner_intersect(solids, tolerance, exec_state, args).await?;
Ok(solids.into())
}
@ -144,18 +190,19 @@ pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValu
/// ```no_run
/// // Intersect two cubes using the stdlib functions.
///
/// fn cube(center) {
/// fn cube(center, size) {
/// return startSketchOn('XY')
/// |> 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])
/// |> 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])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0])
/// part002 = cube([8, 8])
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// |> translate(z = 1)
///
/// intersectedPart = intersect([part001, part002])
/// ```
@ -165,18 +212,19 @@ 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) {
/// fn cube(center, size) {
/// return startSketchOn('XY')
/// |> 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])
/// |> 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])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0])
/// part002 = cube([8, 8])
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// |> translate(z = 1)
///
/// // This is the equivalent of: intersect([part001, part002])
/// intersectedPart = part001 & part002
@ -186,25 +234,57 @@ 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?;
// TODO: call the engine union operation.
// TODO: figure out all the shit after for the faces etc.
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?;
// For now just return the first solid.
// Til we have a proper implementation.
Ok(vec![solids[0].clone()])
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)
}
/// Subtract removes tool solids from base solids, leaving the remaining material.
@ -212,7 +292,23 @@ 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)?;
let solids = inner_subtract(solids, tools, exec_state, args).await?;
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?;
Ok(solids.into())
}
@ -227,20 +323,19 @@ 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) {
/// fn cube(center, size) {
/// return startSketchOn('XY')
/// |> 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])
/// |> 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])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0])
/// part002 = startSketchOn('XY')
/// |> circle(center = [0, 0], radius = 2)
/// |> extrude(length = 10)
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// |> translate(z = 1)
///
/// subtractedPart = subtract([part001], tools=[part002])
/// ```
@ -250,20 +345,19 @@ 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) {
/// fn cube(center, size) {
/// return startSketchOn('XY')
/// |> 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])
/// |> 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])
/// |> close()
/// |> extrude(length = 10)
/// }
///
/// part001 = cube([0, 0])
/// part002 = startSketchOn('XY')
/// |> circle(center = [0, 0], radius = 2)
/// |> extrude(length = 10)
/// part001 = cube([0, 0], 10)
/// part002 = cube([7, 3], 5)
/// |> translate(z = 1)
///
/// // This is the equivalent of: subtract([part001], tools=[part002])
/// subtractedPart = part001 - part002
@ -273,26 +367,59 @@ 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?;
// TODO: call the engine union operation.
// TODO: figure out all the shit after for the faces etc.
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?;
// For now just return the first solid.
// Til we have a proper implementation.
Ok(vec![solids[0].clone()])
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)
}

View File

@ -1,8 +1,5 @@
use std::fmt::Write;
#[cfg(feature = "cli")]
use clap::ValueEnum;
use crate::parsing::{
ast::types::{
Annotation, ArrayExpression, ArrayRangeExpression, BinaryExpression, BinaryOperator, BinaryPart, BodyItem,
@ -867,29 +864,6 @@ 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]
@ -909,7 +883,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| RELEVANT_EXTENSIONS.contains(&ext.to_string_lossy().to_string()))
.is_some_and(|ext| crate::RELEVANT_FILE_EXTENSIONS.contains(&ext.to_string_lossy().to_string()))
{
files.push(path);
}

View File

@ -178,7 +178,7 @@ description: Artifact commands intersect_cubes.kcl
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 10.0,
"distance": 20.0,
"faces": null,
"opposite": "None"
}
@ -342,7 +342,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 +364,7 @@ description: Artifact commands intersect_cubes.kcl
"segment": {
"type": "line",
"end": {
"x": 18.0,
"x": 12.0,
"y": -2.0,
"z": 0.0
},
@ -381,8 +381,8 @@ description: Artifact commands intersect_cubes.kcl
"segment": {
"type": "line",
"end": {
"x": 18.0,
"y": 18.0,
"x": 12.0,
"y": 8.0,
"z": 0.0
},
"relative": false
@ -398,8 +398,8 @@ description: Artifact commands intersect_cubes.kcl
"segment": {
"type": "line",
"end": {
"x": -2.0,
"y": 18.0,
"x": 2.0,
"y": 8.0,
"z": 0.0
},
"relative": false
@ -544,5 +544,41 @@ 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
}
}
]

View File

@ -1,23 +1,23 @@
```mermaid
flowchart LR
subgraph path2 [Path]
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]"]
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]"]
7[Solid2d]
end
subgraph path24 [Path]
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]"]
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]"]
29[Solid2d]
end
1["Plane<br>[27, 44, 0]"]
8["Sweep Extrusion<br>[306, 326, 0]"]
1["Plane<br>[33, 50, 0]"]
8["Sweep Extrusion<br>[328, 354, 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>[27, 44, 0]"]
30["Sweep Extrusion<br>[306, 326, 0]"]
23["Plane<br>[33, 50, 0]"]
30["Sweep Extrusion<br>[328, 354, 0]"]
31[Wall]
32[Wall]
33[Wall]

View File

@ -101,16 +101,20 @@ description: Result of parsing intersect_cubes.kcl
},
"operator": "-",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -149,16 +153,20 @@ description: Result of parsing intersect_cubes.kcl
},
"operator": "-",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -246,16 +254,20 @@ description: Result of parsing intersect_cubes.kcl
},
"operator": "+",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -294,16 +306,20 @@ description: Result of parsing intersect_cubes.kcl
},
"operator": "-",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -386,16 +402,20 @@ description: Result of parsing intersect_cubes.kcl
},
"operator": "+",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -434,16 +454,20 @@ description: Result of parsing intersect_cubes.kcl
},
"operator": "+",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -526,16 +550,20 @@ description: Result of parsing intersect_cubes.kcl
},
"operator": "-",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -574,16 +602,20 @@ description: Result of parsing intersect_cubes.kcl
},
"operator": "+",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -656,14 +688,38 @@ description: Result of parsing intersect_cubes.kcl
"arg": {
"commentStart": 0,
"end": 0,
"raw": "10",
"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"
},
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "BinaryExpression",
"type": "BinaryExpression"
}
}
],
@ -719,6 +775,16 @@ 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,
@ -780,6 +846,18 @@ 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": {
@ -825,61 +903,129 @@ description: Result of parsing intersect_cubes.kcl
"type": "Identifier"
},
"init": {
"arguments": [
"body": [
{
"commentStart": 0,
"elements": [
"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,
"raw": "8",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 8.0,
"suffix": "None"
}
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 0,
"end": 0,
"raw": "8",
"raw": "5",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 8.0,
"value": 5.0,
"suffix": "None"
}
}
],
"end": 0,
"start": 0,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"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,
"name": "cube",
"start": 0,
"type": "Identifier"
"type": "CallExpression",
"type": "CallExpression"
},
"path": [],
"start": 0,
"type": "Name"
},
{
"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
}
],
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
"type": "PipeExpression",
"type": "PipeExpression"
},
"start": 0,
"type": "VariableDeclarator"

View File

@ -1,14 +1,15 @@
fn cube(center) {
fn cube(center, size) {
return startSketchOn(XY)
|> 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])
|> 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])
|> close()
|> extrude(length = 10)
|> extrude(length = 2 * size)
}
part001 = cube([0, 0])
part002 = cube([8, 8])
part001 = cube([0, 0], 10)
part002 = cube([7, 3], 5)
|> translate(z = 1)
fullPart = intersect([part001, part002])

View File

@ -10,7 +10,7 @@ description: Operations executed intersect_cubes.kcl
"name": "cube",
"functionSourceRange": [
7,
328,
356,
0
],
"unlabeledArg": null,
@ -38,7 +38,7 @@ description: Operations executed intersect_cubes.kcl
"length": {
"value": {
"type": "Number",
"value": 10.0,
"value": 20.0,
"ty": {
"type": "Default",
"len": {
@ -75,7 +75,7 @@ description: Operations executed intersect_cubes.kcl
"name": "cube",
"functionSourceRange": [
7,
328,
356,
0
],
"unlabeledArg": null,

View File

@ -7,182 +7,365 @@ description: Variables in memory after executing intersect_cubes.kcl
"type": "Function"
},
"fullPart": {
"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",
"type": "HomArray",
"value": [
{
"type": "Solid",
"value": {
"type": "Solid",
"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
"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"
}
],
"to": [
-10.0,
-10.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"sourceRange": []
"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"
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[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"
}
}
}
}
]
},
"part001": {
"type": "Solid",
@ -354,7 +537,7 @@ description: Variables in memory after executing intersect_cubes.kcl
"type": "Mm"
}
},
"height": 10.0,
"height": 20.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
@ -408,12 +591,12 @@ description: Variables in memory after executing intersect_cubes.kcl
"sourceRange": []
},
"from": [
-2.0,
2.0,
-2.0
],
"tag": null,
"to": [
18.0,
12.0,
-2.0
],
"type": "ToPoint",
@ -427,13 +610,13 @@ description: Variables in memory after executing intersect_cubes.kcl
"sourceRange": []
},
"from": [
18.0,
12.0,
-2.0
],
"tag": null,
"to": [
18.0,
18.0
12.0,
8.0
],
"type": "ToPoint",
"units": {
@ -446,13 +629,13 @@ description: Variables in memory after executing intersect_cubes.kcl
"sourceRange": []
},
"from": [
18.0,
18.0
12.0,
8.0
],
"tag": null,
"to": [
-2.0,
18.0
2.0,
8.0
],
"type": "ToPoint",
"units": {
@ -465,12 +648,12 @@ description: Variables in memory after executing intersect_cubes.kcl
"sourceRange": []
},
"from": [
-2.0,
18.0
2.0,
8.0
],
"tag": null,
"to": [
-2.0,
2.0,
-2.0
],
"type": "ToPoint",
@ -510,11 +693,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: 67 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -2,17 +2,18 @@
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing intersect_cubes.kcl
---
fn cube(center) {
fn cube(center, size) {
return startSketchOn(XY)
|> 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])
|> 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])
|> close()
|> extrude(length = 10)
|> extrude(length = 2 * size)
}
part001 = cube([0, 0])
part002 = cube([8, 8])
part001 = cube([0, 0], 10)
part002 = cube([7, 3], 5)
|> translate(z = 1)
fullPart = intersect([part001, part002])

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -342,8 +342,8 @@ description: Artifact commands subtract_cylinder_from_cube.kcl
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": 2.0,
"y": 0.0,
"x": 4.0,
"y": 2.0,
"z": 0.0
}
}
@ -364,8 +364,8 @@ description: Artifact commands subtract_cylinder_from_cube.kcl
"segment": {
"type": "arc",
"center": {
"x": 0.0,
"y": 0.0
"x": 2.0,
"y": 2.0
},
"radius": 2.0,
"start": {
@ -410,7 +410,7 @@ description: Artifact commands subtract_cylinder_from_cube.kcl
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 10.0,
"distance": 5.0,
"faces": null,
"opposite": "None"
}
@ -458,5 +458,19 @@ description: Artifact commands subtract_cylinder_from_cube.kcl
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "boolean_subtract",
"target_ids": [
"[uuid]"
],
"tool_ids": [
"[uuid]"
],
"tolerance": 0.0000001
}
}
]

View File

@ -30,7 +30,7 @@ flowchart LR
21["SweepEdge Opposite"]
22["SweepEdge Adjacent"]
23["Plane<br>[363, 382, 0]"]
27["Sweep Extrusion<br>[429, 449, 0]"]
27["Sweep Extrusion<br>[429, 448, 0]"]
28[Wall]
29["Cap Start"]
30["Cap End"]

View File

@ -876,24 +876,24 @@ description: Result of parsing subtract_cylinder_from_cube.kcl
{
"commentStart": 0,
"end": 0,
"raw": "0",
"raw": "2",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"value": 2.0,
"suffix": "None"
}
},
{
"commentStart": 0,
"end": 0,
"raw": "0",
"raw": "2",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 0.0,
"value": 2.0,
"suffix": "None"
}
}
@ -963,12 +963,12 @@ description: Result of parsing subtract_cylinder_from_cube.kcl
"arg": {
"commentStart": 0,
"end": 0,
"raw": "10",
"raw": "5",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"value": 5.0,
"suffix": "None"
}
}

View File

@ -10,7 +10,7 @@ fn cube(center) {
part001 = cube([0, 0])
part002 = startSketchOn('XY')
|> circle(center = [0, 0], radius = 2)
|> extrude(length = 10)
|> circle(center = [2, 2], radius = 2)
|> extrude(length = 5)
fullPart = subtract([part001], tools=[part002])

View File

@ -88,7 +88,7 @@ description: Operations executed subtract_cylinder_from_cube.kcl
"length": {
"value": {
"type": "Number",
"value": 10.0,
"value": 5.0,
"ty": {
"type": "Default",
"len": {

View File

@ -7,182 +7,365 @@ description: Variables in memory after executing subtract_cylinder_from_cube.kcl
"type": "Function"
},
"fullPart": {
"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",
"type": "HomArray",
"value": [
{
"type": "Solid",
"value": {
"type": "Solid",
"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
"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"
}
],
"to": [
-10.0,
-10.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"sourceRange": []
"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": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[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": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
}
}
]
},
"part001": {
"type": "Solid",
@ -388,18 +571,18 @@ description: Variables in memory after executing subtract_cylinder_from_cube.kcl
},
"ccw": true,
"center": [
0.0,
0.0
2.0,
2.0
],
"from": [
2.0,
0.0
4.0,
2.0
],
"radius": 2.0,
"tag": null,
"to": [
2.0,
0.0
4.0,
2.0
],
"type": "Circle",
"units": {
@ -438,12 +621,12 @@ description: Variables in memory after executing subtract_cylinder_from_cube.kcl
},
"start": {
"from": [
2.0,
0.0
4.0,
2.0
],
"to": [
2.0,
0.0
4.0,
2.0
],
"units": {
"type": "Mm"
@ -460,7 +643,7 @@ description: Variables in memory after executing subtract_cylinder_from_cube.kcl
"type": "Mm"
}
},
"height": 10.0,
"height": 5.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -14,7 +14,7 @@ fn cube(center) {
part001 = cube([0, 0])
part002 = startSketchOn(XY)
|> circle(center = [0, 0], radius = 2)
|> extrude(length = 10)
|> circle(center = [2, 2], radius = 2)
|> extrude(length = 5)
fullPart = subtract([part001], tools = [part002])

View File

@ -178,7 +178,7 @@ description: Artifact commands union_cubes.kcl
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 10.0,
"distance": 20.0,
"faces": null,
"opposite": "None"
}
@ -342,8 +342,8 @@ description: Artifact commands union_cubes.kcl
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": 10.0,
"y": 0.0,
"x": 2.0,
"y": -2.0,
"z": 0.0
}
}
@ -364,8 +364,8 @@ description: Artifact commands union_cubes.kcl
"segment": {
"type": "line",
"end": {
"x": 30.0,
"y": 0.0,
"x": 12.0,
"y": -2.0,
"z": 0.0
},
"relative": false
@ -381,8 +381,8 @@ description: Artifact commands union_cubes.kcl
"segment": {
"type": "line",
"end": {
"x": 30.0,
"y": 20.0,
"x": 12.0,
"y": 8.0,
"z": 0.0
},
"relative": false
@ -398,8 +398,8 @@ description: Artifact commands union_cubes.kcl
"segment": {
"type": "line",
"end": {
"x": 10.0,
"y": 20.0,
"x": 2.0,
"y": 8.0,
"z": 0.0
},
"relative": false
@ -544,5 +544,41 @@ description: Artifact commands union_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_union",
"solid_ids": [
"[uuid]",
"[uuid]"
],
"tolerance": 0.0000001
}
}
]

View File

@ -1,23 +1,23 @@
```mermaid
flowchart LR
subgraph path2 [Path]
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]"]
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]"]
7[Solid2d]
end
subgraph path24 [Path]
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]"]
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]"]
29[Solid2d]
end
1["Plane<br>[27, 44, 0]"]
8["Sweep Extrusion<br>[306, 326, 0]"]
1["Plane<br>[33, 50, 0]"]
8["Sweep Extrusion<br>[328, 354, 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>[27, 44, 0]"]
30["Sweep Extrusion<br>[306, 326, 0]"]
23["Plane<br>[33, 50, 0]"]
30["Sweep Extrusion<br>[328, 354, 0]"]
31[Wall]
32[Wall]
33[Wall]

View File

@ -101,16 +101,20 @@ description: Result of parsing union_cubes.kcl
},
"operator": "-",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -149,16 +153,20 @@ description: Result of parsing union_cubes.kcl
},
"operator": "-",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -246,16 +254,20 @@ description: Result of parsing union_cubes.kcl
},
"operator": "+",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -294,16 +306,20 @@ description: Result of parsing union_cubes.kcl
},
"operator": "-",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -386,16 +402,20 @@ description: Result of parsing union_cubes.kcl
},
"operator": "+",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -434,16 +454,20 @@ description: Result of parsing union_cubes.kcl
},
"operator": "+",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -526,16 +550,20 @@ description: Result of parsing union_cubes.kcl
},
"operator": "-",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -574,16 +602,20 @@ description: Result of parsing union_cubes.kcl
},
"operator": "+",
"right": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"raw": "10",
"name": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
},
"path": [],
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "Name",
"type": "Name"
},
"start": 0,
"type": "BinaryExpression",
@ -656,14 +688,38 @@ description: Result of parsing union_cubes.kcl
"arg": {
"commentStart": 0,
"end": 0,
"raw": "10",
"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"
},
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"suffix": "None"
}
"type": "BinaryExpression",
"type": "BinaryExpression"
}
}
],
@ -719,6 +775,16 @@ description: Result of parsing union_cubes.kcl
"start": 0,
"type": "Identifier"
}
},
{
"type": "Parameter",
"identifier": {
"commentStart": 0,
"end": 0,
"name": "size",
"start": 0,
"type": "Identifier"
}
}
],
"start": 0,
@ -780,6 +846,18 @@ description: Result of parsing union_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": {
@ -825,61 +903,129 @@ description: Result of parsing union_cubes.kcl
"type": "Identifier"
},
"init": {
"arguments": [
"body": [
{
"commentStart": 0,
"elements": [
"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,
"raw": "20",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 20.0,
"suffix": "None"
}
"type": "ArrayExpression",
"type": "ArrayExpression"
},
{
"commentStart": 0,
"end": 0,
"raw": "10",
"raw": "5",
"start": 0,
"type": "Literal",
"type": "Literal",
"value": {
"value": 10.0,
"value": 5.0,
"suffix": "None"
}
}
],
"end": 0,
"start": 0,
"type": "ArrayExpression",
"type": "ArrayExpression"
}
],
"callee": {
"abs_path": false,
"commentStart": 0,
"end": 0,
"name": {
"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,
"name": "cube",
"start": 0,
"type": "Identifier"
"type": "CallExpression",
"type": "CallExpression"
},
"path": [],
"start": 0,
"type": "Name"
},
{
"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
}
],
"commentStart": 0,
"end": 0,
"start": 0,
"type": "CallExpression",
"type": "CallExpression"
"type": "PipeExpression",
"type": "PipeExpression"
},
"start": 0,
"type": "VariableDeclarator"

View File

@ -1,14 +1,15 @@
fn cube(center) {
fn cube(center, size) {
return startSketchOn(XY)
|> 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])
|> 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])
|> close()
|> extrude(length = 10)
|> extrude(length = 2 * size)
}
part001 = cube([0, 0])
part002 = cube([20, 10])
part001 = cube([0, 0], 10)
part002 = cube([7, 3], 5)
|> translate(z = 1)
fullPart = union([part001, part002])

View File

@ -10,7 +10,7 @@ description: Operations executed union_cubes.kcl
"name": "cube",
"functionSourceRange": [
7,
328,
356,
0
],
"unlabeledArg": null,
@ -38,7 +38,7 @@ description: Operations executed union_cubes.kcl
"length": {
"value": {
"type": "Number",
"value": 10.0,
"value": 20.0,
"ty": {
"type": "Default",
"len": {
@ -75,7 +75,7 @@ description: Operations executed union_cubes.kcl
"name": "cube",
"functionSourceRange": [
7,
328,
356,
0
],
"unlabeledArg": null,

View File

@ -7,182 +7,365 @@ description: Variables in memory after executing union_cubes.kcl
"type": "Function"
},
"fullPart": {
"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",
"type": "HomArray",
"value": [
{
"type": "Solid",
"value": {
"type": "Solid",
"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
"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"
}
],
"to": [
-10.0,
-10.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"sourceRange": []
"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"
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[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"
}
}
}
}
]
},
"part001": {
"type": "Solid",
@ -354,7 +537,7 @@ description: Variables in memory after executing union_cubes.kcl
"type": "Mm"
}
},
"height": 10.0,
"height": 20.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
@ -408,13 +591,13 @@ description: Variables in memory after executing union_cubes.kcl
"sourceRange": []
},
"from": [
10.0,
0.0
2.0,
-2.0
],
"tag": null,
"to": [
30.0,
0.0
12.0,
-2.0
],
"type": "ToPoint",
"units": {
@ -427,13 +610,13 @@ description: Variables in memory after executing union_cubes.kcl
"sourceRange": []
},
"from": [
30.0,
0.0
12.0,
-2.0
],
"tag": null,
"to": [
30.0,
20.0
12.0,
8.0
],
"type": "ToPoint",
"units": {
@ -446,13 +629,13 @@ description: Variables in memory after executing union_cubes.kcl
"sourceRange": []
},
"from": [
30.0,
20.0
12.0,
8.0
],
"tag": null,
"to": [
10.0,
20.0
2.0,
8.0
],
"type": "ToPoint",
"units": {
@ -465,13 +648,13 @@ description: Variables in memory after executing union_cubes.kcl
"sourceRange": []
},
"from": [
10.0,
20.0
2.0,
8.0
],
"tag": null,
"to": [
10.0,
0.0
2.0,
-2.0
],
"type": "ToPoint",
"units": {
@ -510,12 +693,12 @@ description: Variables in memory after executing union_cubes.kcl
},
"start": {
"from": [
10.0,
0.0
2.0,
-2.0
],
"to": [
10.0,
0.0
2.0,
-2.0
],
"units": {
"type": "Mm"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

@ -2,17 +2,18 @@
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing union_cubes.kcl
---
fn cube(center) {
fn cube(center, size) {
return startSketchOn(XY)
|> 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])
|> 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])
|> close()
|> extrude(length = 10)
|> extrude(length = 2 * size)
}
part001 = cube([0, 0])
part002 = cube([20, 10])
part001 = cube([0, 0], 10)
part002 = cube([7, 3], 5)
|> translate(z = 1)
fullPart = union([part001, part002])

View File

@ -1,6 +1,6 @@
[package]
name = "kcl-python-bindings"
version = "0.3.58"
version = "0.3.59"
edition = "2021"
repository = "https://github.com/kittycad/modeling-app"
exclude = ["tests/*", "files/*", "venv/*"]

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-test-server"
description = "A test server for KCL"
version = "0.1.58"
version = "0.1.59"
edition = "2021"
license = "MIT"

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-to-core"
description = "Utility methods to convert kcl to engine core executable tests"
version = "0.1.58"
version = "0.1.59"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -1,6 +1,6 @@
[package]
name = "kcl-wasm-lib"
version = "0.1.58"
version = "0.1.59"
edition = "2021"
repository = "https://github.com/KittyCAD/modeling-app"
rust-version = "1.83"

View File

@ -292,3 +292,22 @@ pub fn get_kcl_version() -> String {
kcl_lib::version().to_string()
}
/// Get the allowed import file extensions.
#[wasm_bindgen]
pub fn import_file_extensions() -> Result<Vec<String>, String> {
console_error_panic_hook::set_once();
Ok(kcl_lib::IMPORT_FILE_EXTENSIONS.iter().map(|s| s.to_string()).collect())
}
/// Get the allowed relevant file extensions (imports + kcl).
#[wasm_bindgen]
pub fn relevant_file_extensions() -> Result<Vec<String>, String> {
console_error_panic_hook::set_once();
Ok(kcl_lib::RELEVANT_FILE_EXTENSIONS
.iter()
.map(|s| s.to_string())
.collect::<Vec<String>>())
}

View File

@ -14,6 +14,7 @@ import {
commandBarActor,
useCommandBarState,
} from '@src/machines/commandBarMachine'
import toast from 'react-hot-toast'
export const COMMAND_PALETTE_HOTKEY = 'mod+k'
@ -35,13 +36,23 @@ export const CommandBar = () => {
commandBarActor.send({ type: 'Close' })
}, [pathname])
/**
* if the engine connection is about to end, we don't want users
* to be able to perform commands that might require that connection,
* so we just close the command palette.
* TODO: instead, let each command control whether it is disabled, and
* don't just bail out
*/
useEffect(() => {
if (
immediateState.type !== EngineConnectionStateType.ConnectionEstablished
!commandBarActor.getSnapshot().matches('Closed') &&
(immediateState.type === EngineConnectionStateType.Disconnecting ||
immediateState.type === EngineConnectionStateType.Disconnected)
) {
commandBarActor.send({ type: 'Close' })
toast.error('Exiting command flow because engine disconnected')
}
}, [immediateState])
}, [immediateState, commandBarActor])
// Hook up keyboard shortcuts
useHotkeyWrapper([COMMAND_PALETTE_HOTKEY], () => {

View File

@ -4,6 +4,7 @@ import type { MouseEventHandler } from 'react'
import { useCallback, useContext, useEffect, useMemo } from 'react'
import { useHotkeys } from 'react-hotkeys-hook'
import { useAppState } from '@src/AppState'
import { ActionIcon } from '@src/components/ActionIcon'
import type { CustomIconName } from '@src/components/CustomIcon'
import { MachineManagerContext } from '@src/components/MachineManagerProvider'
@ -16,7 +17,10 @@ import { sidebarPanes } from '@src/components/ModelingSidebar/ModelingPanes'
import Tooltip from '@src/components/Tooltip'
import { DEV } from '@src/env'
import { useModelingContext } from '@src/hooks/useModelingContext'
import { useNetworkContext } from '@src/hooks/useNetworkContext'
import { NetworkHealthState } from '@src/hooks/useNetworkStatus'
import { useKclContext } from '@src/lang/KclProvider'
import { EngineConnectionStateType } from '@src/lang/std/engineConnection'
import { SIDEBAR_BUTTON_SUFFIX } from '@src/lib/constants'
import { isDesktop } from '@src/lib/isDesktop'
import { useSettings } from '@src/machines/appMachine'
@ -52,6 +56,16 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
: 'pointer-events-auto '
const showDebugPanel = settings.app.showDebugPanel
const { overallState, immediateState } = useNetworkContext()
const { isExecuting } = useKclContext()
const { isStreamReady } = useAppState()
const reliesOnEngine =
(overallState !== NetworkHealthState.Ok &&
overallState !== NetworkHealthState.Weak) ||
isExecuting ||
immediateState.type !== EngineConnectionStateType.ConnectionEstablished ||
!isStreamReady
const paneCallbackProps = useMemo(
() => ({
kclContext,
@ -93,6 +107,8 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
sidebarName: 'Export part',
icon: 'floppyDiskArrow',
keybinding: 'Ctrl + Shift + E',
disable: () =>
reliesOnEngine ? 'Need engine connection to export' : undefined,
action: () =>
commandBarActor.send({
type: 'Find and select command',

12
src/lang/wasmUtils.ts Normal file
View File

@ -0,0 +1,12 @@
import {
import_file_extensions,
relevant_file_extensions,
} from '@rust/kcl-wasm-lib/pkg/kcl_wasm_lib'
export function importFileExtensions(): string[] {
return import_file_extensions()
}
export function relevantFileExtensions(): string[] {
return relevant_file_extensions()
}

View File

@ -1,5 +1,4 @@
import type { Models } from '@kittycad/lib/dist/types/src'
import type { FileImportFormat_type } from '@kittycad/lib/dist/types/src/models'
import type { UnitAngle, UnitLength } from '@rust/kcl-lib/bindings/ModelingCmd'
@ -36,29 +35,6 @@ export const PROJECT_IMAGE_NAME = `thumbnail.png`
export const FILE_PERSIST_KEY = `${PROJECT_FOLDER}-last-opened` as const
/** The default name given to new kcl files in a project */
export const DEFAULT_FILE_NAME = 'Untitled'
/** The file endings that will appear in
* the file explorer if found in a project directory */
// TODO: make stp part of this enum as an alias to step
// TODO: make glb part of this enum as it is in fact supported
export type NativeFileType = 'kcl'
export type RelevantFileType =
| FileImportFormat_type
| NativeFileType
| 'stp'
| 'glb'
export const NATIVE_FILE_TYPE: NativeFileType = 'kcl'
export const RELEVANT_FILE_TYPES: RelevantFileType[] = [
'kcl',
'fbx',
'gltf',
'glb',
'obj',
'ply',
'sldprt',
'stp',
'step',
'stl',
] as const
/** The default name for a tutorial project */
export const ONBOARDING_PROJECT_NAME = 'Tutorial Project $nn'
/**

View File

@ -2,9 +2,14 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { Configuration } from '@rust/kcl-lib/bindings/Configuration'
import { isRelevantFile, listProjects } from '@src/lib/desktop'
import { initPromise } from '@src/lang/wasm'
import { listProjects } from '@src/lib/desktop'
import type { DeepPartial } from '@src/lib/types'
beforeAll(async () => {
await initPromise
})
// Mock the electron window global
const mockElectron = {
readdir: vi.fn(),
@ -112,41 +117,6 @@ describe('desktop utilities', () => {
mockElectron.kittycad.mockResolvedValue({})
})
describe('isRelevantFile', () => {
it('finds supported extension files relevant', () => {
expect(isRelevantFile('part.kcl')).toEqual(true)
expect(isRelevantFile('part.fbx')).toEqual(true)
expect(isRelevantFile('part.gltf')).toEqual(true)
expect(isRelevantFile('part.glb')).toEqual(true)
expect(isRelevantFile('part.obj')).toEqual(true)
expect(isRelevantFile('part.ply')).toEqual(true)
expect(isRelevantFile('part.sldprt')).toEqual(true)
expect(isRelevantFile('part.stp')).toEqual(true)
expect(isRelevantFile('part.step')).toEqual(true)
expect(isRelevantFile('part.stl')).toEqual(true)
})
// TODO: we should be lowercasing the extension here to check. .sldprt or .SLDPRT should be supported
// But the api doesn't allow it today, so revisit this and the tests once this is done
it('finds (now) supported uppercase extension files *not* relevant', () => {
expect(isRelevantFile('part.KCL')).toEqual(false)
expect(isRelevantFile('part.FBX')).toEqual(false)
expect(isRelevantFile('part.GLTF')).toEqual(false)
expect(isRelevantFile('part.GLB')).toEqual(false)
expect(isRelevantFile('part.OBJ')).toEqual(false)
expect(isRelevantFile('part.PLY')).toEqual(false)
expect(isRelevantFile('part.SLDPRT')).toEqual(false)
expect(isRelevantFile('part.STP')).toEqual(false)
expect(isRelevantFile('part.STEP')).toEqual(false)
expect(isRelevantFile('part.STL')).toEqual(false)
})
it("doesn't find .docx or .SLDASM relevant", () => {
expect(isRelevantFile('paper.docx')).toEqual(false)
expect(isRelevantFile('assembly.SLDASM')).toEqual(false)
})
})
describe('listProjects', () => {
it('does not list .git directories', async () => {
const projects = await listProjects(mockConfig)

View File

@ -10,13 +10,13 @@ import {
parseAppSettings,
parseProjectSettings,
} from '@src/lang/wasm'
import { relevantFileExtensions } from '@src/lang/wasmUtils'
import {
DEFAULT_DEFAULT_LENGTH_UNIT,
PROJECT_ENTRYPOINT,
PROJECT_FOLDER,
PROJECT_IMAGE_NAME,
PROJECT_SETTINGS_FILE_NAME,
RELEVANT_FILE_TYPES,
SETTINGS_FILE_NAME,
TELEMETRY_FILE_NAME,
TELEMETRY_RAW_FILE_NAME,
@ -201,15 +201,13 @@ export async function listProjects(
return projects
}
// TODO: we should be lowercasing the extension here to check. .sldprt or .SLDPRT should be supported
// But the api doesn't allow it today, so revisit this and the tests once this is done
export const isRelevantFile = (filename: string): boolean =>
RELEVANT_FILE_TYPES.some((ext) => filename.endsWith('.' + ext))
const collectAllFilesRecursiveFrom = async (
path: string,
canReadWritePath: boolean
) => {
const RELEVANT_FILE_EXTENSIONS = relevantFileExtensions()
const isRelevantFile = (filename: string): boolean =>
RELEVANT_FILE_EXTENSIONS.some((ext) => filename.endsWith('.' + ext))
// Make sure the filesystem object exists.
try {
await window.electron.stat(path)

View File

@ -3,8 +3,13 @@ import os from 'os'
import path from 'path'
import { v4 as uuidv4 } from 'uuid'
import { initPromise } from '@src/lang/wasm'
import getCurrentProjectFile from '@src/lib/getCurrentProjectFile'
beforeAll(async () => {
await initPromise
})
describe('getCurrentProjectFile', () => {
test('with explicit open file with space (URL encoded)', async () => {
const name = `kittycad-modeling-projects-${uuidv4()}`

View File

@ -1,17 +1,12 @@
import {
importFileExtensions,
relevantFileExtensions,
} from '@src/lang/wasmUtils'
import type { Stats } from 'fs'
import * as fs from 'fs/promises'
import * as path from 'path'
import {
NATIVE_FILE_TYPE,
PROJECT_ENTRYPOINT,
RELEVANT_FILE_TYPES,
type RelevantFileType,
} from '@src/lib/constants'
const shouldWrapExtension = (extension: string) =>
RELEVANT_FILE_TYPES.includes(extension as RelevantFileType) &&
extension !== NATIVE_FILE_TYPE
import { PROJECT_ENTRYPOINT } from '@src/lib/constants'
/// Get the current project file from the path.
/// This is used for double-clicking on a file in the file explorer,
@ -19,6 +14,12 @@ const shouldWrapExtension = (extension: string) =>
export default async function getCurrentProjectFile(
pathString: string
): Promise<string | Error> {
// Extract the values into an array
const allFileImportFormats: string[] = importFileExtensions()
const relevantExtensions: string[] = relevantFileExtensions()
const shouldWrapExtension = (extension: string) =>
allFileImportFormats.includes(extension)
// Fix for "." path, which is the current directory.
let sourcePath = pathString === '.' ? process.cwd() : pathString
@ -71,12 +72,9 @@ export default async function getCurrentProjectFile(
// Check if the extension on what we are trying to open is a relevant file type.
const extension = path.extname(sourcePath).slice(1).toLowerCase()
if (
!RELEVANT_FILE_TYPES.includes(extension as RelevantFileType) &&
extension !== 'toml'
) {
if (!relevantExtensions.includes(extension) && extension !== 'toml') {
return new Error(
`File type (${extension}) cannot be opened with this app: '${sourcePath}', try opening one of the following file types: ${RELEVANT_FILE_TYPES.join(
`File type (${extension}) cannot be opened with this app: '${sourcePath}', try opening one of the following file types: ${relevantExtensions.join(
', '
)}`
)

View File

@ -15,6 +15,7 @@ import type {
format_number as FormatNumber,
get_kcl_version as GetKclVersion,
get_tangential_arc_to_info as GetTangentialArcToInfo,
import_file_extensions as ImportFileExtensions,
is_kcl_empty_or_only_settings as IsKclEmptyOrOnlySettings,
is_points_ccw as IsPointsCcw,
kcl_lint as KclLint,
@ -23,6 +24,7 @@ import type {
parse_project_settings as ParseProjectSettings,
parse_wasm as ParseWasm,
recast_wasm as RecastWasm,
relevant_file_extensions as RelevantFileExtensions,
serialize_configuration as SerializeConfiguration,
serialize_project_configuration as SerializeProjectConfiguration,
} from '@rust/kcl-wasm-lib/pkg/kcl_wasm_lib'
@ -111,3 +113,9 @@ export const serialize_project_configuration: typeof SerializeProjectConfigurati
(...args) => {
return getModule().serialize_project_configuration(...args)
}
export const import_file_extensions: typeof ImportFileExtensions = () => {
return getModule().import_file_extensions()
}
export const relevant_file_extensions: typeof RelevantFileExtensions = () => {
return getModule().relevant_file_extensions()
}

View File

@ -45,7 +45,8 @@ export function useDemoCode() {
}
// Don't run if the network isn't healthy or the connection isn't established
if (
overallState !== NetworkHealthState.Ok ||
overallState === NetworkHealthState.Disconnected ||
overallState === NetworkHealthState.Issue ||
immediateState.type !== EngineConnectionStateType.ConnectionEstablished
) {
return