Skip to content

Scripting API

Materials

from ArtisanPlugin.Scripting import RealtimeRenderApi as rtr

The viewer carries its own material catalogue - metals, gems, pearls, enamels, ceramics - and applies them to parts, where a part is one mesh of the exported model. Because the exporter joins each Rhino layer into one part named after the layer, the natural way to restyle a piece is by layer name, and SetMaterialByLayer is the call to reach for first.

Viewer-only, all of it: the Rhino document is never modified and no material table entry changes. Assignments made here are persisted the same way a click in the viewer is, so they survive UpdateRender’s model reload and reopening the window. To change the document use Design/Render materials or the Studio scene.

The catalogue names

materialName is a viewer catalogue id, upper-cased for you. The families:

  • Metals: YELLOW_GOLD, WHITE_GOLD, ROSE_GOLD (each with _LIGHT/_DARK variants), GREEN_GOLD, GOLD_2NGOLD_6N, SILVER, PLATINUM, TITANIUM - and every one takes a finish suffix: _BRUSHED, _FLORENTINE, _HAMMERED, _ROUGH, _SANDBLAST.
  • Gems: DIAMOND (plus _BLACK, _CHAMPAGNE, _COGNAC_01, fancy colors…), RUBY, SAPPHIRE (many colors), EMERALD, MORGANITE, AQUAMARINE, TOPAZ_*, TOURMALINE_*, TANZANITE, AMETHYST, CITRINE, PERIDOT, garnets, ALEXANDRITE and more.
  • Others: PEARL (12 variants), ENAMEL_*_TRANSLUCENT / ENAMEL_*_OPAQUE, CERAMIC_*, LEATHER_*.

An unknown name is not an error - the page falls back silently, so a misspelled material just looks grey. Spell from this list.

Restyle a whole layer

count = rtr.SetMaterialByLayer("Metal 01", "ROSE_GOLD")     # -> parts changed
ParameterDefaultMeaning
layerNamerequiredThe Rhino layer, matched against the viewer’s parts
materialNamerequiredA catalogue name from the list above

The layer matches case-insensitively and treats spaces and underscores as equal, so "METAL_01", "metal 01" and "Metal 01" all hit the same layer. Returns how many parts changed.

This is the one material call that waits and validates: when nothing matches it throws “No viewer part matches layer ‘<name>’. Available: …” listing every layer the viewer actually has - so a script (or an AI agent) can read the error and correct itself. It gives the page 5 seconds and then throws “The viewer did not respond in time.”

List the viewer’s parts

import json

raw = rtr.GetViewerItems()                 # -> str, never None
items = json.loads(json.loads(raw))        # -> [{"uuid": ..., "layer": ..., "material": ..., ...}]

Returns the viewer’s parts as JSON: an array of objects carrying at least a uuid, a layer and a material. You only need it when addressing single parts - SetMaterialByLayer looks the layer up for you.

Two things about the string. It is JSON produced by JSON.stringify inside the page and then JSON-encoded again on the way out of WebView2, so in Python it takes two json.loads passes to reach the array. And it never returns None: when the page has not finished loading you get the literal string "[]". Waits up to 5 seconds, then throws “The viewer did not respond in time.”

Set a single part’s material

rtr.SetViewerMaterial(part_uuid, "YELLOW_GOLD")     # -> None
ParameterDefaultMeaning
partUuidrequiredA uuid from GetViewerItems()
materialNamerequiredA catalogue name

The by-uuid variant, for when two parts share a layer look you want to break up. Fire and forget: an unknown uuid or material name simply does nothing, with no error. An empty partUuid throws “Part uuid is required (see GetViewerItems()).”

Fine-tune a material live

rtr.EditViewerMaterial("YELLOW_GOLD", color="#f5c518", roughness=0.35)   # -> None
rtr.EditViewerMaterial("DIAMOND", ior=2.42, opacity=0.95)
ParameterDefaultMeaning
materialNamerequiredThe catalogue material to edit
colorNoneCSS color ("#b76e79", "white")
roughness-1 (untouched)01, metals
ior-1 (untouched)index of refraction, gems, ~1.42.4
opacity-1 (untouched)01

Edits the material everywhere it is currently applied - it mutates the shared catalogue entry, not one part. Pass only what you want changed; passing nothing throws “Pass at least one property to edit (color, roughness, ior, opacity).”

The edit is ephemeral: re-applying the material from the catalogue (including via SetMaterialByLayer) resets it to stock. Order matters - assign materials first, fine-tune second.