Fix 'Shallow Select' mode behavior for selection context transference (#2604)

* Fix ancestor always returning None during shallow select

* Fixes

* fix shift remove on both

* cleanup

* one more cleanup

* final(?) fix

* some cleanup

* more stuff

* make shallow the default

* fixes

* fix

* fix

* fix

* Code review

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
mTvare 2025-04-30 08:54:48 +05:30 committed by GitHub
parent 23b2c5bdf2
commit 90be1f42c6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 179 additions and 71 deletions

View file

@ -310,13 +310,10 @@ impl OverlayContext {
}
pub fn draw_angle(&mut self, pivot: DVec2, radius: f64, arc_radius: f64, offset_angle: f64, angle: f64) {
let color_line = COLOR_OVERLAY_BLUE;
let end_point1 = pivot + radius * DVec2::from_angle(angle + offset_angle);
let end_point2 = pivot + radius * DVec2::from_angle(offset_angle);
self.line(pivot, end_point1, Some(color_line), None);
self.line(pivot, end_point2, Some(color_line), None);
self.line(pivot, end_point1, None, None);
self.dashed_line(pivot, end_point2, None, None, Some(2.), Some(2.), Some(0.5));
self.draw_arc(pivot, arc_radius, offset_angle, (angle) % TAU + offset_angle);
}

View file

@ -261,11 +261,21 @@ impl LayerNodeIdentifier {
metadata.get_relations(self).and_then(|relations| relations.last_child)
}
/// Does the layer have children? If so, then it is a folder
/// Does the layer have children? If so, then it is a folder.
pub fn has_children(self, metadata: &DocumentMetadata) -> bool {
self.first_child(metadata).is_some()
}
/// Is the layer a child of the given layer?
pub fn is_child_of(self, metadata: &DocumentMetadata, parent: &LayerNodeIdentifier) -> bool {
parent.children(metadata).any(|child| child == self)
}
/// Is the layer an ancestor of the given layer?
pub fn is_ancestor_of(self, metadata: &DocumentMetadata, child: &LayerNodeIdentifier) -> bool {
child.ancestors(metadata).any(|ancestor| ancestor == self)
}
/// Iterator over all direct children (excluding self and recursive children)
pub fn children(self, metadata: &DocumentMetadata) -> AxisIter {
AxisIter {

View file

@ -10,6 +10,7 @@ fn draw_dashed_line(line_start: DVec2, line_end: DVec2, transform: DAffine2, ove
overlay_context.dashed_line(min_viewport, max_viewport, None, None, Some(2.), Some(2.), Some(0.5));
}
/// Draws a solid line with a length annotation between two points transformed by the given affine transformations.
fn draw_line_with_length(line_start: DVec2, line_end: DVec2, transform: DAffine2, document_to_viewport: DAffine2, overlay_context: &mut OverlayContext, label_alignment: LabelAlignment) {
let transform_to_document = document_to_viewport.inverse() * transform;

View file

@ -267,7 +267,7 @@ impl Fsm for ArtboardToolFsmState {
let constrain_square = input.keyboard.get(constrain_axis_or_aspect as usize);
tool_data.resize_artboard(responses, document, input, from_center, constrain_square);
// AutoPanning
// Auto-panning
let messages = [
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
@ -306,7 +306,7 @@ impl Fsm for ArtboardToolFsmState {
bounds.bounds[0] = position.round();
bounds.bounds[1] = position.round() + size.round();
// AutoPanning
// Auto-panning
let messages = [
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
@ -345,7 +345,7 @@ impl Fsm for ArtboardToolFsmState {
})
}
// AutoPanning
// Auto-panning
let messages = [
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),
@ -377,25 +377,25 @@ impl Fsm for ArtboardToolFsmState {
ArtboardToolFsmState::Ready { hovered }
}
(ArtboardToolFsmState::ResizingBounds, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
// AutoPanning
// Auto-panning
let _ = tool_data.auto_panning.shift_viewport(input, responses);
ArtboardToolFsmState::ResizingBounds
}
(ArtboardToolFsmState::Dragging, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
// AutoPanning
// Auto-panning
tool_data.auto_panning.shift_viewport(input, responses);
ArtboardToolFsmState::Dragging
}
(ArtboardToolFsmState::Drawing, ArtboardToolMessage::PointerOutsideViewport { .. }) => {
// AutoPanning
// Auto-panning
tool_data.auto_panning.shift_viewport(input, responses);
ArtboardToolFsmState::Drawing
}
(state, ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }) => {
// AutoPanning
// Auto-panning
let messages = [
ArtboardToolMessage::PointerOutsideViewport { constrain_axis_or_aspect, center }.into(),
ArtboardToolMessage::PointerMove { constrain_axis_or_aspect, center }.into(),

View file

@ -52,8 +52,8 @@ pub enum SelectOptionsUpdate {
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug, Hash, serde::Serialize, serde::Deserialize, specta::Type)]
pub enum NestedSelectionBehavior {
#[default]
Deepest,
Shallowest,
Deepest,
}
impl fmt::Display for NestedSelectionBehavior {
@ -115,7 +115,7 @@ impl ToolMetadata for SelectTool {
impl SelectTool {
fn deep_selection_widget(&self) -> WidgetHolder {
let layer_selection_behavior_entries = [NestedSelectionBehavior::Deepest, NestedSelectionBehavior::Shallowest]
let layer_selection_behavior_entries = [NestedSelectionBehavior::Shallowest, NestedSelectionBehavior::Deepest]
.iter()
.map(|mode| {
MenuListEntry::new(format!("{mode:?}"))
@ -125,7 +125,7 @@ impl SelectTool {
.collect();
DropdownInput::new(vec![layer_selection_behavior_entries])
.selected_index(Some((self.tool_data.nested_selection_behavior == NestedSelectionBehavior::Shallowest) as u32))
.selected_index(Some((self.tool_data.nested_selection_behavior == NestedSelectionBehavior::Deepest) as u32))
.tooltip("Choose if clicking nested layers directly selects the deepest, or selects the shallowest and deepens by double clicking")
.widget_holder()
}
@ -288,11 +288,24 @@ impl ToolTransition for SelectTool {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum SelectToolFsmState {
Ready { selection: NestedSelectionBehavior },
Drawing { selection_shape: SelectionShapeType, has_drawn: bool },
Dragging { axis: Axis, using_compass: bool, has_dragged: bool },
Ready {
selection: NestedSelectionBehavior,
},
Drawing {
selection_shape: SelectionShapeType,
has_drawn: bool,
},
Dragging {
axis: Axis,
using_compass: bool,
has_dragged: bool,
deepest: bool,
remove: bool,
},
ResizingBounds,
SkewingBounds { skew: Key },
SkewingBounds {
skew: Key,
},
RotatingBounds,
DraggingPivot,
}
@ -918,7 +931,7 @@ impl Fsm for SelectToolFsmState {
let axis_state = compass_rose_state.axis_type().filter(|_| can_grab_compass_rose);
(axis_state.unwrap_or_default(), axis_state.is_some())
};
SelectToolFsmState::Dragging { axis, using_compass, has_dragged: false }
SelectToolFsmState::Dragging { axis, using_compass, has_dragged: false, deepest: input.keyboard.key(select_deepest), remove: input.keyboard.key(extend_selection) }
}
// Dragging near the transform cage bounding box to rotate it
else if rotating_bounds {
@ -954,7 +967,8 @@ impl Fsm for SelectToolFsmState {
// Dragging a selection box
else {
tool_data.layers_dragging = selected;
if !input.keyboard.key(extend_selection) && !input.keyboard.key(remove_from_selection) {
let extend = input.keyboard.key(extend_selection);
if !extend && !input.keyboard.key(remove_from_selection) {
responses.add(DocumentMessage::DeselectAllLayers);
tool_data.layers_dragging.clear();
}
@ -964,13 +978,13 @@ impl Fsm for SelectToolFsmState {
selected = intersection_list;
match tool_data.nested_selection_behavior {
NestedSelectionBehavior::Shallowest if !input.keyboard.key(select_deepest) => drag_shallowest_manipulation(responses, selected, tool_data, document),
_ => drag_deepest_manipulation(responses, selected, tool_data, document),
NestedSelectionBehavior::Shallowest if !input.keyboard.key(select_deepest) => drag_shallowest_manipulation(responses, selected, tool_data, document, false, extend),
_ => drag_deepest_manipulation(responses, selected, tool_data, document, false),
}
tool_data.get_snap_candidates(document, input);
responses.add(DocumentMessage::StartTransaction);
SelectToolFsmState::Dragging { axis: Axis::None, using_compass: false, has_dragged: false }
SelectToolFsmState::Dragging { axis: Axis::None, using_compass: false, has_dragged: false, deepest: input.keyboard.key(select_deepest), remove: input.keyboard.key(extend_selection) }
} else {
let selection_shape = if input.keyboard.key(lasso_select) { SelectionShapeType::Lasso } else { SelectionShapeType::Box };
SelectToolFsmState::Drawing { selection_shape, has_drawn: false }
@ -986,7 +1000,16 @@ impl Fsm for SelectToolFsmState {
let selection = tool_data.nested_selection_behavior;
SelectToolFsmState::Ready { selection }
}
(SelectToolFsmState::Dragging { axis, using_compass, has_dragged }, SelectToolMessage::PointerMove(modifier_keys)) => {
(
SelectToolFsmState::Dragging {
axis,
using_compass,
has_dragged,
deepest,
remove,
},
SelectToolMessage::PointerMove(modifier_keys),
) => {
if !has_dragged {
responses.add(ToolMessage::UpdateHints);
}
@ -1028,7 +1051,7 @@ impl Fsm for SelectToolFsmState {
}
tool_data.drag_current += mouse_delta;
// AutoPanning
// Auto-panning
let messages = [
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
SelectToolMessage::PointerMove(modifier_keys).into(),
@ -1039,6 +1062,8 @@ impl Fsm for SelectToolFsmState {
axis,
using_compass,
has_dragged: true,
deepest,
remove,
}
}
(SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerMove(modifier_keys)) => {
@ -1080,7 +1105,7 @@ impl Fsm for SelectToolFsmState {
selected.apply_transformation(bounds.original_bound_transform * transformation * bounds.original_bound_transform.inverse(), None);
// AutoPanning
// Auto-panning
let messages = [
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
SelectToolMessage::PointerMove(modifier_keys).into(),
@ -1169,7 +1194,7 @@ impl Fsm for SelectToolFsmState {
let snapped_mouse_position = mouse_position;
tool_data.pivot.set_viewport_position(snapped_mouse_position, document, responses);
// AutoPanning
// Auto-panning
let messages = [
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
SelectToolMessage::PointerMove(modifier_keys).into(),
@ -1190,7 +1215,7 @@ impl Fsm for SelectToolFsmState {
extend_lasso(&mut tool_data.lasso_polygon, tool_data.drag_current);
}
// AutoPanning
// Auto-panning
let messages = [
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
SelectToolMessage::PointerMove(modifier_keys).into(),
@ -1227,17 +1252,32 @@ impl Fsm for SelectToolFsmState {
let selection = tool_data.nested_selection_behavior;
SelectToolFsmState::Ready { selection }
}
(SelectToolFsmState::Dragging { axis, using_compass, has_dragged }, SelectToolMessage::PointerOutsideViewport(_)) => {
// AutoPanning
(
SelectToolFsmState::Dragging {
axis,
using_compass,
has_dragged,
deepest,
remove,
},
SelectToolMessage::PointerOutsideViewport(_),
) => {
// Auto-panning
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
tool_data.drag_current += shift;
tool_data.drag_start += shift;
}
SelectToolFsmState::Dragging { axis, using_compass, has_dragged }
SelectToolFsmState::Dragging {
axis,
using_compass,
has_dragged,
deepest,
remove,
}
}
(SelectToolFsmState::ResizingBounds | SelectToolFsmState::SkewingBounds { .. }, SelectToolMessage::PointerOutsideViewport(_)) => {
// AutoPanning
// Auto-panning
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
if let Some(bounds) = &mut tool_data.bounding_box_manager {
bounds.center_of_transformation += shift;
@ -1248,13 +1288,13 @@ impl Fsm for SelectToolFsmState {
self
}
(SelectToolFsmState::DraggingPivot, SelectToolMessage::PointerOutsideViewport(_)) => {
// AutoPanning
// Auto-panning
let _ = tool_data.auto_panning.shift_viewport(input, responses);
self
}
(SelectToolFsmState::Drawing { .. }, SelectToolMessage::PointerOutsideViewport(_)) => {
// AutoPanning
// Auto-panning
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
tool_data.drag_start += shift;
}
@ -1262,7 +1302,7 @@ impl Fsm for SelectToolFsmState {
self
}
(state, SelectToolMessage::PointerOutsideViewport(modifier_keys)) => {
// AutoPanning
// Auto-panning
let messages = [
SelectToolMessage::PointerOutsideViewport(modifier_keys.clone()).into(),
SelectToolMessage::PointerMove(modifier_keys).into(),
@ -1271,7 +1311,7 @@ impl Fsm for SelectToolFsmState {
state
}
(SelectToolFsmState::Dragging { has_dragged, .. }, SelectToolMessage::DragStop { remove_from_selection }) => {
(SelectToolFsmState::Dragging { has_dragged, remove, deepest, .. }, SelectToolMessage::DragStop { remove_from_selection }) => {
// Deselect layer if not snap dragging
responses.add(DocumentMessage::EndTransaction);
tool_data.axis_align = false;
@ -1306,15 +1346,28 @@ impl Fsm for SelectToolFsmState {
.collect(),
});
}
} else if let Some(selecting_layer) = tool_data.select_single_layer.take() {
} else if tool_data.select_single_layer.take().is_some() {
// Previously, we may have had many layers selected. If the user clicks without dragging, we should just select the one layer that has been clicked.
if !has_dragged {
if selecting_layer == LayerNodeIdentifier::ROOT_PARENT {
log::error!("selecting_layer should not be ROOT_PARENT");
} else {
responses.add(NodeGraphMessage::SelectedNodesSet {
nodes: vec![selecting_layer.to_node()],
});
let selected = document.click_list(input).collect::<Vec<_>>();
let intersection = document.find_deepest(&selected);
if let Some(intersection) = intersection {
tool_data.layer_selected_on_start = Some(intersection);
match tool_data.nested_selection_behavior {
NestedSelectionBehavior::Shallowest if remove && !deepest => drag_shallowest_manipulation(responses, selected, tool_data, document, true, true),
NestedSelectionBehavior::Deepest if remove => drag_deepest_manipulation(responses, selected, tool_data, document, true),
NestedSelectionBehavior::Shallowest if !deepest => drag_shallowest_manipulation(responses, selected, tool_data, document, false, true),
_ => {
responses.add(DocumentMessage::DeselectAllLayers);
tool_data.layers_dragging.clear();
drag_deepest_manipulation(responses, selected, tool_data, document, false)
}
}
tool_data.get_snap_candidates(document, input);
responses.add(DocumentMessage::StartTransaction);
}
}
}
@ -1528,7 +1581,7 @@ impl Fsm for SelectToolFsmState {
]);
responses.add(FrontendMessage::UpdateInputHints { hint_data });
}
SelectToolFsmState::Dragging { axis, using_compass, has_dragged } if *has_dragged => {
SelectToolFsmState::Dragging { axis, using_compass, has_dragged, .. } if *has_dragged => {
let mut hint_data = vec![
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
HintGroup(vec![
@ -1591,16 +1644,59 @@ fn not_artboard(document: &DocumentMessageHandler) -> impl Fn(&LayerNodeIdentifi
|&layer| layer != LayerNodeIdentifier::ROOT_PARENT && !document.network_interface.is_artboard(&layer.to_node(), &[])
}
fn drag_shallowest_manipulation(responses: &mut VecDeque<Message>, selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData, document: &DocumentMessageHandler) {
for layer in selected {
let ancestor = layer
.ancestors(document.metadata())
.filter(not_artboard(document))
.find(|&ancestor| document.network_interface.selected_nodes().selected_layers_contains(ancestor, document.metadata()));
fn drag_shallowest_manipulation(responses: &mut VecDeque<Message>, selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData, document: &DocumentMessageHandler, remove: bool, exists: bool) {
if selected.is_empty() {
return;
}
let new_selected = ancestor.unwrap_or_else(|| layer.ancestors(document.metadata()).filter(not_artboard(document)).last().unwrap_or(layer));
tool_data.layers_dragging.retain(|layer| !layer.ancestors(document.metadata()).any(|ancestor| ancestor == new_selected));
tool_data.layers_dragging.push(new_selected);
let clicked_layer = document.find_deepest(&selected).unwrap_or_else(|| {
LayerNodeIdentifier::ROOT_PARENT
.children(document.metadata())
.next()
.expect("ROOT_PARENT should have at least one layer when clicking")
});
let metadata = document.metadata();
let selected_layers = document.network_interface.selected_nodes().selected_layers(document.metadata()).collect::<Vec<_>>();
let final_selection: Option<LayerNodeIdentifier> = (!selected_layers.is_empty() && selected_layers != vec![LayerNodeIdentifier::ROOT_PARENT]).then_some(()).and_then(|_| {
let mut relevant_layers = document.network_interface.selected_nodes().selected_layers(document.metadata()).collect::<Vec<_>>();
if !relevant_layers.contains(&clicked_layer) {
relevant_layers.push(clicked_layer);
}
clicked_layer
.ancestors(metadata)
.filter(not_artboard(document))
.find(|&ancestor| relevant_layers.iter().all(|layer| *layer == ancestor || ancestor.is_ancestor_of(metadata, layer)))
.and_then(|least_common_ancestor| {
let common_siblings: Vec<_> = least_common_ancestor.children(metadata).collect();
(clicked_layer == least_common_ancestor)
.then_some(least_common_ancestor)
.or_else(|| common_siblings.iter().find(|&&child| clicked_layer == child || child.is_ancestor_of(metadata, &clicked_layer)).copied())
})
});
if final_selection.is_some_and(|layer| selected_layers.iter().any(|selected| layer.is_child_of(metadata, selected))) {
if exists && remove && selected_layers.len() == 1 {
responses.add(DocumentMessage::DeselectAllLayers);
tool_data.layers_dragging.clear();
}
return;
}
if !exists && !remove {
responses.add(DocumentMessage::DeselectAllLayers);
tool_data.layers_dragging.clear();
}
let new_selected = final_selection.unwrap_or_else(|| clicked_layer.ancestors(document.metadata()).filter(not_artboard(document)).last().unwrap_or(clicked_layer));
tool_data.layers_dragging.extend(vec![new_selected]);
tool_data.layers_dragging.retain(|&selected_layer| !selected_layer.is_child_of(metadata, &new_selected));
if remove {
tool_data.layers_dragging.retain(|&selected_layer| clicked_layer != selected_layer);
if selected_layers.contains(&new_selected) {
tool_data.layers_dragging.retain(|&selected_layer| new_selected != selected_layer);
}
}
responses.add(NodeGraphMessage::SelectedNodesSet {
@ -1619,15 +1715,18 @@ fn drag_shallowest_manipulation(responses: &mut VecDeque<Message>, selected: Vec
});
}
fn drag_deepest_manipulation(responses: &mut VecDeque<Message>, selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData, document: &DocumentMessageHandler) {
tool_data.layers_dragging.append(&mut vec![
document.find_deepest(&selected).unwrap_or(
LayerNodeIdentifier::ROOT_PARENT
.children(document.metadata())
.next()
.expect("ROOT_PARENT should have a layer child when clicking"),
),
]);
fn drag_deepest_manipulation(responses: &mut VecDeque<Message>, selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData, document: &DocumentMessageHandler, remove: bool) {
let layer = document.find_deepest(&selected).unwrap_or(
LayerNodeIdentifier::ROOT_PARENT
.children(document.metadata())
.next()
.expect("ROOT_PARENT should have a layer child when clicking"),
);
if !remove {
tool_data.layers_dragging.extend(vec![layer]);
} else {
tool_data.layers_dragging.retain(|&selected_layer| layer != selected_layer);
}
responses.add(NodeGraphMessage::SelectedNodesSet {
nodes: tool_data
.layers_dragging

View file

@ -702,7 +702,7 @@ impl Fsm for TextToolFsmState {
});
responses.add(NodeGraphMessage::RunDocumentGraph);
// AutoPanning
// Auto-panning
let messages = [
TextToolMessage::PointerOutsideViewport { center, lock_ratio }.into(),
TextToolMessage::PointerMove { center, lock_ratio }.into(),
@ -725,7 +725,7 @@ impl Fsm for TextToolFsmState {
TextToolFsmState::Placing
}
(TextToolFsmState::ResizingBounds | TextToolFsmState::Dragging, TextToolMessage::PointerOutsideViewport { .. }) => {
// AutoPanning
// Auto-panning
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, responses) {
if let Some(bounds) = &mut tool_data.bounding_box_manager {
bounds.center_of_transformation += shift;

View file

@ -242,7 +242,7 @@ impl MessageHandler<TransformLayerMessage, TransformData<'_>> for TransformLayer
if matches!(axis_constraint, Axis::Both | Axis::X) && translation.x != 0. {
let end = if self.local { (quad[1] - quad[0]).rotate(e1) + quad[0] } else { quad[1] };
overlay_context.line(quad[0], end, None, None);
overlay_context.dashed_line(quad[0], end, None, None, Some(2.), Some(2.), Some(0.5));
let x_transform = DAffine2::from_translation((quad[0] + end) / 2.);
overlay_context.text(&format_rounded(translation.x, 3), COLOR_OVERLAY_BLUE, None, x_transform, 4., [Pivot::Middle, Pivot::End]);
@ -250,7 +250,7 @@ impl MessageHandler<TransformLayerMessage, TransformData<'_>> for TransformLayer
if matches!(axis_constraint, Axis::Both | Axis::Y) && translation.y != 0. {
let end = if self.local { (quad[3] - quad[0]).rotate(e1) + quad[0] } else { quad[3] };
overlay_context.line(quad[0], end, None, None);
overlay_context.dashed_line(quad[0], end, None, None, Some(2.), Some(2.), Some(0.5));
let x_parameter = viewport_translate.x.clamp(-1., 1.);
let y_transform = DAffine2::from_translation((quad[0] + end) / 2. + x_parameter * DVec2::X * 0.);
let pivot_selection = if x_parameter >= -1e-3 { Pivot::Start } else { Pivot::End };
@ -258,9 +258,10 @@ impl MessageHandler<TransformLayerMessage, TransformData<'_>> for TransformLayer
overlay_context.text(&format_rounded(translation.y, 2), COLOR_OVERLAY_BLUE, None, y_transform, 3., [pivot_selection, Pivot::Middle]);
}
}
if matches!(axis_constraint, Axis::Both) && translation.x != 0. && translation.y != 0. {
overlay_context.dashed_line(quad[1], quad[2], None, None, Some(2.), Some(2.), Some(0.5));
overlay_context.dashed_line(quad[3], quad[2], None, None, Some(2.), Some(2.), Some(0.5));
overlay_context.line(quad[1], quad[2], None, None);
overlay_context.line(quad[3], quad[2], None, None);
}
}
TransformOperation::Scaling(scale) => {
@ -274,7 +275,7 @@ impl MessageHandler<TransformLayerMessage, TransformData<'_>> for TransformLayer
let end_point = pivot + local_edge * scale.max(1.);
if scale > 0. {
overlay_context.dashed_line(pivot, boundary_point, None, None, Some(4.), Some(4.), Some(0.5));
overlay_context.dashed_line(pivot, boundary_point, None, None, Some(2.), Some(2.), Some(0.5));
}
overlay_context.line(boundary_point, end_point, None, None);