Created
January 24, 2024 14:46
-
-
Save gavxin/63bdd92e38de3033aee05aed5daa77bc to your computer and use it in GitHub Desktop.
bevy ui simple ProgressBar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use bevy::{ecs::system::Command, prelude::*}; | |
pub struct ProgressBarPlugin; | |
impl Plugin for ProgressBarPlugin { | |
fn build(&self, app: &mut App) { | |
app.register_type::<ProgressBarValues>() | |
.add_systems(Update, progress_bar_system); | |
} | |
} | |
pub struct AddProgressBar { | |
pub background_image: Handle<Image>, | |
pub foreground_image: Handle<Image>, | |
pub right_to_left: bool, | |
pub values: ProgressBarValues, | |
pub style: Style, | |
pub entity: Entity, | |
} | |
impl Default for AddProgressBar { | |
fn default() -> Self { | |
Self { | |
background_image: Handle::default(), | |
foreground_image: Handle::default(), | |
right_to_left: false, | |
values: ProgressBarValues { | |
min: 0., | |
max: 100., | |
step: 1., | |
value: 100., | |
}, | |
style: Default::default(), | |
entity: Entity::PLACEHOLDER, | |
} | |
} | |
} | |
impl Command for AddProgressBar { | |
fn apply(self, world: &mut World) { | |
let percent = self.values.as_percent(); | |
let entity = if self.entity == Entity::PLACEHOLDER { | |
world.spawn_empty().id() | |
} else { | |
self.entity | |
}; | |
world | |
.entity_mut(entity) | |
.insert(( | |
self.values, | |
NodeBundle { | |
style: self.style, | |
..default() | |
}, | |
)) | |
.with_children(|builder| { | |
builder.spawn(( | |
Name::new("progress_bar_bg"), | |
ImageBundle { | |
style: Style { | |
width: Val::Percent(100.), | |
height: Val::Percent(100.), | |
..default() | |
}, | |
image: self.background_image.into(), | |
..default() | |
}, | |
)); | |
let right = if self.right_to_left { | |
Val::Px(0.) | |
} else { | |
Val::Auto | |
}; | |
let justify_content = if self.right_to_left { | |
JustifyContent::FlexEnd | |
} else { | |
JustifyContent::FlexStart | |
}; | |
builder | |
.spawn(( | |
ProgressBarForeground, | |
Name::new("progress_bar_fg"), | |
NodeBundle { | |
style: Style { | |
width: Val::Percent(percent), | |
height: Val::Percent(100.), | |
right, | |
justify_content, | |
position_type: PositionType::Absolute, | |
overflow: Overflow::clip(), | |
..default() | |
}, | |
..default() | |
}, | |
)) | |
.with_children(|builder| { | |
builder.spawn(ImageBundle { | |
image: self.foreground_image.into(), | |
..default() | |
}); | |
}); | |
}); | |
} | |
} | |
#[derive(Component)] | |
pub struct ProgressBarForeground; | |
#[derive(Component, Debug, Reflect)] | |
pub struct ProgressBarValues { | |
pub min: f32, | |
pub max: f32, | |
pub step: f32, | |
value: f32, | |
} | |
impl ProgressBarValues { | |
pub fn as_percent(&self) -> f32 { | |
100. * ((self.value - self.min) / self.step).round() * self.step / (self.max - self.min) | |
} | |
pub fn value(&self) -> f32 { | |
self.value | |
} | |
pub fn set_value(&mut self, value: f32) { | |
self.value = ((value.clamp(self.min, self.max) - self.min) / self.step).round() * self.step | |
+ self.min; | |
} | |
} | |
fn progress_bar_system( | |
mut query: Query<(&Children, &mut ProgressBarValues), Changed<ProgressBarValues>>, | |
mut foreground_query: Query<&mut Style, With<ProgressBarForeground>>, | |
) { | |
for (children, mut bar) in query.iter_mut() { | |
let value = bar.value(); | |
bar.set_value(value); | |
let width: Val = Val::Percent(bar.as_percent()); | |
for child in children.iter() { | |
if let Ok(mut style) = foreground_query.get_mut(*child) { | |
style.width = width; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment