### Install Dependencies with npm Source: https://github.com/xiangechen/chili3d/blob/main/plugins/helloworld-ts/README.md Run this command to install the necessary project dependencies before building or packaging the plugin. ```bash npm install ``` -------------------------------- ### Install WASM Artifacts Source: https://github.com/xiangechen/chili3d/blob/main/cpp/CMakeLists.txt Installs the compiled WASM executable, its corresponding `.wasm` file, and TypeScript definition file to the specified installation prefix. ```cmake install(TARGETS ${TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.wasm DESTINATION ${CMAKE_INSTALL_PREFIX}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.d.ts DESTINATION ${CMAKE_INSTALL_PREFIX}) ``` -------------------------------- ### Development Build Commands Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Commands for starting the development server, building for production, and previewing the production build. ```bash npm run dev # Start development server with Rspack npm run build # Production build npm run preview # Preview production build ``` -------------------------------- ### Start Development Server Source: https://github.com/xiangechen/chili3d/blob/main/README.md Launch the development server for Chili3D. The application will be accessible at http://localhost:8080. ```bash npm run dev ``` -------------------------------- ### Install Dependencies for WASM Module Source: https://github.com/xiangechen/chili3d/blob/main/cpp/README.md Run this command to clone the repository and install all necessary dependencies for the WebAssembly module, especially when compiling for the first time or after cleaning the build directory. ```bash npm run setup:wasm ``` -------------------------------- ### Test Commit Example Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Example of a commit message for adding or updating tests, following the format (): . ```git ✅ test(core): add unit tests for result pattern error handling ``` -------------------------------- ### Feature Commit Example Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Example of a commit message for a new feature, following the format (): . ```git ✨ feat(core): add observable collection for reactive data binding ``` -------------------------------- ### Docs Commit Example Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Example of a commit message for documentation changes, following the format (): . ```git 📝 docs(readme): update installation instructions ``` -------------------------------- ### Chore Commit Example Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Example of a commit message for build, dependency, or maintenance tasks, following the format (): . ```git 🔧 chore(deps): upgrade typescript to 5.9.3 ``` -------------------------------- ### Refactor Commit Example Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Example of a commit message for code refactoring, following the format (): . ```git ♻️ refactor(ui): extract button component ``` -------------------------------- ### Fix Commit Example Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Example of a commit message for a bug fix, following the format (): . ```git 🐛 fix(three): resolve texture loading error in WebGL renderer ``` -------------------------------- ### Manual Transaction Control Source: https://context7.com/xiangechen/chili3d/llms.txt For more control, instantiate `Transaction` manually, then use `start()`, `commit()`, and `rollback()` methods. Ensure `rollback()` is called in a `catch` block to handle errors. ```typescript // Manual transaction control const trans = new Transaction(document, "Manual Transaction"); trans.start(); try { // Make changes document.modelManager.rootNode.add(someNode); trans.commit(); } catch (e) { trans.rollback(); throw e; } ``` -------------------------------- ### Rstest Test Structure Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Example structure for a test file using Rstest, including describe, test, and expect from @rstest/core. Assumes TestDocument utility. ```typescript // Part of the Chili3d Project, under the AGPL-3.0 License. // See LICENSE file in the project root for full license information. import { describe, test, expect } from "@rstest/core"; import { TestDocument } from "../src/test-utils"; describe("FeatureName", () => { test("should do something", () => { const doc = new TestDocument(); const result = someFunction(); expect(result).toEqual(expectedValue); }); }); ``` -------------------------------- ### Set up Project and C++ Standard Source: https://github.com/xiangechen/chili3d/blob/main/cpp/CMakeLists.txt Initializes the CMake project and sets the C++ standard to C++17. Configures build types and Ninja response file usage. ```cmake cmake_minimum_required (VERSION 3.30) project (chili-wasm) set (CMAKE_CXX_STANDARD 17) set (TARGET chili-wasm) set (CMAKE_CONFIGURATION_TYPES Debug;Release) set (CMAKE_NINJA_FORCE_RESPONSE_FILE 1 CACHE INTERNAL "") ``` -------------------------------- ### WebAssembly Build Commands Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Commands for building the C++ WebAssembly module and setting up its dependencies. ```bash npm run build:wasm # Build C++ WASM module with CMake npm run setup:wasm # Setup WASM dependencies ``` -------------------------------- ### Package Chili3D Plugin Source: https://github.com/xiangechen/chili3d/blob/main/plugins/helloworld-js/README.md Run this command to package the plugin into a .chiliplugin file. This script is cross-platform. ```bash npm run package ``` -------------------------------- ### Initialize WASM and Run Tests Source: https://github.com/xiangechen/chili3d/blob/main/cpp/test/index.html Initializes the Chili3D WebAssembly module and then runs several test cases for face mesh, edge mesh, and shape functionalities. This code should be executed when the window loads. ```javascript window.onload = async () => { const initWasm = await import('../build/target/release/chili-wasm.js'); const wasm = await initWasm.default(); test("test face mesh", (expect) => { const location = { x: 0, y: 0, z: 0 }; const direction = { x: 0, y: 0, z: 1 }; const xDirection = { x: 1, y: 0, z: 0 }; const ax3 = { location, direction, xDirection }; const box = wasm.ShapeFactory.box(ax3, 1, 2, 3).shape; const mesher = new wasm.Mesher(box, 0.1); const mesh = mesher.mesh(); expect(mesh.faceMeshData.position.length).toBe(72); expect(mesh.faceMeshData.index.length).toBe(36); expect(mesh.faceMeshData.group.length).toBe(12); expect(mesh.faceMeshData.normal.length).toBe(72); expect(mesh.faceMeshData.uv.length).toBe(48); }) test("test edge mesh", (expect) => { const location = { x: 0, y: 0, z: 0 }; const direction = { x: 0, y: 0, z: 1 }; const xDirection = { x: 1, y: 0, z: 0 }; const ax3 = { location, direction, xDirection }; const box = wasm.ShapeFactory.box(ax3, 1, 1, 1).shape; const mesher = new wasm.Mesher(box, 0.1); const mesh = mesher.mesh(); expect(mesh.edgeMeshData.position.length).toBe(72); expect(mesh.edgeMeshData.group.length).toBe(24); }) test("test shape", (expect) => { const location = { x: 0, y: 0, z: 0 }; const direction = { x: 0, y: 0, z: 1 }; const xDirection = { x: 1, y: 0, z: 0 }; const ax3 = { location, direction, xDirection }; const box = wasm.ShapeFactory.box(ax3, 1, 1, 1).shape; const edges = wasm.Shape.findSubShapes(box, wasm.TopAbs_ShapeEnum.TopAbs_EDGE); expect(edges.length).toBe(12); expect(edges[0].shapeType()).toBe(wasm.TopAbs_ShapeEnum.TopAbs_EDGE); const curve = wasm.Edge.curve(wasm.TopoDS.edge(edges[0])); const newEdge = wasm.Edge.fromCurve(curve.get()); expect(wasm.Edge.curveLength(newEdge)).toBe(1); const faces = wasm.Shape.findAncestor(box, edges[1], wasm.TopAbs_ShapeEnum.TopAbs_FACE); expect(faces.length).toBe(2); expect(faces[0].shapeType()).toBe(wasm.TopAbs_ShapeEnum.TopAbs_FACE) const faceEdges = wasm.Shape.findSubShapes(faces[0], wasm.TopAbs_ShapeEnum.TopAbs_EDGE); expect(faceEdges.length).toBe(4); }) } ``` -------------------------------- ### Configure Version Header and Include Paths Source: https://github.com/xiangechen/chili3d/blob/main/cpp/CMakeLists.txt Includes a CMake script to manage version information and configures the include directories for the project, including the generated version header. ```cmake include(build/occt/adm/cmake/version.cmake) configure_file("build/occt/adm/templates/Standard_Version.hxx.in" "include/Standard_Version.hxx" @ONLY) list (APPEND OcctIncludeDirs ${CMAKE_CURRENT_BINARY_DIR}/include) ``` -------------------------------- ### Build the Chili3D Plugin Source: https://github.com/xiangechen/chili3d/blob/main/plugins/helloworld-ts/README.md Execute this command to compile the TypeScript source code into JavaScript, preparing it for packaging. ```bash npm run build ``` -------------------------------- ### Define and Register a Custom Plugin Command Source: https://context7.com/xiangechen/chili3d/llms.txt Create a `Plugin` object to register custom commands, UI contributions, and localization resources. The `commands` array should list all command classes. ```typescript import { command, Plugin, IApplication, ICommand, PubSub } from "@chili3d/core"; // Define a custom command @command({ key: "myPlugin.hello", icon: { type: "path", value: "icons/hello.svg" }, }) export class HelloCommand implements ICommand { async execute(application: IApplication): Promise { PubSub.default.pub("showToast", "myPlugin.helloMessage"); } } // Export the plugin configuration const MyPlugin: Plugin = { // Register commands commands: [HelloCommand], // Add ribbon UI contributions ribbons: [ { tabName: "ribbon.tab.tools", groups: [ { groupName: "ribbon.group.myPlugin", items: ["myPlugin.hello"], }, ], }, ], // Provide localization i18nResources: [ { language: "en", display: "English", translation: { "command.myPlugin.hello": "Say Hello", "myPlugin.helloMessage": "Hello from MyPlugin!", "ribbon.group.myPlugin": "My Plugin", }, }, { language: "zh-CN", display: "Simplified Chinese", translation: { "command.myPlugin.hello": "Say Hi", "myPlugin.helloMessage": "MyPlugin says Hi!", "ribbon.group.myPlugin": "My Plugin", }, }, ], }; export default MyPlugin; ``` -------------------------------- ### Clone Chili3D Repository Source: https://github.com/xiangechen/chili3d/blob/main/README.md Clone the Chili3D repository to your local machine. ```bash git clone https://github.com/xiangechen/chili3d.git cd chili3d ``` -------------------------------- ### Initialize Chili3D Application Source: https://context7.com/xiangechen/chili3d/llms.txt Use AppBuilder to initialize the Chili3D application with IndexedDB, OpenCascade WebAssembly, Three.js, and UI components. Handles success and error cases during initialization and subsequent operations like creating documents or loading files. ```typescript import { AppBuilder } from "@chili3d/builder"; import { Logger } from "@chili3d/core"; // Initialize the application with all required components new AppBuilder() .useIndexedDB() // Enable IndexedDB for document storage .useWasmOcc() // Load OpenCascade WebAssembly module .useThree() // Initialize Three.js for 3D rendering .useUI() // Set up the user interface .build() .then(async (app) => { Logger.info("Application initialized successfully"); // Create a new document const document = await app.newDocument("MyProject"); // Load a file from URL (STEP, IGES, or native format) await app.loadFileFromUrl("https://example.com/model.step"); // Load a plugin await app.pluginManager.loadFromUrl("/plugins/my-plugin.chiliplugin"); }) .catch((err) => { console.error("Failed to initialize:", err.message); }); ``` -------------------------------- ### Code Quality Commands Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Commands for linting, auto-fixing code with Biome, and formatting all code. ```bash npm run check # Biome linting and auto-fix (run before commits!) npm run format # Format all code (Biome + clang-format) ``` -------------------------------- ### Collect OCCT Source Files and Include Directories Source: https://github.com/xiangechen/chili3d/blob/main/cpp/CMakeLists.txt Gathers all C/C++ source files and include directories for the OCCT libraries based on the identified packages. This prepares them for compilation. ```cmake set (OcctSourceFolders) set (OcctIncludeDirs) foreach(package ${OcctUsedPackages}) if (NOT package STREQUAL "") list (APPEND OcctSourceFolders build/occt/src/${package}/*.c*) list (APPEND OcctIncludeDirs build/occt/src/${package}) endif() endforeach() ``` -------------------------------- ### Compile WASM Module Source: https://github.com/xiangechen/chili3d/blob/main/cpp/README.md Execute this command to build the current project's WebAssembly module. The compiled output will be placed in the 'packages/chili-wasm/lib' directory. ```bash npm run build:wasm ``` -------------------------------- ### Create and Modify Parametric Box, Cylinder, and Sphere Nodes Source: https://context7.com/xiangechen/chili3d/llms.txt Demonstrates creating parametric geometry nodes (BoxNode, CylinderNode, SphereNode) with initial parameters and modifying them later. All modifications should be wrapped in Transactions for undo/redo functionality. ```typescript import { BoxNode, CylinderNode, SphereNode } from "@chili3d/app"; import { Plane, XYZ, Transaction } from "@chili3d/core"; // Get the active document const document = app.activeView?.document; // Create a parametric box node const boxNode = new BoxNode({ document: document, plane: Plane.XY, dx: 100, dy: 50, dz: 30 }); // Add to document within a transaction (for undo support) Transaction.execute(document, "Create Box", () => { document.modelManager.rootNode.add(boxNode); }); // Modify box parameters (automatically updates shape) boxNode.dx = 150; boxNode.dy = 75; boxNode.location = new XYZ({ x: 50, y: 0, z: 0 }); // Create a cylinder node const cylinderNode = new CylinderNode({ document: document, normal: XYZ.unitZ, center: new XYZ({ x: 200, y: 0, z: 0 }), radius: 25, dz: 80 }); Transaction.execute(document, "Create Cylinder", () => { document.modelManager.rootNode.add(cylinderNode); }); // Create a sphere node const sphereNode = new SphereNode({ document: document, center: new XYZ({ x: 0, y: 100, z: 25 }), radius: 25 }); Transaction.execute(document, "Create Sphere", () => { document.modelManager.rootNode.add(sphereNode); }); // Modify sphere after creation sphereNode.radius = 35; sphereNode.center = new XYZ({ x: 0, y: 100, z: 35 }); ``` -------------------------------- ### Build Chili3D WASM Executable Source: https://github.com/xiangechen/chili3d/blob/main/cpp/CMakeLists.txt Creates the main executable for the Chili3D WASM project. It includes OCCT headers and applies Emscripten-specific compile and link options for web deployment. ```cmake add_executable (${TARGET} ${ChiliWasmSourceFiles}) target_include_directories (${TARGET} PUBLIC ${OcctIncludeDirs}) target_compile_options (${TARGET} PUBLIC $<$:-Os> $<$:-flto> $,-sDISABLE_EXCEPTION_CATCHING=1,-sDISABLE_EXCEPTION_CATCHING=0> ) ``` -------------------------------- ### C++ WebAssembly File Header Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Required file header for C++ WebAssembly files, specifying project and license information (LGPL-3.0). ```cpp // Part of the Chili3d Project, under the LGPL-3.0 License. // See LICENSE-chili-wasm.text file in the project root for full license information. ``` -------------------------------- ### Link Libraries and Apply Emscripten Options Source: https://github.com/xiangechen/chili3d/blob/main/cpp/CMakeLists.txt Links the OCCT static library to the Chili3D WASM executable and applies various Emscripten linker flags for web environment, modularization, exception handling, stack/heap size, and memory growth. ```cmake target_link_libraries(${TARGET} PUBLIC occt) target_link_options (${TARGET} PUBLIC $,-Os,-O0> $,-flto,-fno-lto> $,-sDISABLE_EXCEPTION_CATCHING=1,-sDISABLE_EXCEPTION_CATCHING=0> -sMODULARIZE=1 -sEXPORT_ES6=1 -sSTACK_SIZE=8MB -sINITIAL_HEAP=64MB -sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=4GB -sENVIRONMENT="web" --bind --emit-tsd "${TARGET}.d.ts" ) ``` -------------------------------- ### Testing Commands Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Commands for running tests with Rstest, including coverage, single files, patterns, and directories. ```bash npm run test # Run all tests with Rstest npm run testc # Run tests with coverage npx rstest path/to/file.test.ts # Run single test file npx rstest -t "test name" # Run tests matching pattern npx rstest packages/core/test/ # Run all tests in directory ``` -------------------------------- ### Internal Package Imports Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Demonstrates the correct way to import internal packages using their names, not relative paths. Also shows type-only imports. ```typescript // Internal packages - use package names, not relative paths import { AppBuilder } from "@chili3d/builder"; import { type IApplication, Logger } from "@chili3d/core"; // Type-only imports import type { ICommand } from "./command"; // External packages import * as THREE from "three"; ``` -------------------------------- ### Build OCCT Static Library for WASM Source: https://github.com/xiangechen/chili3d/blob/main/cpp/CMakeLists.txt Compiles the OCCT source files into a static library. Applies optimization flags for release builds and Emscripten-specific options for exception handling. ```cmake add_library(occt STATIC ${OcctSourceFiles}) target_include_directories (occt PUBLIC ${OcctIncludeDirs}) target_compile_options (occt PUBLIC $<$:-Os> $<$:-flto> $,-sDISABLE_EXCEPTION_CATCHING=1,-sDISABLE_EXCEPTION_CATCHING=0> -DOCCT_NO_PLUGINS ) ``` -------------------------------- ### Create Advanced Parametric Nodes: Prism, Revolve, Sweep Source: https://context7.com/xiangechen/chili3d/llms.txt Illustrates the creation of advanced parametric geometry nodes including PrismNode (extrusion), RevolvedNode (revolution), and SweepedNode (sweeping). Use Transactions for all node creations and modifications. ```typescript import { PrismNode, RevolvedNode, SweepedNode } from "@chili3d/app"; import { Line, XYZ, Transaction } from "@chili3d/core"; const document = app.activeView?.document; const shapeFactory = app.shapeFactory; // Create a prism (extruded) node const profile = shapeFactory.rect(Plane.XY, 40, 30).value; const prismNode = new PrismNode({ document: document, section: profile, length: 100 }); Transaction.execute(document, "Create Prism", () => { document.modelManager.rootNode.add(prismNode); }); // Modify prism length prismNode.length = 150; // Create a revolved node const revolveProfile = shapeFactory.polygon([ { x: 20, y: 0, z: 0 }, { x: 40, y: 0, z: 0 }, { x: 40, y: 0, z: 60 }, { x: 20, y: 0, z: 60 } ]).value; const revolvedNode = new RevolvedNode({ document: document, profile: revolveProfile, axis: { point: XYZ.zero, direction: XYZ.unitZ }, angle: 270 // Partial revolution }); Transaction.execute(document, "Create Revolve", () => { document.modelManager.rootNode.add(revolvedNode); }); // Create a swept node const sweepProfile = shapeFactory.circle(XYZ.unitX, XYZ.zero, 10).value; const sweepPath = shapeFactory.polygon([ { x: 0, y: 0, z: 0 }, { x: 100, y: 0, z: 0 }, { x: 100, y: 100, z: 50 } ]).value; const sweepNode = new SweepedNode({ document: document, profile: [sweepProfile], path: sweepPath, round: true }); Transaction.execute(document, "Create Sweep", () => { document.modelManager.rootNode.add(sweepNode); }); ``` -------------------------------- ### Define OCCT Toolkits and Packages Source: https://github.com/xiangechen/chili3d/blob/main/cpp/CMakeLists.txt Lists the required Open CASCADE Technology (OCCT) toolkits and then determines the used packages by parsing PACKAGES files. This helps in managing dependencies for the WASM build. ```cmake set (OcctToolkits # FoundationClasses TKernel TKMath # ModelingData TKG2d TKG3d TKGeomBase TKBRep # ModelingAlgorithms TKGeomAlgo TKTopAlgo TKPrim TKBO TKBool TKHLR TKFillet TKOffset TKFeat TKMesh TKShHealing # Visualization TKService TKV3d # ApplicationFramework TKCDF TKLCAF TKCAF TKStdL TKStd TKVCAF TKBin TKBinL TKBinXCAF # DataExchange TKDE TKXSBase TKXCAF TKDESTEP TKDEIGES TKDESTL ) set (OcctUsedPackages) foreach(toolkit ${OcctToolkits}) file (STRINGS build/occt/src/${toolkit}/PACKAGES OcctPackages) list (APPEND OcctUsedPackages ${OcctPackages}) endforeach() list (REMOVE_DUPLICATES OcctUsedPackages) ``` -------------------------------- ### Glob OCCT Source Files Source: https://github.com/xiangechen/chili3d/blob/main/cpp/CMakeLists.txt Finds all C/C++ source files for OCCT based on the previously defined folders. This is used to add OCCT sources to the build. ```cmake file (GLOB OcctSourceFiles ${OcctSourceFolders}) ``` -------------------------------- ### Initialize Chili3D Tracking Source: https://github.com/xiangechen/chili3d/blob/main/public/index.html This JavaScript snippet initializes the Chili3D tracking script. Ensure this code is included in your project to enable tracking functionality. ```javascript Chili3D (function(c,l,a,r,i,t,y){ c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); })(window, document, "clarity", "script", "k1qrtibhcl"); ``` -------------------------------- ### Serialize and Deserialize Objects with Serializer Source: https://context7.com/xiangechen/chili3d/llms.txt Use Serializer.serializeObject to convert an object instance into a JSON-compatible format. Use Serializer.deserializeObject to restore the object from its serialized representation. Ensure the document object is available for deserialization. ```typescript // Serialize an object to JSON const data = new CustomData({ name: "Test", value: 42, points: [XYZ.zero, XYZ.unitX] }); const serialized = Serializer.serializeObject(data); // Result: { "__cla$$": "CustomData", "name": "Test", "value": 42, "points": [...] } // Deserialize back to object const restored = Serializer.deserializeObject(document, serialized); ``` -------------------------------- ### Glob Chili3D WASM Source Files Source: https://github.com/xiangechen/chili3d/blob/main/cpp/CMakeLists.txt Finds all header and source files for the Chili3D WASM project. `CONFIGURE_DEPENDS` ensures these are re-evaluated if files change. ```cmake set (ChiliWasmSourcesFolder src) file (GLOB ChiliWasmSourceFiles CONFIGURE_DEPENDS ${ChiliWasmSourcesFolder}/*.hpp ${ChiliWasmSourcesFolder}/*.cpp ) ``` -------------------------------- ### Generate Complex 3D Shapes with Prism, Sweep, Revolve, and Loft Source: https://context7.com/xiangechen/chili3d/llms.txt Create advanced 3D geometries by extruding profiles (prism), sweeping profiles along paths, revolving profiles around an axis, or lofting between multiple cross-sections. These methods allow for intricate shape creation. ```typescript import { Line, Plane, XYZ, Continuity } from "@chili3d/core"; const shapeFactory = app.shapeFactory; // PRISM: Extrude a profile along a vector const rectFace = shapeFactory.rect(Plane.XY, 50, 30).value; const prismResult = shapeFactory.prism( rectFace, new XYZ({ x: 0, y: 0, z: 100 }) // Extrusion vector ); // SWEEP: Sweep a profile along a path const circleProfile = shapeFactory.circle(XYZ.unitZ, XYZ.zero, 10).value; const pathWire = shapeFactory.polygon([ { x: 0, y: 0, z: 0 }, { x: 50, y: 0, z: 50 }, { x: 100, y: 0, z: 50 }, { x: 150, y: 0, z: 0 } ]).value; const sweepResult = shapeFactory.sweep( [circleProfile], // Profile(s) pathWire, // Path true // Round corners ); // REVOLVE: Rotate a profile around an axis const profile = shapeFactory.polygon([ { x: 20, y: 0, z: 0 }, { x: 50, y: 0, z: 0 }, { x: 50, y: 0, z: 80 }, { x: 30, y: 0, z: 100 }, { x: 20, y: 0, z: 80 } ]).value; const axis: Line = { point: XYZ.zero, direction: XYZ.unitZ }; const revolveResult = shapeFactory.revolve( profile, axis, 360 // Angle in degrees (full revolution) ); // LOFT: Create smooth surface through multiple sections const section1 = shapeFactory.circle(XYZ.unitZ, new XYZ({ x: 0, y: 0, z: 0 }), 30).value; const section2 = shapeFactory.circle(XYZ.unitZ, new XYZ({ x: 0, y: 0, z: 50 }), 20).value; const section3 = shapeFactory.circle(XYZ.unitZ, new XYZ({ x: 0, y: 0, z: 100 }), 35).value; const loftResult = shapeFactory.loft( [section1, section2, section3], true, // isSolid false, // isRuled Continuity.C2 // Surface continuity ); ``` -------------------------------- ### Implement a Cancelable Command Source: https://context7.com/xiangechen/chili3d/llms.txt Extend `CancelableCommand` for commands that involve interactive steps and can be canceled mid-execution. The `executeAsync` method should contain the command logic. ```typescript // Cancelable command with interactive steps @command({ key: "myPlugin.interactiveBox", icon: "icon-box", }) export class InteractiveBox extends CancelableCommand { protected async executeAsync(): Promise { // Command logic with step-based user interaction // Can be canceled mid-execution if (this.isCanceled) return; Transaction.execute(this.document, "Interactive Box", () => { // Create geometry based on user input }); } } ``` -------------------------------- ### TypeScript File Header Source: https://github.com/xiangechen/chili3d/blob/main/AGENTS.md Required file header for all TypeScript files, specifying project and license information. ```typescript // Part of the Chili3d Project, under the AGPL-3.0 License. // See LICENSE file in the project root for full license information. ``` -------------------------------- ### Document Management Operations Source: https://context7.com/xiangechen/chili3d/llms.txt Manage documents using the application instance. Supports creating new documents, saving, loading, serializing, and closing documents. Also handles file imports and selection management. ```typescript import { DOCUMENT_FILE_EXTENSION } from "@chili3d/core"; // Create a new document const document = await app.newDocument("ProjectName"); // Access document properties console.log("Document ID:", document.id); console.log("Document Name:", document.name); // Access model manager for scene graph const rootNode = document.modelManager.rootNode; const materials = document.modelManager.materials; // Save document to storage await document.save(); // Open existing document by ID const loadedDoc = await app.openDocument("document-id-here"); // Serialize document to JSON const serialized = document.serialize(); // Load document from serialized data const restoredDoc = await app.loadDocument(serialized); // Import files (STEP, IGES, BREP, or native format) await app.importFiles([file1, file2]); // Load file from URL await app.loadFileFromUrl("https://example.com/model.step"); // Close document await document.close(); // Access document from active view const activeDoc = app.activeView?.document; // Selection management const selection = document.selection; selection.select([node1, node2]); const selectedNodes = selection.getSelected(); selection.clearSelection(); ``` -------------------------------- ### Register a Simple Non-Cancelable Command Source: https://context7.com/xiangechen/chili3d/llms.txt Use the `@command` decorator to register commands that can be executed and have undo/redo support. Ensure the document is available before executing. ```typescript import { command, CancelableCommand, IApplication, ICommand, PubSub, Transaction } from "@chili3d/core"; import { BoxNode } from "@chili3d/app"; // Simple non-cancelable command @command({ key: "myPlugin.createDefaultBox", icon: "icon-box", }) export class CreateDefaultBox implements ICommand { async execute(application: IApplication): Promise { const document = application.activeView?.document; if (!document) return; Transaction.execute(document, "Create Default Box", () => { const box = new BoxNode({ document: document, plane: Plane.XY, dx: 100, dy: 100, dz: 100 }); document.modelManager.rootNode.add(box); }); PubSub.default.pub("showToast", "Box created!"); } } ``` -------------------------------- ### Math Utilities: XYZ and Plane Operations Source: https://context7.com/xiangechen/chili3d/llms.txt Utilize XYZ for points and vectors, and Plane for geometric plane operations. Supports vector arithmetic, angle calculations, comparisons, rotations, and plane projections/intersections. ```typescript import { XYZ, Plane, MathUtils } from "@chili3d/core"; // Create XYZ points/vectors const point1 = new XYZ({ x: 10, y: 20, z: 30 }); const point2 = new XYZ({ x: 50, y: 60, z: 70 }); // Static unit vectors const xAxis = XYZ.unitX; // (1, 0, 0) const yAxis = XYZ.unitY; // (0, 1, 0) const zAxis = XYZ.unitZ; // (0, 0, 1) const origin = XYZ.zero; // (0, 0, 0) // Vector operations const sum = point1.add(point2); // Vector addition const diff = point2.sub(point1); // Vector subtraction const scaled = point1.multiply(2); // Scalar multiplication const normalized = diff.normalize(); // Unit vector const length = diff.length(); // Vector magnitude const distance = point1.distanceTo(point2); // Vector products const dotProduct = point1.dot(point2); // Dot product const crossProduct = xAxis.cross(yAxis); // Cross product (returns zAxis) // Angle calculations const angle = point1.angleTo(point2); // Angle in radians [0, PI] const angleOnPlane = point1.angleOnPlaneTo(point2, zAxis); // [0, 2PI] // Vector comparisons const isParallel = point1.isParallelTo(point2); const isPerpendicular = xAxis.isPerpendicularTo(yAxis); // true const isEqual = point1.isEqualTo(point2, 1e-6); // Rotate vector around axis const rotated = point1.rotate(zAxis, Math.PI / 4); // 45 degrees // Create planes const xyPlane = Plane.XY; // XY plane at origin const customPlane = new Plane({ origin: new XYZ({ x: 0, y: 0, z: 50 }), normal: XYZ.unitZ, xvec: XYZ.unitX }); // Plane operations const projected = customPlane.project(point1); // Project point onto plane const translated = customPlane.translateTo(new XYZ({ x: 100, y: 0, z: 50 })); // Line-plane intersection const line = { point: origin, direction: new XYZ({ x: 1, y: 1, z: 1 }) }; const intersection = customPlane.intersectLine(line); ``` -------------------------------- ### Execute Synchronous and Asynchronous Transactions Source: https://context7.com/xiangechen/chili3d/llms.txt Wrap document modifications in `Transaction.execute` for synchronous operations or `Transaction.executeAsync` for asynchronous ones to ensure atomic undo/redo. All document modifications should be wrapped. ```typescript import { Transaction, BoxNode, CylinderNode } from "@chili3d/core"; const document = app.activeView?.document; // Synchronous transaction Transaction.execute(document, "Create Multiple Shapes", () => { const box = new BoxNode({ document: document, plane: Plane.XY, dx: 100, dy: 100, dz: 50 }); document.modelManager.rootNode.add(box); const cylinder = new CylinderNode({ document: document, normal: XYZ.unitZ, center: new XYZ({ x: 150, y: 0, z: 0 }), radius: 25, dz: 80 }); document.modelManager.rootNode.add(cylinder); }); // Async transaction await Transaction.executeAsync(document, "Async Operation", async () => { // Async operations here const shape = await someAsyncShapeCreation(); document.modelManager.rootNode.add(shape); }); ``` -------------------------------- ### Undo and Redo Operations Source: https://context7.com/xiangechen/chili3d/llms.txt Use `document.history.undo()` and `document.history.redo()` to revert or reapply changes within the transaction history. ```typescript // Undo/Redo operations document.history.undo(); document.history.redo(); ``` -------------------------------- ### Create 2D Curves and Wires with Shape Factory Source: https://context7.com/xiangechen/chili3d/llms.txt Use the shape factory to generate basic 2D geometric entities like lines, circles, arcs, ellipses, rectangles, polygons, and Bezier curves. These are foundational for subsequent 3D operations. ```typescript import { Plane, XYZ } from "@chili3d/core"; const shapeFactory = app.shapeFactory; // Create a line edge const lineResult = shapeFactory.line( { x: 0, y: 0, z: 0 }, // Start point { x: 100, y: 50, z: 0 } // End point ); // Create a circle edge const circleResult = shapeFactory.circle( XYZ.unitZ, // Normal direction new XYZ({ x: 50, y: 50, z: 0 }),// Center point 25 // Radius ); // Create an arc const arcResult = shapeFactory.arc( XYZ.unitZ, // Normal new XYZ({ x: 0, y: 0, z: 0 }), // Center new XYZ({ x: 30, y: 0, z: 0 }), // Start point 90 // Angle in degrees ); // Create an ellipse const ellipseResult = shapeFactory.ellipse( XYZ.unitZ, // Normal new XYZ({ x: 0, y: 0, z: 0 }), // Center XYZ.unitX, // X-direction 50, // Major radius 30 // Minor radius ); // Create a rectangle face const rectResult = shapeFactory.rect( Plane.XY, // Plane 100, // dx (width) 60 // dy (height) ); // Create a polygon wire from points const polygonResult = shapeFactory.polygon([ { x: 0, y: 0, z: 0 }, { x: 100, y: 0, z: 0 }, { x: 100, y: 100, z: 0 }, { x: 50, y: 150, z: 0 }, { x: 0, y: 100, z: 0 } ]); // Create a bezier curve const bezierResult = shapeFactory.bezier([ { x: 0, y: 0, z: 0 }, { x: 30, y: 50, z: 0 }, { x: 70, y: 50, z: 0 }, { x: 100, y: 0, z: 0 } ]); ``` -------------------------------- ### Test Runner Function Source: https://github.com/xiangechen/chili3d/blob/main/cpp/test/index.html An asynchronous function to run named tests. It sets up a test environment, executes a provided test function, and appends the results to the output. It requires the 'expect' function for assertions. ```javascript async function test(name, fn) { var passed = 0, failed = 0; const expect = (actual) => { return { toBe(expected) { if (actual !== expected) { div.append(failedMessage(actual, expected)); failed++; } else { passed++; } } }; }; const div = document.createElement('div'); div.className = 'test'; output.append(div); const title = document.createElement('h2'); div.innerHTML = name output.append(title); const start = performance.now(); fn(expect); const end = performance.now(); div.append(resultMessage(passed, failed, end - start)); } ``` -------------------------------- ### Apply Fillet and Chamfer to Box Edges Source: https://context7.com/xiangechen/chili3d/llms.txt Modifies a solid box by applying fillets (rounded edges) or chamfers (beveled edges) to specified edge indices. Ensure correct edge indices are provided for the desired effect. ```typescript const shapeFactory = app.shapeFactory; // Create a box to modify const box = shapeFactory.box(Plane.XY, 100, 100, 50).value; // Apply fillet to specific edges (by edge index) const filletResult = shapeFactory.fillet( box, [0, 1, 2, 3], // Edge indices to fillet 5 // Fillet radius ); if (filletResult.isOk) { console.log("Fillet applied successfully"); } // Apply chamfer to specific edges const chamferResult = shapeFactory.chamfer( box, [4, 5, 6, 7], // Edge indices to chamfer 3 // Chamfer distance ); // Create thick solid (shell) from a shape const thickResult = shapeFactory.makeThickSolidBySimple( box, -2 // Thickness (negative for inward) ); ``` -------------------------------- ### 3D Model Import and Export Source: https://context7.com/xiangechen/chili3d/llms.txt Handle importing and exporting 3D models using supported formats via OpenCascade. Includes reading files, exporting selected nodes, and downloading exported files. ```typescript import { readFilesAsync, download } from "@chili3d/core"; // Supported import formats (via OpenCascade) const importFormats = app.dataExchange.importFormats(); // Typically: [".step", ".stp", ".iges", ".igs", ".brep", ".brp"] // Supported export formats const exportFormats = app.dataExchange.exportFormats(); // Typically: [".step", ".iges", ".brep", ".stl", ".stl binary", ".ply", ".ply binary"] // Read files via file dialog const filesResult = await readFilesAsync(".step,.stp,.iges", true); if (filesResult.isOk) { await app.importFiles(filesResult.value); } // Export selected nodes const nodes = document.selection.getSelected(); const exportData = await app.dataExchange.export(".step", nodes); if (exportData) { // Download the exported file download(exportData, "exported-model.step"); } // Drag and drop support is built-in // Files dropped on the application window are automatically imported ``` -------------------------------- ### Create Primitive Shapes with Shape Factory Source: https://context7.com/xiangechen/chili3d/llms.txt Access the shapeFactory from the application instance to create various 3D primitive shapes like boxes, cylinders, spheres, cones, and pyramids. Operations return a Result which should be checked for success before accessing the value. ```typescript import { Plane, XYZ } from "@chili3d/core"; // Access shape factory from the application const shapeFactory = app.shapeFactory; // Create a box (returns Result) const boxResult = shapeFactory.box( Plane.XY, // Base plane 100, // dx (width) 50, // dy (depth) 30 // dz (height) ); if (boxResult.isOk) { const boxShape = boxResult.value; console.log("Box created successfully"); } // Create a cylinder const cylinderResult = shapeFactory.cylinder( XYZ.unitZ, new XYZ({ x: 0, y: 0, z: 0 }), 25, 100 ); // Create a sphere const sphereResult = shapeFactory.sphere( new XYZ({ x: 0, y: 0, z: 50 }), 30 ); // Create a cone const coneResult = shapeFactory.cone( XYZ.unitZ, new XYZ({ x: 0, y: 0, z: 0 }), 30, 10, 50 ); // Create a pyramid const pyramidResult = shapeFactory.pyramid( Plane.XY, 60, 40, 80 ); ``` -------------------------------- ### Define Source Groups in CMake Source: https://github.com/xiangechen/chili3d/blob/main/cpp/CMakeLists.txt Organizes source files into logical groups within the build system for better project management in IDEs. ```cmake source_group ("Sources" FILES ${ChiliWasmSourceFiles}) source_group ("OCCT" FILES ${OcctSourceFiles}) ``` -------------------------------- ### Failed Message Helper Function Source: https://github.com/xiangechen/chili3d/blob/main/cpp/test/index.html A helper function to create and format a paragraph element indicating a test failure, showing the expected versus actual values. ```javascript function failedMessage(actual, expected) { const p = document.createElement('p'); p.innerHTML = `Expected ${expected}, but got ${actual}`; p.className = 'failed'; return p; } ``` -------------------------------- ### Custom Serialization Logic with Decorators Source: https://context7.com/xiangechen/chili3d/llms.txt Implement custom serialization and deserialization logic for complex types by providing serialize and deserialize functions directly within the @serializable decorator. This allows for fine-grained control over how specific classes are handled during the serialization process. ```typescript // Custom serialization for complex types @serializable({ serialize: (target: MyClass) => ({ customField: target.computedValue }), deserialize: (data) => new MyClass(data.customField) }) export class MyClass { // ... } ``` -------------------------------- ### Result Message Helper Function Source: https://github.com/xiangechen/chili3d/blob/main/cpp/test/index.html A helper function to create and format a paragraph element displaying test results (passed, failed, time). It adds a 'failed' class if any tests failed. ```javascript function resultMessage(passed, failed, time) { const p = document.createElement('p'); p.className = 'result'; p.innerHTML = `Passed: ${passed}, Failed: ${failed}, Time: ${time}`; if (failed > 0) { p.className += ' failed'; } return p; } ``` -------------------------------- ### Define Serializable Class with @serializable Source: https://context7.com/xiangechen/chili3d/llms.txt Use the @serializable decorator to mark a class for serialization. Properties intended for serialization should be decorated with @serialize. Ensure all necessary types like XYZ are imported. ```typescript import { serializable, serialize, Serializer, IDocument } from "@chili3d/core"; // Mark a class as serializable @serializable() export class CustomData { @serialize() name: string; @serialize() value: number; @serialize() points: XYZ[]; constructor(options: { name: string; value: number; points?: XYZ[] }) { this.name = options.name; this.value = options.value; this.points = options.points ?? []; } } ``` -------------------------------- ### Remove Clarity Analytics Script Source: https://github.com/xiangechen/chili3d/blob/main/README.md To disable data collection, open public/index.html and delete lines containing this JavaScript code. ```javascript ```