From 4053b7dd0c95c67962acac1c191047e7affaebc1 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 13 Feb 2019 10:32:25 -0800 Subject: [PATCH] Add zoom in and zoom out buttons for input devices without gesture support --- demo/src/main.rs | 35 +++++++++++++++++++++++++++-------- demo/src/ui.rs | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/demo/src/main.rs b/demo/src/main.rs index 4dada8d8..76e9deb8 100644 --- a/demo/src/main.rs +++ b/demo/src/main.rs @@ -10,7 +10,7 @@ //! A demo app for Pathfinder. -use crate::ui::{DemoUI, UIEvent}; +use crate::ui::{DemoUI, UIAction, UIEvent}; use clap::{App, Arg}; use euclid::Size2D; use jemallocator; @@ -51,7 +51,10 @@ const MAIN_FRAMEBUFFER_HEIGHT: u32 = 800; const MOUSELOOK_ROTATION_SPEED: f32 = 0.007; const CAMERA_VELOCITY: f32 = 25.0; +// How much the scene is scaled when a scale gesture is performed. const CAMERA_SCALE_SPEED_2D: f32 = 2.0; +// How much the scene is scaled when a zoom button is clicked. +const CAMERA_ZOOM_AMOUNT_2D: f32 = 0.1; const BACKGROUND_COLOR: ColorU = ColorU { r: 32, g: 32, b: 32, a: 255 }; @@ -342,14 +345,30 @@ impl DemoApp { self.dirty = true; } - self.ui.update(&mut self.renderer.debug_ui, &mut ui_event); + let mut ui_action = UIAction::None; + self.ui.update(&mut self.renderer.debug_ui, &mut ui_event, &mut ui_action); - // Open a new file if requested. - if let Some(path) = self.ui.file_to_open.take() { - let scene = load_scene(&path); - self.scene_thread_proxy.load_scene(scene); - update_drawable_size(&self.window, &self.scene_thread_proxy); - self.dirty = true; + // Handle UI actions. + match ui_action { + UIAction::None => {} + UIAction::OpenFile(path) => { + let scene = load_scene(&path); + self.scene_thread_proxy.load_scene(scene); + update_drawable_size(&self.window, &self.scene_thread_proxy); + self.dirty = true; + } + UIAction::ZoomIn => { + if let Camera::TwoD { ref mut scale, .. } = self.camera { + *scale *= 1.0 + CAMERA_ZOOM_AMOUNT_2D; + self.dirty = true; + } + } + UIAction::ZoomOut => { + if let Camera::TwoD { ref mut scale, .. } = self.camera { + *scale *= 1.0 - CAMERA_ZOOM_AMOUNT_2D; + self.dirty = true; + } + } } // Switch camera mode (2D/3D) if requested. diff --git a/demo/src/ui.rs b/demo/src/ui.rs index 592c3670..4052e319 100644 --- a/demo/src/ui.rs +++ b/demo/src/ui.rs @@ -37,11 +37,15 @@ const ROTATE_PANEL_HEIGHT: i32 = PADDING * 2 + SLIDER_HEIGHT; static EFFECTS_PNG_NAME: &'static str = "demo-effects"; static OPEN_PNG_NAME: &'static str = "demo-open"; static ROTATE_PNG_NAME: &'static str = "demo-rotate"; +static ZOOM_IN_PNG_NAME: &'static str = "demo-zoom-in"; +static ZOOM_OUT_PNG_NAME: &'static str = "demo-zoom-out"; pub struct DemoUI { effects_texture: Texture, open_texture: Texture, rotate_texture: Texture, + zoom_in_texture: Texture, + zoom_out_texture: Texture, effects_panel_visible: bool, rotate_panel_visible: bool, @@ -50,7 +54,6 @@ pub struct DemoUI { pub gamma_correction_effect_enabled: bool, pub stem_darkening_effect_enabled: bool, pub subpixel_aa_effect_enabled: bool, - pub file_to_open: Option, pub rotation: i32, } @@ -59,18 +62,21 @@ impl DemoUI { let effects_texture = Texture::from_png(EFFECTS_PNG_NAME); let open_texture = Texture::from_png(OPEN_PNG_NAME); let rotate_texture = Texture::from_png(ROTATE_PNG_NAME); + let zoom_in_texture = Texture::from_png(ZOOM_IN_PNG_NAME); + let zoom_out_texture = Texture::from_png(ZOOM_OUT_PNG_NAME); DemoUI { effects_texture, open_texture, rotate_texture, + zoom_in_texture, + zoom_out_texture, threed_enabled: options.threed, effects_panel_visible: false, rotate_panel_visible: false, gamma_correction_effect_enabled: false, stem_darkening_effect_enabled: false, subpixel_aa_effect_enabled: false, - file_to_open: None, rotation: SLIDER_WIDTH / 2, } } @@ -79,7 +85,7 @@ impl DemoUI { (self.rotation as f32 / SLIDER_WIDTH as f32 * 2.0 - 1.0) * PI } - pub fn update(&mut self, debug_ui: &mut DebugUI, event: &mut UIEvent) { + pub fn update(&mut self, debug_ui: &mut DebugUI, event: &mut UIEvent, action: &mut UIAction) { let bottom = debug_ui.framebuffer_size().height as i32 - PADDING; // Draw effects button. @@ -94,7 +100,7 @@ impl DemoUI { let open_button_position = Point2DI32::new(open_button_x, open_button_y); if self.draw_button(debug_ui, event, open_button_position, &self.open_texture) { if let Ok(Response::Okay(file)) = nfd::open_file_dialog(Some("svg"), None) { - self.file_to_open = Some(PathBuf::from(file)); + *action = UIAction::OpenFile(PathBuf::from(file)); } } @@ -111,13 +117,28 @@ impl DemoUI { "3D", self.threed_enabled); - // Draw rotate button, if applicable. + // Draw rotate and zoom buttons, if applicable. if !self.threed_enabled { let rotate_button_y = bottom - BUTTON_HEIGHT; let rotate_button_position = Point2DI32::new(ROTATE_PANEL_X, rotate_button_y); if self.draw_button(debug_ui, event, rotate_button_position, &self.rotate_texture) { self.rotate_panel_visible = !self.rotate_panel_visible; } + + let zoom_in_button_x = ROTATE_PANEL_X + BUTTON_WIDTH + PADDING; + let zoom_in_button_position = Point2DI32::new(zoom_in_button_x, rotate_button_y); + if self.draw_button(debug_ui, event, zoom_in_button_position, &self.zoom_in_texture) { + *action = UIAction::ZoomIn; + } + + let zoom_out_button_x = ROTATE_PANEL_X + (BUTTON_WIDTH + PADDING) * 2; + let zoom_out_button_position = Point2DI32::new(zoom_out_button_x, rotate_button_y); + if self.draw_button(debug_ui, + event, + zoom_out_button_position, + &self.zoom_out_texture) { + *action = UIAction::ZoomOut; + } } // Draw effects panel, if necessary. @@ -264,6 +285,14 @@ impl DemoUI { } } +#[derive(Clone, Debug, PartialEq)] +pub enum UIAction { + None, + OpenFile(PathBuf), + ZoomIn, + ZoomOut, +} + pub enum UIEvent { None, MouseDown(Point2DI32),