70 lines
2.1 KiB
Rust
70 lines
2.1 KiB
Rust
use bevy::{
|
|
color::palettes::css::*,
|
|
ecs::{component::HookContext, world::DeferredWorld},
|
|
prelude::*,
|
|
ui::Val::*,
|
|
};
|
|
|
|
use crate::game::consumables::{Fuel, FuelChanged};
|
|
|
|
#[derive(Component)]
|
|
#[require(Label)]
|
|
#[component(on_add = FuelGauge::refresh_label)]
|
|
pub struct FuelGauge(Entity);
|
|
|
|
impl FuelGauge {
|
|
/// Default bundle for a machine's fuel gauge widget. Give it the ID of the
|
|
/// machine whose info it is displaying.
|
|
pub fn bundle(target: Entity) -> impl Bundle {
|
|
(
|
|
FuelGauge(target),
|
|
Node {
|
|
min_width: Px(20.0),
|
|
min_height: Px(10.0),
|
|
..default()
|
|
},
|
|
BackgroundColor(GREEN.into()),
|
|
Text::new("Fuel: "),
|
|
)
|
|
}
|
|
|
|
/// Observer system to update the [`FuelGauge`] widget when a machine emits a
|
|
/// [`FuelChanged`] event.
|
|
pub fn detect_fuel_change(
|
|
event: Trigger<FuelChanged>,
|
|
fuel_levels: Query<&Fuel>,
|
|
mut gauges: Query<(&FuelGauge, &mut Text)>,
|
|
) {
|
|
// Find the FuelGauge that references the same Entity as the event target.
|
|
// That gauge's `Text` is the one to update.
|
|
let (_, mut label) = gauges
|
|
.iter_mut()
|
|
.find(|(gauge, _label)| gauge.0 == event.target())
|
|
.expect("Couldn't find any fuel gauges");
|
|
|
|
let fuel = fuel_levels.get(event.target()).expect(
|
|
"Logic error: a `FuelChanged` event was targetted at an entity with no `Fuel` component.",
|
|
);
|
|
label.0 = format!("Fuel: {}", fuel.0);
|
|
}
|
|
|
|
fn refresh_label(mut world: DeferredWorld, ctx: HookContext) {
|
|
// Get the machine ID from the FuelGauge component.
|
|
let Some(machine_id) = world.get::<FuelGauge>(ctx.entity).map(|fg| fg.0) else {
|
|
panic!("Couldn't get a FuelGauge during it's on-add hook run!");
|
|
};
|
|
// and fuel level
|
|
let Some(fuel) = world.get::<Fuel>(machine_id).map(|lvl| lvl.0) else {
|
|
// TODO: Maybe don't panic and just emit a warning.
|
|
panic!("Couldn't get a Fuel for a machine during a FuelGauge on-add hook.");
|
|
};
|
|
|
|
// Get an excl ref to the Text component so we can redraw its text
|
|
let Some(mut label) = world.get_mut::<Text>(ctx.entity) else {
|
|
panic!()
|
|
};
|
|
|
|
label.0 = format!("Fuel: {}", fuel);
|
|
}
|
|
}
|