Conveyors and producers: goods flow from presses down the belts
Deploy web Studio / deploy (push) Successful in 1m4s

- 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.
This commit is contained in:
grabowski committed 2026-10-24 21:46:10 +07:00
1 parent a202283a60
commit 18dd324543
20 files changed
+617 -18

No files matched your search

+26 -2
View File
@@ -32,7 +32,9 @@ fn prefab_kiosk(o) { // draw around (0, 0) in the object's own
`d`), default a click. `mount: ["house_wall"]`: the prefab sits on objects of
those types; the Studio snaps it onto the nearest one and moves, turns,
copies and deletes it with its host. `storey: true`: placed on the storey the
view shows (level `1f` puts it at z = 1 × `storey_h`).
view shows (level `1f` puts it at z = 1 × `storey_h`). `directed: true` (with
`shape: "line"`): the way matters, so the Studio turns the piece to run from
where the drag starts (rot 0, 90, 180 or 270; conveyors).
- `o` holds `id, type, name, x, y, z, rot, p` (the props with defaults
filled in), `pts`, `tag`, `info`, `level`.
- The engine sets the object's frame before calling the prefab. All
@@ -56,6 +58,7 @@ shaded automatically by face direction.
| `layer("ground" \| "floor" \| "main")`, `layer(name, #{sort, zfirst, cls, before})` | where new sprites go |
| `tag(x, y, z, text[, prio[, id[, kind]]])` | label; `kind` "signtag" / "warntag" always shows |
| `info(id, name[, detail])`, `info(id, #{name, detail, rows: [[k, v], …]})` | tooltip |
| `info_row(key, value)` | one row more in the tooltip of the object being drawn (a belt's speed) |
| `focus(x, y, z)`, `bounds(x0, y0, x1, y1[, depth])`, `defs(svg)`, `warn(msg)` | framing and extras |
| `level()`, `rot()`, `cfg()`, `cfg(name)`, `objects()` | inputs (`objects()`: every document object, props resolved) |
| `objects_of(types)` | objects of a type or a list of types shown on this level |
@@ -64,7 +67,7 @@ shaded automatically by face direction.
| `mount_of(o, hosts[, tol])` | the host o sits on (nearest centre line within `p.t / 2 + tol`, default 0.3 m, same height), with `u, v` = o's position in the host's frame; `()` if none |
| `mounted(h, types, hosts[, tol])` | the objects of `types` whose host is h, each with `u, v` |
| `frame(o)`, `frame(x, y, z, rot)` | draw in another frame from here on (a window draws in its wall's frame) |
| `to_world(x, y)`, `to_local(x, y)`, `local_of(o, x, y)` | between the current frame (or o's) and world plan coordinates |
| `to_world(x, y)`, `to_local(x, y)`, `local_of(o, x, y)`, `world_of(o, u, v)` | between the current frame (or o's) and world plan coordinates |
| `vis(nx, ny)` | is a face with that outward normal turned to the viewer? |
| `dv(dx, dy, dz)` | screen vector of a world vector (CSS motion) |
| `along_x()` | should a mover run along x in this rotation? |
@@ -117,6 +120,27 @@ depth sort needs. `fence` (designs `style`: mesh, wood, bars, half stone,
cobble, brick) and the site `wall` use it; `house_wall` has its own version
(`wall_ext`, house.rhai).
## Production lines
`producer` and `conveyor` (stdlib/industry.rhai) work together through the
document, like house parts:
- A producer makes one of its `product` goods every 60 / `rate` seconds (its
ram goes down once per item) and puts them out on its local +x side.
- A conveyor carries goods along its local +x at `speed` m/s. When its start
lies on a producer's output side, it carries that producer's goods at its
rate; when its start is at another conveyor's end, it carries on with what
that one carries (followed back up to 12 belts). The gap between goods is
speed / rate, so a faster belt spreads them out. A stopped producer or belt
stops the goods after it. Alone a conveyor carries its own `item` every
`gap` metres.
- Belts meeting at a corner do not overlap: the belt a feeding belt runs into
runs through the corner and the feeding one stops at its side; at a T the
belt stops at the side. `rise` lifts the end (an incline).
- The goods ride a group that moves one gap per loop (`iso-ride`), so their
drawing order never changes; the first fades in, the last fades out.
Tooltips show speed, rate and where the goods come from (`info_row`).
## House parts
`house_wall`, `window`, `door`, `floor`, `roof`, `stairs` and the furniture