Developer Documentation

Customizer allows you to design parametric objects that can be customized with an easy web interface. We currently support OpenSCAD designs. Just upload your OpenSCAD script to Thingiverse and then anyone can open it in Customizer and customize it. Also, if you tag your Thing with the "customizer" tag, then your Thing page will automatically display an Open In Customizer button as a shortcut.

To make your customized Thing easy to use, here are some Best Practices.

Parameters

Most OpenSCAD scripts will just work (see: limitations). However, to provide the best experience, you'll want to format your parameters using special comments. These comments will allow you to define certain paramaters to be for instance, multiple choice drop down boxes or min-max sliders.

Parameters should be placed at the top of your script before the first module declaration and should be in the following form:

// variable description
variable name = default value; // possible values

The variable description line is optional, but is useful to give the user an idea of what the parameter defines.

Variable name will automatically be formatted to be more readable. For instance small_box_height would be labeled "Small Box Height" on the form.

The possible values comment at the end is also optional. If not defined, the user will see a simple text box where they can enter any value. By formatting the possible values, you can define the following form inputs as a comma delimeted list inside [ ]:

  • Drop down box
    Numbers: [0, 1, 2, 3]
    Strings: [foo, bar, baz]
    Labeled values: [10:Small, 20:Medium, 30:Large]
  • Slider
    Numbers only allowed, specify any of the following:
    max (min is set to 0 automatically): [100]
    min/max: [10:100]
    min/step/max: [0:0.5:100]
  • Image To Surface
    [image_surface:100x100]
    Upload an image which will be turned into a heightmap .dat file to be used with OpenSCAD surface() function. More Info.
  • Image To Array
    [image_array:100x100]
    Upload an image which will be turned into a heightmap array. More Info.
  • Polygon Drawing Canvas
    [draw_polygon:100x100]
    This will return an array with two elements, the first will be an array of points (each a 2 element array) and the second will be an array of paths that reference the indices of the points in the previous array
    You can then referece the [0] and [1] elements when constructing a polygon primitive in OpenSCAD.
    You can specify the x and y dimensions of the polygon with the size argument, otherwise the polygon will be 1 mm in the x direction and 1 mm in the y direction. This is to allow for easy scaling to a specific dimension.
    Additionally, you can set a default shape to appear by setting the variable equal to an [[points],[paths]] array. (hint: you can get this output from the customizer app by viewing your javascript console while using the Polygon Canvas)
    • For example:
      my_polygon_variable = [[[-1,1],[1,1],[1,-1],[-1,-1]],[[0,1,2,3]] ]; //[draw_polygon:100x100]
      polygon(points = my_polygon_variable[0], paths = my_polygon_variable[1]);

Variable default values must be either a number or a string enclosed in quotes. Variables that equal other variables or include operations such as + - / * will be ignored and cannot be customized. So for instance, the following variables will not result in a form input on the web page:

  • hole_radius = hole_diameter / 2;
  • height = 4 * 25.4;
  • function foo(x) = pow((1-x), 3);

A common operation may be to define hole_radius = 10 / 2 so it would be better to change it to hole_diameter = 10 and hole_radius = hole_diameter / 2. That way only the hole_diameter parameter would be shown on the form and the hole_radius would not, but still get calculated.

Parameter Tabs

Parameters can be grouped into tabs. This allows you to separate similar parameters that share a common theme or relate to a specific section of a multi-part design. Additionally, Customizer will pass the name of the tab the user is currently on to a special string param called "preview_tab" (note: this value will not be changed when saving the final stl, so set a sane default and feel free to change what is rendered in previews based on tab selected). To create a tab, use a one line block comment like this:

/* [Tab Name] */

The following tab names are reserved for special functionality:

  • [Global]
    Parameters in the global tab will always be shown on every tab no matter which tab is selected. Note: there will be no tab for global params, they will just always be shown.
  • [Hidden]
    Parameters in the hidden tab will never be displayed. Not even the tab will be shown. This provides a more natural way to have parameters in your code that you don't want the user to see.

Here is an example that shows the part param on every tab, makes two tabs, and hides the secret param. It also highlights the shape based on the tab the user is on using the automatically set "preview_tab" string param:

/* [Global] */

// Which one would you like to see?
part = "both"; // [first:Cube Only,second:Cylinder Only,both:Cube and Cylinder]

/* [Cube] */

cube_size = 10; // [1:100]
cube_text = "Foo";

/* [Cylinder] */

cylinder_size = 10; // [1:100]
cylinder_text = "Bar";

/* [Hidden] */

secret = 42;
preview_tab = "";

print_part();

module print_part() {
	if (part == "first") {
		mycube();
	} else if (part == "second") {
		mycylinder();
	} else if (part == "both") {
		both();
	} else {
		both();
	}
}

module both() {
	translate([-cube_size, 0, 0]) mycube();
	translate([cube_size, 0, 0]) mycylinder();
}

module mycube() {
	highlight("Cube") translate([0, 0, cube_size/2]) cube(cube_size, center=true);
}

module mycylinder() {
	highlight("Cylinder") cylinder(r=cube_size/2, h=cylinder_size);
}

module highlight(this_tab) {
  if (preview_tab == this_tab) {
    color("red") child(0);
  } else {
    child(0);
  }
}

Default Preview Rotation

Some designs look best when viewed from a certain angle. For instance, perhaps your script adds text to the bottom of your object and you want people to see the bottom when the page loads. You can control the default view by adding a comment formatted like this:

// preview[view:south, tilt:top]

The view parameter defaults to "south east" and can take the following values:

  • north
  • north east
  • east
  • south east
  • south
  • south west
  • west
  • north west

The tilt parameter defaults to "top diagonal" and can take the following values:

  • top
  • top diagonal
  • side
  • bottom diagonal
  • bottom

Multiple STL Output

If you would like to make your script create multiple STL files for things like build plates or dualstrusion, create a parameter called "part" and make it Drop Down Box. Customizer will then loop through all the possible part values when it compiles your final script and create an STL for each value. Users can then also use the part drop down to preview what each part will look like.

Here is a simple script example. When this script is run through customizer, it will create three STL files. One for the first part, one for the second part, and one for both parts:

// Which one would you like to see?
part = "first"; // [first:Cube Only,second:Cylinder Only,both:Cube and Cylinder]

cube_size = 10; // [1:100]
cylinder_size = 10; // [1:100]

print_part();

module print_part() {
	if (part == "first") {
		mycube();
	} else if (part == "second") {
		mycylinder();
	} else if (part == "both") {
		both();
	} else {
		both();
	}
}

module both() {
	translate([-cube_size, 0, 0]) mycube();
	translate([cube_size, 0, 0]) mycylinder();
}

module mycube() {
	translate([0, 0, cube_size/2]) cube(cube_size, center=true);
}

module mycylinder() {
	cylinder(r=cube_size/2, h=cylinder_size);
}

Image To Surface

Try: online tool

Customizer provides a special parameter type that allows users to upload an image and Customizer will turn that image into a grayscale OpenSCAD Surface .dat file. This can be used to for instance create a lithopane, to emboss a pattern or logo on the side of an object in your design, or to visualize a 3D terrain from map data. Here is how you can request a 100 x 100 pixel image from the user:

filename_variable = "foo.dat"; // [image_surface:100x100]
surface(file=filename_variable);

This will create a .dat file that is 100 x 100 mm in size. Images larger or smaller than the requested size will automatically be stretched to fit. The minimum size is 1x1 and the maximum size is 150x150. If you request a size larger than the maximum, it will fall back to 150. The larger the size, the longer it will take to process, so it's best to keep the size as small as possible. The Z axis will be between 0 and 1 based on a 256 color grayscale range. Black pixels are 0, White pixels are 1, and gray would be 0.5. Therefore, you can request a size and then scale the z axis as needed. Here is a complete example which makes a surface where pure white is 10mm tall and pure black is 0mm:

height = 10; // [1:100]

// Load a 100x100 pixel image. (images will be automatically stretched to fit) Simple, high contrast images like logos work best.
image_file = "image-surface.dat"; // [image_surface:100x100]

scale([1,1,height]) surface(file=image_file, center=true, convexity=5);

Note: you cannot specify a default .dat file. See also: Image To Array.

Image To Array

Try: online tool

This works just like the Image To Surface parameter, except this outputs an array instead of creating a surface() .dat file. Although easy to use, one of the limitations of the OpenSCAD surface() function is that it only creates a flat heightmap. By using Image To Array, you will get an array of values between 0 and 1 for each pixel in an image. This way you can programatically generate more complex shapes based on image data. (you just have to build the polyhedrons yourself!) The array will be a flat array, all rows condensed into a single list. So you'll need to handle looping through each row of the image based on the dimensions you request. Here's the syntax (default value is a circle shape):

image_array = [0.5,0.5,0.5, 0.5,0,0.5, 0.5,0.5,0.5]; // [image_array:3x3]

The array you get can be passed onto for instance the bitmap library included in MCAD. But beware, that bitmap library can be very slow with large arrays!

Example

You can use the following form to preview what your script will look like after Customizer parses your parameters.

Preview

Preview

Spinner

Current Limitations

  • Scripts must have all the code they need in a single .scad file
  • Only put one .scad file in your Thingiverse entry
  • Cannot import external files (like .stl or .dxf files) - You can include openscad polygons and polyhedrons inline inside your script to get around this for now.

Eventually we hope to remove these limitations. Although you cannot include external libraries, the following are automatically available to be included in your script:

  • Build Plate use <utils/build_plate.scad>
  • MCAD use <MCAD/filename.scad>
  • Pin Connectors use <pins/pins.scad>
  • Write.scad use <write/Write.scad>
    Includes the following fonts:
    • write/Letters.dxf
    • write/BlackRose.dxf
    • write/orbitron.dxf
    • write/knewave.dxf
    • write/braille.dxf
  • The text() function supports all the fonts from Google as well as some basic fonts such as Helvetica
  • 3DVector use <utils/3dvector.scad>
  • hsvToRGB use <utils/hsvtorgb.scad>

If you'd like to have access to any other common libraries, let us know!