Skip to content

Commit 2900271

Browse files
authored
Merge branch 'master' into bevel-algo
2 parents 102b7ee + 38e542e commit 2900271

File tree

14 files changed

+648
-240
lines changed

14 files changed

+648
-240
lines changed

editor/src/messages/input_mapper/utility_types/input_mouse.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use glam::DVec2;
66
use std::collections::VecDeque;
77

88
// Origin is top left
9+
pub type DocumentPosition = DVec2;
910
pub type ViewportPosition = DVec2;
1011
pub type EditorPosition = DVec2;
1112

editor/src/messages/portfolio/document/document_message_handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2321,7 +2321,7 @@ pub struct ClickXRayIter<'a> {
23212321
}
23222322

23232323
fn quad_to_path_lib_segments(quad: Quad) -> Vec<path_bool_lib::PathSegment> {
2324-
quad.edges().into_iter().map(|[start, end]| path_bool_lib::PathSegment::Line(start, end)).collect()
2324+
quad.all_edges().into_iter().map(|[start, end]| path_bool_lib::PathSegment::Line(start, end)).collect()
23252325
}
23262326

23272327
fn click_targets_to_path_lib_segments<'a>(click_targets: impl Iterator<Item = &'a ClickTarget>, transform: DAffine2) -> Vec<path_bool_lib::PathSegment> {

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,10 @@ impl PTZ {
653653
(((self.tilt + std::f64::consts::PI) % std::f64::consts::TAU) + std::f64::consts::TAU) % std::f64::consts::TAU - std::f64::consts::PI
654654
}
655655

656+
pub fn unmodified_tilt(&self) -> f64 {
657+
self.tilt
658+
}
659+
656660
/// Set a new tilt angle in radians.
657661
pub fn set_tilt(&mut self, tilt: f64) {
658662
self.tilt = tilt;

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

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use graphene_std::vector::{HandleId, PointId};
1414

1515
use glam::{DAffine2, DMat2, DVec2};
1616
use std::collections::{HashMap, VecDeque};
17+
use std::f64::consts::PI;
1718

1819
#[derive(Debug, PartialEq, Clone, Copy)]
1920
struct AnchorPoint {
@@ -305,17 +306,17 @@ pub enum TransformOperation {
305306
}
306307

307308
impl TransformOperation {
308-
pub fn apply_transform_operation(&self, selected: &mut Selected, increment_mode: bool, local: bool, quad: Quad, transform: DAffine2) {
309+
pub fn apply_transform_operation(&self, selected: &mut Selected, increment_mode: bool, local: bool, quad: Quad, transform: DAffine2, pivot: DVec2, local_transform: DAffine2) {
309310
let local_axis_transform_angle = (quad.top_left() - quad.top_right()).to_angle();
310311
if self != &TransformOperation::None {
311312
let transformation = match self {
312313
TransformOperation::Grabbing(translation) => {
313-
let translate = DAffine2::from_translation(transform.transform_vector2(translation.to_dvec(transform, increment_mode)));
314+
let translate = DAffine2::from_translation(transform.transform_vector2(translation.to_dvec(local_transform, increment_mode)));
314315
if local {
315316
let resolved_angle = if local_axis_transform_angle > 0. {
316-
local_axis_transform_angle - std::f64::consts::PI
317-
} else {
318317
local_axis_transform_angle
318+
} else {
319+
local_axis_transform_angle - PI
319320
};
320321
DAffine2::from_angle(resolved_angle) * translate * DAffine2::from_angle(-resolved_angle)
321322
} else {
@@ -333,7 +334,7 @@ impl TransformOperation {
333334
TransformOperation::None => unreachable!(),
334335
};
335336

336-
selected.update_transforms(transformation);
337+
selected.update_transforms(transformation, Some(pivot));
337338
self.hints(selected.responses, local);
338339
}
339340
}
@@ -350,7 +351,7 @@ impl TransformOperation {
350351
self.is_constraint_to_axis() || !matches!(self, TransformOperation::Grabbing(_))
351352
}
352353

353-
pub fn constrain_axis(&mut self, axis: Axis, selected: &mut Selected, increment_mode: bool, mut local: bool, quad: Quad, transform: DAffine2) -> bool {
354+
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 {
354355
(*self, local) = match self {
355356
TransformOperation::Grabbing(translation) => {
356357
let (translation, local) = translation.with_constraint(axis, local);
@@ -362,19 +363,19 @@ impl TransformOperation {
362363
}
363364
_ => (*self, false),
364365
};
365-
self.apply_transform_operation(selected, increment_mode, local, quad, transform);
366+
self.apply_transform_operation(selected, increment_mode, local, quad, transform, pivot, local_transform);
366367
local
367368
}
368369

369-
pub fn grs_typed(&mut self, typed: Option<f64>, selected: &mut Selected, increment_mode: bool, local: bool, quad: Quad, transform: DAffine2) {
370+
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) {
370371
match self {
371372
TransformOperation::None => (),
372373
TransformOperation::Grabbing(translation) => translation.typed_distance = typed,
373374
TransformOperation::Rotating(rotation) => rotation.typed_angle = typed,
374375
TransformOperation::Scaling(scale) => scale.typed_factor = typed,
375376
};
376377

377-
self.apply_transform_operation(selected, increment_mode, local, quad, transform);
378+
self.apply_transform_operation(selected, increment_mode, local, quad, transform, pivot, local_transform);
378379
}
379380

380381
pub fn hints(&self, responses: &mut VecDeque<Message>, local: bool) {
@@ -456,15 +457,15 @@ impl TransformOperation {
456457
}
457458
}
458459

459-
pub fn negate(&mut self, selected: &mut Selected, increment_mode: bool, local: bool, quad: Quad, transform: DAffine2) {
460+
pub fn negate(&mut self, selected: &mut Selected, increment_mode: bool, local: bool, quad: Quad, transform: DAffine2, pivot: DVec2, local_transform: DAffine2) {
460461
if *self != TransformOperation::None {
461462
*self = match self {
462463
TransformOperation::Scaling(scale) => TransformOperation::Scaling(scale.negate()),
463464
TransformOperation::Rotating(rotation) => TransformOperation::Rotating(rotation.negate()),
464465
TransformOperation::Grabbing(translation) => TransformOperation::Grabbing(translation.negate()),
465466
_ => *self,
466467
};
467-
self.apply_transform_operation(selected, increment_mode, local, quad, transform);
468+
self.apply_transform_operation(selected, increment_mode, local, quad, transform, pivot, local_transform);
468469
}
469470
}
470471
}
@@ -590,11 +591,14 @@ impl<'a> Selected<'a> {
590591
responses.add(GraphOperationMessage::Vector { layer, modification_type });
591592

592593
if let Some((id, initial)) = handle.mirror {
593-
let direction = viewspace.transform_vector2(new_pos_viewport - relative).try_normalize();
594-
let length = viewspace.transform_vector2(initial - relative).length();
595-
let new_relative = direction.map_or(initial - relative, |direction| viewspace.inverse().transform_vector2(-direction * length));
596-
let modification_type = id.set_relative_position(new_relative);
597-
responses.add(GraphOperationMessage::Vector { layer, modification_type });
594+
// When the handle is scaled to zero, don't update the mirror handle
595+
if (new_pos_viewport - relative).length_squared() > f64::EPSILON {
596+
let direction = viewspace.transform_vector2(new_pos_viewport - relative).try_normalize();
597+
let length = viewspace.transform_vector2(initial - relative).length();
598+
let new_relative = direction.map_or(initial - relative, |direction| viewspace.inverse().transform_vector2(-direction * length));
599+
let modification_type = id.set_relative_position(new_relative);
600+
responses.add(GraphOperationMessage::Vector { layer, modification_type });
601+
}
598602
}
599603
}
600604
}
@@ -624,8 +628,8 @@ impl<'a> Selected<'a> {
624628
}
625629
}
626630

627-
pub fn update_transforms(&mut self, delta: DAffine2) {
628-
let pivot = DAffine2::from_translation(*self.pivot);
631+
pub fn update_transforms(&mut self, delta: DAffine2, pivot: Option<DVec2>) {
632+
let pivot = DAffine2::from_translation(pivot.unwrap_or_else(|| *self.pivot));
629633
let transformation = pivot * delta * pivot.inverse();
630634
match self.tool_type {
631635
ToolType::Pen => self.apply_transform_pen(transformation),

editor/src/messages/tool/common_functionality/compass_rose.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::consts::{COMPASS_ROSE_ARROW_CLICK_TARGET_ANGLE, COMPASS_ROSE_HOVER_RING_DIAMETER, COMPASS_ROSE_RING_INNER_DIAMETER};
2+
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
23
use crate::messages::prelude::DocumentMessageHandler;
34

45
use glam::{DAffine2, DVec2};
@@ -10,9 +11,27 @@ pub struct CompassRose {
1011
}
1112

1213
impl CompassRose {
13-
pub fn refresh_transform(&mut self, document: &DocumentMessageHandler) {
14-
let [min, max] = document.selected_visible_and_unlock_layers_bounding_box_viewport().unwrap_or([DVec2::ZERO, DVec2::ONE]);
15-
self.compass_center = (DAffine2::from_translation(min) * DAffine2::from_scale(max - min)).transform_point2(DVec2::splat(0.5));
14+
fn get_layer_pivot_transform(layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> DAffine2 {
15+
let [min, max] = document.metadata().nonzero_bounding_box(layer);
16+
17+
let bounds_transform = DAffine2::from_translation(min) * DAffine2::from_scale(max - min);
18+
let layer_transform = document.metadata().transform_to_viewport(layer);
19+
layer_transform * bounds_transform
20+
}
21+
pub fn refresh_position(&mut self, document: &DocumentMessageHandler) {
22+
let selected_nodes = document.network_interface.selected_nodes(&[]).unwrap();
23+
let mut layers = selected_nodes.selected_visible_and_unlocked_layers(&document.network_interface);
24+
25+
let Some(first) = layers.next() else { return };
26+
let count = layers.count() + 1;
27+
let transform = if count == 1 {
28+
Self::get_layer_pivot_transform(first, document)
29+
} else {
30+
let [min, max] = document.selected_visible_and_unlock_layers_bounding_box_viewport().unwrap_or([DVec2::ZERO, DVec2::ONE]);
31+
DAffine2::from_translation(min) * DAffine2::from_scale(max - min)
32+
};
33+
34+
self.compass_center = transform.transform_point2(DVec2::splat(0.5));
1635
}
1736

1837
pub fn compass_rose_position(&self) -> DVec2 {

editor/src/messages/tool/common_functionality/pivot.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,12 @@ impl Pivot {
111111
.selected_visible_and_unlocked_layers(&document.network_interface)
112112
{
113113
let transform = Self::get_layer_pivot_transform(layer, document);
114+
// Only update the pivot when computed position is finite.
115+
if transform.matrix2.determinant().abs() <= f64::EPSILON {
116+
return;
117+
};
114118
let pivot = transform.inverse().transform_point2(position);
115-
// Only update the pivot when computed position is finite. Infinite can happen when scale is 0.
116-
if pivot.is_finite() {
117-
responses.add(GraphOperationMessage::TransformSetPivot { layer, pivot });
118-
}
119+
responses.add(GraphOperationMessage::TransformSetPivot { layer, pivot });
119120
}
120121
}
121122

editor/src/messages/tool/common_functionality/shape_editor.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,14 +733,16 @@ impl ShapeState {
733733
}
734734

735735
/// Move the selected points by dragging the mouse.
736+
#[allow(clippy::too_many_arguments)]
736737
pub fn move_selected_points(
737738
&self,
738739
handle_lengths: Option<OpposingHandleLengths>,
739740
document: &DocumentMessageHandler,
740741
delta: DVec2,
741742
equidistant: bool,
742-
responses: &mut VecDeque<Message>,
743743
in_viewport_space: bool,
744+
opposite_handle_position: Option<DVec2>,
745+
responses: &mut VecDeque<Message>,
744746
) {
745747
for (&layer, state) in &self.selected_shape_state {
746748
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue };
@@ -791,6 +793,11 @@ impl ShapeState {
791793

792794
let new_relative = if equidistant {
793795
-(handle_position - anchor_position)
796+
}
797+
// If the handle is very close to the anchor, return the original position
798+
else if (handle_position - anchor_position).length_squared() < f64::EPSILON * 1e5 {
799+
let Some(opposite_handle_position) = opposite_handle_position else { continue };
800+
opposite_handle_position - anchor_position
794801
} else {
795802
// TODO: Is this equivalent to `transform_to_document_space`? If changed, the before and after should be tested.
796803
let transform = document.metadata().document_to_viewport.inverse() * transform_to_viewport_space;

0 commit comments

Comments
 (0)