From 9fab001f15169d6e219cbccc10629f9242f300cd Mon Sep 17 00:00:00 2001 From: tevans-3 Date: Sat, 22 Aug 2026 16:16:50 -0600 Subject: [PATCH 1/7] split refactor into separate pr --- examples/2d/2d_shapes.rs | 8 ++-- examples/helpers/checkbox.rs | 75 +++++++++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/examples/2d/2d_shapes.rs b/examples/2d/2d_shapes.rs index d750dad0dc560..0c0f4c8338b79 100644 --- a/examples/2d/2d_shapes.rs +++ b/examples/2d/2d_shapes.rs @@ -19,7 +19,7 @@ use bevy::{ feathers::{controls::FeathersCheckbox, theme::UiTheme, FeathersPlugins}, ui_widgets::{checkbox_self_update, ValueChange}, }; -use checkbox::feathers_option_checkbox; +use checkbox::{feathers_option_checkbox, IsChecked}; use scene::{bottom_left_scene, top_left_scene}; #[path = "../helpers/checkbox.rs"] @@ -172,15 +172,15 @@ fn spawn_buttons(commands: &mut Commands) { commands.spawn_scene(bsn! { bottom_left_scene() Children [ - feathers_option_checkbox("ROTATE", Some(CheckboxInput::Rotation)), - feathers_option_checkbox("WIREFRAME", Some(CheckboxInput::Wireframe)), + feathers_option_checkbox("ROTATE", Some(CheckboxInput::Rotation), IsChecked(false)), + feathers_option_checkbox("WIREFRAME", Some(CheckboxInput::Wireframe), IsChecked(false)), ] }); } else { commands.spawn_scene(bsn! { top_left_scene() // so the user can immediately see the control in browser w/o scrolling Children [ - feathers_option_checkbox("ROTATE", Some(CheckboxInput::Rotation)), + feathers_option_checkbox("ROTATE", Some(CheckboxInput::Rotation), IsChecked(false)), ] }); } diff --git a/examples/helpers/checkbox.rs b/examples/helpers/checkbox.rs index 1184cd4974c16..f4994186e5f0d 100644 --- a/examples/helpers/checkbox.rs +++ b/examples/helpers/checkbox.rs @@ -4,19 +4,54 @@ use bevy::{ feathers::{controls::FeathersCheckbox, display::caption}, picking::hover::Hovered, prelude::*, + ui::Checked, ui_widgets::checkbox_self_update, }; -/// Creates a single feathers checkbox that allows configuration of a setting. -/// -/// Examples that use this to create a checkbox should handle its `ValueChange` events. -/// If there is a need to identify the checkbox that originated the value change, -/// query which `checkbox_identifier` with the `FeathersCheckbox` is the value change's -/// source entity. -pub fn feathers_option_checkbox( - option_name: &str, - checkbox_identifier: Option, -) -> Box +/// A newtype bool wrapper to indicate a widget's checked status. +pub struct IsChecked(pub bool); + +/// Helper to create a single checked feathers checkbox. +fn checked_checkbox(option_name: &str, checkbox_identifier: Option) -> Box +where + T: Template + Clone + Default + Send + Sync + Unpin + 'static, +{ + if let Some(identifier) = checkbox_identifier { + Box::new(bsn! { + Node { + align_items: AlignItems::Center, + column_gap: px(5), + } + Children [ + @FeathersCheckbox { + @caption: bsn! { caption(option_name) } + } + Checked + Hovered::default() + template_value(identifier) + on(checkbox_self_update) + ] + }) + } else { + Box::new(bsn! { + Node { + align_items: AlignItems::Center, + column_gap: px(5), + } + Children [ + @FeathersCheckbox { + @caption: bsn! { caption(option_name) } + } + Checked + Hovered::default() + on(checkbox_self_update) + ] + }) + } +} + +/// Helper to create a single unchecked feathers checkbox. +fn unchecked_checkbox(option_name: &str, checkbox_identifier: Option) -> Box where T: Template + Clone + Default + Send + Sync + Unpin + 'static, { @@ -51,3 +86,23 @@ where }) } } + +/// Creates a single feathers checkbox that allows configuration of a setting. +/// +/// Examples that use this to create a checkbox should handle its `ValueChange` events. +/// If there is a need to identify the checkbox that originated the value change, +/// query which `checkbox_identifier` with the `FeathersCheckbox` is the value change's +/// source entity. +pub fn feathers_option_checkbox( + option_name: &str, + checkbox_identifier: Option, + status: IsChecked, +) -> Box +where + T: Template + Clone + Default + Send + Sync + Unpin + 'static, +{ + match status { + IsChecked(true) => checked_checkbox(option_name, checkbox_identifier), + IsChecked(false) => unchecked_checkbox(option_name, checkbox_identifier), + } +} From f651a9bb2007b4748dd561a4e00b854a380049db Mon Sep 17 00:00:00 2001 From: tevans-3 Date: Sat, 22 Aug 2026 16:48:25 -0600 Subject: [PATCH 2/7] rebase --- examples/3d/3d_shapes.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/3d/3d_shapes.rs b/examples/3d/3d_shapes.rs index 5edb6c777f3cc..778a21c1a9b70 100644 --- a/examples/3d/3d_shapes.rs +++ b/examples/3d/3d_shapes.rs @@ -261,6 +261,7 @@ fn uv_debug_texture() -> Image { fn toggle_wireframe( mut wireframe_config: ResMut, keyboard: Res>, +/// Spawns the control widgets in the top left corner of the screen. ) { if keyboard.just_pressed(KeyCode::Space) { wireframe_config.global = !wireframe_config.global; From 394e4a2122e4d2b4642551f780d025e2a63a1d50 Mon Sep 17 00:00:00 2001 From: tevans-3 Date: Sat, 22 Aug 2026 16:59:38 -0600 Subject: [PATCH 3/7] remove comment from 3d_shapes --- examples/3d/3d_shapes.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/3d/3d_shapes.rs b/examples/3d/3d_shapes.rs index 778a21c1a9b70..5edb6c777f3cc 100644 --- a/examples/3d/3d_shapes.rs +++ b/examples/3d/3d_shapes.rs @@ -261,7 +261,6 @@ fn uv_debug_texture() -> Image { fn toggle_wireframe( mut wireframe_config: ResMut, keyboard: Res>, -/// Spawns the control widgets in the top left corner of the screen. ) { if keyboard.just_pressed(KeyCode::Space) { wireframe_config.global = !wireframe_config.global; From ee41b5c7fcd53a7ddf10337c3bdde2778d6d8a47 Mon Sep 17 00:00:00 2001 From: tevans-3 Date: Mon, 24 Aug 2026 11:21:45 -0600 Subject: [PATCH 4/7] condense checkbox helper into one function --- examples/helpers/checkbox.rs | 81 ++++++++++-------------------------- 1 file changed, 21 insertions(+), 60 deletions(-) diff --git a/examples/helpers/checkbox.rs b/examples/helpers/checkbox.rs index f4994186e5f0d..16356d54475f0 100644 --- a/examples/helpers/checkbox.rs +++ b/examples/helpers/checkbox.rs @@ -11,47 +11,26 @@ use bevy::{ /// A newtype bool wrapper to indicate a widget's checked status. pub struct IsChecked(pub bool); -/// Helper to create a single checked feathers checkbox. -fn checked_checkbox(option_name: &str, checkbox_identifier: Option) -> Box -where - T: Template + Clone + Default + Send + Sync + Unpin + 'static, -{ - if let Some(identifier) = checkbox_identifier { - Box::new(bsn! { - Node { - align_items: AlignItems::Center, - column_gap: px(5), - } - Children [ - @FeathersCheckbox { - @caption: bsn! { caption(option_name) } - } - Checked - Hovered::default() - template_value(identifier) - on(checkbox_self_update) - ] - }) - } else { - Box::new(bsn! { - Node { - align_items: AlignItems::Center, - column_gap: px(5), - } - Children [ - @FeathersCheckbox { - @caption: bsn! { caption(option_name) } - } - Checked - Hovered::default() - on(checkbox_self_update) - ] - }) - } +impl IsChecked { + fn checked(&self) -> bool { + match self { + IsChecked(true) => true, + IsChecked(false) => false, + } + } } -/// Helper to create a single unchecked feathers checkbox. -fn unchecked_checkbox(option_name: &str, checkbox_identifier: Option) -> Box +/// Creates a single feathers checkbox that allows configuration of a setting. +/// +/// Examples that use this to create a checkbox should handle its `ValueChange` events. +/// If there is a need to identify the checkbox that originated the value change, +/// query which `checkbox_identifier` with the `FeathersCheckbox` is the value change's +/// source entity. +pub fn feathers_option_checkbox( + option_name: &str, + checkbox_identifier: Option, + status: IsChecked, +) -> Box where T: Template + Clone + Default + Send + Sync + Unpin + 'static, { @@ -68,6 +47,7 @@ where Hovered::default() template_value(identifier) on(checkbox_self_update) + {status.checked().then(|| bsn! { Checked })} ] }) } else { @@ -82,27 +62,8 @@ where } Hovered::default() on(checkbox_self_update) + {status.checked().then(|| bsn! { Checked })} ] }) } -} - -/// Creates a single feathers checkbox that allows configuration of a setting. -/// -/// Examples that use this to create a checkbox should handle its `ValueChange` events. -/// If there is a need to identify the checkbox that originated the value change, -/// query which `checkbox_identifier` with the `FeathersCheckbox` is the value change's -/// source entity. -pub fn feathers_option_checkbox( - option_name: &str, - checkbox_identifier: Option, - status: IsChecked, -) -> Box -where - T: Template + Clone + Default + Send + Sync + Unpin + 'static, -{ - match status { - IsChecked(true) => checked_checkbox(option_name, checkbox_identifier), - IsChecked(false) => unchecked_checkbox(option_name, checkbox_identifier), - } -} +} \ No newline at end of file From 748f22ad3bfc59efd14acb9c14446838d9f1e370 Mon Sep 17 00:00:00 2001 From: tevans-3 Date: Tue, 25 Aug 2026 08:55:12 -0600 Subject: [PATCH 5/7] address comments --- examples/2d/2d_shapes.rs | 7 ++-- examples/helpers/checkbox.rs | 63 ++++++++++++++---------------------- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/examples/2d/2d_shapes.rs b/examples/2d/2d_shapes.rs index 0c0f4c8338b79..f58066a4f3bbd 100644 --- a/examples/2d/2d_shapes.rs +++ b/examples/2d/2d_shapes.rs @@ -20,7 +20,7 @@ use bevy::{ ui_widgets::{checkbox_self_update, ValueChange}, }; use checkbox::{feathers_option_checkbox, IsChecked}; -use scene::{bottom_left_scene, top_left_scene}; +use scene::top_left_scene; #[path = "../helpers/checkbox.rs"] mod checkbox; @@ -29,6 +29,7 @@ mod checkbox; mod theme; #[path = "../helpers/scene.rs"] +#[expect(dead_code, reason = "not all scenes used")] mod scene; /// Various settings for the demo. @@ -166,11 +167,11 @@ fn setup( spawn_buttons(&mut commands); } -/// Spawns the checkboxes in the bottom left corner of the screen. +/// Spawns the checkboxes in the top left corner of the screen. fn spawn_buttons(commands: &mut Commands) { if !cfg!(target_arch = "wasm32") { commands.spawn_scene(bsn! { - bottom_left_scene() + top_left_scene() Children [ feathers_option_checkbox("ROTATE", Some(CheckboxInput::Rotation), IsChecked(false)), feathers_option_checkbox("WIREFRAME", Some(CheckboxInput::Wireframe), IsChecked(false)), diff --git a/examples/helpers/checkbox.rs b/examples/helpers/checkbox.rs index 16356d54475f0..9996ac6d1b13a 100644 --- a/examples/helpers/checkbox.rs +++ b/examples/helpers/checkbox.rs @@ -11,13 +11,13 @@ use bevy::{ /// A newtype bool wrapper to indicate a widget's checked status. pub struct IsChecked(pub bool); -impl IsChecked { - fn checked(&self) -> bool { - match self { - IsChecked(true) => true, - IsChecked(false) => false, - } - } +impl IsChecked { + fn checked(&self) -> bool { + match self { + IsChecked(true) => true, + IsChecked(false) => false, + } + } } /// Creates a single feathers checkbox that allows configuration of a setting. @@ -34,36 +34,21 @@ pub fn feathers_option_checkbox( where T: Template + Clone + Default + Send + Sync + Unpin + 'static, { - if let Some(identifier) = checkbox_identifier { - Box::new(bsn! { - Node { - align_items: AlignItems::Center, - column_gap: px(5), - } - Children [ - @FeathersCheckbox { - @caption: bsn! { caption(option_name) } - } - Hovered::default() - template_value(identifier) - on(checkbox_self_update) - {status.checked().then(|| bsn! { Checked })} - ] - }) - } else { - Box::new(bsn! { - Node { - align_items: AlignItems::Center, - column_gap: px(5), + Box::new(bsn! { + Node { + align_items: AlignItems::Center, + column_gap: px(5), + } + Children [ + @FeathersCheckbox { + @caption: bsn! { caption(option_name) } } - Children [ - @FeathersCheckbox { - @caption: bsn! { caption(option_name) } - } - Hovered::default() - on(checkbox_self_update) - {status.checked().then(|| bsn! { Checked })} - ] - }) - } -} \ No newline at end of file + Hovered::default() + {checkbox_identifier.is_some().then(|| + { bsn! { template_value(checkbox_identifier.unwrap()) } + })} + on(checkbox_self_update) + {status.checked().then(|| bsn! { Checked })} + ] + }) +} From 3b7ead4511cc9d71824ff2b7c66e97c533076fa1 Mon Sep 17 00:00:00 2001 From: tevans-3 Date: Thu, 27 Aug 2026 21:57:52 -0600 Subject: [PATCH 6/7] address comments --- examples/2d/2d_shapes.rs | 23 +++++++---------------- examples/helpers/checkbox.rs | 5 +++-- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/examples/2d/2d_shapes.rs b/examples/2d/2d_shapes.rs index f58066a4f3bbd..e2313539c1620 100644 --- a/examples/2d/2d_shapes.rs +++ b/examples/2d/2d_shapes.rs @@ -169,22 +169,13 @@ fn setup( /// Spawns the checkboxes in the top left corner of the screen. fn spawn_buttons(commands: &mut Commands) { - if !cfg!(target_arch = "wasm32") { - commands.spawn_scene(bsn! { - top_left_scene() - Children [ - feathers_option_checkbox("ROTATE", Some(CheckboxInput::Rotation), IsChecked(false)), - feathers_option_checkbox("WIREFRAME", Some(CheckboxInput::Wireframe), IsChecked(false)), - ] - }); - } else { - commands.spawn_scene(bsn! { - top_left_scene() // so the user can immediately see the control in browser w/o scrolling - Children [ - feathers_option_checkbox("ROTATE", Some(CheckboxInput::Rotation), IsChecked(false)), - ] - }); - } + commands.spawn_scene(bsn! { + top_left_scene() + Children [ + feathers_option_checkbox("ROTATE", Some(CheckboxInput::Rotation), IsChecked(false)), + {(!cfg!(target_arch = "wasm32")).then(|| { bsn! { feathers_option_checkbox("WIREFRAME", Some(CheckboxInput::Wireframe), IsChecked(false)) }})} + ] + }); } fn handle_value_change_checkbox( diff --git a/examples/helpers/checkbox.rs b/examples/helpers/checkbox.rs index 9996ac6d1b13a..b4f4fd05d93c1 100644 --- a/examples/helpers/checkbox.rs +++ b/examples/helpers/checkbox.rs @@ -44,8 +44,9 @@ where @caption: bsn! { caption(option_name) } } Hovered::default() - {checkbox_identifier.is_some().then(|| - { bsn! { template_value(checkbox_identifier.unwrap()) } + { + checkbox_identifier.map(|checkbox_identifier| { + bsn! { template_value(checkbox_identifier) } })} on(checkbox_self_update) {status.checked().then(|| bsn! { Checked })} From 3b682ae87e20f2baa07b357d9b64ee7656a7500d Mon Sep 17 00:00:00 2001 From: thomas Date: Sun, 30 Aug 2026 17:32:26 -0600 Subject: [PATCH 7/7] fixed formatting issue --- examples/helpers/checkbox.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/helpers/checkbox.rs b/examples/helpers/checkbox.rs index b4f4fd05d93c1..65e052c102808 100644 --- a/examples/helpers/checkbox.rs +++ b/examples/helpers/checkbox.rs @@ -47,7 +47,8 @@ where { checkbox_identifier.map(|checkbox_identifier| { bsn! { template_value(checkbox_identifier) } - })} + }) + } on(checkbox_self_update) {status.checked().then(|| bsn! { Checked })} ]