diff --git a/emigui/src/containers/area.rs b/emigui/src/containers/area.rs index 05f2e703..4b220fcb 100644 --- a/emigui/src/containers/area.rs +++ b/emigui/src/containers/area.rs @@ -165,8 +165,8 @@ impl Area { let input = ctx.input(); if move_interact.active { - state.pos += input.mouse_move; - state.vel = input.mouse_velocity; + state.pos += input.mouse.delta; + state.vel = input.mouse.velocity; } else { let stop_speed = 20.0; // Pixels per second. let friction_coeff = 1000.0; // Pixels per second squared. @@ -208,8 +208,8 @@ impl Area { } fn mouse_pressed_on_area(ctx: &Context, layer: Layer) -> bool { - if let Some(mouse_pos) = ctx.input().mouse_pos { - ctx.input().mouse_pressed && ctx.memory().layer_at(mouse_pos) == Some(layer) + if let Some(mouse_pos) = ctx.input().mouse.pos { + ctx.input().mouse.pressed && ctx.memory().layer_at(mouse_pos) == Some(layer) } else { false } diff --git a/emigui/src/containers/menu.rs b/emigui/src/containers/menu.rs index c0e416f5..5b4175aa 100644 --- a/emigui/src/containers/menu.rs +++ b/emigui/src/containers/menu.rs @@ -99,7 +99,7 @@ fn menu_impl<'c>( }) }); - if menu_interact.hovered && ui.input().mouse_released { + if menu_interact.hovered && ui.input().mouse.released { bar_state.open_menu = None; } } @@ -113,7 +113,7 @@ fn interact_with_menu_button( menu_id: Id, button_interact: &GuiResponse, ) { - if button_interact.hovered && input.mouse_pressed { + if button_interact.hovered && input.mouse.pressed { if bar_state.open_menu.is_some() { bar_state.open_menu = None; } else { @@ -122,7 +122,7 @@ fn interact_with_menu_button( } } - if button_interact.hovered && input.mouse_released && bar_state.open_menu.is_some() { + if button_interact.hovered && input.mouse.released && bar_state.open_menu.is_some() { let time_since_open = input.time - bar_state.open_time; if time_since_open < 0.4 { // A quick click diff --git a/emigui/src/containers/popup.rs b/emigui/src/containers/popup.rs index eaec9d90..e748cdac 100644 --- a/emigui/src/containers/popup.rs +++ b/emigui/src/containers/popup.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use crate::*; pub fn show_tooltip(ctx: &Arc, add_contents: impl FnOnce(&mut Ui)) { - if let Some(mouse_pos) = ctx.input().mouse_pos { + if let Some(mouse_pos) = ctx.input().mouse.pos { // TODO: default size let id = Id::tooltip(); let window_pos = mouse_pos + vec2(16.0, 16.0); diff --git a/emigui/src/containers/resize.rs b/emigui/src/containers/resize.rs index d41372e5..d8ea082c 100644 --- a/emigui/src/containers/resize.rs +++ b/emigui/src/containers/resize.rs @@ -212,7 +212,7 @@ impl Resize { let corner_interact = ui.interact_rect(corner_rect, id.with("corner")); if corner_interact.active { - if let Some(mouse_pos) = ui.input().mouse_pos { + if let Some(mouse_pos) = ui.input().mouse.pos { // This is the desired size. We may not be able to achieve it. state.size = mouse_pos - position + 0.5 * corner_interact.rect.size() diff --git a/emigui/src/containers/scroll_area.rs b/emigui/src/containers/scroll_area.rs index 0ec34211..1452cd91 100644 --- a/emigui/src/containers/scroll_area.rs +++ b/emigui/src/containers/scroll_area.rs @@ -147,7 +147,7 @@ impl ScrollArea { // Dragg contents to scroll (for touch screens mostly): let content_interact = ui.interact_rect(inner_rect, id.with("area")); if content_interact.active { - state.offset.y -= ui.input().mouse_move.y; + state.offset.y -= ui.input().mouse.delta.y; } } @@ -181,11 +181,11 @@ impl ScrollArea { let interact_id = id.with("vertical"); let handle_interact = ui.interact_rect(handle_rect, interact_id); - if let Some(mouse_pos) = ui.input().mouse_pos { + if let Some(mouse_pos) = ui.input().mouse.pos { if handle_interact.active { if inner_rect.top() <= mouse_pos.y && mouse_pos.y <= inner_rect.bottom() { state.offset.y += - ui.input().mouse_move.y * content_size.y / inner_rect.height(); + ui.input().mouse.delta.y * content_size.y / inner_rect.height(); } } else { // Check for mouse down outside handle: diff --git a/emigui/src/containers/window.rs b/emigui/src/containers/window.rs index 580b0990..cfd5ba94 100644 --- a/emigui/src/containers/window.rs +++ b/emigui/src/containers/window.rs @@ -303,7 +303,7 @@ fn resize_window( ) -> Option { if let Some(window_interaction) = window_interaction(ctx, possible, area_layer, id, rect) { window_interaction.set_cursor(ctx); - if let Some(mouse_pos) = ctx.input().mouse_pos { + if let Some(mouse_pos) = ctx.input().mouse.pos { let mut rect = window_interaction.start_rect; // prevent drift if window_interaction.is_resize() { @@ -350,7 +350,7 @@ fn window_interaction( if window_interaction.is_none() { if let Some(hover_window_interaction) = resize_hover(ctx, possible, area_layer, rect) { hover_window_interaction.set_cursor(ctx); - if ctx.input().mouse_pressed { + if ctx.input().mouse.pressed { ctx.memory().active_id = Some(id); window_interaction = Some(hover_window_interaction); ctx.memory().window_interaction = window_interaction; @@ -375,7 +375,7 @@ fn resize_hover( area_layer: Layer, rect: Rect, ) -> Option { - if let Some(mouse_pos) = ctx.input().mouse_pos { + if let Some(mouse_pos) = ctx.input().mouse.pos { if let Some(top_layer) = ctx.memory().layer_at(mouse_pos) { if top_layer != area_layer && top_layer.order != Order::Background { return None; // Another window is on top here diff --git a/emigui/src/context.rs b/emigui/src/context.rs index 29897615..e41d0c1d 100644 --- a/emigui/src/context.rs +++ b/emigui/src/context.rs @@ -176,7 +176,7 @@ impl Context { let area_state = self.memory().areas.get(area_layer.id).clone(); if let Some(mut area_state) = area_state { // Throw windows because it is fun: - area_state.vel = self.input().mouse_velocity; + area_state.vel = self.input().mouse.velocity; self.memory().areas.set_state(area_layer, area_state); } } @@ -197,7 +197,7 @@ impl Context { } let new_input = GuiInput::from_last_and_new(&self.raw_input, &new_raw_input); self.previus_input = std::mem::replace(&mut self.input, new_input); - self.input.mouse_velocity = self.mouse_vel(); + self.input.mouse.velocity = self.mouse_vel(); self.raw_input = new_raw_input; } @@ -304,7 +304,7 @@ impl Context { pub fn contains_mouse(&self, layer: Layer, clip_rect: Rect, rect: Rect) -> bool { let rect = rect.intersect(clip_rect); - if let Some(mouse_pos) = self.input.mouse_pos { + if let Some(mouse_pos) = self.input.mouse.pos { rect.contains(mouse_pos) && self.memory().layer_at(mouse_pos) == Some(layer) } else { false @@ -324,7 +324,7 @@ impl Context { let mut memory = self.memory(); let active = interaction_id.is_some() && memory.active_id == interaction_id; - if self.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 @@ -351,14 +351,14 @@ impl Context { active: false, } } - } else if self.input.mouse_released { + } else if self.input.mouse.released { InteractInfo { rect, hovered, clicked: hovered && active, active, } - } else if self.input.mouse_down { + } else if self.input.mouse.down { InteractInfo { rect, hovered: hovered && active, diff --git a/emigui/src/examples/app.rs b/emigui/src/examples/app.rs index 0718e77f..e1101e80 100644 --- a/emigui/src/examples/app.rs +++ b/emigui/src/examples/app.rs @@ -449,7 +449,7 @@ impl Painting { let current_line = self.lines.last_mut().unwrap(); if interact.active { - if let Some(mouse_pos) = ui.input().mouse_pos { + if let Some(mouse_pos) = ui.input().mouse.pos { let canvas_pos = mouse_pos - rect.min; if current_line.last() != Some(&canvas_pos) { current_line.push(canvas_pos); diff --git a/emigui/src/input.rs b/emigui/src/input.rs index 648fa1c2..d02da24c 100644 --- a/emigui/src/input.rs +++ b/emigui/src/input.rs @@ -45,28 +45,7 @@ pub struct RawInput { /// What emigui maintains #[derive(Clone, Debug, Default)] pub struct GuiInput { - // TODO: mouse: Mouse as separate - // - /// Is the button currently down? - /// true the frame when it is pressed, - /// false the frame it is released. - pub mouse_down: bool, - - /// The mouse went from !down to down - pub mouse_pressed: bool, - - /// The mouse went from down to !down - pub mouse_released: bool, - - /// Current position of the mouse in points. - /// None for touch screens when finger is not down. - pub mouse_pos: Option, - - /// How much the mouse moved compared to last frame, in points. - pub mouse_move: Vec2, - - /// Current velocity of mouse cursor, if any. - pub mouse_velocity: Vec2, + pub mouse: MouseInput, /// How many pixels the user scrolled pub scroll_delta: Vec2, @@ -99,6 +78,31 @@ pub struct GuiInput { pub web: Option, } +/// What emigui maintains +#[derive(Clone, Debug, Default)] +pub struct MouseInput { + /// Is the button currently down? + /// true the frame when it is pressed, + /// false the frame it is released. + pub down: bool, + + /// The mouse went from !down to down + pub pressed: bool, + + /// The mouse went from down to !down + pub released: bool, + + /// Current position of the mouse in points. + /// None for touch screens when finger is not down. + pub pos: Option, + + /// How much the mouse moved compared to last frame, in points. + pub delta: Vec2, + + /// Current velocity of mouse cursor. + pub velocity: Vec2, +} + #[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Deserialize)] #[serde(default)] pub struct Web { @@ -147,22 +151,9 @@ pub enum Key { impl GuiInput { pub fn from_last_and_new(last: &RawInput, new: &RawInput) -> GuiInput { - let mouse_move = new - .mouse_pos - .and_then(|new| last.mouse_pos.map(|last| new - last)) - .unwrap_or_default(); let dt = (new.time - last.time) as f32; - let mut mouse_velocity = mouse_move / dt; - if !mouse_velocity.is_finite() { - mouse_velocity = Vec2::zero(); - } GuiInput { - mouse_down: new.mouse_down && new.mouse_pos.is_some(), - mouse_pressed: !last.mouse_down && new.mouse_down, - mouse_released: last.mouse_down && !new.mouse_down, - mouse_pos: new.mouse_pos, - mouse_move, - mouse_velocity, + mouse: MouseInput::from_last_and_new(last, new), scroll_delta: new.scroll_delta, screen_size: new.screen_size, pixels_per_point: new.pixels_per_point.unwrap_or(1.0), @@ -177,6 +168,28 @@ impl GuiInput { } } +impl MouseInput { + pub fn from_last_and_new(last: &RawInput, new: &RawInput) -> MouseInput { + let delta = new + .mouse_pos + .and_then(|new| last.mouse_pos.map(|last| new - last)) + .unwrap_or_default(); + let dt = (new.time - last.time) as f32; + let mut velocity = delta / dt; + if !velocity.is_finite() { + velocity = Vec2::zero(); + } + MouseInput { + down: new.mouse_down && new.mouse_pos.is_some(), + pressed: !last.mouse_down && new.mouse_down, + released: last.mouse_down && !new.mouse_down, + pos: new.mouse_pos, + delta, + velocity, + } + } +} + impl RawInput { pub fn ui(&self, ui: &mut crate::Ui) { use crate::label; @@ -200,16 +213,11 @@ impl RawInput { impl GuiInput { pub fn ui(&self, ui: &mut crate::Ui) { use crate::label; - ui.add(label!("mouse_down: {}", self.mouse_down)); - ui.add(label!("mouse_pressed: {}", self.mouse_pressed)); - ui.add(label!("mouse_released: {}", self.mouse_released)); - ui.add(label!("mouse_pos: {:?}", self.mouse_pos)); - ui.add(label!("mouse_move: {:?}", self.mouse_move)); - ui.add(label!( - "mouse_velocity: [{:3.0} {:3.0}] points/sec", - self.mouse_velocity.x, - self.mouse_velocity.y - )); + crate::containers::CollapsingHeader::new("mouse") + .default_open(true) + .show(ui, |ui| { + self.mouse.ui(ui); + }); ui.add(label!("scroll_delta: {:?}", self.scroll_delta)); ui.add(label!("screen_size: {:?}", self.screen_size)); ui.add(label!("pixels_per_point: {}", self.pixels_per_point)); @@ -223,6 +231,22 @@ impl GuiInput { } } +impl MouseInput { + pub fn ui(&self, ui: &mut crate::Ui) { + use crate::label; + ui.add(label!("down: {}", self.down)); + ui.add(label!("pressed: {}", self.pressed)); + ui.add(label!("released: {}", self.released)); + ui.add(label!("pos: {:?}", self.pos)); + ui.add(label!("delta: {:?}", self.delta)); + ui.add(label!( + "velocity: [{:3.0} {:3.0}] points/sec", + self.velocity.x, + self.velocity.y + )); + } +} + impl Web { pub fn ui(&self, ui: &mut crate::Ui) { use crate::label; diff --git a/emigui/src/widgets/slider.rs b/emigui/src/widgets/slider.rs index b4bd3f18..071c1af8 100644 --- a/emigui/src/widgets/slider.rs +++ b/emigui/src/widgets/slider.rs @@ -154,7 +154,7 @@ impl<'a> Widget for Slider<'a> { let range = self.range.clone(); debug_assert!(range.start() <= range.end()); - if let Some(mouse_pos) = ui.input().mouse_pos { + if let Some(mouse_pos) = ui.input().mouse.pos { if interact.active { self.set_value_f32(remap_clamp(mouse_pos.x, left..=right, range.clone())); } diff --git a/emigui/src/widgets/text_edit.rs b/emigui/src/widgets/text_edit.rs index 7463ad44..3bc73afd 100644 --- a/emigui/src/widgets/text_edit.rs +++ b/emigui/src/widgets/text_edit.rs @@ -75,7 +75,7 @@ impl<'t> Widget for TextEdit<'t> { if interact.clicked { ui.request_kb_focus(id); - if let Some(mouse_pos) = ui.input().mouse_pos { + if let Some(mouse_pos) = ui.input().mouse.pos { state.cursor = Some(galley.char_at(mouse_pos - interact.rect.min).char_idx); } }