mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-02 00:18:11 +08:00
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:
co-authored by
Keavon Chambers
parent
5c9d3c5d75
commit
208e907fa4
@@ -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()))
|
||||||
|
|||||||
Reference in New Issue
Block a user