Minimum viewport scale cover when zooming (#1282)

* Minimum viewport scale cover

* Update const name
This commit is contained in:
0HyperCube 2023-06-03 21:35:19 +01:00 committed by Keavon Chambers
parent 26473a8002
commit 4d1c5fc8bf
3 changed files with 34 additions and 7 deletions

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_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.,

View File

@ -181,8 +181,12 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
}
#[remain::unsorted]
Navigation(message) => {
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) => {

View File

@ -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<NavigationMessage, (&Document, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>)> for NavigationMessageHandler {
impl MessageHandler<NavigationMessage, (&Document, Option<[DVec2; 2]>, &InputPreprocessorMessageHandler, Option<[DVec2; 2]>)> for NavigationMessageHandler {
#[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::*;
let old_zoom = self.zoom;
#[remain::sorted]
match message {
DecreaseCanvasZoom { center_on_mouse } => {
@ -157,6 +164,8 @@ impl MessageHandler<NavigationMessage, (&Document, &InputPreprocessorMessageHand
let amount = 1. + difference * VIEWPORT_ZOOM_MOUSE_RATE;
self.zoom *= amount;
self.zoom *= Self::clamp_zoom(self.zoom, document_bounds, old_zoom, ipp);
if let Some(mouse) = zoom_from_viewport {
let zoom_factor = self.snapped_scale() / zoom_start;
@ -192,6 +201,7 @@ impl MessageHandler<NavigationMessage, (&Document, &InputPreprocessorMessageHand
}
SetCanvasZoom { zoom_factor } => {
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<NavigationMessage, (&Document, &InputPreprocessorMessageHand
let mut zoom_factor = 1. + scroll.abs() * VIEWPORT_ZOOM_WHEEL_RATE;
if ipp.mouse.scroll_delta.y > 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.
}
}
}