Skip to content

Interactive Typst content creator using Vello and Bevy.

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

voxell-tech/velyst

Repository files navigation

Velyst

Interactive Typst content creator using Vello and Bevy.

hello world

Associated example here!

Quickstart

Velyst renders Typst content using Typst functions. To get started rendering a simple box, create a function inside a .typ file:

#let main(width, height) = {
  // Convert float to length
  let width = (width * 1pt)
  let height = (height * 1pt)

  box(width: width, height: height, fill: white)
}

Then, in your .rs file, register your Typst asset file and function.

use bevy::prelude::*;
use bevy_vello::VelloPlugin;
use velyst::{prelude::*, typst_element::prelude::*, VelystPlugin};

fn main() {
    App::new()
        .add_plugins((DefaultPlugins, VelloPlugin::default()))
        .add_plugins(VelystPlugin::default())
        .register_typst_asset::<HelloWorld>()
        .compile_typst_func::<HelloWorld, MainFunc>()
        .render_typst_func::<MainFunc>()
        .insert_resource(MainFunc {
            width: 100.0,
            height: 100.0,
        })
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2dBundle::default());
}

struct HelloWorld;

// Path to the Typst file that you created.
impl TypstPath for HelloWorld {
    fn path() -> &'static str {
        "typst/hello_world.typ"
    }
}

// `main` function in Typst with their respective values.
// These values can be something else as long as they can be used to
// evaluate the respective input arguments needed for the function.
#[derive(Resource, Default)]
struct MainFunc {
    width: f64,
    height: f64,
}

impl TypstFunc for MainFunc {
    // Name of the function in the Typst file.
    fn func_name(&self) -> &str {
        "main"
    }

    // Create a ContextElem with the correct function arguments.
    fn content(&self, func: foundations::Func) -> Content {
        elem::context(func, |args| {
            args.push(self.width);
            args.push(self.height);
        })
        .pack()
    }
}

Interactions

Velyst comes with built-in interactions using bevy_ui.

game ui

Associated example here!

Join the community!

You can join us on the Voxell discord server.

License

velyst is dual-licensed under either:

This means you can select the license you prefer! This dual-licensing approach is the de-facto standard in the Rust ecosystem and there are very good reasons to include both.