From 6f4fbe2d7b1e2ccdb8a729132f0ebeb1ed3cc3ab Mon Sep 17 00:00:00 2001 From: panpanpro888 <77934024+panpanpro888@users.noreply.github.com> Date: Sun, 21 Dec 2025 20:07:27 +0200 Subject: [PATCH 1/4] Add command line option to choose a starting scene in the `testbed_*` examples --- examples/testbed/2d.rs | 49 ++++++++++++++++++++++++++- examples/testbed/3d.rs | 49 ++++++++++++++++++++++++++- examples/testbed/ui.rs | 76 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 171 insertions(+), 3 deletions(-) diff --git a/examples/testbed/2d.rs b/examples/testbed/2d.rs index 1751e0f152a2f..a5de249a870f6 100644 --- a/examples/testbed/2d.rs +++ b/examples/testbed/2d.rs @@ -4,13 +4,22 @@ mod helpers; +use argh::FromArgs; use bevy::prelude::*; use helpers::Next; +#[derive(FromArgs)] +/// 2d testbed +pub struct Args { + #[argh(positional)] + scene: Option, +} + fn main() { + let args: Args = argh::from_env(); + let mut app = App::new(); app.add_plugins((DefaultPlugins,)) - .init_state::() .add_systems(OnEnter(Scene::Shapes), shapes::setup) .add_systems(OnEnter(Scene::Bloom), bloom::setup) .add_systems(OnEnter(Scene::Text), text::setup) @@ -20,6 +29,16 @@ fn main() { .add_systems(Update, switch_scene) .add_systems(Update, gizmos::draw_gizmos.run_if(in_state(Scene::Gizmos))); + match args.scene { + None => app.init_state::(), + Some(Scene::Shapes) => app.insert_state(Scene::Shapes), + Some(Scene::Bloom) => app.insert_state(Scene::Bloom), + Some(Scene::Text) => app.insert_state(Scene::Text), + Some(Scene::Sprite) => app.insert_state(Scene::Sprite), + Some(Scene::SpriteSlicing) => app.insert_state(Scene::SpriteSlicing), + Some(Scene::Gizmos) => app.insert_state(Scene::Gizmos), + }; + #[cfg(feature = "bevy_ci_testing")] app.add_systems(Update, helpers::switch_scene_in_ci::); @@ -37,6 +56,34 @@ enum Scene { Gizmos, } +impl std::str::FromStr for Scene { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "shapes" => Ok(Scene::Shapes), + "bloom" => Ok(Scene::Bloom), + "text" => Ok(Scene::Text), + "sprite" => Ok(Scene::Sprite), + "spriteslicing" => Ok(Scene::SpriteSlicing), + "gizmos" => Ok(Scene::Gizmos), + _ => Err(format!( + "Scene '{}' doesn't exist. Available scenes:\n\t{}", + s, + [ + "Shapes", + "Bloom", + "Text", + "Sprite", + "SpriteSlicing", + "Gizmos" + ] + .join("\n\t") + )), + } + } +} + impl Next for Scene { fn next(&self) -> Self { match self { diff --git a/examples/testbed/3d.rs b/examples/testbed/3d.rs index 64183894865e0..afffa0205568a 100644 --- a/examples/testbed/3d.rs +++ b/examples/testbed/3d.rs @@ -4,13 +4,22 @@ mod helpers; +use argh::FromArgs; use bevy::prelude::*; use helpers::Next; +#[derive(FromArgs)] +/// 3d testbed +pub struct Args { + #[argh(positional)] + scene: Option, +} + fn main() { + let args: Args = argh::from_env(); + let mut app = App::new(); app.add_plugins((DefaultPlugins,)) - .init_state::() .add_systems(OnEnter(Scene::Light), light::setup) .add_systems(OnEnter(Scene::Bloom), bloom::setup) .add_systems(OnEnter(Scene::Gltf), gltf::setup) @@ -28,6 +37,16 @@ fn main() { .run_if(in_state(Scene::GltfCoordinateConversion)), ); + match args.scene { + None => app.init_state::(), + Some(Scene::Light) => app.insert_state(Scene::Light), + Some(Scene::Bloom) => app.insert_state(Scene::Bloom), + Some(Scene::Gltf) => app.insert_state(Scene::Gltf), + Some(Scene::Animation) => app.insert_state(Scene::Animation), + Some(Scene::Gizmos) => app.insert_state(Scene::Gizmos), + Some(Scene::GltfCoordinateConversion) => app.insert_state(Scene::GltfCoordinateConversion), + }; + #[cfg(feature = "bevy_ci_testing")] app.add_systems(Update, helpers::switch_scene_in_ci::); @@ -45,6 +64,34 @@ enum Scene { GltfCoordinateConversion, } +impl std::str::FromStr for Scene { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "light" => Ok(Scene::Light), + "bloom" => Ok(Scene::Bloom), + "gltf" => Ok(Scene::Gltf), + "animation" => Ok(Scene::Animation), + "gizmos" => Ok(Scene::Gizmos), + "gltfcoordinateconversion" => Ok(Scene::GltfCoordinateConversion), + _ => Err(format!( + "Scene '{}' doesn't exist. Available scenes:\n\t{}", + s, + [ + "Light", + "Bloom", + "Gltf", + "Animation", + "Gizmos", + "GltfCoordinateConversion" + ] + .join("\n\t") + )), + } + } +} + impl Next for Scene { fn next(&self) -> Self { match self { diff --git a/examples/testbed/ui.rs b/examples/testbed/ui.rs index edba5ce0803bc..c9786b3936154 100644 --- a/examples/testbed/ui.rs +++ b/examples/testbed/ui.rs @@ -4,10 +4,20 @@ mod helpers; +use argh::FromArgs; use bevy::prelude::*; use helpers::Next; +#[derive(FromArgs)] +/// ui testbed +pub struct Args { + #[argh(positional)] + scene: Option, +} + fn main() { + let args: Args = argh::from_env(); + let mut app = App::new(); app.add_plugins(DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { @@ -19,7 +29,6 @@ fn main() { }), ..Default::default() })) - .init_state::() .add_systems(OnEnter(Scene::Image), image::setup) .add_systems(OnEnter(Scene::Text), text::setup) .add_systems(OnEnter(Scene::Grid), grid::setup) @@ -35,6 +44,25 @@ fn main() { .add_systems(OnEnter(Scene::ViewportCoords), viewport_coords::setup) .add_systems(Update, switch_scene); + match args.scene { + None => app.init_state::(), + Some(Scene::Image) => app.insert_state(Scene::Image), + Some(Scene::Text) => app.insert_state(Scene::Text), + Some(Scene::Grid) => app.insert_state(Scene::Grid), + Some(Scene::Borders) => app.insert_state(Scene::Borders), + Some(Scene::BoxShadow) => app.insert_state(Scene::BoxShadow), + Some(Scene::TextWrap) => app.insert_state(Scene::TextWrap), + Some(Scene::Overflow) => app.insert_state(Scene::Overflow), + Some(Scene::Slice) => app.insert_state(Scene::Slice), + Some(Scene::LayoutRounding) => app.insert_state(Scene::LayoutRounding), + Some(Scene::LinearGradient) => app.insert_state(Scene::LinearGradient), + Some(Scene::RadialGradient) => app.insert_state(Scene::RadialGradient), + Some(Scene::Transformations) => app.insert_state(Scene::Transformations), + #[cfg(feature = "bevy_ui_debug")] + Some(Scene::DebugOutlines) => app.insert_state(Scene::DebugOutlines), + Some(Scene::ViewportCoords) => app.insert_state(Scene::ViewportCoords), + }; + #[cfg(feature = "bevy_ui_debug")] { app.add_systems(OnEnter(Scene::DebugOutlines), debug_outlines::setup); @@ -68,6 +96,52 @@ enum Scene { ViewportCoords, } +impl std::str::FromStr for Scene { + type Err = String; + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "image" => Ok(Scene::Image), + "text" => Ok(Scene::Text), + "grid" => Ok(Scene::Grid), + "borders" => Ok(Scene::Borders), + "boxshadow" => Ok(Scene::BoxShadow), + "textwrap" => Ok(Scene::TextWrap), + "overflow" => Ok(Scene::Overflow), + "slice" => Ok(Scene::Slice), + "layoutrounding" => Ok(Scene::LayoutRounding), + "lineargradient" => Ok(Scene::LinearGradient), + "radialgradient" => Ok(Scene::RadialGradient), + "transformations" => Ok(Scene::Transformations), + #[cfg(feature = "bevy_ui_debug")] + "debugoutlines" => Ok(Scene::DebugOutlines), + "viewportcoords" => Ok(Scene::ViewportCoords), + _ => Err(format!( + "Scene '{}' doesn't exist. Available scenes:\n\t{}", + s, + [ + "Image", + "Text", + "Grid", + "Borders", + "BoxShadow", + "TextWrap", + "Overflow", + "Slice", + "LayoutRounding", + "LinearGradient", + "RadialGradient", + "Transformations", + #[cfg(feature = "bevy_ui_debug")] + "DebugOutlines", + "ViewportCoords", + ] + .join("\n\t") + )), + } + } +} + impl Next for Scene { fn next(&self) -> Self { match self { From 2e7ee5c1c7b1c82b2fe70e2ea5c33a07962d58ec Mon Sep 17 00:00:00 2001 From: panpanpro888 <77934024+panpanpro888@users.noreply.github.com> Date: Mon, 22 Dec 2025 14:33:02 +0200 Subject: [PATCH 2/4] Simplify match statement in examples/testbed/2d.rs Co-authored-by: Bayley Foster <43776524+apekros@users.noreply.github.com> --- examples/testbed/2d.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/testbed/2d.rs b/examples/testbed/2d.rs index a5de249a870f6..c30f6a6a6ee7d 100644 --- a/examples/testbed/2d.rs +++ b/examples/testbed/2d.rs @@ -31,12 +31,7 @@ fn main() { match args.scene { None => app.init_state::(), - Some(Scene::Shapes) => app.insert_state(Scene::Shapes), - Some(Scene::Bloom) => app.insert_state(Scene::Bloom), - Some(Scene::Text) => app.insert_state(Scene::Text), - Some(Scene::Sprite) => app.insert_state(Scene::Sprite), - Some(Scene::SpriteSlicing) => app.insert_state(Scene::SpriteSlicing), - Some(Scene::Gizmos) => app.insert_state(Scene::Gizmos), + Some(scene) => app.insert_state(scene), }; #[cfg(feature = "bevy_ci_testing")] From 73331855e106501d3875c3c2adcd1190c9d378cb Mon Sep 17 00:00:00 2001 From: panpanpro888 <77934024+panpanpro888@users.noreply.github.com> Date: Mon, 22 Dec 2025 14:33:18 +0200 Subject: [PATCH 3/4] Simplify match statement in examples/testbed/ui.rs Co-authored-by: Bayley Foster <43776524+apekros@users.noreply.github.com> --- examples/testbed/ui.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/examples/testbed/ui.rs b/examples/testbed/ui.rs index c9786b3936154..f9ab140152cd1 100644 --- a/examples/testbed/ui.rs +++ b/examples/testbed/ui.rs @@ -46,21 +46,7 @@ fn main() { match args.scene { None => app.init_state::(), - Some(Scene::Image) => app.insert_state(Scene::Image), - Some(Scene::Text) => app.insert_state(Scene::Text), - Some(Scene::Grid) => app.insert_state(Scene::Grid), - Some(Scene::Borders) => app.insert_state(Scene::Borders), - Some(Scene::BoxShadow) => app.insert_state(Scene::BoxShadow), - Some(Scene::TextWrap) => app.insert_state(Scene::TextWrap), - Some(Scene::Overflow) => app.insert_state(Scene::Overflow), - Some(Scene::Slice) => app.insert_state(Scene::Slice), - Some(Scene::LayoutRounding) => app.insert_state(Scene::LayoutRounding), - Some(Scene::LinearGradient) => app.insert_state(Scene::LinearGradient), - Some(Scene::RadialGradient) => app.insert_state(Scene::RadialGradient), - Some(Scene::Transformations) => app.insert_state(Scene::Transformations), - #[cfg(feature = "bevy_ui_debug")] - Some(Scene::DebugOutlines) => app.insert_state(Scene::DebugOutlines), - Some(Scene::ViewportCoords) => app.insert_state(Scene::ViewportCoords), + Some(scene) => app.insert_state(scene), }; #[cfg(feature = "bevy_ui_debug")] From f72982d6829fa5f89aa893027d8a89a945d0e5ee Mon Sep 17 00:00:00 2001 From: panpanpro888 <77934024+panpanpro888@users.noreply.github.com> Date: Mon, 22 Dec 2025 14:33:31 +0200 Subject: [PATCH 4/4] Simplify match statement examples/testbed/3d.rs Co-authored-by: Bayley Foster <43776524+apekros@users.noreply.github.com> --- examples/testbed/3d.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/testbed/3d.rs b/examples/testbed/3d.rs index afffa0205568a..c84ac5f242530 100644 --- a/examples/testbed/3d.rs +++ b/examples/testbed/3d.rs @@ -39,12 +39,7 @@ fn main() { match args.scene { None => app.init_state::(), - Some(Scene::Light) => app.insert_state(Scene::Light), - Some(Scene::Bloom) => app.insert_state(Scene::Bloom), - Some(Scene::Gltf) => app.insert_state(Scene::Gltf), - Some(Scene::Animation) => app.insert_state(Scene::Animation), - Some(Scene::Gizmos) => app.insert_state(Scene::Gizmos), - Some(Scene::GltfCoordinateConversion) => app.insert_state(Scene::GltfCoordinateConversion), + Some(scene) => app.insert_state(scene), }; #[cfg(feature = "bevy_ci_testing")]