pixfx

Rust API

Use the engine directly from Rust: look up effects, render their frames, step live instances, composite, hash and export.

Crates

The crates are not on crates.io yet. Depend on them by path or git:

[dependencies]
pixfx-core = { path = "../pixfx-rs/crates/pixfx-core" }
pixfx-effects = { path = "../pixfx-rs/crates/pixfx-effects" }
pixfx-export = { path = "../pixfx-rs/crates/pixfx-export" }

They need the nightly toolchain pinned in the repository's rust-toolchain.toml, edition 2024, and forbid unsafe.

Example

This program is checked to compile and run against the current source.

use std::path::Path;

use pixfx_core::{Frame, Instance, Layer, OptValue, Options, composite, frame_hash, hex, render_frames};
use pixfx_export::{write_gif, write_sheet};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let fx = pixfx_effects::effect("fire/campfire").ok_or("fire/campfire is not registered")?;

    // render one loop with options, glow room and no edge fade
    let mut opts = Options { seed: Some(7), light: 1.2, ..Options::default() };
    opts.palette = Some(vec![hex("#0d1033")?, hex("#3a62e0")?, hex("#ffffff")?]);
    opts.extra.insert("height".into(), OptValue::Num(30.0));
    let rendered = render_frames(fx, &opts, fx.meta().glow_margin());

    let out = Path::new("out");
    let files = write_sheet(&rendered, fx.meta(), out, "blue_campfire")?;
    write_gif(&out.join("blue_campfire.gif"), &rendered, 3)?;
    println!("{}", files.json.display());

    // live: step an instance and draw it into a frame you own
    let meta = fx.meta();
    let mut inst = Instance::new(fx, Options {
        x: f64::from(meta.origin.0),
        y: f64::from(meta.origin.1),
        ..Options::default()
    });
    let mut frame = Frame::new(meta.size.0, meta.size.1, 0, 0);
    inst.update(1.0 / 60.0);
    frame.clear();
    inst.draw(&mut frame, Layer::Both);
    let mut rgba = vec![0u8; frame.w as usize * frame.h as usize * 4];
    composite(&frame, &mut rgba, None);
    println!("hash {:016x}", frame_hash(&frame));
    Ok(())
}

pixfx-effects

ItemWhat it is
EFFECTS: &[&'static dyn Effect]Every effect, in registry order.
effect(id) -> Option<&'static dyn Effect>Look one up by id.
fire::CANDLE, fire::CAMPFIRE, fire::BRAZIERThe effects as statics.

pixfx-core

Effect, Meta, Options

ItemWhat it is
trait Effectmeta() -> &Meta and spawn(&Options, seed) -> Box<dyn EffectState>. See Write an effect.
trait EffectStateupdate(dt) for one simulation sub-step (default: nothing) and draw(&mut Painter, t, Layer).
struct Metaid, name, desc, tags, size, origin, duration, looping, fps, seed; is_screen() and glow_margin(). See Concepts.
struct Optionsx, y, flip, angle, seed: Option<u64>, light, palette: Option<Vec<Rgba>>, extra: BTreeMap<String, OptValue>. Default is origin (0, 0), no flip, angle 0, effect seed, light 1, effect palette.
enum OptValueNum(f64) or Ramp(Vec<Rgba>): an effect's own option.
Options::palette_or, ramp_or, num_orFor effects: resolve an option against its default (ramps resampled to the default's length).
enum LayerBack, Front, Both.
find(list, id)Find an effect by id in any list.

Instance

MethodDoes
Instance::new(effect, opts)Spawn with opts.seed or the effect's seed. opts.x, opts.y place the origin in frame space.
update(dt)Advance by at most MAX_DT (0.25 s) in sub-steps of at most 1/120 s. A step failing valid_dt (NaN, infinite, negative) is ignored.
draw(&mut Frame, Layer)Draw at the current time on top of what is in the frame. Clear the frame first for a fresh image.
stop(), done(), t()As in Concepts.

Frames and output

ItemWhat it is
struct Frame { w, h, ox, oy, color, light }w×h pixels whose top-left is at (ox, oy) in world space. color: ABGR words. light: xBGR words. Frame::new, clear().
render_frames(effect, &opts, margin) -> RenderedEvery frame of one loop or one-shot at the effect's fps, at its origin whatever opts.x/y say. Margin 0 eases light out at the edge.
struct Rendered { w, h, fps, margin, frames }The result.
composite(&frame, &mut out, bg)Colour over an optional RGBA background, plus light, into RGBA8 bytes (w × h × 4).
composite_px(c, l, ground)One pixel of composite.
edge_fade(&mut frame)Ease light out over the last 8 pixels of the frame.
frame_hash(&frame) -> u64FNV-1a 64 over colour then light words, little-endian: a stable fingerprint for golden tests.

Colour, math, painter

pixfx-export

ItemWhat it is
write_sheet(&rendered, &meta, out_dir, name) -> Result<SheetFiles, ExportError>Write <name>.png, _color.png, _light.png and .json, creating out_dir. See Sprite sheet format.
write_gif(path, &rendered, scale) -> Result<(), ExportError>A looping GIF over a dark backdrop, each pixel scale×scale.
Grid, beanfx_json, FileNamesThe pure layout and JSON functions behind write_sheet.
enum ExportErrorIo, Png, Gif, Json, or TooBig { w, h, scale } when a scaled image exceeds the format's size field.