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

+5 -1
View File
@@ -23,7 +23,11 @@ then windows and doors with x, y on a wall line (they sit on that wall and cut t
the wall's +y side, rot + 180 swings it the other way), a roof (w x d = outer size of the walls) and furniture \
(fronts face local -y, backs go against a wall). Level gf shows the house cut open; a part's storey is its z / 3 m. \
Fences (props.style: mesh, wood, bars, half stone, cobble, brick) and site walls join where their centre-line ends \
meet, so for a plot boundary put each piece's ends exactly on the next piece's end or line.";
meet, so for a plot boundary put each piece's ends exactly on the next piece's end or line. \
Production lines (category Industry): a producer (props.rate per minute, product) puts goods out on its local +x \
side; a conveyor (rot 0 runs towards +x, 90 +y, 180 -x, 270 -y; w = length, props.speed m/s) starting exactly \
at that side carries them, and a conveyor whose start is at another's end carries on with them (corners join). \
The gap between goods is speed / rate, so set the rate on the producer and the speeds on the belts.";
fn tool(name: &str, description: &str, props: Value, required: &[&str]) -> Value {
json!({ "name": name, "description": description,
+17 -4
View File
@@ -72,12 +72,25 @@ fn demo_passes_the_check() {
assert!(f.is_empty(), "{f:?}");
}
/// The house demo: every view draws every object without warnings or depth-sort cycles
/// (walls must not overlap), and the project passes the check.
/// The house and factory demos: every view draws every object without warnings or
/// depth-sort cycles (walls and belts must not overlap), and the projects pass the check.
#[test]
fn house_demo_renders_every_view_cleanly() {
let p =
Project::load(Path::new(env!("CARGO_MANIFEST_DIR")).join("../../examples/house")).unwrap();
example_renders_every_view_cleanly("house");
}
#[test]
fn factory_demo_renders_every_view_cleanly() {
example_renders_every_view_cleanly("factory");
}
fn example_renders_every_view_cleanly(name: &str) {
let p = Project::load(
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../examples")
.join(name),
)
.unwrap();
assert!(p.runtime.is_ok(), "{:?}", p.runtime.as_ref().err());
for l in p.manifest.levels() {
for rot in 0..4 {