Basics · PartScript Help ×

Basics

Files

A .parts file holds any number of props, parts (def), variables (set), and, for buildings, kits and buildings. A project is every .parts file in the folders you build, plus any file they import, plus the standard parts: a prop or part defined in one file can be used from any other. Each name is defined once; a second def of the same name is a mistake.

try it
# Comments start with a hash and a space.
set oak=#7a5a32/wood

def plank len=1
  box at=len/2,0,0 size=len,.12,.02 mat=oak

prop bench_demo "Bench" garden
  plank at=-.8,-.12,.45 len=1.6 repeat 3 every 0,.13,0
  box at=-.7,0,on size=.06,.4,.44 mat=oak mirror x

A block (prop, def, kit, building) runs until the next unindented line. Its lines are indented, by any amount. end closes a block early, and is never needed.

Lines

One statement per line. The first word says what it is (a shape like box, or use, group, set, ...). Then come its arguments by name (at=0,0,1), its options (turn=0,0,45), and copy phrases (repeat 5 every .3,0,0). Their order does not matter, except that copy phrases are written as phrases.

Props

prop NAME ["Title"] [subcategory] [option=value ...]

NAME is lower_snake_case and is the model's asset id (the .glb is NAME.glb). The title and the subcategory are for people and catalogues. Header options:

optionwhat it does
hero=1a larger triangle budget (6,000 instead of 2,500)
budget=Nthis prop's triangle budget
seed=Ndeals every rand(), pick(), odds() and scatter again: a new take on the same prop (Project.build(name, seed=N) and partscript build --seed N do it without editing the file)
px=autotexel density sized to the prop (about 80 texels across its longest side)
ao=autogrounded shading faded over the prop's own height
for v=a,b,cvariants: the prop is made once per value, with {v} replaced by it everywhere
desc="...", dd=, mount=, col=, replace=1metadata a host may read

Variants make a family of props from one block:

try it
prop traffic_cone_demo_{c} "Traffic Cone" street for c=e25a1a,d8c020,3a8ae2
  cylinder radius=.16 height=.64 mat=#{c}/plastic top_radius=.03 sides=12
  bevel_box size=.42,.42,.05 bevel=.015 mat=rubber

That is three props: traffic_cone_demo_e25a1a and two more.

Variables

set names a value. Unindented, it holds for its own file (and the parts defined there, wherever they are used); indented, for the rest of its block.

try it
set paint=#2a4a6a/paint
prop locker_demo "Locker"
  set w=.4 h=1.8
  box size=w,.5,h mat=paint
  box at=0,-.255,h*.8 size=w*.8,.01,.12 mat=steel_dark repeat 4 every 0,0,-.05

A variable can hold a number, a material, a word, a line of points, or an expression that is worked out where it is used.

Expressions

Anywhere a number goes, an expression can: w/2, -h+.1, sin(30)*r, max(a,b), atan(rise/run). Angles are degrees. The expressions reference lists every function, and the special names (i, here, rand(), noise()).

Two forms

Every shape line can name its arguments, the readable form these docs use, or give them in order, a shorthand that is quicker to type once you know it:

box at=0,0,on size=.4,.3,.2 mat=wood turn=0,0,45 repeat 5 every .3,0,0 mirror x
b 0,0,~ .4,.3,.2 wood r=0,0,45 *5@.3,0,0 mx
readableshorthand
box, bevel_box, box_between, cylinder, sphere, panel, extrude, group, decal, arch_wallb, bb, bx, c, sph, pan, ext, at, trim, archwall
turn= sides= scale= top_radius= axis= jitter=r= s= s= rt= ax= jit=
on, on(z) in a position~, ~z
repeat N every V · grid AxB every V · ring N [step D]*N@V · *AxB@V · *N%D
scatter N over W,D [apart G] · within R · on NAME*N~W,D,G · *N~R · *N^NAME
mirror xymx my

Both parse to the same thing. partscript fmt rewrites a file into either form.