use bevy_ecs::{component::Mutable, prelude::*, reflect::ReflectComponent};
use bevy_reflect::{Reflect, TypePath};
use bevy_time::{Time, Timer, TimerMode};
use core::time::Duration;
use crate::variable_property::VariableProperty;
#[derive(Reflect)]
pub struct IntervalProperty<T: VariableProperty + TypePath> {
property: T,
timer: Timer,
curr: Option<T::Output>,
}
impl<T: VariableProperty + TypePath> IntervalProperty<T> {
pub fn tick_value(&mut self, delta: Duration) -> Option<&T::Output> {
self.timer.tick(delta);
if self.timer.just_finished() {
self.curr = Some(self.property.get_value());
self.get_curr_value()
} else {
None
}
}
pub fn get_curr_value(&self) -> Option<&T::Output> {
self.curr.as_ref()
}
}
impl<T: VariableProperty + TypePath> IntervalProperty<T> {
pub fn new(property: T, interval: f32) -> Self {
Self {
property,
timer: Timer::from_seconds(interval, TimerMode::Repeating),
curr: None,
}
}
pub fn new_with_initial_value(property: T, interval: f32, init: T::Output) -> Self {
Self {
property,
timer: Timer::from_seconds(interval, TimerMode::Repeating),
curr: Some(init),
}
}
pub fn new_with_generated_inital_value(property: T, interval: f32) -> Self {
let curr = Some(property.get_value());
Self {
property,
timer: Timer::from_seconds(interval, TimerMode::Repeating),
curr,
}
}
}
impl<T: VariableProperty + Default + TypePath> Default for IntervalProperty<T> {
fn default() -> Self {
Self {
property: Default::default(),
timer: Timer::new(Duration::from_secs_f32(1.0), TimerMode::Repeating),
curr: None,
}
}
}
pub trait IntervalPropertyComponent:
AsMut<IntervalProperty<Self::Property>> + Component<Mutability = Mutable> + Sized
{
type Property: VariableProperty + TypePath;
type TargetComponent: Component<Mutability = Mutable>;
fn update(
new_value: &<Self::Property as VariableProperty>::Output,
target: &mut Self::TargetComponent,
);
fn system(
mut query: Query<(
&mut Self,
&mut Self::TargetComponent,
Option<&PauseIntervalProperty<Self>>,
)>,
time: Res<Time>,
) {
let delta = time.delta();
for (mut source, mut target, maybe_pause) in query.iter_mut() {
if let Some(new_value) =
AsMut::<IntervalProperty<Self::Property>>::as_mut(&mut *source).tick_value(delta)
{
if maybe_pause.is_none() {
Self::update(new_value, target.as_mut());
}
}
}
}
}
#[derive(Default)]
struct PhantomDataWrapper<T: IntervalPropertyComponent>(std::marker::PhantomData<T>);
impl<T: IntervalPropertyComponent> PhantomDataWrapper<T> {
pub fn new() -> Self {
Self(std::marker::PhantomData)
}
}
impl<T: IntervalPropertyComponent> TypePath for PhantomDataWrapper<T> {
fn type_path() -> &'static str {
"bevy_variable_property::PhantomDataWrapper"
}
fn short_type_path() -> &'static str {
"PhantomDataWrapper"
}
}
#[derive(Component, Reflect)]
#[reflect(Component)]
pub struct PauseIntervalProperty<T: IntervalPropertyComponent>(PhantomDataWrapper<T>);
impl<T: IntervalPropertyComponent> Default for PauseIntervalProperty<T> {
fn default() -> Self {
Self(PhantomDataWrapper::<T>::new())
}
}