mirror of https://github.com/wayvr-org/wayvr.git
wgui: Swipe logic works (wip)
This commit is contained in:
parent
97e6263bd1
commit
2ec9c6a8c5
|
|
@ -456,7 +456,7 @@ impl Layout {
|
|||
if event_result.can_propagate() {
|
||||
let mut params = EventParams {
|
||||
state: &self.state,
|
||||
layout: l,
|
||||
taffy_layout: l,
|
||||
alterables,
|
||||
node_id,
|
||||
style,
|
||||
|
|
|
|||
|
|
@ -26,12 +26,17 @@ pub mod rectangle;
|
|||
pub mod sprite;
|
||||
pub mod util;
|
||||
|
||||
const SWIPE_START_THRESHOLD_UNITS: f32 = 16.0;
|
||||
|
||||
pub struct WidgetData {
|
||||
hovered: DeviceBitmask,
|
||||
pressed: DeviceBitmask,
|
||||
pub scrolling_target: Vec2, // normalized, 0.0-1.0. Not used in case if overflow != scroll
|
||||
pub scrolling_cur: Vec2, // normalized, used for smooth scrolling animation
|
||||
pub scrolling_cur_prev: Vec2, // for motion interpolation while rendering between ticks
|
||||
scrolling_target: Vec2, // normalized, 0.0-1.0. Not used in case if overflow != scroll
|
||||
scrolling_cur: Vec2, // normalized, used for smooth scrolling animation
|
||||
scrolling_cur_prev: Vec2, // for motion interpolation while rendering between ticks
|
||||
press_down_start_mouse_pos: Option<Vec2>,
|
||||
swipe_running: bool,
|
||||
swipe_scroll_start: Vec2, // normalized, 0.0-1.0
|
||||
pub transform: glam::Mat4,
|
||||
pub cached_absolute_boundary: drawing::Boundary, // updated in Layout::push_event_widget
|
||||
}
|
||||
|
|
@ -124,6 +129,9 @@ impl WidgetState {
|
|||
scrolling_cur_prev: Vec2::default(),
|
||||
transform: glam::Mat4::IDENTITY,
|
||||
cached_absolute_boundary: drawing::Boundary::default(),
|
||||
press_down_start_mouse_pos: None,
|
||||
swipe_running: false,
|
||||
swipe_scroll_start: Vec2::default(),
|
||||
},
|
||||
obj,
|
||||
event_listeners: EventListenerCollection::default(),
|
||||
|
|
@ -193,7 +201,7 @@ pub struct EventParams<'a> {
|
|||
pub style: &'a taffy::Style,
|
||||
pub state: &'a LayoutState,
|
||||
pub alterables: &'a mut EventAlterables,
|
||||
pub layout: &'a taffy::Layout,
|
||||
pub taffy_layout: &'a taffy::Layout,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd)]
|
||||
|
|
@ -222,6 +230,22 @@ fn get_scroll_enabled(style: &taffy::Style) -> (bool, bool) {
|
|||
)
|
||||
}
|
||||
|
||||
const OVERFLOW_START_THRESHOLD_UNITS: f32 = 3.0; // don't show scrollbars for nearly non-scrollable lists
|
||||
|
||||
fn get_scroll_active_axis(style: &taffy::Style, taffy_layout: &taffy::Layout) -> (bool, bool) {
|
||||
let (enabled_horiz, enabled_vert) = get_scroll_enabled(style);
|
||||
if !enabled_horiz && !enabled_vert {
|
||||
return (false, false);
|
||||
}
|
||||
|
||||
let overflow = Vec2::new(taffy_layout.scroll_width(), taffy_layout.scroll_height());
|
||||
|
||||
(
|
||||
overflow.x >= OVERFLOW_START_THRESHOLD_UNITS,
|
||||
overflow.y >= OVERFLOW_START_THRESHOLD_UNITS,
|
||||
)
|
||||
}
|
||||
|
||||
pub struct ScrollbarInfo {
|
||||
// total contents size of the currently scrolling widget
|
||||
content_size: Vec2,
|
||||
|
|
@ -230,15 +254,13 @@ pub struct ScrollbarInfo {
|
|||
handle_size: Vec2,
|
||||
}
|
||||
|
||||
pub fn get_scrollbar_info(l: &taffy::Layout) -> Option<ScrollbarInfo> {
|
||||
let overflow_start_threshold_units = 3.0; // don't show scrollbars for nearly non-scrollable lists
|
||||
|
||||
let overflow = Vec2::new(l.scroll_width(), l.scroll_height());
|
||||
if overflow.x < overflow_start_threshold_units && overflow.y < overflow_start_threshold_units {
|
||||
pub fn get_scrollbar_info(taffy_layout: &taffy::Layout) -> Option<ScrollbarInfo> {
|
||||
let overflow = Vec2::new(taffy_layout.scroll_width(), taffy_layout.scroll_height());
|
||||
if overflow.x < OVERFLOW_START_THRESHOLD_UNITS && overflow.y < OVERFLOW_START_THRESHOLD_UNITS {
|
||||
return None; // not overflowing
|
||||
}
|
||||
|
||||
let content_size = Vec2::new(l.content_size.width, l.content_size.height);
|
||||
let content_size = Vec2::new(taffy_layout.content_size.width, taffy_layout.content_size.height);
|
||||
let handle_size = 1.0 - (overflow / content_size);
|
||||
|
||||
Some(ScrollbarInfo {
|
||||
|
|
@ -247,6 +269,15 @@ pub fn get_scrollbar_info(l: &taffy::Layout) -> Option<ScrollbarInfo> {
|
|||
})
|
||||
}
|
||||
|
||||
impl ScrollbarInfo {
|
||||
fn get_potential_scroll_axis_multiplier(&self, taffy_layout: &taffy::Layout) -> Vec2 {
|
||||
Vec2::new(
|
||||
self.content_size.x - taffy_layout.content_box_width(),
|
||||
self.content_size.y - taffy_layout.content_box_height(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn WidgetObj {
|
||||
pub fn get_as<T: 'static>(&self) -> Option<&T> {
|
||||
let any = self.as_any();
|
||||
|
|
@ -433,13 +464,13 @@ impl WidgetState {
|
|||
return false;
|
||||
}
|
||||
|
||||
let l = params.layout;
|
||||
let l = params.taffy_layout;
|
||||
let overflow = Vec2::new(l.scroll_width(), l.scroll_height());
|
||||
if overflow.x == 0.0 && overflow.y == 0.0 {
|
||||
return false; // not overflowing
|
||||
}
|
||||
|
||||
let Some(info) = get_scrollbar_info(params.layout) else {
|
||||
let Some(info) = get_scrollbar_info(l) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
|
@ -510,6 +541,9 @@ impl WidgetState {
|
|||
)?);
|
||||
}
|
||||
Event::MouseDown(e) => {
|
||||
self.data.press_down_start_mouse_pos = Some(e.pos);
|
||||
self.data.swipe_scroll_start = self.data.scrolling_target;
|
||||
|
||||
if hovered && self.data.set_device_pressed(e.device, true) {
|
||||
res = Some(self.invoke_listeners(
|
||||
&mut invoke_data,
|
||||
|
|
@ -519,6 +553,11 @@ impl WidgetState {
|
|||
}
|
||||
}
|
||||
Event::MouseUp(e) => {
|
||||
if self.data.swipe_running {
|
||||
self.data.swipe_running = false;
|
||||
// TODO: kinetic scroll
|
||||
}
|
||||
|
||||
if self.data.set_device_pressed(e.device, false) {
|
||||
res = Some(self.invoke_listeners(
|
||||
&mut invoke_data,
|
||||
|
|
@ -526,10 +565,50 @@ impl WidgetState {
|
|||
CallbackMetadata::MouseButton(*e),
|
||||
)?);
|
||||
}
|
||||
|
||||
self.data.press_down_start_mouse_pos = None;
|
||||
}
|
||||
Event::MouseMotion(e) => {
|
||||
let hover_state_changed = self.data.set_device_hovered(e.device, hovered);
|
||||
if let Some(start_mouse_pos) = &self.data.press_down_start_mouse_pos {
|
||||
let (active_x, active_y) =
|
||||
get_scroll_active_axis(&invoke_data.params.style, &invoke_data.params.taffy_layout);
|
||||
|
||||
if !self.data.swipe_running {
|
||||
if active_x && (e.pos.x - start_mouse_pos.x).abs() >= SWIPE_START_THRESHOLD_UNITS {
|
||||
self.data.swipe_running = true;
|
||||
}
|
||||
|
||||
if active_y && (e.pos.y - start_mouse_pos.y).abs() >= SWIPE_START_THRESHOLD_UNITS {
|
||||
self.data.swipe_running = true;
|
||||
}
|
||||
|
||||
if self.data.swipe_running {
|
||||
// Cancel eventual MousePress event so the buttons won't click
|
||||
// if we started swiping
|
||||
// TODO?
|
||||
}
|
||||
}
|
||||
|
||||
if self.data.swipe_running
|
||||
&& let Some(scrollbar_info) = get_scrollbar_info(invoke_data.params.taffy_layout)
|
||||
{
|
||||
let mouse_diff = e.pos - start_mouse_pos;
|
||||
|
||||
let mult = scrollbar_info.get_potential_scroll_axis_multiplier(invoke_data.params.taffy_layout);
|
||||
|
||||
let scroll_diff_x = if mult.x != 0.0 { -mouse_diff.x / mult.x } else { 0.0 };
|
||||
let scroll_diff_y = if mult.y != 0.0 { -mouse_diff.y / mult.y } else { 0.0 };
|
||||
|
||||
self.data.scrolling_target = (self.data.swipe_scroll_start + Vec2::new(scroll_diff_x, scroll_diff_y))
|
||||
.clamp(Vec2::splat(0.0), Vec2::splat(1.0));
|
||||
invoke_data.params.alterables.mark_tick(self.obj.get_id());
|
||||
|
||||
*invoke_data.event_result = EventResult::Consumed;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
let hover_state_changed = self.data.set_device_hovered(e.device, hovered);
|
||||
if hover_state_changed {
|
||||
if self.data.is_hovered() {
|
||||
res =
|
||||
|
|
|
|||
Loading…
Reference in New Issue