Restore select tool functionality and shallow select mode (#1583)

* Restore select tool functionality

* UI tweak

* Change all of the things

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube
2024-01-18 22:28:45 +00:00
committed by GitHub
co-authored by Keavon Chambers
parent 5c9d3c5d75
commit 208e907fa4
4 changed files with 150 additions and 133 deletions
@@ -398,12 +398,29 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer }); responses.add(FrontendMessage::UpdateDocumentLayerStructure { data_buffer });
} }
DuplicateSelectedLayers => { DuplicateSelectedLayers => {
// TODO: Reimplement selected layer duplication self.backup(responses);
// self.backup(responses); for layer_ancestors in self.metadata.shallowest_unique_layers(self.selected_nodes.selected_layers(&self.metadata)) {
// self.layer_range_selection_reference = None; let Some(layer) = layer_ancestors.last().copied() else { continue };
// for path in self.selected_layers_sorted() { let Some(parent) = layer.parent(&self.metadata) else { continue };
// responses.add(DocumentOperation::DuplicateLayer { path: path.to_vec() }); let Some(node) = self.network().nodes.get(&layer.to_node()).and_then(|node| node.inputs.first()).and_then(|input| input.as_node()) else {
// } continue;
};
let nodes = NodeGraphMessageHandler::copy_nodes(
self.network(),
&self
.network()
.upstream_flow_back_from_nodes(vec![node], false)
.enumerate()
.map(|(index, (_, node_id))| (node_id, NodeId(index as u64)))
.collect(),
)
.collect();
let id = NodeId(generate_uuid());
let insert_index = -1;
responses.add(GraphOperationMessage::NewCustomLayer { id, nodes, parent, insert_index });
}
} }
FlipSelectedLayers { flip_axis } => { FlipSelectedLayers { flip_axis } => {
self.backup(responses); self.backup(responses);
@@ -86,33 +86,20 @@ impl SelectedEdges {
let mut pivot = self.pivot_from_bounds(min, max); let mut pivot = self.pivot_from_bounds(min, max);
if let Some(center_around) = center_around { if let Some(center_around) = center_around {
// The below ratio is: `dragging edge / being centered`. let center_around = transform.inverse().transform_point2(center_around);
// The `is_finite()` checks are in case the user is dragging the edge where the pivot is located (in which case the centering mode is ignored).
if self.top { if self.top {
let ratio = (center_around.y - min.y) / (center_around.y - self.bounds[0].y); pivot.y = center_around.y;
if ratio.is_finite() { max.y = center_around.y * 2. - min.y;
max.y = center_around.y + ratio * (self.bounds[1].y - center_around.y);
pivot.y = center_around.y;
}
} else if self.bottom { } else if self.bottom {
let ratio = (max.y - center_around.y) / (self.bounds[1].y - center_around.y); pivot.y = center_around.y;
if ratio.is_finite() { min.y = center_around.y * 2. - max.y;
min.y = center_around.y - ratio * (center_around.y - self.bounds[0].y);
pivot.y = center_around.y;
}
} }
if self.left { if self.left {
let ratio = (center_around.x - min.x) / (center_around.x - self.bounds[0].x); pivot.x = center_around.x;
if ratio.is_finite() { max.x = center_around.x * 2. - min.x;
max.x = center_around.x + ratio * (self.bounds[1].x - center_around.x);
pivot.x = center_around.x;
}
} else if self.right { } else if self.right {
let ratio = (max.x - center_around.x) / (self.bounds[1].x - center_around.x); pivot.x = center_around.x;
if ratio.is_finite() { min.x = center_around.x * 2. - max.x;
min.x = center_around.x - ratio * (center_around.x - self.bounds[0].x);
pivot.x = center_around.x;
}
} }
} }
@@ -128,7 +115,9 @@ impl SelectedEdges {
let delta_size = new_size - size; let delta_size = new_size - size;
min -= delta_size * min_pivot; min -= delta_size * min_pivot;
max = min + new_size; max = min + new_size;
} else if let Some(SizeSnapData { manager, points, snap_data }) = snap { }
if let Some(SizeSnapData { manager, points, snap_data }) = snap {
let view_to_doc = snap_data.document.metadata.document_to_viewport.inverse(); let view_to_doc = snap_data.document.metadata.document_to_viewport.inverse();
let bounds_to_doc = view_to_doc * transform; let bounds_to_doc = view_to_doc * transform;
let mut best_snap = SnappedPoint::infinite_snap(pivot); let mut best_snap = SnappedPoint::infinite_snap(pivot);
@@ -140,7 +129,13 @@ impl SelectedEdges {
let normalised = (bounds_space - self.bounds[0]) / (self.bounds[1] - self.bounds[0]); let normalised = (bounds_space - self.bounds[0]) / (self.bounds[1] - self.bounds[0]);
let updated = normalised * (max - min) + min; let updated = normalised * (max - min) + min;
point.document_point = bounds_to_doc.transform_point2(updated); point.document_point = bounds_to_doc.transform_point2(updated);
let mut snapped = if !(self.top || self.bottom) || !(self.left || self.right) { let mut snapped = if constrain {
let constraint = SnapConstraint::Line {
origin: point.document_point,
direction: (point.document_point - bounds_to_doc.transform_point2(pivot)).normalize_or_zero(),
};
manager.constrained_snap(&snap_data, point, constraint, None)
} else if !(self.top || self.bottom) || !(self.left || self.right) {
let axis = if !(self.top || self.bottom) { DVec2::X } else { DVec2::Y }; let axis = if !(self.top || self.bottom) { DVec2::X } else { DVec2::Y };
let constraint = SnapConstraint::Line { let constraint = SnapConstraint::Line {
origin: point.document_point, origin: point.document_point,
@@ -158,10 +153,10 @@ impl SelectedEdges {
let snapped_bounds = bounds_to_doc.inverse().transform_point2(snapped.snapped_point_document); let snapped_bounds = bounds_to_doc.inverse().transform_point2(snapped.snapped_point_document);
let mut scale_factor = (snapped_bounds - pivot) / (updated - pivot); let mut scale_factor = (snapped_bounds - pivot) / (updated - pivot);
if !(self.left || self.right) { if !(self.left || self.right) && !constrain {
scale_factor.x = 1. scale_factor.x = 1.
} }
if !(self.top || self.bottom) { if !(self.top || self.bottom) && !constrain {
scale_factor.y = 1. scale_factor.y = 1.
} }
@@ -115,7 +115,7 @@ impl ArtboardToolData {
fn start_resizing(&mut self, _selected_edges: (bool, bool, bool, bool), _document: &DocumentMessageHandler, _input: &InputPreprocessorMessageHandler) { fn start_resizing(&mut self, _selected_edges: (bool, bool, bool, bool), _document: &DocumentMessageHandler, _input: &InputPreprocessorMessageHandler) {
if let Some(bounds) = &mut self.bounding_box_manager { if let Some(bounds) = &mut self.bounding_box_manager {
bounds.center_of_transformation = (bounds.bounds[0] + bounds.bounds[1]) / 2.; bounds.center_of_transformation = bounds.transform.transform_point2((bounds.bounds[0] + bounds.bounds[1]) / 2.);
} }
} }
@@ -1,18 +1,20 @@
#![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_arguments)]
use super::tool_prelude::*; use super::tool_prelude::*;
use crate::application::generate_uuid;
use crate::consts::{ROTATE_SNAP_ANGLE, SELECTION_TOLERANCE}; use crate::consts::{ROTATE_SNAP_ANGLE, SELECTION_TOLERANCE};
use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition; use crate::messages::input_mapper::utility_types::input_mouse::ViewportPosition;
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext; use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis}; use crate::messages::portfolio::document::utility_types::misc::{AlignAggregate, AlignAxis, FlipAxis};
use crate::messages::portfolio::document::utility_types::transformation::Selected; use crate::messages::portfolio::document::utility_types::transformation::Selected;
use crate::messages::tool;
use crate::messages::tool::common_functionality::graph_modification_utils::is_layer_fed_by_node_of_name; use crate::messages::tool::common_functionality::graph_modification_utils::is_layer_fed_by_node_of_name;
use crate::messages::tool::common_functionality::pivot::Pivot; use crate::messages::tool::common_functionality::pivot::Pivot;
use crate::messages::tool::common_functionality::snapping::{self, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnappedPoint}; use crate::messages::tool::common_functionality::snapping::{self, SnapCandidatePoint, SnapConstraint, SnapData, SnapManager, SnappedPoint};
use crate::messages::tool::common_functionality::transformation_cage::*; use crate::messages::tool::common_functionality::transformation_cage::*;
use graph_craft::document::NodeNetwork; use graph_craft::document::{NodeId, NodeNetwork};
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use std::fmt; use std::fmt;
@@ -96,21 +98,21 @@ impl ToolMetadata for SelectTool {
} }
impl SelectTool { impl SelectTool {
// fn deep_selection_widget(&self) -> WidgetHolder { fn deep_selection_widget(&self) -> WidgetHolder {
// let layer_selection_behavior_entries = [NestedSelectionBehavior::Deepest, NestedSelectionBehavior::Shallowest] let layer_selection_behavior_entries = [NestedSelectionBehavior::Deepest, NestedSelectionBehavior::Shallowest]
// .iter() .iter()
// .map(|mode| { .map(|mode| {
// MenuListEntry::new(mode.to_string()) MenuListEntry::new(mode.to_string())
// .value(mode.to_string()) .value(mode.to_string())
// .on_update(move |_| SelectToolMessage::SelectOptions(SelectOptionsUpdate::NestedSelectionBehavior(*mode)).into()) .on_update(move |_| SelectToolMessage::SelectOptions(SelectOptionsUpdate::NestedSelectionBehavior(*mode)).into())
// }) })
// .collect(); .collect();
// DropdownInput::new(vec![layer_selection_behavior_entries]) 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::Shallowest) as u32))
// .tooltip("Choose if clicking nested layers directly selects the deepest, or selects the shallowest and deepens by double clicking") .tooltip("Choose if clicking nested layers directly selects the deepest, or selects the shallowest and deepens by double clicking")
// .widget_holder() .widget_holder()
// } }
fn pivot_widget(&self, disabled: bool) -> WidgetHolder { fn pivot_widget(&self, disabled: bool) -> WidgetHolder {
PivotInput::new(self.tool_data.pivot.to_pivot_position()) PivotInput::new(self.tool_data.pivot.to_pivot_position())
@@ -163,10 +165,12 @@ impl SelectTool {
impl LayoutHolder for SelectTool { impl LayoutHolder for SelectTool {
fn layout(&self) -> Layout { fn layout(&self) -> Layout {
let mut widgets = Vec::new(); let mut widgets = Vec::new();
// widgets.push(self.deep_selection_widget()); // TODO: Reenable once Deep/Shallow Selection is implemented again
// Select mode (Deep/Shallow)
widgets.push(self.deep_selection_widget());
// Pivot // Pivot
// widgets.push(Separator::new(SeparatorType::Related).widget_holder()); // TODO: Reenable once Deep/Shallow Selection is implemented again widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.push(self.pivot_widget(self.tool_data.selected_layers_count == 0)); widgets.push(self.pivot_widget(self.tool_data.selected_layers_count == 0));
// Align // Align
@@ -179,13 +183,11 @@ impl LayoutHolder for SelectTool {
let disabled = self.tool_data.selected_layers_count == 0; let disabled = self.tool_data.selected_layers_count == 0;
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.extend(self.flip_widgets(disabled)); widgets.extend(self.flip_widgets(disabled));
widgets.push(PopoverButton::new("Flip", "Coming soon").disabled(disabled).widget_holder());
// Boolean // Boolean
if self.tool_data.selected_layers_count >= 2 { if self.tool_data.selected_layers_count >= 2 {
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
widgets.extend(self.boolean_widgets()); widgets.extend(self.boolean_widgets());
widgets.push(PopoverButton::new("Boolean", "Coming soon").widget_holder());
} }
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }])) Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }]))
@@ -259,7 +261,7 @@ struct SelectToolData {
layer_selected_on_start: Option<LayerNodeIdentifier>, layer_selected_on_start: Option<LayerNodeIdentifier>,
select_single_layer: Option<LayerNodeIdentifier>, select_single_layer: Option<LayerNodeIdentifier>,
has_dragged: bool, has_dragged: bool,
not_duplicated_layers: Option<Vec<LayerNodeIdentifier>>, non_duplicated_layers: Option<Vec<LayerNodeIdentifier>>,
bounding_box_manager: Option<BoundingBoxManager>, bounding_box_manager: Option<BoundingBoxManager>,
snap_manager: SnapManager, snap_manager: SnapManager,
cursor: MouseCursorIcon, cursor: MouseCursorIcon,
@@ -300,57 +302,54 @@ impl SelectToolData {
/// Duplicates the currently dragging layers. Called when Alt is pressed and the layers have not yet been duplicated. /// Duplicates the currently dragging layers. Called when Alt is pressed and the layers have not yet been duplicated.
fn start_duplicates(&mut self, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) { fn start_duplicates(&mut self, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
responses.add(DocumentMessage::DeselectAllLayers); self.non_duplicated_layers = Some(self.layers_dragging.clone());
let mut new_dragging = Vec::new();
for layer_ancestors in document.metadata().shallowest_unique_layers(self.layers_dragging.iter().copied().rev()) {
let Some(layer) = layer_ancestors.last().copied() else { continue };
let Some(parent) = layer.parent(&document.metadata) else { continue };
// Take the selected layers and store them in a separate list. // Copy the layer
self.not_duplicated_layers = Some(self.layers_dragging.clone()); let node = layer.to_node();
let Some(node) = document.network().nodes.get(&node).and_then(|node| node.inputs.first()).and_then(|input| input.as_node()) else {
continue;
};
// Duplicate each previously selected layer and select the new ones. let nodes = NodeGraphMessageHandler::copy_nodes(
for layer_ancestors in document.metadata().shallowest_unique_layers(self.layers_dragging.iter().copied()) { document.network(),
let layer = *layer_ancestors.last().unwrap(); &document
// Moves the original back to its starting position. .network()
responses.add_front(GraphOperationMessage::TransformChange { .upstream_flow_back_from_nodes(vec![node], false)
.enumerate()
.map(|(index, (_, node_id))| (node_id, NodeId(index as u64)))
.collect(),
)
.collect();
// Moves the layer back to its starting position.
responses.add(GraphOperationMessage::TransformChange {
layer, layer,
transform: DAffine2::from_translation(self.drag_start - self.drag_current), transform: DAffine2::from_translation(self.drag_start - self.drag_current),
transform_in: TransformIn::Viewport, transform_in: TransformIn::Viewport,
skip_rerender: true, skip_rerender: true,
}); });
// Copy the layers. let id = NodeId(generate_uuid());
// Not using the Copy message allows us to retrieve the ids of the new layers to initialize the drag. let insert_index = -1;
todo!(); let layer = LayerNodeIdentifier::new_unchecked(id);
// let layer = match document.document_legacy.layer(layer_path) { responses.add(GraphOperationMessage::NewCustomLayer { id, nodes, parent, insert_index });
// Ok(layer) => layer.clone(), new_dragging.push(layer);
// Err(e) => {
// warn!("Could not access selected layer {layer_path:?}: {e:?}");
// continue;
// }
// };
// let layer_metadata = *document.layer_metadata(layer_path);
// *layer_path.last_mut().unwrap() = generate_uuid();
// responses.add(Operation::InsertLayer {
// layer: Box::new(layer),
// destination_path: layer_path.clone(),
// insert_index: -1,
// duplicating: false,
// });
// responses.add(DocumentMessage::UpdateLayerMetadata {
// layer_path: layer_path.clone(),
// layer_metadata,
// });
} }
let nodes = new_dragging.iter().map(|layer| layer.to_node()).collect();
responses.add(NodeGraphMessage::SelectedNodesSet { nodes });
self.layers_dragging = new_dragging;
} }
/// Removes the duplicated layers. Called when Alt is released and the layers have previously been duplicated. /// Removes the duplicated layers. Called when Alt is released and the layers have previously been duplicated.
fn stop_duplicates(&mut self, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) { fn stop_duplicates(&mut self, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
let Some(originals) = self.not_duplicated_layers.take() else { let Some(original) = self.non_duplicated_layers.take() else {
return; return;
}; };
responses.add(DocumentMessage::DeselectAllLayers);
// Delete the duplicated layers // Delete the duplicated layers
for layer_ancestors in document.metadata().shallowest_unique_layers(self.layers_dragging.iter().copied()) { for layer_ancestors in document.metadata().shallowest_unique_layers(self.layers_dragging.iter().copied()) {
responses.add(GraphOperationMessage::DeleteLayer { responses.add(GraphOperationMessage::DeleteLayer {
@@ -358,22 +357,17 @@ impl SelectToolData {
}); });
} }
// Move the original to under the mouse for &layer in &original {
for layer_ancestors in document.metadata().shallowest_unique_layers(originals.iter().copied()) { responses.add(GraphOperationMessage::TransformChange {
responses.add_front(GraphOperationMessage::TransformChange { layer,
layer: *layer_ancestors.last().unwrap(),
transform: DAffine2::from_translation(self.drag_current - self.drag_start), transform: DAffine2::from_translation(self.drag_current - self.drag_start),
transform_in: TransformIn::Viewport, transform_in: TransformIn::Viewport,
skip_rerender: true, skip_rerender: true,
}); });
} }
let nodes = original.iter().map(|layer| layer.to_node()).collect();
// Select the originals responses.add(NodeGraphMessage::SelectedNodesSet { nodes });
responses.add(NodeGraphMessage::SelectedNodesSet { self.layers_dragging = original;
nodes: originals.iter().map(|layer| layer.to_node()).collect::<Vec<_>>(),
});
self.layers_dragging = originals;
} }
} }
@@ -455,7 +449,7 @@ impl Fsm for SelectToolFsmState {
self self
} }
(SelectToolFsmState::Ready, SelectToolMessage::DragStart { add_to_selection, select_deepest: _ }) => { (SelectToolFsmState::Ready, SelectToolMessage::DragStart { add_to_selection, select_deepest }) => {
tool_data.drag_start = input.mouse.position; tool_data.drag_start = input.mouse.position;
tool_data.drag_current = input.mouse.position; tool_data.drag_current = input.mouse.position;
@@ -538,11 +532,14 @@ impl Fsm for SelectToolFsmState {
tool_data.layers_dragging = selected; tool_data.layers_dragging = selected;
SelectToolFsmState::RotatingBounds SelectToolFsmState::RotatingBounds
} else if intersection.is_some_and(|intersection| selected.iter().any(|selected_layer| intersection.starts_with(*selected_layer, document.metadata()))) } else if intersection.is_some_and(|intersection| selected.iter().any(|selected_layer| intersection.starts_with(*selected_layer, document.metadata()))) {
&& tool_data.nested_selection_behavior == NestedSelectionBehavior::Deepest
{
responses.add(DocumentMessage::StartTransaction); responses.add(DocumentMessage::StartTransaction);
tool_data.select_single_layer = intersection;
if tool_data.nested_selection_behavior == NestedSelectionBehavior::Deepest {
tool_data.select_single_layer = intersection;
} else {
tool_data.select_single_layer = intersection.and_then(|intersection| intersection.ancestors(&document.metadata).find(|ancestor| selected.contains(ancestor)));
}
tool_data.layers_dragging = selected; tool_data.layers_dragging = selected;
@@ -552,7 +549,7 @@ impl Fsm for SelectToolFsmState {
} else { } else {
tool_data.layers_dragging = selected; tool_data.layers_dragging = selected;
if !input.keyboard.key(add_to_selection) && tool_data.nested_selection_behavior == NestedSelectionBehavior::Deepest { if !input.keyboard.key(add_to_selection) {
responses.add(DocumentMessage::DeselectAllLayers); responses.add(DocumentMessage::DeselectAllLayers);
tool_data.layers_dragging.clear(); tool_data.layers_dragging.clear();
} }
@@ -564,8 +561,8 @@ impl Fsm for SelectToolFsmState {
selected = vec![intersection]; selected = vec![intersection];
match tool_data.nested_selection_behavior { match tool_data.nested_selection_behavior {
NestedSelectionBehavior::Shallowest => drag_shallowest_manipulation(responses, selected, tool_data, document), NestedSelectionBehavior::Shallowest if !input.keyboard.key(select_deepest) => drag_shallowest_manipulation(responses, selected, tool_data, document),
NestedSelectionBehavior::Deepest => drag_deepest_manipulation(responses, selected, tool_data), _ => drag_deepest_manipulation(responses, selected, tool_data),
} }
tool_data.get_snap_candidates(document, input); tool_data.get_snap_candidates(document, input);
SelectToolFsmState::Dragging SelectToolFsmState::Dragging
@@ -579,18 +576,28 @@ impl Fsm for SelectToolFsmState {
SelectToolFsmState::DrawingBox SelectToolFsmState::DrawingBox
} }
}; };
tool_data.not_duplicated_layers = None; tool_data.non_duplicated_layers = None;
state state
} }
(SelectToolFsmState::Dragging, SelectToolMessage::PointerMove { axis_align, duplicate, .. }) => { (SelectToolFsmState::Dragging, SelectToolMessage::PointerMove { axis_align, duplicate, .. }) => {
tool_data.has_dragged = true; tool_data.has_dragged = true;
if input.keyboard.key(duplicate) && tool_data.non_duplicated_layers.is_none() {
tool_data.start_duplicates(document, responses);
} else if !input.keyboard.key(duplicate) && tool_data.non_duplicated_layers.is_some() {
tool_data.stop_duplicates(document, responses);
}
let axis_align = input.keyboard.key(axis_align); let axis_align = input.keyboard.key(axis_align);
let mouse_position = axis_align_drag(axis_align, input.mouse.position, tool_data.drag_start); let mouse_position = axis_align_drag(axis_align, input.mouse.position, tool_data.drag_start);
let total_mouse_delta_document = document.metadata.document_to_viewport.inverse().transform_vector2(mouse_position - tool_data.drag_start); let total_mouse_delta_document = document.metadata.document_to_viewport.inverse().transform_vector2(mouse_position - tool_data.drag_start);
let snap_data = SnapData::ignore(document, input, &tool_data.layers_dragging); // Ignore the non duplicated layers if the current layers have not spawned yet.
let layers_exist = tool_data.layers_dragging.iter().all(|&layer| document.metadata().click_target(layer).is_some());
let ignore = tool_data.non_duplicated_layers.as_ref().filter(|_| !layers_exist).unwrap_or(&tool_data.layers_dragging);
let snap_data = SnapData::ignore(document, input, ignore);
let mouse_delta_document = document.metadata.document_to_viewport.inverse().transform_vector2(mouse_position - tool_data.drag_current); let mouse_delta_document = document.metadata.document_to_viewport.inverse().transform_vector2(mouse_position - tool_data.drag_current);
let mut offset = mouse_delta_document; let mut offset = mouse_delta_document;
let mut best_snap = SnappedPoint::infinite_snap(document.metadata.document_to_viewport.inverse().transform_point2(mouse_position)); let mut best_snap = SnappedPoint::infinite_snap(document.metadata.document_to_viewport.inverse().transform_point2(mouse_position));
@@ -627,22 +634,12 @@ impl Fsm for SelectToolFsmState {
} }
tool_data.drag_current += mouse_delta; tool_data.drag_current += mouse_delta;
// TODO: Reenable this feature after fixing it
if false {
if input.keyboard.key(duplicate) && tool_data.not_duplicated_layers.is_none() {
tool_data.start_duplicates(document, responses);
} else if !input.keyboard.key(duplicate) && tool_data.not_duplicated_layers.is_some() {
tool_data.stop_duplicates(document, responses);
}
}
SelectToolFsmState::Dragging SelectToolFsmState::Dragging
} }
(SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerMove { axis_align, center, .. }) => { (SelectToolFsmState::ResizingBounds, SelectToolMessage::PointerMove { axis_align, center, .. }) => {
if let Some(bounds) = &mut tool_data.bounding_box_manager { if let Some(bounds) = &mut tool_data.bounding_box_manager {
if let Some(movement) = &mut bounds.selected_edges { if let Some(movement) = &mut bounds.selected_edges {
let (_center, constrain) = (input.keyboard.key(center), input.keyboard.key(axis_align)); let (center, constrain) = (input.keyboard.key(center), input.keyboard.key(axis_align));
let center = false; // TODO: Reenable this feature after fixing it
let center = center.then_some(bounds.center_of_transformation); let center = center.then_some(bounds.center_of_transformation);
let snap = Some(SizeSnapData { let snap = Some(SizeSnapData {
@@ -944,21 +941,32 @@ impl Fsm for SelectToolFsmState {
} }
} }
fn not_artboard<'a>(document: &'a DocumentMessageHandler) -> impl Fn(&LayerNodeIdentifier) -> bool + 'a {
|&layer| !document.metadata.is_artboard(layer)
}
fn drag_shallowest_manipulation(responses: &mut VecDeque<Message>, selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData, document: &DocumentMessageHandler) { fn drag_shallowest_manipulation(responses: &mut VecDeque<Message>, selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData, document: &DocumentMessageHandler) {
let layer = selected[0]; for layer in selected {
let ancestor = layer let ancestor = layer
.ancestors(document.metadata()) .ancestors(document.metadata())
.find(|&ancestor| document.selected_nodes.selected_layers_contains(ancestor, document.metadata())); .filter(not_artboard(document))
.find(|&ancestor| document.selected_nodes.selected_layers_contains(ancestor, document.metadata()));
let new_selected = ancestor.unwrap_or_else(|| layer.child_of_root(document.metadata())); let new_selected = ancestor.unwrap_or_else(|| {
layer
.ancestors(document.metadata())
.take_while(|&layer| layer != LayerNodeIdentifier::ROOT)
.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);
}
tool_data.layers_dragging = vec![new_selected];
responses.add(NodeGraphMessage::SelectedNodesSet { responses.add(NodeGraphMessage::SelectedNodesSet {
nodes: tool_data.layers_dragging.iter().map(|layer| layer.to_node()).collect(), nodes: tool_data.layers_dragging.iter().map(|layer| layer.to_node()).collect(),
}); });
// tool_data
// .snap_manager
// .start_snap(document, input, document.bounding_boxes(Some(&tool_data.layers_dragging), None, font_cache), true, true);
} }
fn drag_deepest_manipulation(responses: &mut VecDeque<Message>, mut selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData) { fn drag_deepest_manipulation(responses: &mut VecDeque<Message>, mut selected: Vec<LayerNodeIdentifier>, tool_data: &mut SelectToolData) {
@@ -966,9 +974,6 @@ fn drag_deepest_manipulation(responses: &mut VecDeque<Message>, mut selected: Ve
responses.add(NodeGraphMessage::SelectedNodesSet { responses.add(NodeGraphMessage::SelectedNodesSet {
nodes: tool_data.layers_dragging.iter().map(|layer| layer.to_node()).collect(), nodes: tool_data.layers_dragging.iter().map(|layer| layer.to_node()).collect(),
}); });
// tool_data
// .snap_manager
// .start_snap(document, input, document.bounding_boxes(Some(&tool_data.layers_dragging), None, font_cache), true, true);
} }
fn edit_layer_shallowest_manipulation(document: &DocumentMessageHandler, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>) { fn edit_layer_shallowest_manipulation(document: &DocumentMessageHandler, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>) {
@@ -977,7 +982,7 @@ fn edit_layer_shallowest_manipulation(document: &DocumentMessageHandler, layer:
return; return;
} }
let Some(new_selected) = layer.ancestors(document.metadata()).find(|ancestor| { let Some(new_selected) = layer.ancestors(document.metadata()).filter(not_artboard(document)).find(|ancestor| {
ancestor ancestor
.parent(document.metadata()) .parent(document.metadata())
.is_some_and(|parent| document.selected_nodes.selected_layers_contains(parent, document.metadata())) .is_some_and(|parent| document.selected_nodes.selected_layers_contains(parent, document.metadata()))