Skip to content

Commit 738f815

Browse files
0HyperCubeKeavon
authored andcommitted
Better local grab
1 parent 0298f9a commit 738f815

File tree

3 files changed

+132
-236
lines changed

3 files changed

+132
-236
lines changed

editor/src/messages/portfolio/document/utility_types/transformation.rs

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ use crate::messages::portfolio::document::graph_operation::utility_types::{Modif
55
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
66
use crate::messages::prelude::*;
77
use crate::messages::tool::common_functionality::shape_editor::ShapeState;
8+
use crate::messages::tool::transform_layer::transform_layer_message_handler::OtherUsefulParameters;
89
use crate::messages::tool::utility_types::ToolType;
910
use glam::{DAffine2, DMat2, DVec2};
1011
use graphene_std::renderer::Quad;
1112
use graphene_std::vector::misc::{HandleId, ManipulatorPointId};
1213
use graphene_std::vector::{HandleExt, PointId, VectorModificationType};
1314
use std::collections::{HashMap, VecDeque};
14-
use std::f64::consts::PI;
1515

1616
#[derive(Debug, PartialEq, Clone, Copy)]
1717
struct AnchorPoint {
@@ -156,22 +156,21 @@ pub struct Translation {
156156
}
157157

158158
impl Translation {
159-
pub fn to_dvec(self, transform: DAffine2, increment_mode: bool) -> DVec2 {
159+
pub fn to_dvec(self, state: &OtherUsefulParameters) -> DVec2 {
160160
let displacement = if let Some(value) = self.typed_distance {
161161
match self.constraint {
162-
Axis::X => transform.transform_vector2(DVec2::new(value, 0.)),
163-
Axis::Y => transform.transform_vector2(DVec2::new(0., value)),
162+
Axis::X => DVec2::X * value,
163+
Axis::Y => DVec2::Y * value,
164164
Axis::Both => self.dragged_distance,
165165
}
166166
} else {
167167
match self.constraint {
168168
Axis::Both => self.dragged_distance,
169-
Axis::X => DVec2::new(self.dragged_distance.x, 0.),
170-
Axis::Y => DVec2::new(0., self.dragged_distance.y),
169+
Axis::X => DVec2::X * self.dragged_distance.dot(state.constraint_axis(self.constraint).unwrap_or_default()),
170+
Axis::Y => DVec2::Y * self.dragged_distance.dot(state.constraint_axis(self.constraint).unwrap_or_default()),
171171
}
172172
};
173-
let displacement = transform.inverse().transform_vector2(displacement);
174-
if increment_mode { displacement.round() } else { displacement }
173+
if state.is_rounded_to_intervals { displacement.round() } else { displacement }
175174
}
176175

177176
#[must_use]
@@ -327,36 +326,19 @@ impl TransformType {
327326

328327
impl TransformOperation {
329328
#[allow(clippy::too_many_arguments)]
330-
pub fn apply_transform_operation(&self, selected: &mut Selected, increment_mode: bool, local: bool, quad: Quad, transform: DAffine2, pivot: DVec2, local_transform: DAffine2) {
331-
let local_axis_transform_angle = (quad.top_left() - quad.top_right()).to_angle();
329+
pub fn apply_transform_operation(&self, selected: &mut Selected, state: &OtherUsefulParameters, document: &DocumentMessageHandler) {
332330
if self != &TransformOperation::None {
333-
let transformation = match self {
334-
TransformOperation::Grabbing(translation) => {
335-
let translate = DAffine2::from_translation(transform.transform_vector2(translation.to_dvec(local_transform, increment_mode)));
336-
if local {
337-
let resolved_angle = if local_axis_transform_angle > 0. {
338-
local_axis_transform_angle
339-
} else {
340-
local_axis_transform_angle - PI
341-
};
342-
DAffine2::from_angle(resolved_angle) * translate * DAffine2::from_angle(-resolved_angle)
343-
} else {
344-
translate
345-
}
346-
}
347-
TransformOperation::Rotating(rotation) => DAffine2::from_angle(rotation.to_f64(increment_mode)),
348-
TransformOperation::Scaling(scale) => {
349-
if local {
350-
DAffine2::from_angle(local_axis_transform_angle) * DAffine2::from_scale(scale.to_dvec(increment_mode)) * DAffine2::from_angle(-local_axis_transform_angle)
351-
} else {
352-
DAffine2::from_scale(scale.to_dvec(increment_mode))
353-
}
354-
}
331+
let mut transformation = match self {
332+
TransformOperation::Grabbing(translation) => DAffine2::from_translation(translation.to_dvec(state)),
333+
TransformOperation::Rotating(rotation) => DAffine2::from_angle(rotation.to_f64(state.is_rounded_to_intervals)),
334+
TransformOperation::Scaling(scale) => DAffine2::from_scale(scale.to_dvec(state.is_rounded_to_intervals)),
355335
TransformOperation::None => unreachable!(),
356336
};
337+
let normalized_transform = state.local_to_viewport_transform();
338+
transformation = normalized_transform * transformation * normalized_transform.inverse();
357339

358-
selected.update_transforms(transformation, Some(pivot), Some(*self));
359-
self.hints(selected.responses, local);
340+
selected.update_transforms(transformation, Some(state.pivot_viewport(document)), Some(*self));
341+
self.hints(selected.responses, state.is_transforming_in_local_space);
360342
}
361343
}
362344

@@ -373,32 +355,33 @@ impl TransformOperation {
373355
}
374356

375357
#[allow(clippy::too_many_arguments)]
376-
pub fn constrain_axis(&mut self, axis: Axis, selected: &mut Selected, increment_mode: bool, mut local: bool, quad: Quad, transform: DAffine2, pivot: DVec2, local_transform: DAffine2) -> bool {
377-
(*self, local) = match self {
358+
pub fn constrain_axis(&mut self, axis: Axis, selected: &mut Selected, state: &OtherUsefulParameters, document: &DocumentMessageHandler) -> bool {
359+
let resulting_local;
360+
(*self, resulting_local) = match self {
378361
TransformOperation::Grabbing(translation) => {
379-
let (translation, local) = translation.with_constraint(axis, local);
380-
(TransformOperation::Grabbing(translation), local)
362+
let (translation, resulting_local) = translation.with_constraint(axis, state.is_transforming_in_local_space);
363+
(TransformOperation::Grabbing(translation), resulting_local)
381364
}
382365
TransformOperation::Scaling(scale) => {
383-
let (scale, local) = scale.with_constraint(axis, local);
384-
(TransformOperation::Scaling(scale), local)
366+
let (scale, resulting_local) = scale.with_constraint(axis, state.is_transforming_in_local_space);
367+
(TransformOperation::Scaling(scale), resulting_local)
385368
}
386369
_ => (*self, false),
387370
};
388-
self.apply_transform_operation(selected, increment_mode, local, quad, transform, pivot, local_transform);
389-
local
371+
self.apply_transform_operation(selected, state, document);
372+
resulting_local
390373
}
391374

392375
#[allow(clippy::too_many_arguments)]
393-
pub fn grs_typed(&mut self, typed: Option<f64>, selected: &mut Selected, increment_mode: bool, local: bool, quad: Quad, transform: DAffine2, pivot: DVec2, local_transform: DAffine2) {
376+
pub fn grs_typed(&mut self, typed: Option<f64>, selected: &mut Selected, state: &OtherUsefulParameters, document: &DocumentMessageHandler) {
394377
match self {
395378
TransformOperation::None => (),
396379
TransformOperation::Grabbing(translation) => translation.typed_distance = typed,
397380
TransformOperation::Rotating(rotation) => rotation.typed_angle = typed,
398381
TransformOperation::Scaling(scale) => scale.typed_factor = typed,
399382
};
400383

401-
self.apply_transform_operation(selected, increment_mode, local, quad, transform, pivot, local_transform);
384+
self.apply_transform_operation(selected, state, document);
402385
}
403386

404387
pub fn hints(&self, responses: &mut VecDeque<Message>, local: bool) {
@@ -481,15 +464,15 @@ impl TransformOperation {
481464
}
482465

483466
#[allow(clippy::too_many_arguments)]
484-
pub fn negate(&mut self, selected: &mut Selected, increment_mode: bool, local: bool, quad: Quad, transform: DAffine2, pivot: DVec2, local_transform: DAffine2) {
467+
pub fn negate(&mut self, selected: &mut Selected, state: &OtherUsefulParameters, document: &DocumentMessageHandler) {
485468
if *self != TransformOperation::None {
486469
*self = match self {
487470
TransformOperation::Scaling(scale) => TransformOperation::Scaling(scale.negate()),
488471
TransformOperation::Rotating(rotation) => TransformOperation::Rotating(rotation.negate()),
489472
TransformOperation::Grabbing(translation) => TransformOperation::Grabbing(translation.negate()),
490473
_ => *self,
491474
};
492-
self.apply_transform_operation(selected, increment_mode, local, quad, transform, pivot, local_transform);
475+
self.apply_transform_operation(selected, state, document);
493476
}
494477
}
495478
}

editor/src/messages/tool/tool_messages/select_tool.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,19 @@ impl SelectToolData {
593593
}
594594
}
595595

596+
/// Bounding boxes are unfortunately not axis aligned. The bounding boxes are found after a transformation is applied to all of the layers.
597+
/// This uses some rather confusing logic to determine what transform that should be.
598+
pub fn create_bounding_box_transform(document: &DocumentMessageHandler) -> DAffine2 {
599+
// Update bounds
600+
document
601+
.network_interface
602+
.selected_nodes()
603+
.selected_visible_and_unlocked_layers(&document.network_interface)
604+
.find(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[]))
605+
.map(|layer| document.metadata().transform_to_viewport_with_first_transform_node_if_group(layer, &document.network_interface))
606+
.unwrap_or_default()
607+
}
608+
596609
impl Fsm for SelectToolFsmState {
597610
type ToolData = SelectToolData;
598611
type ToolOptions = ();
@@ -633,14 +646,7 @@ impl Fsm for SelectToolFsmState {
633646
}
634647
}
635648

636-
// Update bounds
637-
let mut transform = document
638-
.network_interface
639-
.selected_nodes()
640-
.selected_visible_and_unlocked_layers(&document.network_interface)
641-
.find(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[]))
642-
.map(|layer| document.metadata().transform_to_viewport_with_first_transform_node_if_group(layer, &document.network_interface))
643-
.unwrap_or_default();
649+
let mut transform = create_bounding_box_transform(&document);
644650

645651
// Check if the matrix is not invertible
646652
let mut transform_tampered = false;

0 commit comments

Comments
 (0)