OpenSCAD Playground

repository·main·Indexed 19 days ago

https://github.com/openscad/openscad-playground

A web-based port of OpenSCAD to WebAssembly providing an interactive, browser-based CAD environment. It features a Monaco editor, PrimeReact UI, and a Manifold-backed fast renderer. The project includes a virtualized filesystem (OverlayFS) for managing libraries, a pseudo-parser for symbol discovery, and a Web Worker-based runner to execute OpenSCAD commands without blocking the main thread.

Tokens
7K
Snippets
24
Records
29
Agent score
66%

What's inside openscad-playground

  1. Add new OpenSCAD libraries

    main

    The build system uses a webpack plugin that reads libs-config.json to manage library dependencies. To add a new library, you must update three files:

    1. libs-config.json: Add metadata for the library (repo URL, branch, and file inclusion/exclusion rules).
    2. src/fs/zip-archives.ts: Register the .zip archive so it appears in the UI file explorer and supports automatic imports.
    3. LICENSE.md: Add the library's license to ensure proper disclosure.
  2. Build and deploy OpenSCAD Playground

    main

    To create a full deployment build, use build:all. Note that you must edit the homepage field in package.json to match your deployment root before building.

    After building, copy the dist directory to your deployment target (e.g., a GitHub Pages directory).

    npm run build:all  # Build libraries and compile the application
    npm install
    
    rm -fR ../ochafik.github.io/openscad2 && cp -R dist ../ochafik.github.io/openscad2 
    # Now commit and push changes, wait for site update and enjoy!
  3. Run OpenSCAD Playground locally

    main

    To run a local development environment, ensure you have Node.js (>=22), npm, git, wget/curl, and zip installed. You must first build the libraries and WASM components before starting the server.

    Follow these steps:

    1. Download WASM and build OpenSCAD libraries.
    2. Install project dependencies.
    3. Start the development server.

    The application will be available at http://localhost:4000/.

    npm run build:libs  # Download WASM and build all OpenSCAD libraries
    npm install
    npm run start
    # http://localhost:4000/
  4. Run OpenSCAD Playground in production mode

    main

    To test the production build (which tests inlining and serving under a prefix), use the start:production command. The application will be available at http://localhost:3000/dist/.

    npm run build:libs  # Download WASM and build all OpenSCAD libraries
    npm install
    npm run start:production
    # http://localhost:3000/dist/
  5. Build a custom OpenSCAD WASM binary

    main

    If you want to use a custom OpenSCAD fork or branch instead of the prebuilt binary, you can link your local directory to the libs/openscad path within the project.

    1. Remove the existing library directory.
    2. Create a symbolic link to your local OpenSCAD source.
    3. Remove any existing native build directories to avoid conflicts.
    4. Run the WASM build command. You can pass WASM_BUILD=Debug to debug crashes.
    # Optional: use your own openscad fork / branch
    rm -fR libs/openscad
    ln -s $PWD/../absolute/path/to/your/openscad libs/openscad
    
    # If you had a native build directory, delete it.
    rm -fR libs/openscad/build
    
    # Build WASM binary
    npm run build:libs:wasm
    
    # Continue the build
    npm run build:libs
    npm run start
  6. Define a Source for the Playground

    main

    A Source object represents the input files or content for the OpenSCAD playground. It can represent a single file's content or a directory (indicated by a trailing slash in the path) that points to a ZIP file via the url property.

    • path: The file path or directory path (if ending in /).
    • url: (Optional) The URL to a ZIP file if the path is a directory.
    • content: (Optional) The raw string content of the file.
    // Example of a single file source
    const fileSource: Source = {
      path: 'main.scad',
      content: 'cube([10, 10, 10]);'
    };
    
    // Example of a directory source via a ZIP URL
    const dirSource: Source = {
      path: 'library/',
      url: 'https://example.com/library.zip'
    };
  7. Define geometry using IndexedPolyhedron

    main

    When working with raw geometry in the playground, you can represent 3D objects using the IndexedPolyhedron type. This structure uses an indexed approach to define shapes, which is more memory-efficient than raw triangles.

    • vertices: An array of Vertex objects defining points in 3D space.
    • faces: An array of Face objects. Each face contains a vertices tuple of three indices pointing into the vertex array, and a colorIndex pointing into the colors array.
    • colors: An array of Color values used by the faces.
    // Example of an IndexedPolyhedron structure
    const myShape: IndexedPolyhedron = {
      vertices: [
        { x: 0, y: 0, z: 0 },
        { x: 1, y: 0, z: 0 },
        { x: 1, y: 1, z: 0 },
        { x: 0, y: 1, z: 0 }
      ],
      faces: [
        { vertices: [0, 1, 2], colorIndex: 0 },
        { vertices: [0, 2, 3], colorIndex: 0 }
      ],
      colors: [
        [1, 1, 1, 1] // White
      ]
    };
  8. Configure library metadata in libs-config.json

    main

    When adding a library to libs-config.json, use the following schema to define how the library is fetched and packaged into a zip archive for the playground.

    {
      "name": "LibraryName",
      "repo": "https://github.com/user/repo.git", 
      "branch": "main",
      "zipIncludes": ["*.scad", "LICENSE", "examples"],
      "zipExcludes": ["**/tests/**"],
      "workingDir": "."
    }
  9. Initialize the OpenSCAD Playground application

    main

    The application entrypoint initializes the virtual filesystem, registers the OpenSCAD language, and sets up state persistence based on the environment (Standalone vs. Web).

    To run the application, the entrypoint performs the following sequence:

    1. Filesystem Setup: Calls createEditorFS to initialize the editor's filesystem. It uses a /libraries/ prefix and enables persistence if isInStandaloneMode() is true.
    2. Language Registration: Calls registerOpenSCADLanguage to associate the OpenSCAD language with the filesystem and handle ZIP archives.
    3. State Persistence:
      • In Standalone Mode: Reads/writes state to /state.json using BrowserFS.
      • In Web Mode: Reads/writes state via URL fragments using readStateFromFragment and writeStateInFragment.
    4. App Rendering: Renders the <App /> component with the initialized initialState, statePersister, and fs.
    // Conceptual initialization flow used in src/index.tsx
    
    const fs = await createEditorFS({prefix: '/libraries/', allowPersistence: isInStandaloneMode()});
    await registerOpenSCADLanguage(fs, '/', zipArchives);
    
    // State persistence setup
    if (isInStandaloneMode()) {
      statePersister = {
        set: async ({view, params}) => {
          fs.writeFile('/state.json', JSON.stringify({view, params}));
        }
      };
    } else {
      persistedState = await readStateFromFragment();
      statePersister = {
        set: writeStateInFragment,
      };
    }
    
    const initialState = createInitialState(persistedState);
    
    // Render the App
    root.render(
      <React.StrictMode>
        <App initialState={initialState} statePersister={statePersister} fs={fs} />
      </React.StrictMode>
    );
  10. Configure OpenSCAD Libraries build via webpack.libs.config.js

    main

    The webpack.libs.config.js file is used to orchestrate the building of OpenSCAD libraries using the OpenSCADLibrariesPlugin. It uses an environment variable to determine which libraries are built.

    To control the build scope, set the LIBS_BUILD_MODE environment variable before running the webpack task. If not provided, it defaults to 'all'.

    # Example: Build only specific libraries (assuming buildMode logic supports it)
    LIBS_BUILD_MODE=some_mode npm run build
  11. Reference: Library build commands

    main

    The following npm commands are available for managing library builds and assets.

    npm run build:libs        # Build all libraries
    npm run build:libs:clean  # Clean all build artifacts
    npm run build:libs:wasm   # Download/build just the WASM binary
    npm run build:libs:fonts   # Download/build just the fonts
  12. Embed the OpenSCAD Playground using the App component

    main

    The App component is the primary entrypoint for embedding the OpenSCAD Playground into your own application. To use it, you must provide an initial state, a state persister for saving/loading state, and a filesystem (FS) implementation.

    When initialized, the component sets up a Model instance which manages the OpenSCAD lifecycle, rendering, and file operations. It also sets up global keyboard shortcuts:

    • F5: Render preview (model.render({isPreview: true, now: true}))
    • F6: Render full render (model.render({isPreview: false, now: true}))
    • F7: Export (model.export())

    The component provides ModelContext and FSContext to its children, allowing sub-components to access the shared model and filesystem.

    import { App } from './components/App';
    
    // Example usage (requires implementation of State, StatePersister, and FS)
    <App 
      initialState={myInitialState} 
      statePersister={myPersister} 
      fs={myFilesystem} 
    />