Code Mode parameters

Learn how to define parameters in Code Mode scripts to create customizable, parametric 3D designs.

Code Mode parameters

Parameters allow users to customize your 3D models without editing code. When you define parameters, CADit automatically generates a panel with sliders, text fields, dropdowns, and other controls.

Defining parameters

Use the defineParams function from @cadit-app/script-params to define parameters and your main function together:

import { defineParams } from '@cadit-app/script-params';
import { Manifold } from '@cadit-app/manifold-3d/manifoldCAD';

export default defineParams({
  params: {
    width: { type: 'number', default: 20, min: 5, max: 100 },
    height: { type: 'number', default: 10, min: 1, max: 50 },
    hollow: { type: 'boolean', default: false },
  },
  main: (params) => {
    const box = Manifold.cube([params.width, params.height, params.width], true);

    if (params.hollow) {
      const inner = Manifold.cube([params.width - 2, params.height - 2, params.width - 2], true);
      return box.subtract(inner);
    }

    return box;
  },
});

The params object defines each parameter with a name, type, default value, and optional constraints. The main function receives the current parameter values and returns the 3D geometry.

Parameter types

Number parameters

Use number, float, or int for numeric values. All render as text fields with validation.

params: {
  size: { type: 'number', default: 10 },
  radius: { type: 'float', default: 5.5, min: 0.1, max: 50 },
  segments: { type: 'int', default: 32, min: 3, max: 128 },
}
OptionDescription
defaultInitial value (required)
minMinimum allowed value
maxMaximum allowed value
stepIncrement for stepping (optional)

Slider

Displays a draggable slider for numeric values. Requires min and max.

params: {
  thickness: {
    type: 'slider',
    default: 2,
    min: 0.5,
    max: 10,
    step: 0.5,
  },
}

Text

Accepts string input.

params: {
  label: { type: 'text', default: 'Hello' },
  name: { type: 'text', default: '', maxLength: 50 },
}
OptionDescription
defaultInitial text value (required)
maxLengthMaximum character length
placeholderHint text shown when empty

Boolean, switch, and checkbox

Toggle controls for true/false values. All three types work the same way but may render slightly differently.

params: {
  showLabel: { type: 'boolean', default: true },
  hollow: { type: 'switch', default: false },
  rounded: { type: 'checkbox', default: true },
}

Choice (dropdown)

Presents a dropdown menu with predefined options.

params: {
  style: {
    type: 'choice',
    default: 'rounded',
    options: ['rounded', 'chamfered', 'sharp'],
  },
  quality: {
    type: 'choice',
    default: 'M',
    options: [
      { value: 'L', label: 'Low (fast)' },
      { value: 'M', label: 'Medium' },
      { value: 'H', label: 'High (slow)' },
    ],
  },
}

Options can be simple strings or objects with value and label properties.

Radio

Similar to choice but renders as radio buttons instead of a dropdown. Useful when you have few options and want them all visible.

params: {
  alignment: {
    type: 'radio',
    default: 'center',
    options: ['left', 'center', 'right'],
  },
}

Button grid

Displays a grid of buttons, optionally with images. Useful for pattern or style selection.

params: {
  pattern: {
    type: 'buttonGrid',
    default: 'grid',
    options: [
      { value: 'grid', caption: 'Grid' },
      { value: 'honeycomb', caption: 'Honeycomb' },
      { value: 'voronoi', caption: 'Voronoi' },
    ],
  },
}

Each option can include:

PropertyDescription
valueThe value returned when selected (required)
captionLabel text for the button
imageURL to an image (displays instead of caption)

Font

Opens a font selector. The value is a URL to the selected font file.

params: {
  textFont: {
    type: 'font',
    default: 'https://example.com/fonts/arial.ttf',
  },
}

Image

Allows uploading an image file. Useful for scripts that trace or project images onto geometry.

params: {
  sourceImage: {
    type: 'image',
    default: null,
    label: 'Upload image',
  },
}

The value is an object with fileName, fileType, and dataUrl (base64-encoded content), or null if no image is selected.

Shape2d

Allows selecting a 2D shape from the canvas. The selected shape's path data becomes available to your script.

params: {
  outline: {
    type: 'shape2d',
    label: 'Select a 2D shape',
  },
}

To use the selected shape:

main: (params) => {
  if (!params.outline?.shapeData) {
    return Manifold.cube([10, 10, 10]); // fallback
  }

  const paths = params.outline.shapeData.doodlePaths;
  // Convert paths to geometry...
}

The shapeData object contains doodlePaths, an array of path contours with points and optional holes.

Shape3d

Allows selecting an existing 3D object. The selected object's mesh data becomes available to your script.

params: {
  baseMesh: {
    type: 'shape3d',
    label: 'Select a 3D object',
  },
}

To use the selected mesh:

import { hasShape3dMesh, toManifold } from '@cadit-app/script-params';
import { Manifold, Mesh } from '@cadit-app/manifold-3d/manifoldCAD';

main: (params) => {
  const base = toManifold(params.baseMesh, Mesh, Manifold);

  if (!base) {
    return Manifold.sphere(10); // fallback
  }

  return base.scale([1.2, 1.2, 1.2]);
}

Preset

Allows selecting from predefined parameter configurations. When a preset is selected, it overrides multiple parameter values at once.

params: {
  preset: {
    type: 'preset',
    default: 'small',
    presets: [
      { value: 'small', label: 'Small', presetValues: { width: 10, height: 10, depth: 10 } },
      { value: 'medium', label: 'Medium', presetValues: { width: 25, height: 25, depth: 25 } },
      { value: 'large', label: 'Large', presetValues: { width: 50, height: 50, depth: 50 } },
    ],
  },
  width: { type: 'number', default: 10 },
  height: { type: 'number', default: 10 },
  depth: { type: 'number', default: 10 },
}

Embedded parameters

Embed another script's parameters as a collapsible section. Useful for combining multiple scripts or adding optional features.

import { embedParams } from '@cadit-app/script-params';
import qrCodeScript from '@cadit-app/qr-code';

params: {
  size: { type: 'number', default: 50 },
  qrCode: embedParams(qrCodeScript, {
    label: 'QR Code (optional)',
    enabled: false,
    showSettings: false,
  }),
}

The embedded value contains:

PropertyDescription
enabledWhether the embedded feature is active
showSettingsWhether the settings are expanded
paramsThe nested parameter values

Parameter labels and descriptions

Add label and description to any parameter for better UI:

params: {
  wallThickness: {
    type: 'number',
    default: 2,
    min: 0.5,
    label: 'Wall thickness (mm)',
    description: 'Thickness of the outer wall. Values below 1mm may not print well.',
  },
}

The label appears next to the input control. The description appears as a tooltip or help text.

Using parameters in code

Parameters are passed to your main function as a typed object:

main: (params) => {
  // params.width is a number
  // params.label is a string
  // params.hollow is a boolean

  const geometry = createGeometry(params.width, params.height);
  return geometry;
}

TypeScript infers the correct types from your parameter definitions. If you define width as type: 'number', then params.width is typed as number.

Example: parametric box with optional hole

import { defineParams } from '@cadit-app/script-params';
import { Manifold } from '@cadit-app/manifold-3d/manifoldCAD';

export default defineParams({
  params: {
    width: { type: 'slider', default: 30, min: 10, max: 100, label: 'Width (mm)' },
    height: { type: 'slider', default: 20, min: 5, max: 50, label: 'Height (mm)' },
    depth: { type: 'slider', default: 30, min: 10, max: 100, label: 'Depth (mm)' },
    wallThickness: { type: 'number', default: 2, min: 0.5, max: 10, label: 'Wall thickness' },
    addHole: { type: 'switch', default: false, label: 'Add mounting hole' },
    holeDiameter: { type: 'number', default: 5, min: 2, max: 20, label: 'Hole diameter' },
  },
  main: (params) => {
    // Create outer box
    const outer = Manifold.cube([params.width, params.height, params.depth], true);

    // Create inner cavity
    const inner = Manifold.cube([
      params.width - params.wallThickness * 2,
      params.height - params.wallThickness,
      params.depth - params.wallThickness * 2,
    ], true).translate([0, params.wallThickness / 2, 0]);

    let result = outer.subtract(inner);

    // Add mounting hole if enabled
    if (params.addHole) {
      const hole = Manifold.cylinder(
        params.wallThickness + 1,
        params.holeDiameter / 2
      ).translate([0, -params.height / 2, 0]);

      result = result.subtract(hole);
    }

    return result;
  },
});

Tips

  • Set sensible default values so the model looks correct when first loaded
  • Use min and max to prevent values that would break your geometry
  • Group related parameters together in your code for clarity
  • Use slider for values users will frequently adjust
  • Use choice or radio instead of free text when there are specific valid options
  • Add label with units (mm, degrees, etc.) when applicable