Multi-select, select joined walls and fences, pond with swimming fish
Deploy web Studio / deploy (push) Successful in 1m27s
Deploy web Studio / deploy (push) Successful in 1m27s
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.
This commit is contained in:
1 parent
e4017ce2a8
commit
19f4c83ae8
21 files changed
+759
-59
No files matched your search
@@ -485,6 +485,63 @@ fn fences_join_like_walls_in_every_design() {
|
||||
.contains("iso-seam"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ponds_have_fish_swimming_in_every_shape() {
|
||||
let r = Runtime::new(&Bundle::default()).unwrap();
|
||||
for (shape, edge, rot) in [
|
||||
("natural", "stone", 0.0),
|
||||
("round", "grass", 90.0),
|
||||
("square", "stone", 0.0),
|
||||
] {
|
||||
let mut doc = Doc::default();
|
||||
let mut o = obj(
|
||||
"pond",
|
||||
"pond",
|
||||
3.0,
|
||||
-2.0,
|
||||
json!({"w": 9, "d": 5, "shape": shape, "edge": edge, "fish": 6, "lilies": 4}),
|
||||
);
|
||||
o.rot = rot;
|
||||
doc.objects.push(o);
|
||||
for view in 0..4u8 {
|
||||
let b = r.build("site", view, &cfg(), &doc).unwrap();
|
||||
assert!(
|
||||
b.scene.warnings.is_empty(),
|
||||
"{shape}: {:?}",
|
||||
b.scene.warnings
|
||||
);
|
||||
let out = render(&b.scene, view, &RenderOpts::default());
|
||||
assert_eq!(
|
||||
out.html.matches("iso-a iso-swim").count(),
|
||||
6,
|
||||
"{shape}/{view}"
|
||||
);
|
||||
assert!(!out.html.contains("NaN"), "{shape}/{view}");
|
||||
assert!(out.html.contains("iso-fish iso-koi") && out.html.contains("iso-lily"));
|
||||
assert!(out.html.contains("iso-a iso-rip"));
|
||||
assert_eq!(out.cycles, 0);
|
||||
}
|
||||
// the pond stays inside its 9 x 5 m (turned: 5 x 9 m) rectangle; the reeds stand on its edge
|
||||
let bx = r.build("site", 0, &cfg(), &doc).unwrap().boxes["pond"];
|
||||
let (hw, hd) = if rot == 0.0 { (4.5, 2.5) } else { (2.5, 4.5) };
|
||||
assert!(
|
||||
bx[0] >= 3.0 - hw - 1e-6
|
||||
&& bx[3] <= 3.0 + hw + 1e-6
|
||||
&& bx[1] >= -2.0 - hd - 1e-6
|
||||
&& bx[4] <= -2.0 + hd + 1e-6,
|
||||
"{shape}: {bx:?}"
|
||||
);
|
||||
}
|
||||
// no fish: no school
|
||||
let mut doc = Doc::default();
|
||||
doc.objects
|
||||
.push(obj("p", "pond", 0.0, 0.0, json!({"fish": 0})));
|
||||
let b = r.build("site", 0, &cfg(), &doc).unwrap();
|
||||
assert!(!render(&b.scene, 0, &RenderOpts::default())
|
||||
.html
|
||||
.contains("iso-swim"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn site_walls_join_at_corners() {
|
||||
let r = Runtime::new(&Bundle::default()).unwrap();
|
||||
|
||||
Reference in new issue
Block a user