Skip to main content

propagate

Function propagate 

Source
pub fn propagate(
    scratch: &mut Scratch,
    entities: &Entities,
    parents: &Store<Parent>,
    locals: &Store<Local>,
    globals: &mut Store<Global>,
) -> Propagated
Expand description

Compose every Local into a Global, parents first.

Runs in time proportional to the number of scene nodes plus the highest occupied slot: each node’s ancestry is climbed once across the whole call, not once per node. Allocates only while scratch or globals is still growing to fit the world.

The return value is the only report of a malformed hierarchy — a discarded Propagated turns a parent typo into a thing quietly drawn in the wrong place — so it is #[must_use].

§Example

A hub turned a quarter turn, with a child one unit along its x axis. The child swings round to the y axis rather than staying put, which is the one thing a caller could not have got by adding two vectors — and the reason this crate exists rather than the composition living at each call site.

use renew_ecs::{Entities, Store};
use renew_fixed::{Angle, Fixed, Vec2};
use renew_scene::{Global, Local, Parent, Scratch, propagate};

let mut entities = Entities::new();
let (mut parents, mut locals, mut globals) =
    (Store::default(), Store::default(), Store::default());

let hub = entities.spawn();
locals.insert(hub.index(), Local::new(Vec2::ZERO, Angle::QUARTER));

let arm = entities.spawn();
locals.insert(
    arm.index(),
    Local::new(Vec2::new(Fixed::ONE, Fixed::ZERO), Angle::ZERO),
);
parents.insert(arm.index(), Parent(hub));

let mut scratch = Scratch::new();
let counts = propagate(&mut scratch, &entities, &parents, &locals, &mut globals);
assert_eq!(counts.nodes, 2);

let placed: Global = *globals.get(arm.index()).expect("placed");
assert_eq!(placed.translation(), Vec2::new(Fixed::ZERO, Fixed::ONE));
assert_eq!(placed.rotation(), Angle::QUARTER);