A low-boilerplate framework for making sketches with the nightgraphics crate
The purpose of this crate is to house the artworks ("sketches") and a way
to interact with them in the graphical and command line interfaces. The
design philosophy here is to minimize infrastructural code (such as field
access and modification, and sketch listings) through macros. This is heavily
at odds with the Rust best practices to avoid implicitness, and therefore is
only really appropriate for usage within this workspace.
See nightsketch_derive
for an overview of the code that
is generated by the #[sketch]
, #[param]
, etc macros.
/// If a doc comment preceeds the struct declaration, it is used as the
/// description of the sketch, for example in the help/usage text of the
/// nightgraph-cli command. Similarly, the struct's name is used as the
/// sketches name. Both are overridable with attributes, see the "attributes"
/// section of this README
#[sketch]
pub struct ConcentricCircles {
// Fields defined in the sketch's struct are exposed to the CLI/GUI as
// parameters, if their datatype is supported. The #[param(key=val)]
// attribute allows further customization. Just like the struct,
// doc comments are used for parameter descriptions, and names are
// processed to be "kebab-cased" (such-as-this)
/// Number of circles to place
#[param(default = 5, range = 1..=30)]
circle_count: u32,
/// Spacing between each circle (in mm)
#[param(name = "spacing", default = 0.5, range = 0.01..=10.0)]
circle_spacing: f64,
// Note: when bools are default true, the generate command
// line flag is prefixed with a "-no" to indicate negation,
// e.g. --no-randomize-center
/// Whether or not to randomize each circle's center point
#[param(default = true)]
randomize_center: bool,
// Fields can be skipped, such as for caching certain intermediate
// geometries for subsequent renders
#[param(internal)]
cached_circles: Option<Vec<Circle>>,
}
/// Each sketch needs to implement the `Sketch` trait's `exec` method.
impl Sketch for ConcentricCircles {
fn exec(&self) -> SketchResult<Canvas> {
// The general mechanic of a sketch is adding shapes to a canvas
// which is then returned so that the caller can render it to the
// desired output format, such as SVG or egui shapes.
const WIDTH: f64 = 11. * INCH;
const HEIGHT: f64 = 17. * INCH;
let mut canvas = Canvas::new(point(0, 0), Size::new(11. * INCH, 17. * INCH));
let page_center = point(WIDTH / 2., HEIGHT / 2.);
for n in 0..self.circle_count {
...
}
...
Ok(canvas)
}