Wildlife and nature: animals, beehives, bushes, flowers, rocks, logs
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:
grabowski committed 2026-10-25 13:57:23 +07:00
1 parent 96d472625f
commit e840d36000
22 files changed
+1211 -16

No files matched your search

+4
View File
@@ -206,6 +206,8 @@ pub enum Prim {
/// One fish of a [`Prim::Swim`]: it goes round an ellipse of radii (rx, ry)
/// once every `dur` seconds, `delay` seconds into its round at the start,
/// counter-clockwise (seen from above) unless `cw`; `len` is its length.
/// `shape`: "fish" (or empty), "bird" (wings spread `len` wide, flapping),
/// "bee" or "fly" (a butterfly, fluttering): flocks use the same orbits.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Fish {
pub rx: f64,
@@ -215,4 +217,6 @@ pub struct Fish {
pub cw: bool,
pub len: f64,
pub cls: String,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub shape: String,
}
+89 -4
View File
@@ -307,11 +307,38 @@ impl Ctx<'_> {
let e = 1.0 + l / rx.min(ry) + 0.05;
// a fish nose first along +y (counter-clockwise) or -y
let k = if f.cw { -l } else { l };
// body widest behind the head, a narrow tail root, a forked tail fin
let (b, t) = (body_path(k, l), tail_path(k, l));
// body widest behind the head, a narrow tail root, a forked tail fin; birds,
// bees and butterflies in their own shapes, wings flapping in a group of their own
// wingbeats out of step: each bird or butterfly starts its own way into one
let beat = r3s((f.delay * 0.731).fract());
let body = match f.shape.as_str() {
"bird" => format!(
"<path class=\"iso-bird iso-{}\" d=\"{}\"/><g class=\"iso-a iso-flap\" style=\"animation-delay:-{beat}s\"><path class=\"iso-bird iso-{}\" d=\"{}\"/></g>",
esc(&f.cls),
bird_body(k, l),
esc(&f.cls),
bird_wings(k, l)
),
"fly" => format!(
"<g class=\"iso-a iso-flutter\" style=\"animation-delay:-{beat}s\"><path class=\"iso-wing iso-{}\" d=\"{}\"/></g>",
esc(&f.cls),
fly_wings(k, l)
),
"bee" => format!(
"<path class=\"iso-bee iso-{}\" d=\"{}\"/>",
esc(&f.cls),
bee_path(k, l)
),
_ => format!(
"<path class=\"iso-fish iso-{}\" d=\"{}{}\"/>",
esc(&f.cls),
body_path(k, l),
tail_path(k, l)
),
};
let _ = write!(
self.out,
"<g transform=\"scale({} {})\"><g class=\"iso-a iso-swim\" style=\"animation-duration:{}s;animation-delay:-{}s{}\"><path class=\"iso-swimbox\" d=\"M{} {}L{} {}\"/><g transform=\"translate(1 0) scale({} {})\"><path class=\"iso-fish iso-{}\" d=\"{b}{t}\"/></g></g></g>",
"<g transform=\"scale({} {})\"><g class=\"iso-a iso-swim\" style=\"animation-duration:{}s;animation-delay:-{}s{}\"><path class=\"iso-swimbox\" d=\"M{} {}L{} {}\"/><g transform=\"translate(1 0) scale({} {})\">{body}</g></g></g>",
r3s(rx),
r3s(ry),
r3s(f.dur.max(1.0)),
@@ -323,7 +350,6 @@ impl Ctx<'_> {
r3s(e),
r3s(1.0 / rx),
r3s(1.0 / ry),
esc(&f.cls),
);
}
self.out.push_str("</g>");
@@ -788,6 +814,65 @@ fn body_path(k: f64, l: f64) -> String {
}
/// The forked tail fin behind [`body_path`].
/// A bird seen from above flying along +y (k > 0) or -y: a slim body ...
fn bird_body(k: f64, l: f64) -> String {
format!(
"M0 {}L{} 0L0 {}L{} 0Z",
r3s(0.22 * k),
r3s(0.05 * l),
r3s(-0.3 * k),
r3s(-0.05 * l)
)
}
/// ... and its wings, `l` from tip to tip, swept back.
fn bird_wings(k: f64, l: f64) -> String {
format!(
"M{} {}L{} {}L0 {}L{} {}L{} {}L{} {}L0 {}L{} {}Z",
r3s(-0.5 * l),
r3s(-0.12 * k),
r3s(-0.22 * l),
r3s(0.1 * k),
r3s(0.04 * k),
r3s(0.22 * l),
r3s(0.1 * k),
r3s(0.5 * l),
r3s(-0.12 * k),
r3s(0.2 * l),
r3s(-0.03 * k),
r3s(-0.07 * k),
r3s(-0.2 * l),
r3s(-0.03 * k)
)
}
/// A butterfly's two pairs of wings, `l` across.
fn fly_wings(k: f64, l: f64) -> String {
let w = |s: f64| {
format!(
"M0 {}L{} {}L{} {}L0 {}Z",
r3s(0.08 * k),
r3s(s * 0.5 * l),
r3s(0.32 * k),
r3s(s * 0.42 * l),
r3s(-0.3 * k),
r3s(-0.12 * k)
)
};
format!("{}{}", w(1.0), w(-1.0))
}
/// A bee: a small oval, `l` long.
fn bee_path(k: f64, l: f64) -> String {
format!(
"M0 {}L{} 0L0 {}L{} 0Z",
r3s(0.5 * k),
r3s(0.3 * l),
r3s(-0.5 * k),
r3s(-0.3 * l)
)
}
fn tail_path(k: f64, l: f64) -> String {
format!(
"M0 {}L{} {}L0 {}L{} {}Z",