datacentre.rhai (palette groups Data centre, Cooling, Fire safety, Power):
- dc_building: multi-storey shell (storeys of storey_h), walls in pieces,
slabs, roof with parapet, louvres, front door and loading dock; levels
cut it open storey by storey
- raised_floor; rack_row and dc_pod (cabinets by U, width, depth,
equipment, fill, doors, LEDs; in-row coolers; cold / hot aisle
containment with vent tiles, roof, end doors, ceiling duct, airflow);
dc_cage for colocation
- crah, chiller (air-cooled, dry, adiabatic), cooling_tower, pipe_run
- smoke_detectors (grid + coverage), fire_pipe (VESDA, sprinkler, gas),
gas_bank (Novec 1230, FM-200, Inergen sized for its halls), fire_device
(panels, call points, abort switches, beacons, extinguishers)
- power_cab (UPS, battery, PDU, switchgear, RPP), busway, cable_tray,
transformer
- tooltips sum IT load, kW/m2, cooling redundancy per storey, UPS load,
battery runtime, plant cooling and agent quantity (warning when short)
Engine and stdlib:
- part_hidden(o) in house.rhai: parts on closed storeys inside a
dc_building are not drawn (they only made sort cycles under the slab
above); house parts, furniture and people use it. Existing examples
render byte-identical.
- overhead services sort in their own "ceiling" layer with tight boxes
- sort records which sprites each broken cycle involved; isokit check
names them (Rendered.cycle_at)
examples/datacentre (three storeys and a roof plant), Data centre demo in
the web Studio, tests, SCRIPTING/README/ROADMAP, MCP instructions.
Studio: one selected object with pts (a route, an outlined area) shows a
handle on each point and a + in the middle of each side: drag a point to
move it, drag a + to add one there, double-click a point to remove it
(open routes keep 2, outlines 3). Points snap to the grid and onto wall,
fence and road ends, at any angle; one undo step each. Handles keep their
screen size (new viewer callback onView on every redraw) and follow
re-renders and selection. The viewer captures the pointer, so a double-
click targets the drawing: the last point pressed is remembered instead.
Prefab meta `outline`: the prefab draws pts as its outline. Area has it:
Edit corners turns its rectangle into four points, Rectangle again
removes them.
Routes: where a path doubles back, the lane offset puts a point on each
side, so it rounds into a U-turn instead of a diagonal across the lanes.
The streets demo bus now runs east, three quarters round the roundabout
(clockwise, left-hand traffic), down south street, turns and comes back
by the short way, instead of going round the wrong way on its way out.
Tests: Rust 81 (a doubling-back route: each mover once, no sort cycles),
Studio 134 (corners, move, add, remove, undo), web 100.
Groups: objects of type "group" draw nothing; members carry the group's id
in a new `group` field (groups nest). A hidden group hides everything in it
(Doc::hidden_in_groups, skipped by the driver), a locked one locks it in
the Studio. Removing a group moves its members up into its parent group.
isokit check warns about members of missing groups. New `order` op: the
whole object order at once (each id once), one undo step.
Studio object list as a tree in the document order, front first: each
group sits just after its members, so it draws as one block, and ground
pieces higher in the list lie on top. Groups fold open and shut; every row
has an eye and a lock (shown on hover or when set); a click on a group
selects all of it, so a drag on the map moves it all. Group / Ungroup
(Ctrl+G, Ctrl+Shift+G), Order up/down (Ctrl+] Ctrl+[, with Shift to the
front / back), drag rows above, below or into a group. Group panel: name,
zoom, ungroup, to front / back, lock, hide, delete with contents.
MCP: group field in the object schema, order op, guidance.
Tests: Rust 81 (ops: groups, order, removal; driver: nested hidden
groups), Studio 131, web 100.
New route prefab (routes.rhai): cars, buses, motorbikes, cyclists, people,
deer or elephants move along waypoints, round a loop or there and back.
Each way keeps to the left of the line (or right), corners are rounded
into pieces of at most 45 degrees; there-and-back routes become loops with
U-turns, so the two directions never share a strip.
Engine: Prim::Travel / sprite.begin_travel / script travel(a, b, dur,
windows) ... end(): the mover is drawn at a piece's start and slides to
its end while it is on that piece, hidden otherwise. The renderer writes
keyframes per piece (named by a hash of their content) into one <style>
per view. Each piece is its own sprite with the lane strip as its sort
extent (ext_reset), mitred at the corners, so movers pass in front of and
behind trees, lamps and houses. Movers that look alike and never meet on
a piece share one drawing. iso-travel pauses (not hides) in still,
reduced-motion and ghosted views.
Studio: meta shape "path" draws point by point (snapping like runs) and
saves one object with pts; ending on the first point closes the loop.
MCP: pts in the object schema, route guidance.
Demos: streets gets traffic round the block, a bus, motorbikes, cyclists
and strolling people (replacing the one-axis cars); country gets cars on
the lane.
Tests: Rust 79 (each mover on exactly one piece at every moment, in every
rotation), Studio 125, web 99.
New stdlib module wildlife.rhai:
- Animals (new palette category): Deer (stag with antlers, does, fawns),
Wild boar, Fox, Elephant (bull with tusks, cow, calf), Rabbits. Low-poly
solids from faces (loft, tube), parts drawn back to front by depth, faces
edged in their own shade (class beast). Herds scatter round a spot, each
animal its own sprite facing about the object's rotation. Grazing
animals switch between two head poses (iso-pose2 groups), elephants curl
their trunks, rabbits hop.
- Birds and Butterflies as flocks: swim() takes a shape (bird, fly, bee);
wings flap out of step. Fish output unchanged.
- Beehives on stands with supers, lids, entrances and bees flying round;
Bush (round, flowering, berries); Flowers (bed in rows or meadow); Rocks;
Log or stump. g-meadow and g-soil ground materials.
- polyline() takes 3D points as documented (antlers).
Theme colours for dark and light, viewer CSS for poses, flapping, hopping.
examples/country: elephants in a paddock with a cut corner, deer at a
forest edge, boar, fox, rabbits, an apiary by a meadow, a pond, a lane,
fence and hedgerow at angles; Country demo in the web Studio and deploy.
MCP guidance, README, SCRIPTING, ROADMAP.
Tests: Rust 78, Studio 122; existing examples draw the same (only the
embedded theme CSS grew).
Object frames turn by any angle (quarter turns stay exact, so scenes along
the axes render byte for byte as before); a box in a turned frame is a
prism with its own corners. Rotation is kept as given (normalised to
0..360), no longer snapped to quarter turns.
Depth sort: sprites whose plan outline is not their box carry their convex
outline; when boxes overlap, an outline edge that separates two sprites
orders them. A long diagonal wall sorts right against both sides.
Joints (line_meet, end_cut, cut_box in util.rhai): where a piece off the
axes is involved, corners are mitred and T-junctions slanted; fences put a
corner post or pillar in its own sprite and mitre stone bases; Y joints let
the lowest id run through. Streets: every end part is a cut e + k*w, so
side streets come in at any angle (slanted sidewalk gaps), two streets meet
in a mitre with seam patches; fixes a curve's outer sidewalk that was
skipped when its kerb and back lines had different point counts.
Studio: runs and drags keep to x/y or snap to 45 degree diagonals, Ctrl
gives any angle; a road run turning 45 degrees gets a 45 degree curve;
Rotation is a number box. Streets demo: a diagonal lane with a hedge.
MCP guidance, SCRIPTING/README/ROADMAP.
Tests: Rust 76, Studio and web checks green.
Roads take sidewalks (none, both, left, right): 12 cm high paving with
kerb faces drawn where they face the viewer. Road curve (radius, angle,
left/right) carries a street round a bend; centre lines are true arcs
when cut and offset, so curve joints are seamless. A road ending on
another road's centre line opens that road's kerb and sidewalk (T
junction); two roads ending at one corner close it. Roundabout: ring
radius and width, one or two lanes, up to four arms with flared kerbs,
splitter islands, give-way lines on the entry side (traffic on the left
or right) and a central island with apron.
Studio: a road run drawn corner by corner gets a curve in each corner
(prefab meta `corner`). Tooltips list the streets each one meets.
Engine: open `polyline` primitive (Prim::Poly open) so dashes run on
round curves. examples/streets and a Streets demo in the web Studio;
MCP guidance, docs. ROADMAP: backlog 5-7 done; multi-select and the
hosted copy marked done.
Tests: Rust 72, Studio 113, web 95.
- Robot arm (category Industry): picks goods off the end of the nearest conveyor within its reach
and puts them on the start of another conveyor within reach, or on a pallet a quarter turn on
(pick / put: auto or a side). One move per item coming in (cycle 0) or a set cycle; waits while
the line before it stands. The belt it feeds carries its goods at its pace and starts its loop
when they land (feeds carry a time offset `ph`), so arm and belts stay in step.
- Drawn as a 16-pose flipbook: two-link inverse kinematics per pose, each pose shown for a
sixteenth of the cycle by a stepped CSS animation (iso-flip; pose 0 alone when unanimated).
Poses pointing away from the viewer are drawn before the base, the others after it.
- New sprite method beam(a, b, n, w, mat): a square bar between two 3D points, six faces culled
and shaded like face(). Native, so the factory demo renders in 4.7 ms instead of 18.8 ms.
- Factory demo: a palletiser at the end of the carton line, a loading robot passing drums from the
incline onto the loading belt into the truck. MCP instructions on robot arms.
Checks: 70 Rust tests (arms and belts in step, waiting arm, beam faces from every side),
Studio 109/109, web 90/90.
- Producer (category Industry): a press making cartons, crates, drums, sacks or parts at a set
rate per minute; its ram goes down once per item, a green / red light shows running / stopped.
- Conveyor: drawn the way it runs (new prefab meta `directed`: the Studio turns the piece from
where the drag starts), belt width, height, rise (inclines), speed, goods and spacing; legs,
rails and a drive motor. Corners join without overlap (the receiving belt runs through, the
feeding one stops at its side).
- A conveyor starting on a producer's output side carries its goods at its rate; one starting at
another's end carries on with what that one carries. The gap is speed / rate. A stopped press or
belt stops the goods after it. Tooltips show speed, rate and source.
- The goods ride a group moving one gap per loop (no reordering), first fading in, last out.
- Script API: world_of(o, u, v), info_row(key, value); objects_on falls back to half of p.d.
- Theme: industry colours, LED colours (the marker's LED had none).
- examples/factory + Factory demo in the web Studio; MCP instructions on production lines.
Checks: 68 Rust tests (conveyor joints, feed and spacing, every view of the factory demo),
Studio 108/108 (draw direction, feed from a producer, rate change), web 89/89.
Selection: S.sel stays the object picked last; S.selIds holds everything
selected.
- In the object list, Ctrl+click adds or removes an object and
Shift+click selects a range.
- On the map, Ctrl/Shift+click toggles an object and Shift+drag draws a
box that selects what lies wholly inside it (locked and hidden objects
are left out).
- Ctrl+A selects everything that is not locked; Esc selects nothing.
- Clicking a wall or fence a second time selects every piece of the same
type joined to it; another click goes back to that one piece.
- Dragging one selected object moves them all, together with the windows
and doors on them, as one undo step. Arrow keys, R (turns the group
about its middle), Ctrl+D, Delete, Lock and Hide all work on the whole
selection.
- When all selected objects share a type, the property form edits them
all; fields where they differ show "mixed".
- The agent's system prompt lists the selected objects.
The viewer outlines several objects with selectObj([ids]) and passes the
click event to onPick. A batch op now answers `ids`, one per operation,
so the copies from a group duplicate get selected.
Pond (Nature): natural, round or square, with a stone or grass edge,
fish, lily pads, spreading ripples and reed clumps. The fish come from a
new Swim primitive (script: s.swim). One matrix maps the object's frame
to the screen. Each fish turns round its ellipse with a CSS rotation,
so off-screen pausing and reduced motion apply as for the other
animations. The house demo gets a koi pond in the back garden.
Tests: ponds in every shape and rotation have the right number of fish,
no NaN and no depth-sort cycles, and stay inside their rectangle.
check_studio covers list and map multi-select, a group drag undone in
one step, joined-fence selection, a mixed-value form applied to all, box
select, delete and undo, Ctrl+A, Esc, and a new pond's fish.
Joints: line_joint (util.rhai) applies the house-wall rules to fences and
site walls, so pieces never overlap and the depth sort stays clean.
- A corner is closed: the thicker piece (or, if equal, the one along
world x) runs through, and the other stops at its face.
- On a straight run, two pieces share one post.
- At a T, the stem stops at the other piece's face without a post of its
own.
- A fence that ends at a site or house wall stops at the wall's face.
Fence designs (prop style): mesh, wooden boards, steel bars, mesh on a
stone base, cobble wall, and brick wall with pillars. Board, stone and
brick joints are drawn on the face turned to the viewer. Brick pillars
are separate sprites.
Studio: line prefabs (walls, fences, hedges, roads) can be drawn as a
run by clicking corner after corner. Double-click or Enter ends the run,
clicking the first corner closes it, and Backspace drops the last
corner. A run is one undo step. A drag still draws one piece. Corners
and ends snap onto the ends and lines of the pieces they meet, and a
marker shows where the next corner will snap.
The house demo gets a brick front wall with gate pillars and wooden side
fences in place of the old east fence, which ran over the road. Tests
cover every design's corners, Ts, straight runs and wall stops, with no
depth-sort cycles in any rotation, plus site walls. check_studio draws
and closes a fence run, undoes it in one step, snaps a dragged spur,
and picks a design.
House parts (stdlib isokit/house): house_wall drawn along a line, with ends
that adapt at corners, T-junctions and straight runs so no two walls
overlap; window and door that sit on a wall and cut its opening (door
styles panel, glass, double, sliding, opening; swing and hinge by
rotation); floor (boards, tiles, carpet, stone); roof (hip, gable, flat,
optional solar); stairs.
Furniture (stdlib isokit/furniture): chair, sofa / armchair, table with
chairs, desk with monitor and chair, TV, bed, cupboard, bookshelf, kitchen
run, bathtub, shower, toilet, washbasin, plant, rug, floor lamp.
Cut-open levels: on gf / 1f the walls in front of a room are cut low
(rooms are found by their floors), the roof becomes an outline on the
floor, and storeys above are left out. A part's storey comes from z
(storey_h, default 3 m).
Scripting: objects_of, objects_at, objects_on, mount_of, mounted, frame,
to_world, to_local, local_of. Prefab meta: shape (line / rect), mount,
storey.
Studio: drag to draw lines and rectangles (walls, roads, fences, hedges,
floors, areas, buildings, roofs). The Room tool draws a floor plus walls,
without doubling walls that already stand on an edge. Windows and doors
snap onto walls with a hover preview, and they move, turn, copy and
delete with their wall in one undo step. New parts land on the storey
the view shows. Palette categories collapse, and the palette scrolls
apart from the object list.
The MCP instructions explain house building, and list_prefabs shows
sits_on. examples/house is a furnished bungalow; the web Studio gets a
House demo button. Tests: wall corners and junctions, zero depth-sort
cycles in every view, cut levels, and the house demo in every view;
check_studio covers the room / window / door / storey flow, check_web
the House demo.