Beyond the Basics
A compact reference for the capabilities that go past the core groups and constraints. Everything here is used somewhere in the repo’s worked examples, which are the best place to see each one in a real program.
WorkstationGroup — a complete desk unit
A reusable “seat + screen + desk clutter” motif: desk (anchor), operator chair, computer, and a few accessories seated on the real desktop surface. Drop the finished unit into a room like any group:
with scene.WorkstationGroup() as ws:
ws.set_anchor(scene.AddAsset("a simple flat wooden office desk"))
ws.place_chair(scene.AddAsset("an ergonomic office chair"))
ws.place_computer(scene.AddAsset("an all-in-one desktop computer"))
ws.place_accessories([scene.AddAsset("an articulated desk lamp"),
scene.AddAsset("a small potted succulent for a desk")])
with scene.RoomGroup() as room:
room.place_on_back_left_corner(ws, facing="front")
The desktop items are seated with place_on_top’s surface finder (not the bounding-box top), so hutch desks and prop-inflated meshes don’t float the computer.
Placing objects inside an anchor
place_inside(objs) puts objects into the anchor’s interior — dishes in a cabinet, books in an open shelf. It uses a VLM placement pass to find the interior surfaces. Use it with a few objects; retrieved storage furniture often already ships with contents in the mesh, and stocking a tall fixture with many items grinds them into invisible specks.
Raised and wall-mounted placement: bottom=
Every against-the-wall placement accepts a bottom= height in metres — the lift that makes tiered seating, stage platforms, and high-mounted equipment possible:
room.place_on_back_wall_center(riser)
room.place_on_back_wall_center(seat_row, bottom=0.42) # lifted onto the riser
bottom= positions the object’s AABB bottom, regardless of where the mesh origin sits. A lifted object needs two flags: obj.ignore_overlap = True (so the 2D floor solver doesn’t shove it off the thing it rests on) and obj.is_static = True (so optimization doesn’t drift it). See the media_room worked example for a complete tiered-seating build.
Mirrors
room.place_mirror_full_wall("right_wall")
Covers an entire wall with a single reflective surface (a real Cycles reflection — not a retrieved mirror prop). It occupies all three slots of that wall, so mount nothing else on it. Used by the gym and dance-studio examples.
Pinning and swapping assets
Retrieval is seeded and reproducible, but when you want a specific mesh:
sofa = scene.AddAsset("a modern gray sofa", asset_id="hssd/5f27a543") # durable pin
asset_id bypasses the visual selection entirely — the recompile-safe way to lock an audited asset. After a build you can also inspect obj.retrieval_candidates and swap with scene.reselect_asset(obj, choice).
Object lighting
obj.add_lighting(desc, density) places retrieved ceiling fixtures over an object or group. Two behaviors worth knowing:
- Density is relative to the fixture’s own footprint, not the room. If a retrieved fixture is large, every density value rounds to one light — shrink the fixture (
add_lighting(..., modulate_scale=0.5)) and the density dial starts working again. - Total wattage is fixed by
scene.light_budgetand split across the fixtures — density changes the ceiling’s composition, never the room’s brightness. Brightness isscene.light_budget(and theIDSDL_SKYenvironment variable for daylight).
Faster builds
scene.prefetch_assets(["a modern gray sofa", "a wooden coffee table", ...])
resolves all retrievals concurrently up front; the subsequent AddAsset calls hit the warm cache. Useful for scenes with many distinct assets.
Phase-gated programs
All the worked examples split their build into three phases — 1: floor layout, 2: surface dressing (tabletops, rugs), 3: walls, windows, art, and lighting — so python workbench.py run program.py --phase 1 can verify the layout in about a minute before committing to a full build. The MCP guided flow enforces this structure at its build gates.
Next: if something here doesn’t behave as expected, the compile pipeline that runs underneath is explained in Hierarchical Layout and Constraints — most surprises are one of the two.