From a8d9c3fc42e270ee0de766653a9db7d45b7ee2d5 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 22 Apr 2020 20:01:49 +0200 Subject: [PATCH] Listen to scroll wheel (glium only) --- docs/index.html | 1 + emigui/README.md | 3 +- emigui/src/context.rs | 22 ++++++------ emigui/src/scroll_area.rs | 7 ++++ emigui/src/types.rs | 9 +++++ example_glium/src/main.rs | 73 ++++++++++++++++++++++++--------------- 6 files changed, 77 insertions(+), 38 deletions(-) diff --git a/docs/index.html b/docs/index.html index 8ed88ac3..594395c7 100644 --- a/docs/index.html +++ b/docs/index.html @@ -79,6 +79,7 @@ return { mouse_down: g_mouse_down, mouse_pos: g_mouse_pos, + // TODO: scroll_delta screen_size: { x: window.innerWidth, y: window.innerHeight }, pixels_per_point: pixels_per_point(), time: window.performance.now() / 1000.0, diff --git a/emigui/README.md b/emigui/README.md index 674a0055..dda8fc71 100644 --- a/emigui/README.md +++ b/emigui/README.md @@ -16,7 +16,8 @@ This is the core library crate Emigui. It is fully platform independent without * [ ] Scroll areas * [x] Vertical scrolling * [ ] Horizontal scrolling - * [ ] Scroll-wheel input + * [x] Scroll-wheel input + * [ ] Scroll-wheel input in web verions * [x] Drag background to scroll * [ ] Kinetic scrolling * [ ] Menu bar (File, Edit, etc) diff --git a/emigui/src/context.rs b/emigui/src/context.rs index c863ff1f..7444fa61 100644 --- a/emigui/src/context.rs +++ b/emigui/src/context.rs @@ -125,19 +125,21 @@ impl Context { } } - pub fn interact(&self, layer: Layer, rect: Rect, interaction_id: Option) -> InteractInfo { - let mut memory = self.memory.lock(); - let input = &self.input; - - let hovered = if let Some(mouse_pos) = input.mouse_pos { - rect.contains(mouse_pos) && layer == memory.layer_at(mouse_pos) + pub fn contains_mouse_pos(&self, layer: Layer, rect: &Rect) -> bool { + if let Some(mouse_pos) = self.input.mouse_pos { + rect.contains(mouse_pos) && layer == self.memory.lock().layer_at(mouse_pos) } else { false - }; + } + } + pub fn interact(&self, layer: Layer, rect: Rect, interaction_id: Option) -> InteractInfo { + let hovered = self.contains_mouse_pos(layer, &rect); + + let mut memory = self.memory.lock(); let active = interaction_id.is_some() && memory.active_id == interaction_id; - if input.mouse_pressed { + if self.input.mouse_pressed { if hovered && interaction_id.is_some() { if memory.active_id.is_some() { // Already clicked something else this frame @@ -164,14 +166,14 @@ impl Context { active: false, } } - } else if input.mouse_released { + } else if self.input.mouse_released { InteractInfo { rect, hovered, clicked: hovered && active, active, } - } else if input.mouse_down { + } else if self.input.mouse_down { InteractInfo { rect, hovered: hovered && active, diff --git a/emigui/src/scroll_area.rs b/emigui/src/scroll_area.rs index 206c7891..7ccf9098 100644 --- a/emigui/src/scroll_area.rs +++ b/emigui/src/scroll_area.rs @@ -68,6 +68,13 @@ impl ScrollArea { state.offset.y -= ctx.input.mouse_move.y; } + // TODO: check that nothing else is being inteacted with + if ctx.contains_mouse_pos(outer_region.layer, &outer_rect) + && ctx.memory.lock().active_id.is_none() + { + state.offset.y -= ctx.input.scroll_delta.y; + } + let show_scroll = content_size.y > inner_size.y; if show_scroll { let corner_radius = scroll_bar_width / 2.0; diff --git a/emigui/src/types.rs b/emigui/src/types.rs index 513926c1..3d26e809 100644 --- a/emigui/src/types.rs +++ b/emigui/src/types.rs @@ -8,7 +8,9 @@ use crate::{ // ---------------------------------------------------------------------------- /// What the integration gives to the gui. +/// All coordinates in emigui is in point/logical coordinates. #[derive(Clone, Copy, Debug, Default, Deserialize)] +#[serde(default)] pub struct RawInput { /// Is the button currently down? pub mouse_down: bool, @@ -16,6 +18,9 @@ pub struct RawInput { /// Current position of the mouse in points. pub mouse_pos: Option, + /// How many pixels the user scrolled + pub scroll_delta: Vec2, + /// Size of the screen in points. pub screen_size: Vec2, @@ -46,6 +51,9 @@ pub struct GuiInput { /// How much the mouse moved compared to last frame, in points. pub mouse_move: Vec2, + /// How many pixels the user scrolled + pub scroll_delta: Vec2, + /// Size of the screen in points. pub screen_size: Vec2, @@ -68,6 +76,7 @@ impl GuiInput { mouse_released: last.mouse_down && !new.mouse_down, mouse_pos: new.mouse_pos, mouse_move, + scroll_delta: new.scroll_delta, screen_size: new.screen_size, pixels_per_point: new.pixels_per_point, time: new.time, diff --git a/example_glium/src/main.rs b/example_glium/src/main.rs index abbd41a7..28416a4e 100644 --- a/example_glium/src/main.rs +++ b/example_glium/src/main.rs @@ -20,6 +20,14 @@ fn main() { let context = glutin::ContextBuilder::new(); let display = glium::Display::new(window, context, &events_loop).unwrap(); + display + .gl_window() + .set_inner_size(glutin::dpi::LogicalSize { + width: 1200.0, + height: 800.0, + }); + display.gl_window().set_position((16, 32).into()); // Useful when debugging and constantly restarting it + let pixels_per_point = display.gl_window().get_hidpi_factor() as f32; let mut emigui = Emigui::new(pixels_per_point); @@ -54,34 +62,44 @@ fn main() { } raw_input.time = start_time.elapsed().as_nanos() as f64 * 1e-9; + raw_input.scroll_delta = vec2(0.0, 0.0); - events_loop.poll_events(|event| { - match event { - glutin::Event::WindowEvent { event, .. } => match event { - glutin::WindowEvent::CloseRequested => quit = true, + events_loop.poll_events(|event| match event { + glutin::Event::WindowEvent { event, .. } => match event { + glutin::WindowEvent::CloseRequested => quit = true, - glutin::WindowEvent::Resized(glutin::dpi::LogicalSize { width, height }) => { - raw_input.screen_size = vec2(width as f32, height as f32); + glutin::WindowEvent::Resized(glutin::dpi::LogicalSize { width, height }) => { + raw_input.screen_size = vec2(width as f32, height as f32); + } + glutin::WindowEvent::MouseInput { state, .. } => { + raw_input.mouse_down = state == glutin::ElementState::Pressed; + } + glutin::WindowEvent::CursorMoved { position, .. } => { + raw_input.mouse_pos = Some(pos2(position.x as f32, position.y as f32)); + } + glutin::WindowEvent::KeyboardInput { input, .. } => { + if input.virtual_keycode == Some(glutin::VirtualKeyCode::Q) + && input.modifiers.logo + { + quit = true; } - glutin::WindowEvent::MouseInput { state, .. } => { - raw_input.mouse_down = state == glutin::ElementState::Pressed; - } - glutin::WindowEvent::CursorMoved { position, .. } => { - raw_input.mouse_pos = Some(pos2(position.x as f32, position.y as f32)); - } - glutin::WindowEvent::KeyboardInput { input, .. } => { - if input.virtual_keycode == Some(glutin::VirtualKeyCode::Q) - && input.modifiers.logo - { - quit = true; + } + glutin::WindowEvent::MouseWheel { delta, .. } => { + match delta { + glutin::MouseScrollDelta::LineDelta(x, y) => { + raw_input.scroll_delta = vec2(x, y) * 24.0; + } + glutin::MouseScrollDelta::PixelDelta(delta) => { + // Actually point delta + raw_input.scroll_delta = vec2(delta.x as f32, delta.y as f32); } } - _ => { - // dbg!(event); - } - }, - _ => (), - } + } + _ => { + // dbg!(event); + } + }, + _ => (), }); emigui.new_frame(raw_input); @@ -93,14 +111,15 @@ fn main() { quit = true; } - Window::new("Example APP") - .default_pos(pos2(200.0, 100.0)) + Window::new("Examples") + .default_pos(pos2(100.0, 100.0)) + .default_size(vec2(300.0, 400.0)) .show(region.ctx(), |region| { example_app.ui(region); }); Window::new("Emigui settings") - .default_pos(pos2(200.0, 500.0)) + .default_pos(pos2(100.0, 550.0)) .show(region.ctx(), |region| { emigui.ui(region); }); @@ -113,7 +132,7 @@ fn main() { region.add_label("This window can be reisized, but not smaller than the contents."); }); Window::new("Resize me!") - .default_pos(pos2(600.0, 500.0)) + .default_pos(pos2(600.0, 550.0)) .expand_to_fit_content(false) .show(region.ctx(), |region| { region