docs/bevy/examples/helpers/radio.rs 2.9 K · 103 lines · raw · history

1 /// Helpers to create a basic option menu using Feathers Radio Buttons.
2 /// Using these helpers requires the `bevy_feathers` feature to be enabled.
3 use bevy::{
4 feathers::{
5 controls::FeathersRadio,
6 display::{caption, label},
7 },
8 picking::hover::Hovered,
9 prelude::*,
10 ui::Checked,
11 ui_widgets::RadioGroup,
12 };
13
14 /// A component that wraps a radio button's option value
15 #[derive(Clone, Copy, Component, Default)]
16 pub struct RadioButtonOptionValue<T>(pub T)
17 where
18 T: Clone + Default + Send + Sync + Unpin + 'static;
19
20 /// Returns a [`Node`] appropriate for the outer main UI node as a `Scene`.
21 ///
22 /// This UI is in the bottom left corner and has flex column support
23 pub fn main_ui_node_scene() -> impl Scene {
24 bsn! {
25 Node {
26 flex_direction: FlexDirection::Column,
27 position_type: PositionType::Absolute,
28 row_gap: px(6),
29 left: px(10),
30 bottom: px(10),
31 }
32 }
33 }
34
35 /// Spawns the radio buttons that allow configuration of a setting.
36 ///
37 /// The option at index `selected_option` in the `options` list is marked as selected.
38 ///
39 /// To react to changes in value, create an observer that listens to
40 /// `ValueChange<Entity>>`. Query for the value entity's `RadioButtonOptionValue`
41 /// and unwrap the new option value.
42 ///
43 /// Ensure the radio button self updates its own state by adding the
44 /// `ui_widgets::radio_self_update` observer to the app.
45 pub fn feathers_option_buttons<T>(
46 title: &'static str,
47 options: &[(T, &str)],
48 selected_option: usize,
49 ) -> impl Scene
50 where
51 T: Clone + Default + Send + Sync + Unpin + 'static,
52 {
53 let buttons = options
54 .iter()
55 .cloned()
56 .enumerate()
57 .map(|(option_index, (option_value, option_name))| {
58 feathers_option_button(option_value, option_name, option_index == selected_option)
59 })
60 .collect::<Vec<_>>();
61 // Add the parent node for the row.
62 bsn! {
63 Node {
64 align_items: AlignItems::Center,
65 column_gap: px(5),
66 }
67 RadioGroup
68 Children [
69 @label(title)
70 --
71 {buttons}
72 ]
73 }
74 }
75
76 /// Spawns a single feathers radio button that allows configuration of a setting.
77 fn feathers_option_button<T>(
78 option_value: T,
79 option_name: &str,
80 is_selected: bool,
81 ) -> Box<dyn Scene>
82 where
83 T: Clone + Default + Send + Sync + Unpin + 'static,
84 {
85 if is_selected {
86 Box::new(bsn! {
87 @FeathersRadio {
88 @caption: bsn! { @caption(option_name) }
89 }
90 Hovered
91 Checked
92 RadioButtonOptionValue<T>(option_value)
93 })
94 } else {
95 Box::new(bsn! {
96 @FeathersRadio {
97 @caption: bsn! { @caption(option_name) }
98 }
99 Hovered
100 RadioButtonOptionValue<T>(option_value)
101 })
102 }
103 }