use bevy::{ prelude::*, render::render_resource::Extent3d, transform::components::Transform, window::PrimaryWindow, }; use clap::{Args, Parser, Subcommand}; use studio::headless::{start_headless, HeadlessMode}; #[derive(Parser)] #[command(name = "StorytellerStudioHeadless")] #[command(author = "The Storyteller Team")] #[command(version = "1.0")] #[command( about = "Executable for Storyteller Studio Headless. Allows you to render frames to images." )] #[command(propagate_version = true)] struct StudioArgs { #[command(subcommand)] subcommand: Subcommands, } #[derive(Subcommand)] enum Subcommands { Scene { scene_dir: String, #[arg(long)] orbit: bool, #[arg(long, value_parser = clap::value_parser!(f32))] orbit_radius: Option, #[arg(long, value_parser = clap::value_parser!(f32))] orbit_speed: Option, #[arg(long, short)] output_dir: Option, #[arg(long)] skybox: Option, #[arg(long = "res", value_parser = extent3d_parser)] output_resolution: Option, #[arg(long, value_parser = clap::value_parser!(u32).range(1..))] fps: Option, #[arg(long, value_parser = clap::value_parser!(u32).range(1..))] frames: Option, }, Bvh { bvh_dir: String, #[arg(long, short = 'o', short)] out: Option, #[arg(long)] skybox: Option, #[arg(long = "res", value_parser = extent3d_parser)] output_resolution: Option, #[arg(long, value_parser = clap::value_parser!(u32).range(1..))] fps: Option, #[arg(long, value_parser = clap::value_parser!(u32).range(1..))] frames: Option, }, Mixamo { mixamo_dir: String, #[arg(long, short = 'o', short)] out: Option, #[arg(long)] skybox: Option, #[arg(long = "res", value_parser = extent3d_parser)] output_resolution: Option, #[arg(long, value_parser = clap::value_parser!(u32).range(1..))] fps: Option, #[arg(long, value_parser = clap::value_parser!(u32).range(1..))] frames: Option, }, } #[derive(Args, Clone)] struct CommonArgs {} fn main() { let args = StudioArgs::parse(); let mut app = match args.subcommand { Subcommands::Scene { scene_dir, orbit, orbit_speed, orbit_radius, skybox, output_dir, output_resolution, fps, frames, } => { let output_dir = output_dir.unwrap_or("./screen_shots/".to_string()); let output_res = output_resolution.unwrap_or(Extent3d { width: 1280, height: 720, depth_or_array_layers: 1, }); let fps = fps.unwrap_or(24); let frames = frames.unwrap_or(30); let skybox = skybox.unwrap_or("gum_trees_4k".to_string()); let mut app = start_headless( HeadlessMode::Scene(scene_dir, skybox), fps, &output_dir, frames, output_res, ); let orbit_speed = orbit_speed.unwrap_or(1.0); let orbit_radius = orbit_radius.unwrap_or(8.0); if orbit { app.insert_resource(OrbitSettings { radius: orbit_radius, speed: orbit_speed, }) .add_systems(Update, orbit_scene); } app } Subcommands::Bvh { bvh_dir, skybox, out: output_dir, output_resolution, fps, frames, } => { let output_dir = output_dir.unwrap_or("./screen_shots/".to_string()); let output_res = output_resolution.unwrap_or(Extent3d { width: 1280, height: 720, depth_or_array_layers: 1, }); let fps = fps.unwrap_or(24); let frames = frames.unwrap_or(u32::MAX); let skybox = skybox.unwrap_or("gum_trees_4k".to_string()); start_headless( HeadlessMode::Bvh(bvh_dir, skybox), fps, &output_dir, frames, output_res, ) } Subcommands::Mixamo { mixamo_dir, out, skybox, output_resolution, fps, frames, } => { let output_dir = out.unwrap_or("./screen_shots/".to_string()); let output_res = output_resolution.unwrap_or(Extent3d { width: 1280, height: 720, depth_or_array_layers: 1, }); let fps = fps.unwrap_or(24); let frames = frames.unwrap_or(u32::MAX); let skybox = skybox.unwrap_or("gum_trees_4k".to_string()); start_headless( HeadlessMode::Mixamo(mixamo_dir, skybox), fps, &output_dir, frames, output_res, ) } }; app.run(); } #[derive(Resource)] struct OrbitSettings { radius: f32, speed: f32, } fn orbit_scene( mut camera: Query<&mut Transform, With>, orbit_settings: Res, time: Res