diff --git a/examples/2d.rs b/examples/2d.rs index 4ea7848..4f4d67d 100644 --- a/examples/2d.rs +++ b/examples/2d.rs @@ -5,45 +5,21 @@ //! particle above or below the reference square. use bevy::{ - log::LogPlugin, prelude::*, render::camera::ScalingMode, sprite::{MaterialMesh2dBundle, Mesh2dHandle}, }; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.insert_resource(ClearColor(Color::BLACK)) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,2d=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — 2d".to_string(), - ..default() - }), - ..default() - }), - ) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup) - .add_systems(Update, (utils::close_on_esc, update_plane)) + let app_exit = utils::make_test_app("2d") + .add_systems(Startup, setup) + .add_systems(Update, update_plane) .run(); - - Ok(()) + app_exit.into_result() } fn setup( diff --git a/examples/activate.rs b/examples/activate.rs index a69c5c0..9ca0cce 100644 --- a/examples/activate.rs +++ b/examples/activate.rs @@ -10,44 +10,18 @@ //! [`KillAabbModifier`] to ensure the bubble particles never escape water, and //! are despawned when reaching the surface. -use bevy::{ - core_pipeline::tonemapping::Tonemapping, log::LogPlugin, prelude::*, - render::camera::ScalingMode, -}; +use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*, render::camera::ScalingMode}; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.insert_resource(ClearColor(Color::BLACK)) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,activate=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — activate".to_string(), - ..default() - }), - ..default() - }), - ) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup) - .add_systems(Update, (utils::close_on_esc, update)) + let app_exit = utils::make_test_app("activate") + .add_systems(Startup, setup) + .add_systems(Update, update) .run(); - - Ok(()) + app_exit.into_result() } #[derive(Component)] diff --git a/examples/billboard.rs b/examples/billboard.rs index e30488e..977c5fc 100644 --- a/examples/billboard.rs +++ b/examples/billboard.rs @@ -29,43 +29,18 @@ use std::f32::consts::FRAC_PI_2; -use bevy::{ - core_pipeline::tonemapping::Tonemapping, log::LogPlugin, prelude::*, render::camera::Projection, -}; +use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*, render::camera::Projection}; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.insert_resource(ClearColor(Color::BLACK)) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,billboard=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — billboard".to_string(), - ..default() - }), - ..default() - }), - ) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup) - .add_systems(Update, (utils::close_on_esc, rotate_camera)) + let app_exit = utils::make_test_app("billboard") + .add_systems(Startup, setup) + .add_systems(Update, rotate_camera) .run(); - - Ok(()) + app_exit.into_result() } fn setup( diff --git a/examples/circle.rs b/examples/circle.rs index 18b2ee5..3fa0449 100644 --- a/examples/circle.rs +++ b/examples/circle.rs @@ -5,43 +5,20 @@ use std::f32::consts::FRAC_PI_2; -use bevy::{core_pipeline::tonemapping::Tonemapping, log::LogPlugin, prelude::*}; +use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*}; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod texutils; mod utils; use texutils::make_anim_img; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.insert_resource(ClearColor(Color::BLACK)) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,circle=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — circle".to_string(), - ..default() - }), - ..default() - }), - ) - .add_systems(Update, utils::close_on_esc) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup).run(); - - Ok(()) + let app_exit = utils::make_test_app("circle") + .add_systems(Startup, setup) + .run(); + app_exit.into_result() } fn setup( diff --git a/examples/expr.rs b/examples/expr.rs index b45a954..402f681 100644 --- a/examples/expr.rs +++ b/examples/expr.rs @@ -9,41 +9,18 @@ use bevy::{ core_pipeline::{bloom::BloomSettings, tonemapping::Tonemapping}, - log::LogPlugin, prelude::*, }; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,expr=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — expr".to_string(), - ..default() - }), - ..default() - }), - ) - .add_systems(Update, utils::close_on_esc) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup).run(); - - Ok(()) + let app_exit = utils::make_test_app("expr") + .add_systems(Startup, setup) + .run(); + app_exit.into_result() } fn setup(mut commands: Commands, mut effects: ResMut>) { diff --git a/examples/firework.rs b/examples/firework.rs index 5de4adf..da1fe8b 100644 --- a/examples/firework.rs +++ b/examples/firework.rs @@ -20,41 +20,18 @@ use bevy::{ core_pipeline::{bloom::BloomSettings, tonemapping::Tonemapping}, - log::LogPlugin, prelude::*, }; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,firework=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — firework".to_string(), - ..default() - }), - ..default() - }), - ) - .add_systems(Update, utils::close_on_esc) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup).run(); - - Ok(()) + let app_exit = utils::make_test_app("firework") + .add_systems(Startup, setup) + .run(); + app_exit.into_result() } fn setup(mut commands: Commands, mut effects: ResMut>) { diff --git a/examples/force_field.rs b/examples/force_field.rs index 491665e..055c05b 100644 --- a/examples/force_field.rs +++ b/examples/force_field.rs @@ -14,36 +14,17 @@ //! to the projection on screen; however those particles are actually at a //! different depth, in front or behind the sphere. -use bevy::{core_pipeline::tonemapping::Tonemapping, log::LogPlugin, prelude::*}; +use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*}; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.insert_resource(ClearColor(Color::BLACK)) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,force_field=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — force field".to_string(), - ..default() - }), - ..default() - }), - ) - .add_plugins(HanabiPlugin); + let mut app = utils::make_test_app("force_field"); #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()) - .init_resource::() + app.init_resource::() .register_type::() .add_systems(Update, inspector::inspector_ui) .add_systems( @@ -52,10 +33,10 @@ fn main() -> Result<(), Box> { ); app.add_systems(Startup, setup) - .add_systems(Update, (utils::close_on_esc, spawn_on_click, move_repulsor)) + .add_systems(Update, (spawn_on_click, move_repulsor)) .run(); - Ok(()) + app.run().into_result() } const BALL_RADIUS: f32 = 0.05; @@ -227,7 +208,7 @@ fn setup( commands.spawn(PbrBundle { mesh: meshes.add(Cuboid::new(6., 4., 6.)), material: materials.add(StandardMaterial { - base_color: Color::linear_rgba(0., 0.7, 0., 0.3), + base_color: Color::linear_rgba(0., 0.7, 0., 0.05), unlit: true, alpha_mode: bevy::prelude::AlphaMode::Blend, ..Default::default() @@ -239,7 +220,7 @@ fn setup( commands.spawn(PbrBundle { mesh: meshes.add(Sphere { radius: 0.6 }), material: materials.add(StandardMaterial { - base_color: Color::linear_rgba(0.7, 0., 0., 0.3), + base_color: Color::linear_rgba(0.7, 0., 0., 0.2), unlit: true, alpha_mode: bevy::prelude::AlphaMode::Blend, ..Default::default() diff --git a/examples/gradient.rs b/examples/gradient.rs index da77a52..f3e2b18 100644 --- a/examples/gradient.rs +++ b/examples/gradient.rs @@ -1,42 +1,17 @@ use std::f32::consts::PI; -use bevy::{ - core_pipeline::tonemapping::Tonemapping, log::LogPlugin, prelude::*, render::view::RenderLayers, -}; +use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*, render::view::RenderLayers}; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.insert_resource(ClearColor(Color::BLACK)) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=debug,gradient=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — gradient".to_string(), - ..default() - }), - ..default() - }), - ) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup) - .add_systems(Update, (utils::close_on_esc, update)) + let app_exit = utils::make_test_app("gradient") + .add_systems(Startup, setup) + .add_systems(Update, update) .run(); - - Ok(()) + app_exit.into_result() } fn setup( diff --git a/examples/init.rs b/examples/init.rs index 02900f8..ac3e44f 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -7,44 +7,21 @@ use std::f32::consts::PI; -use bevy::{core_pipeline::tonemapping::Tonemapping, log::LogPlugin, prelude::*}; +use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*}; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; #[derive(Component)] struct RotateSpeed(pub f32); fn main() -> Result<(), Box> { - let mut app = App::default(); - app.insert_resource(ClearColor(Color::BLACK)) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,init=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — init".to_string(), - ..default() - }), - ..default() - }), - ) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup) - .add_systems(Update, (utils::close_on_esc, rotate_effect)) + let app_exit = utils::make_test_app("init") + .add_systems(Startup, setup) + .add_systems(Update, rotate_effect) .run(); - - Ok(()) + app_exit.into_result() } const COLOR: Vec4 = Vec4::new(0.7, 0.7, 1.0, 1.0); diff --git a/examples/instancing.rs b/examples/instancing.rs index e768df7..c4ef46c 100644 --- a/examples/instancing.rs +++ b/examples/instancing.rs @@ -9,13 +9,12 @@ #![allow(dead_code)] -use bevy::{core_pipeline::tonemapping::Tonemapping, log::LogPlugin, prelude::*}; +use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*}; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; use rand::Rng; mod utils; +use utils::*; #[derive(Default, Resource)] struct InstanceManager { @@ -182,33 +181,14 @@ impl InstanceManager { } } -fn main() { - let mut app = App::default(); - app.add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,instancing=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — instancing".to_string(), - ..default() - }), - ..default() - }), - ) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.insert_resource(InstanceManager::new(5, 4)) +fn main() -> Result<(), Box> { + let app_exit = utils::make_test_app("instancing") + .insert_resource(InstanceManager::new(5, 4)) .add_systems(Startup, setup) - .add_systems(Update, (utils::close_on_esc, keyboard_input_system)) + .add_systems(Update, keyboard_input_system) //.add_system(stress_test.after(keyboard_input_system)) .run(); + app_exit.into_result() } fn setup( diff --git a/examples/lifetime.rs b/examples/lifetime.rs index 43bd67e..628ea07 100644 --- a/examples/lifetime.rs +++ b/examples/lifetime.rs @@ -11,40 +11,17 @@ //! quickly, and during 2.25 seconds there's no particle, until the next burst //! spawns some more. -use bevy::{core_pipeline::tonemapping::Tonemapping, log::LogPlugin, prelude::*}; +use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*}; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.insert_resource(ClearColor(Color::BLACK)) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,lifetime=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — lifetime".to_string(), - ..default() - }), - ..default() - }), - ) - .add_systems(Update, utils::close_on_esc) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup).run(); - - Ok(()) + let app_exit = utils::make_test_app("lifetime") + .add_systems(Startup, setup) + .run(); + app_exit.into_result() } fn setup( diff --git a/examples/multicam.rs b/examples/multicam.rs index 0b0684f..15d401e 100644 --- a/examples/multicam.rs +++ b/examples/multicam.rs @@ -2,43 +2,22 @@ use std::f32::consts::FRAC_PI_2; use bevy::{ core_pipeline::tonemapping::Tonemapping, - log::LogPlugin, math::EulerRot, prelude::*, render::{camera::Viewport, view::RenderLayers}, window::WindowResized, }; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; -fn main() { - let mut app = App::default(); - app.add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,multicam=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — multicam".to_string(), - ..default() - }), - ..default() - }), - ) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup) - .add_systems(Update, (utils::close_on_esc, update_camera_viewports)) +fn main() -> Result<(), Box> { + let app_exit = utils::make_test_app("multicam") + .add_systems(Startup, setup) + .add_systems(Update, update_camera_viewports) .run(); + app_exit.into_result() } #[derive(Component)] diff --git a/examples/ordering.rs b/examples/ordering.rs index e0d5627..9d2fa43 100644 --- a/examples/ordering.rs +++ b/examples/ordering.rs @@ -11,41 +11,18 @@ //! do not overlap the bounding box of the effect itself. use bevy::{ core_pipeline::{bloom::BloomSettings, tonemapping::Tonemapping}, - log::LogPlugin, prelude::*, }; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,firework=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — ordering".to_string(), - ..default() - }), - ..default() - }), - ) - .add_systems(Update, utils::close_on_esc) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup).run(); - - Ok(()) + let app_exit = utils::make_test_app("ordering") + .add_systems(Startup, setup) + .run(); + app_exit.into_result() } /// Create the firework particle effect which will be rendered in-between other diff --git a/examples/portal.rs b/examples/portal.rs index 0663b97..7042fa9 100644 --- a/examples/portal.rs +++ b/examples/portal.rs @@ -13,41 +13,18 @@ use bevy::{ core_pipeline::{bloom::BloomSettings, tonemapping::Tonemapping}, - log::LogPlugin, prelude::*, }; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,portal=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — portal".to_string(), - ..default() - }), - ..default() - }), - ) - .add_systems(Update, utils::close_on_esc) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup).run(); - - Ok(()) + let app_exit = utils::make_test_app("portal") + .add_systems(Startup, setup) + .run(); + app_exit.into_result() } fn setup(mut commands: Commands, mut effects: ResMut>) { diff --git a/examples/random.rs b/examples/random.rs index b8119af..08f975c 100644 --- a/examples/random.rs +++ b/examples/random.rs @@ -1,40 +1,17 @@ //! Example of using random spawner params. //! Spawns a random number of particles at random times. -use bevy::{core_pipeline::tonemapping::Tonemapping, log::LogPlugin, prelude::*}; +use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*}; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.insert_resource(ClearColor(Color::BLACK)) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,random=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — random".to_string(), - ..default() - }), - ..default() - }), - ) - .add_systems(Update, utils::close_on_esc) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup).run(); - - Ok(()) + let app_exit = utils::make_test_app("random") + .add_systems(Startup, setup) + .run(); + app_exit.into_result() } fn setup( diff --git a/examples/ribbon.rs b/examples/ribbon.rs index 5c0e1d2..218af55 100644 --- a/examples/ribbon.rs +++ b/examples/ribbon.rs @@ -7,10 +7,9 @@ use bevy::{ math::vec3, }; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; // These determine the shape of the Spirograph: // https://en.wikipedia.org/wiki/Spirograph#Mathematical_basis @@ -22,24 +21,12 @@ const SHAPE_SCALE: f32 = 25.0; const LIFETIME: f32 = 2.5; const TRAIL_SPAWN_RATE: f32 = 256.0; -fn main() { - let mut app = App::default(); - app.add_plugins(DefaultPlugins.set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — ribbon".to_string(), - ..default() - }), - ..default() - })) - .add_plugins(HanabiPlugin) - .add_systems(Update, utils::close_on_esc) - .add_systems(Startup, setup) - .add_systems(Update, move_particle_effect); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.run(); +fn main() -> Result<(), Box> { + let app_exit = utils::make_test_app("ribbon") + .add_systems(Startup, setup) + .add_systems(Update, move_particle_effect) + .run(); + app_exit.into_result() } fn setup(mut commands: Commands, mut effects: ResMut>) { diff --git a/examples/spawn.rs b/examples/spawn.rs index 45d19e5..b4b99d2 100644 --- a/examples/spawn.rs +++ b/examples/spawn.rs @@ -1,17 +1,12 @@ use bevy::{ core_pipeline::tonemapping::Tonemapping, - log::LogPlugin, prelude::*, - render::{ - settings::{WgpuLimits, WgpuSettings}, - RenderPlugin, - }, + render::settings::{WgpuLimits, WgpuSettings}, }; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; /// Set this to `true` to enable WGPU downlevel constraints. This is disabled by /// default to prevent the example from failing to start on devices with a @@ -31,37 +26,11 @@ fn main() -> Result<(), Box> { wgpu_settings.constrained_limits = Some(limits); } - let mut app = App::default(); - app.insert_resource(ClearColor(Color::BLACK)) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,spawn=trace".to_string(), - ..default() - }) - .set(RenderPlugin { - render_creation: wgpu_settings.into(), - synchronous_pipeline_compilation: false, - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — spawn".to_string(), - ..default() - }), - ..default() - }), - ) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup) - .add_systems(Update, (utils::close_on_esc, update_accel)) + let app_exit = utils::make_test_app_with_settings("spawn", wgpu_settings) + .add_systems(Startup, setup) + .add_systems(Update, update_accel) .run(); - - Ok(()) + app_exit.into_result() } /// A simple marker component to identify the effect using a dynamic diff --git a/examples/spawn_on_command.rs b/examples/spawn_on_command.rs index 78cc958..4abf182 100644 --- a/examples/spawn_on_command.rs +++ b/examples/spawn_on_command.rs @@ -7,45 +7,21 @@ use bevy::{ core_pipeline::tonemapping::Tonemapping, - log::LogPlugin, math::Vec3Swizzles, prelude::*, render::camera::{Projection, ScalingMode}, }; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.insert_resource(ClearColor(Color::linear_rgb(0.1, 0.1, 0.1))) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,spawn_on_command=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — spawn on command".to_string(), - ..default() - }), - ..default() - }), - ) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup) - .add_systems(Update, (utils::close_on_esc, update)) + let app_exit = utils::make_test_app("spawn_on_command") + .add_systems(Startup, setup) + .add_systems(Update, update) .run(); - - Ok(()) + app_exit.into_result() } #[derive(Component)] @@ -79,7 +55,7 @@ fn setup( half_size: Vec2::splat(BOX_SIZE / 2.), }), material: materials.add(StandardMaterial { - base_color: Color::BLACK, + base_color: Color::linear_rgb(0.05, 0.05, 0.05), unlit: true, ..Default::default() }), diff --git a/examples/utils/mod.rs b/examples/utils/mod.rs index 3f8de14..c200820 100644 --- a/examples/utils/mod.rs +++ b/examples/utils/mod.rs @@ -1,13 +1,100 @@ #![allow(unused)] -use bevy::prelude::*; +use std::{fmt::Display, num::NonZeroU8}; +use crate::prelude::*; +use bevy::{ + log::LogPlugin, + prelude::*, + render::{settings::WgpuSettings, RenderPlugin}, +}; + +#[cfg(feature = "examples_world_inspector")] +use bevy_inspector_egui::quick::WorldInspectorPlugin; + +/// Helper system to enable closing the example application by pressing the escape key (ESC). pub fn close_on_esc(mut ev_app_exit: EventWriter, input: Res>) { if input.just_pressed(KeyCode::Escape) { ev_app_exit.send(AppExit::Success); } } +/// Calculate a log filter for the LogPlugin based on the example app name. +pub fn get_log_filters(example_name: &str) -> String { + [ + // The example app itself is at trace level so we can see everything + &format!("{}=trace", example_name), + // Default Hanabi to warn, probably don't need more + "bevy_hanabi=warn", + // Prevent HAL from dumping all naga-generated shader code in logs + "wgpu_hal::dx12::device=warn", + ] + .join(",") +} + +/// Create a test app for an example. +pub fn make_test_app(example_name: &str) -> App { + make_test_app_with_settings(example_name, WgpuSettings::default()) +} + +/// Create a test app for an example, with explicit WGPU settings. +pub fn make_test_app_with_settings(example_name: &str, wgpu_settings: WgpuSettings) -> App { + let mut app = App::default(); + app.insert_resource(ClearColor(Color::BLACK)) + .add_plugins( + DefaultPlugins + .set(LogPlugin { + level: bevy::log::Level::INFO, + filter: get_log_filters(example_name), + ..default() + }) + .set(RenderPlugin { + render_creation: wgpu_settings.into(), + synchronous_pipeline_compilation: false, + }) + .set(WindowPlugin { + primary_window: Some(Window { + title: format!("🎆 Hanabi — {}", example_name), + ..default() + }), + ..default() + }), + ) + .add_plugins(HanabiPlugin) + .add_systems(Update, close_on_esc); + + #[cfg(feature = "examples_world_inspector")] + app.add_plugins(WorldInspectorPlugin::default()); + + app +} + +/// Error struct wrapping an app error code. +#[derive(Debug)] +pub struct ExampleFailedError(pub NonZeroU8); + +impl Display for ExampleFailedError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "App terminated with error code {}", self.0.get()) + } +} + +impl std::error::Error for ExampleFailedError {} + +/// Convert an [`AppExit`] into a `Result`, for error code propagation to the OS. +pub trait AppExitIntoResult { + fn into_result(&self) -> Result<(), Box>; +} + +impl AppExitIntoResult for AppExit { + fn into_result(&self) -> Result<(), Box> { + match *self { + AppExit::Success => Ok(()), + AppExit::Error(code) => Err(Box::new(ExampleFailedError(code))), + } + } +} + pub const COLOR_RED: Color = Color::linear_rgb(1., 0., 0.); pub const COLOR_GREEN: Color = Color::linear_rgb(0., 1., 0.); pub const COLOR_BLUE: Color = Color::linear_rgb(0., 0., 1.); diff --git a/examples/visibility.rs b/examples/visibility.rs index 4feb312..b421b34 100644 --- a/examples/visibility.rs +++ b/examples/visibility.rs @@ -12,41 +12,18 @@ use std::time::Duration; -use bevy::{core_pipeline::tonemapping::Tonemapping, log::LogPlugin, prelude::*}; +use bevy::{core_pipeline::tonemapping::Tonemapping, prelude::*}; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; fn main() -> Result<(), Box> { - let mut app = App::default(); - app.insert_resource(ClearColor(Color::BLACK)) - .add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,visibility=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — visibility".to_string(), - ..default() - }), - ..default() - }), - ) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup) - .add_systems(Update, (utils::close_on_esc, update)) + let app_exit = utils::make_test_app("visibility") + .add_systems(Startup, setup) + .add_systems(Update, update) .run(); - - Ok(()) + app_exit.into_result() } fn setup( diff --git a/examples/worms.rs b/examples/worms.rs index a516fb4..a5332e0 100644 --- a/examples/worms.rs +++ b/examples/worms.rs @@ -6,40 +6,19 @@ use std::f32::consts::{FRAC_PI_2, PI}; use bevy::{ core_pipeline::{bloom::BloomSettings, tonemapping::Tonemapping}, - log::LogPlugin, math::{vec3, vec4}, prelude::*, }; use bevy_hanabi::prelude::*; -#[cfg(feature = "examples_world_inspector")] -use bevy_inspector_egui::quick::WorldInspectorPlugin; mod utils; +use utils::*; -fn main() { - let mut app = App::default(); - app.add_plugins( - DefaultPlugins - .set(LogPlugin { - level: bevy::log::Level::INFO, - filter: "bevy_hanabi=warn,worms=trace".to_string(), - ..default() - }) - .set(WindowPlugin { - primary_window: Some(Window { - title: "🎆 Hanabi — worms".to_string(), - ..default() - }), - ..default() - }), - ) - .add_systems(Update, utils::close_on_esc) - .add_plugins(HanabiPlugin); - - #[cfg(feature = "examples_world_inspector")] - app.add_plugins(WorldInspectorPlugin::default()); - - app.add_systems(Startup, setup).run(); +fn main() -> Result<(), Box> { + let app_exit = utils::make_test_app("worms") + .add_systems(Startup, setup) + .run(); + app_exit.into_result() } fn setup(