Improve nudging when tilted and add Artboard tool nudge resizing; disable menu bar entries when no layer is selected (#2098)

* Make nudging follow a tilted viewport

* Add artboard nudge resizing
This commit is contained in:
Keavon Chambers
2024-11-08 16:16:20 -08:00
committed by GitHub
parent 320d030c08
commit 457619794b
12 changed files with 237 additions and 115 deletions
@@ -10,7 +10,7 @@ use bezier_rs::{Bezier, BezierHandles, TValue};
use graphene_core::transform::Transform;
use graphene_core::vector::{ManipulatorPointId, PointId, VectorData, VectorModificationType};
use glam::DVec2;
use glam::{DAffine2, DVec2};
use graphene_std::vector::{HandleId, SegmentId};
#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
@@ -628,7 +628,11 @@ impl ShapeState {
let transform_to_viewport_space = document.metadata().transform_to_viewport(layer);
let transform_to_document_space = document.metadata().transform_to_document(layer);
let delta_transform = if in_viewport_space { transform_to_viewport_space } else { transform_to_document_space };
let delta_transform = if in_viewport_space {
transform_to_viewport_space
} else {
DAffine2::from_angle(document.document_ptz.tilt()) * transform_to_document_space
};
let delta = delta_transform.inverse().transform_vector2(delta);
for &point in state.selected_points.iter() {
@@ -189,7 +189,7 @@ impl SelectedEdges {
if !enlargement_factor.y.is_finite() || old_size.y.abs() < f64::EPSILON * 1000. {
enlargement_factor.y = 1.;
}
let mut pivot = (self.bounds[0] * enlargement_factor - position) / (enlargement_factor - DVec2::splat(1.));
let mut pivot = (self.bounds[0] * enlargement_factor - position) / (enlargement_factor - DVec2::ONE);
if !pivot.x.is_finite() {
pivot.x = 0.;
}
@@ -29,7 +29,7 @@ pub enum ArtboardToolMessage {
// Tool-specific messages
UpdateSelectedArtboard,
DeleteSelected,
NudgeSelected { delta_x: f64, delta_y: f64 },
NudgeSelected { delta_x: f64, delta_y: f64, resize: Key, resize_opposite_corner: Key },
PointerDown,
PointerMove { constrain_axis_or_aspect: Key, center: Key },
PointerOutsideViewport { constrain_axis_or_aspect: Key, center: Key },
@@ -465,19 +465,85 @@ impl Fsm for ArtboardToolFsmState {
ArtboardToolFsmState::Ready { hovered }
}
(_, ArtboardToolMessage::NudgeSelected { delta_x, delta_y }) => {
if let Some(bounds) = &mut tool_data.bounding_box_manager {
if tool_data.selected_artboard.unwrap() == LayerNodeIdentifier::ROOT_PARENT {
log::error!("Selected artboard cannot be ROOT_PARENT");
} else {
responses.add(GraphOperationMessage::ResizeArtboard {
layer: tool_data.selected_artboard.unwrap(),
location: DVec2::new(bounds.bounds[0].x + delta_x, bounds.bounds[0].y + delta_y).round().as_ivec2(),
dimensions: (bounds.bounds[1] - bounds.bounds[0]).round().as_ivec2(),
});
}
(
_,
ArtboardToolMessage::NudgeSelected {
delta_x,
delta_y,
resize,
resize_opposite_corner,
},
) => {
let Some(bounds) = &mut tool_data.bounding_box_manager else {
return ArtboardToolFsmState::Ready { hovered };
};
let Some(selected_artboard) = tool_data.selected_artboard else {
return ArtboardToolFsmState::Ready { hovered };
};
if selected_artboard == LayerNodeIdentifier::ROOT_PARENT {
log::error!("Selected artboard cannot be ROOT_PARENT");
return ArtboardToolFsmState::Ready { hovered };
}
let resize = input.keyboard.key(resize);
let resize_opposite_corner = input.keyboard.key(resize_opposite_corner);
let [existing_top_left, existing_bottom_right] = bounds.bounds;
// Nudge translation without resizing
if !resize {
let delta = DVec2::from_angle(-document.document_ptz.tilt()).rotate(DVec2::new(delta_x, delta_y));
responses.add(GraphOperationMessage::ResizeArtboard {
layer: selected_artboard,
location: DVec2::new(existing_top_left.x + delta.x, existing_top_left.y + delta.y).round().as_ivec2(),
dimensions: (existing_bottom_right - existing_top_left).round().as_ivec2(),
});
return ArtboardToolFsmState::Ready { hovered };
}
// Swap and negate coordinates as needed to match the resize direction that's closest to the current tilt angle
let tilt = (document.document_ptz.tilt() + std::f64::consts::TAU) % std::f64::consts::TAU;
let (delta_x, delta_y, opposite_x, opposite_y) = match ((tilt + std::f64::consts::FRAC_PI_4) / std::f64::consts::FRAC_PI_2).floor() as i32 % 4 {
0 => (delta_x, delta_y, false, false),
1 => (delta_y, -delta_x, false, true),
2 => (-delta_x, -delta_y, true, true),
3 => (-delta_y, delta_x, true, false),
_ => unreachable!(),
};
let size = existing_bottom_right - existing_top_left;
let enlargement = DVec2::new(
if resize_opposite_corner != opposite_x { -delta_x } else { delta_x },
if resize_opposite_corner != opposite_y { -delta_y } else { delta_y },
);
let enlargement_factor = (enlargement + size) / size;
let position = DVec2::new(
existing_top_left.x + if resize_opposite_corner != opposite_x { delta_x } else { 0. },
existing_top_left.y + if resize_opposite_corner != opposite_y { delta_y } else { 0. },
);
let mut pivot = (existing_top_left * enlargement_factor - position) / (enlargement_factor - DVec2::ONE);
if !pivot.x.is_finite() {
pivot.x = 0.;
}
if !pivot.y.is_finite() {
pivot.y = 0.;
}
let scale = DAffine2::from_scale(enlargement_factor);
let pivot = DAffine2::from_translation(pivot);
let transformation = pivot * scale * pivot.inverse();
let document_to_viewport = document.navigation_handler.calculate_offset_transform(input.viewport_bounds.center(), &document.document_ptz);
let to = document_to_viewport.inverse() * document.metadata().downstream_transform_to_viewport(selected_artboard);
let original_transform = document.metadata().upstream_transform(selected_artboard.to_node());
let new = to.inverse() * transformation * to * original_transform;
responses.add(GraphOperationMessage::ResizeArtboard {
layer: selected_artboard,
location: position.round().as_ivec2(),
dimensions: new.transform_vector2(existing_bottom_right - existing_top_left).round().as_ivec2(),
});
ArtboardToolFsmState::Ready { hovered }
}
(ArtboardToolFsmState::Dragging | ArtboardToolFsmState::Drawing | ArtboardToolFsmState::ResizingBounds, ArtboardToolMessage::Abort) => {