use bevy::prelude::*;
use bevy::ui::ScrollPosition;
use super::channels::Channel;
use super::spec::ChannelTransition;
use crate::protocol::style::Style;
#[derive(Component, Debug, Clone)]
pub struct ScrollTransitionInput(pub ChannelTransition);
#[derive(Component, Default)]
pub struct ScrollTransitionState {
pub(crate) target: Vec2,
x: Channel,
y: Channel,
initialized: bool,
}
impl ScrollTransitionState {
pub(crate) fn snap_to(&mut self, value: Vec2) {
self.target = value;
self.x.init(value.x);
self.y.init(value.y);
self.initialized = true;
}
}
pub fn apply_scroll_transition(ec: &mut EntityCommands, style: &Option<Style>) {
match style
.as_ref()
.and_then(|s| s.transition.as_ref())
.and_then(|t| t.for_scroll())
{
Some(spec) => {
ec.insert(ScrollTransitionInput(spec.clone()));
ec.insert_if_new(ScrollTransitionState::default());
}
None => {
ec.remove::<ScrollTransitionInput>();
ec.remove::<ScrollTransitionState>();
}
}
}
pub fn drive_scroll_transition(
time: Res<Time>,
mut query: Query<(
&ScrollTransitionInput,
&mut ScrollTransitionState,
&mut ScrollPosition,
)>,
) {
let dt = time.delta_secs();
for (input, mut state, mut pos) in &mut query {
if !state.initialized {
state.x.init(pos.0.x);
state.y.init(pos.0.y);
state.target = pos.0;
state.initialized = true;
}
let current = Vec2::new(state.x.current, state.y.current);
if pos.0 != current {
state.snap_to(pos.0);
continue;
}
let spec = &input.0;
let target = state.target;
let nx = state.x.drive(target.x, Some(spec), dt);
let ny = state.y.drive(target.y, Some(spec), dt);
if pos.0.x != nx || pos.0.y != ny {
pos.0 = Vec2::new(nx, ny);
}
}
}