diff --git a/src/lib.rs b/src/lib.rs index 8dceba3..e0ef94c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,6 @@ #![doc = include_str!("../README.md")] -use bevy::{ - input::mouse::{MouseMotion, MouseWheel}, - prelude::*, -}; +use bevy::{input::mouse::MouseWheel, prelude::*}; /// A `Plugin` providing the systems and components required to make a ScrollView work. /// @@ -27,13 +24,14 @@ impl Plugin for ScrollViewPlugin { ( create_scroll_view, update_size, - input_mouse_pressed_move, - input_touch_pressed_move, scroll_events, + fling_update, scroll_update, ) .chain(), - ); + ) + .add_observer(on_drag) + .add_observer(on_drag_end); } } @@ -44,12 +42,21 @@ pub struct ScrollView { /// Field which control speed of the scrolling. /// Could be negative number to implement invert scroll pub scroll_speed: f32, + /// Amount of friction to apply to slow down the fling + pub friction: f32, + /// Current vertical velocity + velocity: f32, + /// Drag delta for fling + drag_delta: Option, } impl Default for ScrollView { fn default() -> Self { Self { scroll_speed: 1200.0, + friction: 4.2, + velocity: 0.0, + drag_delta: None, } } } @@ -130,26 +137,6 @@ pub fn create_scroll_view(mut q: Query<&mut Node, Added>) { } } -fn input_mouse_pressed_move( - mut motion_evr: EventReader, - mut q: Query<(&Children, &Interaction), With>, - mut content_q: Query<&mut ScrollableContent>, -) { - for evt in motion_evr.read() { - for (children, &interaction) in q.iter_mut() { - if interaction != Interaction::Pressed { - continue; - } - for child in children.iter() { - let Ok(mut scroll) = content_q.get_mut(child) else { - continue; - }; - scroll.scroll_by(evt.delta.y); - } - } - } -} - fn update_size( mut q: Query<(&Children, &ComputedNode), With>, mut content_q: Query<(&mut ScrollableContent, &ComputedNode), Changed>, @@ -172,27 +159,56 @@ fn update_size( } } -fn input_touch_pressed_move( - touches: Res, - mut q: Query<(&Children, &Interaction), With>, - mut content_q: Query<&mut ScrollableContent>, -) { - for t in touches.iter() { - let Some(touch) = touches.get_pressed(t.id()) else { - continue; - }; +#[derive(Debug, Reflect)] +struct DragDelta { + /// Sum of drag deltas since last reset + pub diff: Vec2, + /// Last time when drag_delta was added to velocity and reset + pub time: f32, +} - for (children, &interaction) in q.iter_mut() { - if interaction != Interaction::Pressed { - continue; - } - for child in children.iter() { - let Ok(mut scroll) = content_q.get_mut(child) else { - continue; - }; - scroll.scroll_by(touch.delta().y); +fn on_drag( + mut drag: Trigger>, + mut q: Query<(&mut ScrollView, &mut Children)>, + mut content_q: Query<&mut ScrollableContent>, + time: Res