Wildlife and nature: animals, beehives, bushes, flowers, rocks, logs
Deploy web Studio / deploy (push) Successful in 1m5s
Deploy web Studio / deploy (push) Successful in 1m5s
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).
This commit is contained in:
1 parent
96d472625f
commit
e840d36000
22 files changed
+1211
-16
No files matched your search
@@ -858,6 +858,101 @@ fn piece(id: &str, kind: &str, a: [f64; 2], b: [f64; 2], props: Value) -> Object
|
||||
o
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wildlife_and_garden_prefabs_draw_from_every_side() {
|
||||
let r = Runtime::new(&Bundle::default()).unwrap();
|
||||
let doc = Doc {
|
||||
objects: vec![
|
||||
obj("deer", "deer", -18.0, 8.0, json!({"n": 5, "r": 4})),
|
||||
obj(
|
||||
"stag",
|
||||
"deer",
|
||||
-8.0,
|
||||
12.0,
|
||||
json!({"n": 1, "mix": "stag", "graze": false}),
|
||||
),
|
||||
obj("boar", "boar", -18.0, -6.0, json!({"n": 3})),
|
||||
obj("fox", "fox", -8.0, -2.0, json!({})),
|
||||
obj(
|
||||
"el",
|
||||
"elephant",
|
||||
6.0,
|
||||
10.0,
|
||||
json!({"n": 3, "mix": "herd", "r": 5}),
|
||||
),
|
||||
obj("rab", "rabbits", -4.0, -12.0, json!({"n": 4})),
|
||||
obj("birds", "birds", 0.0, 0.0, json!({"n": 7})),
|
||||
obj("bf", "butterflies", 10.0, -12.0, json!({"n": 5})),
|
||||
obj("hives", "beehive", 16.0, -6.0, json!({"n": 4})),
|
||||
obj("bed", "flowers", 10.0, -12.0, json!({"w": 5, "d": 3})),
|
||||
obj(
|
||||
"mead",
|
||||
"flowers",
|
||||
20.0,
|
||||
-14.0,
|
||||
json!({"w": 8, "d": 5, "kind": "meadow"}),
|
||||
),
|
||||
obj("b1", "bush", 3.0, -4.0, json!({})),
|
||||
obj("b2", "bush", 5.0, -6.0, json!({"kind": "berries"})),
|
||||
obj("rk", "rocks", 22.0, 6.0, json!({"n": 4})),
|
||||
obj("lg", "log", 14.0, 4.0, json!({})),
|
||||
obj("st", "log", 18.0, 2.0, json!({"kind": "stump"})),
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
for view in 0..4u8 {
|
||||
let b = r.build("site", view, &cfg(), &doc).unwrap();
|
||||
assert!(b.scene.warnings.is_empty(), "{:?}", b.scene.warnings);
|
||||
let out = render(&b.scene, view, &RenderOpts::default());
|
||||
assert!(!out.html.contains("NaN"));
|
||||
// each animal its own sprite: five deer, three boar, one fox, three elephants, four rabbits
|
||||
for (id, n) in [
|
||||
("deer", 5),
|
||||
("stag", 1),
|
||||
("boar", 3),
|
||||
("fox", 1),
|
||||
("el", 3),
|
||||
("rab", 4),
|
||||
] {
|
||||
assert_eq!(sprites_of(&b, id), n, "{id}");
|
||||
}
|
||||
// grazing animals carry two head poses taking turns, the first shown unanimated;
|
||||
// the standing stag and the rabbits have none
|
||||
assert_eq!(
|
||||
out.html.matches("iso-a iso-pose2 iso-pose0").count(),
|
||||
5 + 3 + 1 + 3
|
||||
);
|
||||
assert_eq!(out.html.matches("iso-a iso-pose2\"").count(), 5 + 3 + 1 + 3);
|
||||
assert_eq!(out.html.matches("iso-a iso-hop").count(), 4);
|
||||
// birds flap, butterflies flutter, bees fly round the hives
|
||||
assert_eq!(out.html.matches("iso-a iso-flap").count(), 7);
|
||||
assert_eq!(out.html.matches("iso-a iso-flutter").count(), 5);
|
||||
assert_eq!(out.html.matches("class=\"iso-bee iso-bee\"").count(), 4 * 8);
|
||||
// animal faces are edged in their own shade; antlers on the one stag
|
||||
assert!(out.html.contains("iso-deer iso-beast"));
|
||||
assert!(out.html.contains("iso-antler"));
|
||||
}
|
||||
let b = r.build("site", 0, &cfg(), &doc).unwrap();
|
||||
// a stag stands about 1.5 m at the head, antlers up to 2.1 m; it fits its sort box
|
||||
let st = b.boxes["stag"];
|
||||
assert!(st[5] > 1.9 && st[5] < 2.3, "{st:?}");
|
||||
// an elephant bull: about 3 m tall at the head
|
||||
let el = b.boxes["el"];
|
||||
assert!(el[5] > 2.6 && el[5] < 3.3, "{el:?}");
|
||||
let out = render(&b.scene, 0, &RenderOpts::default());
|
||||
let row = |id: &str, k: &str| {
|
||||
out.info[id]
|
||||
.rows
|
||||
.iter()
|
||||
.find(|r| r.0 == k)
|
||||
.map(|r| r.1.clone())
|
||||
.unwrap_or_default()
|
||||
};
|
||||
assert_eq!(row("deer", "Herd"), "1 stag, 3 does, 1 fawn");
|
||||
assert_eq!(row("el", "Herd"), "1 bull, 1 cow, 1 calf");
|
||||
assert_eq!(row("hives", "Apiary"), "4 hives, 2 supers each");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diagonal_walls_fences_and_hedges_mitre_and_sort() {
|
||||
let r = Runtime::new(&Bundle::default()).unwrap();
|
||||
|
||||
Reference in new issue
Block a user