Minimum viewport scale cover when zooming (#1282)

* Minimum viewport scale cover

* Update const name
This commit is contained in:
0HyperCube
2023-06-03 20:35:19 +00:00
committed by GitHub
parent 8c20624dae
commit 26c477d15f
3 changed files with 34 additions and 7 deletions
+1
View File
@@ -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_MOUSE_RATE: f64 = 1. / 400.;
pub const VIEWPORT_ZOOM_SCALE_MIN: f64 = 0.000_000_1; pub const VIEWPORT_ZOOM_SCALE_MIN: f64 = 0.000_000_1;
pub const VIEWPORT_ZOOM_SCALE_MAX: f64 = 10_000.; 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] = [ 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.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., 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.,
@@ -181,8 +181,12 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
} }
#[remain::unsorted] #[remain::unsorted]
Navigation(message) => { Navigation(message) => {
self.navigation_handler let document_bounds = self.document_bounds(&render_data);
.process_message(message, responses, (&self.document_legacy, ipp, self.selected_visible_layers_bounding_box(&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] #[remain::unsorted]
Overlays(message) => { Overlays(message) => {
@@ -1,6 +1,6 @@
use crate::consts::{ 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_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_WHEEL_RATE, VIEWPORT_ZOOM_TO_FIT_PADDING_SCALE_FACTOR, VIEWPORT_ZOOM_WHEEL_RATE,
}; };
use crate::messages::frontend::utility_types::MouseCursorIcon; use crate::messages::frontend::utility_types::MouseCursorIcon;
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeysGroup}; use crate::messages::input_mapper::utility_types::input_keyboard::{Key, KeysGroup};
@@ -51,11 +51,18 @@ impl Default for NavigationMessageHandler {
} }
} }
impl MessageHandler<NavigationMessage, (&Document, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>)> for NavigationMessageHandler { impl MessageHandler<NavigationMessage, (&Document, Option<[DVec2; 2]>, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>)> for NavigationMessageHandler {
#[remain::check] #[remain::check]
fn process_message(&mut self, message: NavigationMessage, responses: &mut VecDeque<Message>, (document, ipp, selection_bounds): (&Document, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>)) { fn process_message(
&mut self,
message: NavigationMessage,
responses: &mut VecDeque<Message>,
(document, document_bounds, ipp, selection_bounds): (&Document, Option<[DVec2; 2]>, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>),
) {
use NavigationMessage::*; use NavigationMessage::*;
let old_zoom = self.zoom;
#[remain::sorted] #[remain::sorted]
match message { match message {
DecreaseCanvasZoom { center_on_mouse } => { DecreaseCanvasZoom { center_on_mouse } => {
@@ -157,6 +164,8 @@ impl MessageHandler<NavigationMessage, (&Document, &InputPreprocessorMessageHand
let amount = 1. + difference * VIEWPORT_ZOOM_MOUSE_RATE; let amount = 1. + difference * VIEWPORT_ZOOM_MOUSE_RATE;
self.zoom *= amount; self.zoom *= amount;
self.zoom *= Self::clamp_zoom(self.zoom, document_bounds, old_zoom, ipp);
if let Some(mouse) = zoom_from_viewport { if let Some(mouse) = zoom_from_viewport {
let zoom_factor = self.snapped_scale() / zoom_start; let zoom_factor = self.snapped_scale() / zoom_start;
@@ -192,6 +201,7 @@ impl MessageHandler<NavigationMessage, (&Document, &InputPreprocessorMessageHand
} }
SetCanvasZoom { zoom_factor } => { SetCanvasZoom { zoom_factor } => {
self.zoom = zoom_factor.clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX); 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(BroadcastEvent::DocumentIsDirty);
responses.add(DocumentMessage::DirtyRenderDocumentInOutlineView); responses.add(DocumentMessage::DirtyRenderDocumentInOutlineView);
responses.add(PortfolioMessage::UpdateDocumentWidgets); responses.add(PortfolioMessage::UpdateDocumentWidgets);
@@ -243,7 +253,8 @@ impl MessageHandler<NavigationMessage, (&Document, &InputPreprocessorMessageHand
let mut zoom_factor = 1. + scroll.abs() * VIEWPORT_ZOOM_WHEEL_RATE; let mut zoom_factor = 1. + scroll.abs() * VIEWPORT_ZOOM_WHEEL_RATE;
if ipp.mouse.scroll_delta.y > 0 { if ipp.mouse.scroll_delta.y > 0 {
zoom_factor = 1. / zoom_factor 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(self.center_zoom(ipp.viewport_bounds.size(), zoom_factor, ipp.mouse.position));
responses.add(SetCanvasZoom { zoom_factor: self.zoom * zoom_factor }); responses.add(SetCanvasZoom { zoom_factor: self.zoom * zoom_factor });
@@ -351,4 +362,15 @@ impl NavigationMessageHandler {
NavigationMessage::TranslateCanvas { delta }.into() 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.
}
}
} }