2023-02-03 21:22:39 +11:00
|
|
|
pub mod download;
|
2023-03-10 09:18:03 +11:00
|
|
|
mod images;
|
2023-02-03 21:22:39 +11:00
|
|
|
mod simple_text;
|
|
|
|
mod svg;
|
|
|
|
mod test_scenes;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
2023-03-03 09:29:06 +11:00
|
|
|
use anyhow::{anyhow, Result};
|
2023-02-03 21:22:39 +11:00
|
|
|
use clap::{Args, Subcommand};
|
|
|
|
use download::Download;
|
2023-03-10 09:18:03 +11:00
|
|
|
pub use images::ImageCache;
|
2023-02-03 21:22:39 +11:00
|
|
|
pub use simple_text::SimpleText;
|
|
|
|
pub use svg::{default_scene, scene_from_files};
|
|
|
|
pub use test_scenes::test_scenes;
|
|
|
|
|
2023-03-03 09:29:06 +11:00
|
|
|
use vello::{kurbo::Vec2, peniko::Color, SceneBuilder};
|
2023-02-03 21:22:39 +11:00
|
|
|
|
|
|
|
pub struct SceneParams<'a> {
|
|
|
|
pub time: f64,
|
2023-03-17 00:38:43 +11:00
|
|
|
/// Whether blocking should be limited
|
|
|
|
/// Will not change between runs
|
|
|
|
// TODO: Just never block/handle this automatically?
|
|
|
|
pub interactive: bool,
|
2023-02-03 21:22:39 +11:00
|
|
|
pub text: &'a mut SimpleText,
|
2023-03-10 09:18:03 +11:00
|
|
|
pub images: &'a mut ImageCache,
|
2023-02-03 21:22:39 +11:00
|
|
|
pub resolution: Option<Vec2>,
|
2023-03-04 05:47:04 +11:00
|
|
|
pub base_color: Option<vello::peniko::Color>,
|
2023-02-03 21:22:39 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct SceneConfig {
|
|
|
|
// TODO: This is currently unused
|
|
|
|
pub animated: bool,
|
|
|
|
pub name: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct ExampleScene {
|
|
|
|
pub function: Box<dyn FnMut(&mut SceneBuilder, &mut SceneParams)>,
|
|
|
|
pub config: SceneConfig,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct SceneSet {
|
|
|
|
pub scenes: Vec<ExampleScene>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Args, Debug)]
|
|
|
|
/// Shared config for scene selection
|
|
|
|
pub struct Arguments {
|
|
|
|
#[arg(help_heading = "Scene Selection")]
|
2023-02-08 03:26:56 +11:00
|
|
|
#[arg(long, global(false))]
|
2023-02-03 21:22:39 +11:00
|
|
|
/// Whether to use the test scenes created by code
|
|
|
|
test_scenes: bool,
|
|
|
|
#[arg(help_heading = "Scene Selection", global(false))]
|
|
|
|
/// The svg files paths to render
|
|
|
|
svgs: Option<Vec<PathBuf>>,
|
2023-03-03 09:29:06 +11:00
|
|
|
#[arg(help_heading = "Render Parameters")]
|
2023-03-04 09:04:54 +11:00
|
|
|
#[arg(long, global(false), value_parser = parse_color)]
|
2023-03-03 09:29:06 +11:00
|
|
|
/// The base color applied as the blend background to the rasterizer.
|
|
|
|
/// Format is CSS style hexidecimal (#RGB, #RGBA, #RRGGBB, #RRGGBBAA) or
|
|
|
|
/// an SVG color name such as "aliceblue"
|
2023-03-04 09:04:54 +11:00
|
|
|
pub base_color: Option<Color>,
|
2023-02-03 21:22:39 +11:00
|
|
|
#[clap(subcommand)]
|
|
|
|
command: Option<Command>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Subcommand, Debug)]
|
|
|
|
enum Command {
|
|
|
|
/// Download SVG files for testing. By default, downloads a set of files from wikipedia
|
|
|
|
Download(Download),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Arguments {
|
|
|
|
pub fn select_scene_set(
|
|
|
|
&self,
|
2023-03-05 22:33:30 +11:00
|
|
|
#[allow(unused)] command: impl FnOnce() -> clap::Command,
|
2023-02-03 21:22:39 +11:00
|
|
|
) -> Result<Option<SceneSet>> {
|
|
|
|
if let Some(command) = &self.command {
|
|
|
|
command.action()?;
|
|
|
|
Ok(None)
|
|
|
|
} else {
|
2023-03-05 22:33:30 +11:00
|
|
|
// There is no file access on WASM, and on Android we haven't set up the assets
|
|
|
|
// directory.
|
|
|
|
// TODO: Upload the assets directory on Android
|
|
|
|
// Therefore, only render the `test_scenes` (including one SVG example)
|
|
|
|
#[cfg(any(target_arch = "wasm32", target_os = "android"))]
|
2023-02-03 21:22:39 +11:00
|
|
|
return Ok(Some(test_scenes()));
|
2023-03-05 22:33:30 +11:00
|
|
|
#[cfg(not(any(target_arch = "wasm32", target_os = "android")))]
|
2023-02-03 21:22:39 +11:00
|
|
|
if self.test_scenes {
|
|
|
|
Ok(test_scenes())
|
|
|
|
} else if let Some(svgs) = &self.svgs {
|
|
|
|
scene_from_files(&svgs)
|
|
|
|
} else {
|
|
|
|
default_scene(command)
|
|
|
|
}
|
|
|
|
.map(Some)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Command {
|
|
|
|
fn action(&self) -> Result<()> {
|
|
|
|
match self {
|
|
|
|
Command::Download(download) => download.action(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-03-04 09:04:54 +11:00
|
|
|
|
|
|
|
fn parse_color(s: &str) -> Result<Color> {
|
|
|
|
Color::parse(s).ok_or(anyhow!("'{s}' is not a valid color"))
|
|
|
|
}
|