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 },
}
| Option | Description |
|---|---|
default | Initial value (required) |
min | Minimum allowed value |
max | Maximum allowed value |
step | Increment 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 },
}
| Option | Description |
|---|---|
default | Initial text value (required) |
maxLength | Maximum character length |
placeholder | Hint 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:
| Property | Description |
|---|---|
value | The value returned when selected (required) |
caption | Label text for the button |
image | URL 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:
| Property | Description |
|---|---|
enabled | Whether the embedded feature is active |
showSettings | Whether the settings are expanded |
params | The 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
minandmaxto prevent values that would break your geometry - Group related parameters together in your code for clarity
- Use
sliderfor values users will frequently adjust - Use
choiceorradioinstead of free text when there are specific valid options - Add
labelwith units (mm, degrees, etc.) when applicable