From 4d1c5fc8bf866c1a80719c94db1142721779736c Mon Sep 17 00:00:00 2001 From: 0HyperCube <78500760+0HyperCube@users.noreply.github.com> Date: Sat, 3 Jun 2023 21:35:19 +0100 Subject: [PATCH] Minimum viewport scale cover when zooming (#1282) * Minimum viewport scale cover * Update const name --- editor/src/consts.rs | 1 + .../document/document_message_handler.rs | 8 +++-- .../navigation/navigation_message_handler.rs | 32 ++++++++++++++++--- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/editor/src/consts.rs b/editor/src/consts.rs index 02f972a3..50de7447 100644 --- a/editor/src/consts.rs +++ b/editor/src/consts.rs @@ -5,6 +5,7 @@ pub const VIEWPORT_ZOOM_WHEEL_RATE: f64 = (1. / 600.) * 3.; pub const VIEWPORT_ZOOM_MOUSE_RATE: f64 = 1. / 400.; pub const VIEWPORT_ZOOM_SCALE_MIN: f64 = 0.000_000_1; pub const VIEWPORT_ZOOM_SCALE_MAX: f64 = 10_000.; +pub const VIEWPORT_ZOOM_MIN_FRACTION_COVER: f64 = 0.01; pub const VIEWPORT_ZOOM_LEVELS: [f64; 74] = [ 0.0001, 0.000125, 0.00016, 0.0002, 0.00025, 0.00032, 0.0004, 0.0005, 0.00064, 0.0008, 0.001, 0.0016, 0.002, 0.0025, 0.0032, 0.004, 0.005, 0.0064, 0.008, 0.01, 0.01125, 0.015, 0.02, 0.025, 0.03, 0.04, 0.05, 0.06, 0.08, 0.1, 0.125, 0.15, 0.2, 0.25, 0.33333333, 0.4, 0.5, 0.66666666, 0.8, 1., 1.25, 1.6, 2., 2.5, 3.2, 4., 5., 6.4, 8., 10., 12.5, 16., 20., 25., 32., 40., 50., 64., 80., 100., diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 5a4d0218..a1498579 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -181,8 +181,12 @@ impl MessageHandler { - self.navigation_handler - .process_message(message, responses, (&self.document_legacy, ipp, self.selected_visible_layers_bounding_box(&render_data))); + let document_bounds = self.document_bounds(&render_data); + self.navigation_handler.process_message( + message, + responses, + (&self.document_legacy, document_bounds, ipp, self.selected_visible_layers_bounding_box(&render_data)), + ); } #[remain::unsorted] Overlays(message) => { diff --git a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs index 86887c6f..3e62e5a4 100644 --- a/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs +++ b/editor/src/messages/portfolio/document/navigation/navigation_message_handler.rs @@ -1,6 +1,6 @@ use crate::consts::{ - VIEWPORT_ROTATE_SNAP_INTERVAL, VIEWPORT_SCROLL_RATE, VIEWPORT_ZOOM_LEVELS, VIEWPORT_ZOOM_MOUSE_RATE, VIEWPORT_ZOOM_SCALE_MAX, VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR, - VIEWPORT_ZOOM_WHEEL_RATE, + VIEWPORT_ROTATE_SNAP_INTERVAL, VIEWPORT_SCROLL_RATE, VIEWPORT_ZOOM_LEVELS, VIEWPORT_ZOOM_MIN_FRACTION_COVER, VIEWPORT_ZOOM_MOUSE_RATE, VIEWPORT_ZOOM_SCALE_MAX, VIEWPORT_ZOOM_SCALE_MIN, + VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR, VIEWPORT_ZOOM_WHEEL_RATE, }; use crate::messages::frontend::utility_types::MouseCursorIcon; use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeysGroup}; @@ -51,11 +51,18 @@ impl Default for NavigationMessageHandler { } } -impl MessageHandler)> for NavigationMessageHandler { +impl MessageHandler, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>)> for NavigationMessageHandler { #[remain::check] - fn process_message(&mut self, message: NavigationMessage, responses: &mut VecDeque, (document, ipp, selection_bounds): (&Document, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>)) { + fn process_message( + &mut self, + message: NavigationMessage, + responses: &mut VecDeque, + (document, document_bounds, ipp, selection_bounds): (&Document, Option<[DVec2; 2]>, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>), + ) { use NavigationMessage::*; + let old_zoom = self.zoom; + #[remain::sorted] match message { DecreaseCanvasZoom { center_on_mouse } => { @@ -157,6 +164,8 @@ impl MessageHandler { self.zoom = zoom_factor.clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX); + self.zoom *= Self::clamp_zoom(self.zoom, document_bounds, old_zoom, ipp); responses.add(BroadcastEvent::DocumentIsDirty); responses.add(DocumentMessage::DirtyRenderDocumentInOutlineView); responses.add(PortfolioMessage::UpdateDocumentWidgets); @@ -243,7 +253,8 @@ impl MessageHandler 0 { zoom_factor = 1. / zoom_factor - }; + } + zoom_factor *= Self::clamp_zoom(self.zoom * zoom_factor, document_bounds, old_zoom, ipp); responses.add(self.center_zoom(ipp.viewport_bounds.size(), zoom_factor, ipp.mouse.position)); responses.add(SetCanvasZoom { zoom_factor: self.zoom * zoom_factor }); @@ -351,4 +362,15 @@ impl NavigationMessageHandler { NavigationMessage::TranslateCanvas { delta }.into() } + + pub fn clamp_zoom(zoom: f64, document_bounds: Option<[DVec2; 2]>, old_zoom: f64, ipp: &InputPreprocessorMessageHandler) -> f64 { + let document_size = (document_bounds.map(|[min, max]| max - min).unwrap_or_default() / old_zoom) * zoom; + let scale_factor = (document_size / ipp.viewport_bounds.size()).max_element(); + + if scale_factor > f64::EPSILON * 100. && scale_factor.is_finite() && scale_factor < VIEWPORT_ZOOM_MIN_FRACTION_COVER { + VIEWPORT_ZOOM_MIN_FRACTION_COVER / scale_factor + } else { + 1. + } + } }