14 unstable releases (4 breaking)

0.5.0 Sep 21, 2024
0.4.0 Jan 21, 2024
0.3.0 Dec 28, 2023
0.2.0 Oct 22, 2023
0.1.0-alpha.2 Sep 30, 2023

#194 in Visualization

Download history 258/week @ 2024-09-17 68/week @ 2024-09-24 26/week @ 2024-10-01

586 downloads per month

MIT license

6MB
7.5K SLoC

whiskers: interactive sketches for plotter generative art

github Latest version Documentation GitHub

whiskers is a Rust interactive sketch environment for plotter generative art, with a Processing inspired API.

👉 Try the live demo!

It's similar to vsketch, but faster, web-ready, and with vsvg as a much stronger foundation.

image

Installation

Simply add whiskers as a dependency to your project:

cargo add whiskers

Usage

Here is the code for a basic sketch:

use whiskers::prelude::*;

#[sketch_app]  // <- this is the magic to make the sketch interactive
struct HelloWorldSketch {
    width: f64,   // <- interactive UI is automagically built for these fields
    height: f64,
}

impl Default for HelloWorldSketch {
    fn default() -> Self {
        Self {
            width: 400.0,
            height: 300.0,
        }
    }
}

impl App for HelloWorldSketch {
    fn update(&mut self, sketch: &mut Sketch, _ctx: &mut Context) -> anyhow::Result<()> {
        sketch.color(Color::DARK_RED).stroke_width(3.0);

        // the `Sketch` API is a delight to work with
        // this is where the drawing happens:
        sketch
            .translate(sketch.width() / 2.0, sketch.height() / 2.0)
            .rect(0., 0., self.width, self.height);

        Ok(())
    }
}

fn main() -> Result {
    HelloWorldSketch::runner()
        .with_page_size_options(PageSize::A5H)
        .run()
}

This is the result:

image

Features

whiskers is a work in progress, but currently features:

  • Interactive and highly customisable interactive UI.
  • Export to SVG.
  • Drawing with lines, shapes, svg paths.
  • Support for curves: quadratic Béziers, cubic Bézier, Catmull-Rom splines—circles. (Ellipses and arcs are supported but internally converted to cubic Bézier.)
  • Transformations such as translations, rotations, scaling.
  • Pen settings such as line width, color, opacity, layers.
  • Grid helpers for rectangular or hexagonal grid based sketches.
  • Animated sketches support.
  • Random Number Generator UI with seed control (see e.g. asteroid example).
  • Integrated profiler (based on puffin).
  • Web assembly compatibility, export your sketch UI for browsers (demo)
  • Support for inspect variables in the UI (such as randomly generated features of the artwork or debug values)
  • Configuration handling (save/restore config, etc.).
  • Compiled sketches are also a flexible CLI utility with the capability to batch generate sketch outputs with parameter ranges.
  • Export to other format through templating (HPGL, g-code, etc. — for now, please use vpype).
  • ... (please complete this list)

On top of all that, you can import other rust packages for features such as noise and boolean operations, for which you can use noise-rs and geo respectively (see examples noise and astroids).

Isn't that vsketch?

Compared to vsketch, whiskers offers the following advantages:

  • It's in Rust, so it's faaast! 🚀
  • Sketches can be compiled to WebAssembly and published on the Web (try it here).
  • It's built on a stack (mainly egui and wgpu) that's much faster and easier to work with.

On the other hand:

  • It's in Rust, which has a steeper learning curve than Python.
  • Since sketches are compiled, the edit code/execute cycle is heavier than with vsketch.

I have the vague dream to slap a Python front-end on top of whiskers to build vsketch 2.0, but that's a lot of work and other things have a higher priority, so no promises on this front.

Running examples

To run the example, use the following command (in this case to run crates/whiskers/examples/asteroid.rs):

cargo run --release --package whiskers --example asteroid

Non-interactive use

The whiskers::Sketch object can be used stand-alone, without the interactive sketch runner. This is useful if you want to use the drawing capabilities in your own tools.

For example, I use whiskers::Sketch to build the generative asteroids in my Rusteroïds toy game.

Here is how the code could look:

use whiskers::prelude::*;

fn main() -> Result {
    Sketch::with_page_size_options(PageSize::A5)
        .scale(Units::Cm)
        .translate(7.0, 6.0)
        .circle(0.0, 0.0, 2.5)
        .translate(1.0, 4.0)
        .rotate_deg(45.0)
        .rect(0., 0., 4.0, 1.0)
        .save("output.svg")?;

    Ok(())
}

If the viewer feature of *whiskers is enabled (which it is by default), the sketch can be displayed using the basic viewer using sketch.show().

Call to action

This project is at an early the stage and needs your contribution. Please get in touch via discussions on GitHub or the DrawingBots’s Discord server if you feel like helping!

Dependencies

~25–67MB
~1M SLoC