use bevy::{ color::Color, ecs::system::EntityCommands, prelude::{ Component, Entity }, ui::{ node_bundles::ImageBundle, AlignSelf, JustifyContent, PositionType, Val }, }; use sickle_ui::{ prelude::{ LabelConfig, UiContainerExt as _, UiLabelExt as _ }, ui_builder::{ UiBuilder, UiRoot }, ui_commands::SetTextExt, ui_style::{ generated::{ SetAlignSelfExt as _, SetHeightExt as _, SetJustifyContentExt as _, SetPositionTypeExt as _, SetTopExt as _, SetWidthExt as _, }, manual::SetImageExt as _, }, }; use crate::plugins::ui::set::{ SetFont, SetPosition }; /// BannerWidget #[derive(Component)] pub(crate) struct BannerWidget; /// BannerLabel /// A marker component used internally to initialize the label font. #[derive(Component)] struct BannerLabel; /// BannerWidgetConfig pub struct BannerWidgetConfig { pub label: String, pub font: String, pub font_size: f32, } impl BannerWidgetConfig { pub fn from( label: impl Into, font: impl Into, font_size: impl Into ) -> Self { Self { label: label.into(), font: font.into(), font_size: font_size.into(), } } } pub trait UiBannerWidgetExt { fn banner_widget(&mut self, config: BannerWidgetConfig) -> UiBuilder<'_, Entity>; } impl UiBannerWidgetExt for UiBuilder<'_, UiRoot> { fn banner_widget(&mut self, config: BannerWidgetConfig) -> UiBuilder<'_, Entity> { self.container((ImageBundle::default(), BannerWidget), |banner| { banner .style() .position_type(PositionType::Absolute) // Center the children (the label) horizontally. .justify_content(JustifyContent::Center) .width(Val::Px(100.0)) .height(Val::Px(12.0)) // Add a nice looking background image to our widget. .image("ui/label_gradient_transparent.png".into()); // And we'll want a customizable label on the banner. let mut label = banner.label(LabelConfig::default()); label .style() // Align the label relative to the top of the banner. .align_self(AlignSelf::Start) // Move us a few pixels down so we look nice relative to our font. .top(Val::Px(3.0)); // We would like to set a default text style without having to pass in the AssetServer. label .entity_commands() .insert(BannerLabel) .set_text(config.label, None) .font(config.font, config.font_size, Color::rgb(1.0, 1.0, 1.0)); }) } } /// BannerWidgetCommands /// /// An extension trait that exposes the SetFont command. pub trait BannerWidgetCommands<'a> { fn font( &'a mut self, font: impl Into, size: f32, color: Color ) -> &mut EntityCommands<'a>; fn set_position(&'a mut self, x: f32, y: f32) -> &mut EntityCommands<'a>; } impl<'a> BannerWidgetCommands<'a> for EntityCommands<'a> { fn font( &'a mut self, font: impl Into, size: f32, color: Color ) -> &mut EntityCommands<'a> { self.add(SetFont(font.into(), size, color)) } fn set_position(&'a mut self, x: f32, y: f32) -> &mut EntityCommands<'a> { // We insert our custom command into the entity commands queue. self.add(SetPosition(x, y)) } }