Make the transform cage resize about the pivot when Alt is pressed (#2226)
* Change the pivot behaviour when resizing bounds with alt in the select tool * Add scale factor maximum * Fix bug when encountering snapping; tidy up and comment the code --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
fb7eae8f02
commit
5a8eb9dd1b
|
|
@ -68,6 +68,11 @@ pub const MIN_LENGTH_FOR_MIDPOINT_VISIBILITY: f64 = 20.;
|
|||
pub const MIN_LENGTH_FOR_CORNERS_VISIBILITY: f64 = 12.;
|
||||
/// When the width or height of the transform cage is less than this value, only the exterior of the bounding box will act as a click target for resizing.
|
||||
pub const MIN_LENGTH_FOR_RESIZE_TO_INCLUDE_INTERIOR: f64 = 40.;
|
||||
/// When dragging the edge of a cage with Alt, it centers around the pivot.
|
||||
/// However if the pivot is on or near the same edge you are dragging, we should avoid scaling by a massive factor caused by the small denominator.
|
||||
///
|
||||
/// The motion of the user's cursor by an `x` pixel offset results in `x * scale_factor` pixels of offset on the other side.
|
||||
pub const MAXIMUM_ALT_SCALE_FACTOR: f64 = 25.;
|
||||
|
||||
// PATH TOOL
|
||||
pub const MANIPULATOR_GROUP_MARKER_SIZE: f64 = 6.;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::consts::{
|
||||
BOUNDS_ROTATE_THRESHOLD, BOUNDS_SELECT_THRESHOLD, MIN_LENGTH_FOR_CORNERS_VISIBILITY, MIN_LENGTH_FOR_MIDPOINT_VISIBILITY, MIN_LENGTH_FOR_RESIZE_TO_INCLUDE_INTERIOR, SELECTION_DRAG_ANGLE,
|
||||
BOUNDS_ROTATE_THRESHOLD, BOUNDS_SELECT_THRESHOLD, MAXIMUM_ALT_SCALE_FACTOR, MIN_LENGTH_FOR_CORNERS_VISIBILITY, MIN_LENGTH_FOR_MIDPOINT_VISIBILITY, MIN_LENGTH_FOR_RESIZE_TO_INCLUDE_INTERIOR,
|
||||
SELECTION_DRAG_ANGLE,
|
||||
};
|
||||
use crate::messages::frontend::utility_types::MouseCursorIcon;
|
||||
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
|
||||
|
|
@ -8,9 +9,9 @@ use crate::messages::prelude::*;
|
|||
use crate::messages::tool::common_functionality::snapping::SnapTypeConfiguration;
|
||||
|
||||
use graphene_core::renderer::Quad;
|
||||
use graphene_std::renderer::Rect;
|
||||
|
||||
use glam::{DAffine2, DVec2};
|
||||
use graphene_std::renderer::Rect;
|
||||
|
||||
use super::snapping::{self, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnappedPoint};
|
||||
|
||||
|
|
@ -88,6 +89,7 @@ impl SelectedEdges {
|
|||
|
||||
let mut min = self.bounds[0];
|
||||
let mut max = self.bounds[1];
|
||||
|
||||
if self.top {
|
||||
min.y = mouse.y;
|
||||
} else if self.bottom {
|
||||
|
|
@ -100,24 +102,43 @@ impl SelectedEdges {
|
|||
}
|
||||
|
||||
let mut pivot = self.pivot_from_bounds(min, max);
|
||||
|
||||
// Alt: Scaling around the pivot
|
||||
if let Some(center_around) = center_around {
|
||||
let center_around = transform.inverse().transform_point2(center_around);
|
||||
if self.top {
|
||||
pivot.y = center_around.y;
|
||||
max.y = center_around.y * 2. - min.y;
|
||||
} else if self.bottom {
|
||||
pivot.y = center_around.y;
|
||||
min.y = center_around.y * 2. - max.y;
|
||||
|
||||
let calculate_distance = |moving_opposite_to_drag: &mut f64, center: f64, dragging: f64, original_dragging: f64, current_side: bool| {
|
||||
if !current_side {
|
||||
return true;
|
||||
}
|
||||
if self.left {
|
||||
pivot.x = center_around.x;
|
||||
max.x = center_around.x * 2. - min.x;
|
||||
} else if self.right {
|
||||
pivot.x = center_around.x;
|
||||
min.x = center_around.x * 2. - max.x;
|
||||
|
||||
// The motion of the user's cursor by an `x` pixel offset results in `x * scale_factor` pixels of offset on the other side
|
||||
let scale_factor = (center - *moving_opposite_to_drag) / (center - original_dragging);
|
||||
let new_distance = center - scale_factor * (center - dragging);
|
||||
|
||||
// Ignore the Alt key press and scale the dragged edge normally
|
||||
if !new_distance.is_finite() || scale_factor.abs() > MAXIMUM_ALT_SCALE_FACTOR {
|
||||
// Don't go on to check the other sides since this side is already invalid, so Alt-dragging is disabled and updating the pivot would be incorrect
|
||||
return false;
|
||||
}
|
||||
|
||||
*moving_opposite_to_drag = new_distance;
|
||||
|
||||
true
|
||||
};
|
||||
|
||||
// Update the value of the first argument through mutation, and if we make it through all of them without
|
||||
// encountering a case where the pivot is too near the edge, we also update the pivot so scaling occurs around it
|
||||
if calculate_distance(&mut max.y, center_around.y, min.y, self.bounds[0].y, self.top)
|
||||
&& calculate_distance(&mut min.y, center_around.y, max.y, self.bounds[1].y, self.bottom)
|
||||
&& calculate_distance(&mut max.x, center_around.x, min.x, self.bounds[0].x, self.left)
|
||||
&& calculate_distance(&mut min.x, center_around.x, max.x, self.bounds[1].x, self.right)
|
||||
{
|
||||
pivot = center_around;
|
||||
}
|
||||
}
|
||||
|
||||
// Shift: Aspect ratio constraint
|
||||
if constrain {
|
||||
let size = max - min;
|
||||
let min_pivot = (pivot - min) / size;
|
||||
|
|
|
|||
Loading…
Reference in New Issue