bevy-jam-6/src/theme/widget.rs
RobertoMaurizzi 495556500f
Some checks are pending
CI / Format (push) Waiting to run
CI / Docs (push) Waiting to run
CI / Clippy lints (push) Waiting to run
CI / Bevy lints (push) Waiting to run
CI / Tests (push) Waiting to run
CI / Check web (push) Waiting to run
first committ, still fighting with... a lot! 😅
2025-07-06 22:14:17 +08:00

135 lines
3.7 KiB
Rust

//! Helper functions for creating common widgets.
use std::borrow::Cow;
use bevy::{
ecs::{spawn::SpawnWith, system::IntoObserverSystem},
prelude::*,
ui::Val::*,
};
use crate::theme::{interaction::InteractionPalette, palette::*};
/// A root UI node that fills the window and centers its content.
pub fn ui_root(name: impl Into<Cow<'static, str>>) -> impl Bundle {
(
Name::new(name),
Node {
position_type: PositionType::Absolute,
width: Percent(100.0),
height: Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
flex_direction: FlexDirection::Column,
row_gap: Px(20.0),
..default()
},
// Don't block picking events for other UI roots.
Pickable::IGNORE,
)
}
/// A simple header label. Bigger than [`label`].
pub fn header(text: impl Into<String>) -> impl Bundle {
(
Name::new("Header"),
Text(text.into()),
TextFont::from_font_size(40.0),
TextColor(HEADER_TEXT),
)
}
/// A simple text label.
pub fn label(text: impl Into<String>) -> impl Bundle {
(
Name::new("Label"),
Text(text.into()),
TextFont::from_font_size(24.0),
TextColor(LABEL_TEXT),
)
}
/// A large rounded button with text and an action defined as an [`Observer`].
pub fn button<E, B, M, I>(text: impl Into<String>, action: I) -> impl Bundle
where
E: Event,
B: Bundle,
I: IntoObserverSystem<E, B, M>,
{
button_base(
text,
action,
(
Node {
width: Px(380.0),
height: Px(80.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
BorderRadius::MAX,
),
)
}
/// A small square button with text and an action defined as an [`Observer`].
pub fn button_small<E, B, M, I>(text: impl Into<String>, action: I) -> impl Bundle
where
E: Event,
B: Bundle,
I: IntoObserverSystem<E, B, M>,
{
button_base(
text,
action,
Node {
width: Px(30.0),
height: Px(30.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
)
}
/// A simple button with text and an action defined as an [`Observer`]. The button's layout is provided by `button_bundle`.
fn button_base<E, B, M, I>(
text: impl Into<String>,
action: I,
button_bundle: impl Bundle,
) -> impl Bundle
where
E: Event,
B: Bundle,
I: IntoObserverSystem<E, B, M>,
{
let text = text.into();
let action = IntoObserverSystem::into_system(action);
(
Name::new("Button"),
Node::default(),
Children::spawn(SpawnWith(|parent: &mut ChildSpawner| {
parent
.spawn((
Name::new("Button Inner"),
Button,
BackgroundColor(BUTTON_BACKGROUND),
InteractionPalette {
none: BUTTON_BACKGROUND,
hovered: BUTTON_HOVERED_BACKGROUND,
pressed: BUTTON_PRESSED_BACKGROUND,
},
children![(
Name::new("Button Text"),
Text(text),
TextFont::from_font_size(40.0),
TextColor(BUTTON_TEXT),
// Don't bubble picking events from the text up to the button.
Pickable::IGNORE,
)],
))
.insert(button_bundle)
.observe(action);
})),
)
}