Skip to content
Snippets Groups Projects
timing.rs 2.25 KiB
Newer Older
Louis's avatar
Louis committed
use std::time::Duration;

use bevy::prelude::*;
use iyes_loopless::prelude::{AppLooplessStateExt, ConditionSet};

use crate::system::flow::AppState;

#[derive(Debug)]
pub struct GlobalTimer {
	internal: Duration,
}

impl Default for GlobalTimer {
	fn default() -> Self {
		GlobalTimer {
			internal: Duration::ZERO,
		}
	}
}

impl GlobalTimer {
	const GOAL: Duration = Duration::from_secs(10);
	pub fn tick(&mut self, dt: Duration) {
		self.internal += dt;
	}
	pub fn is_triggered(&self) -> bool {
		self.internal >= Self::GOAL
	}
	pub fn settle(&mut self) {
		while self.internal >= Self::GOAL {
			self.internal -= Self::GOAL
		}
	}
	pub fn percent_complete(&self) -> f32 {
		self.internal.as_secs_f32() / Self::GOAL.as_secs_f32()
	}
}

pub fn tick_global_timer(time: Res<Time>, mut timer: ResMut<GlobalTimer>) {
	timer.settle();
	timer.tick(time.delta());
}

#[derive(Copy, Clone, Default, Component)]
pub struct GlobalTimerUi;
pub fn spawn_global_timer_ui(mut commands: Commands, timer: Res<GlobalTimer>) {
	commands
		.spawn_bundle(NodeBundle {
			style: Style {
				size: Size::new(Val::Auto, Val::Px(25.0)),
				position_type: PositionType::Absolute,
				position: UiRect::new(
					Val::Px(0.0),
					Val::Percent((1.0 - timer.percent_complete()) * 100.0),
					Val::Auto,
					Val::Px(0.0),
				),
				..Default::default()
			},
			color: Color::ALICE_BLUE.into(),
			..Default::default()
		})
		.insert(GlobalTimerUi);
}

pub fn update_global_timer_ui(
	timer: Res<GlobalTimer>,
	mut query: Query<&mut Style, With<GlobalTimerUi>>,
) {
	for mut style in &mut query {
		style.position.right = Val::Percent((1.0 - timer.percent_complete()) * 100.0);
	}
}

pub fn remove_global_timer_ui(mut commands: Commands, query: Query<Entity, With<GlobalTimerUi>>) {
	for entity in &query {
		commands.entity(entity).despawn_recursive();
	}
}

pub struct TimingPlugin;
impl Plugin for TimingPlugin {
	fn build(&self, app: &mut App) {
		app.init_resource::<GlobalTimer>()
			.add_system_to_stage(CoreStage::First, tick_global_timer)
			.add_enter_system(AppState::InGame, spawn_global_timer_ui)
			.add_system_set(
				ConditionSet::new()
					.run_in_state(AppState::InGame)
					.with_system(update_global_timer_ui)
					.into(),
			)
			.add_exit_system(AppState::InGame, remove_global_timer_ui);
	}
}