Crafter.Graphics/examples/VulkanAnimated/README.md

1.9 KiB

VulkanAnimated

A live HUD demo: three Observable<float>s drive ProgressBars, three Observable<std::string>s drive Text labels, and an FPS readout in the corner ticks every frame. Everything updates from a single onUpdate listener — no Invalidate() / Redraw() calls.

What it shows

  • Observable<T> data flow: change a value in onUpdate, the next frame's RebuildFrame re-emits the draw list with the new value automatically. No tree rebuild.
  • ProgressBar::bindValue(obs, lo, hi) — the bar fill normalises the observable's current value into 0..1 each frame.
  • Text::bind(observable) — the displayed string is sourced from the observable each frame, replacing any baked-in runs.
  • Composition pattern: a small lambda helper builds one HP/MP-style row (Text + ProgressBar inside an HStack) given the observables and a colour, then the row is dropped into the parent VStack like any other widget.
  • Different update rates per observable: health oscillates at 0.7 rad/s, mana at 1.3, charge advances linearly modulo 1 — visible proof that each observable updates independently.

Run

cd examples/VulkanAnimated
crafter-build -r

You should see "Animated HUD" with three coloured bars (red HP, blue MP, yellow Charge) all moving at different rates, with the FPS readout in the top-right ticking once per frame.

Click Quit to exit.

Notes

The whole tick handler is just:

EventListener<FrameTime> tick(&window.onUpdate, [&](FrameTime ft){
    t += ft.delta.count();
    health = 0.5f + 0.5f * std::sin(t * 0.7f);
    mana   = std::abs(std::sin(t * 1.3f));
    charge = std::fmod(t * 0.3f, 1.0f);
    healthLabel = std::format("HP   {:>3.0f} / 100", health.Get() * 100);
    // …
});

That's the entire animation system. There is deliberately no Animation<T> / tween primitive in the library — drive observables from any source you like.