Selecting an individual anchor point deselects each of the other points (#963)
* Selecting an individual anchor point deselects each of the other points * git gra * Selecting intersecting shapes,selects top shape * Merge commit * cargo fmt * fixed: can't drag multiple selected shapes. * Merge commit * Merge commit * Code review tweaks * Merge commit * Fixed topmost layer and previous_mouse_position * Fixed issues when clicking on anchors * Works * Function name change --------- Co-authored-by: Keavon Chambers <keavon@keavon.com> Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
parent
964cf6df15
commit
b7f2163998
|
|
@ -1062,6 +1062,13 @@ impl Document {
|
|||
}
|
||||
Some(vec![LayerChanged { path: layer_path.clone() }])
|
||||
}
|
||||
Operation::SelectAllAnchors { layer_path } => {
|
||||
let layer = self.layer_mut(&layer_path)?;
|
||||
if let Some(subpath) = layer.as_subpath_mut() {
|
||||
subpath.select_all_anchors();
|
||||
}
|
||||
Some(vec![LayerChanged { path: layer_path.clone() }])
|
||||
}
|
||||
Operation::DeselectAllManipulatorPoints { layer_path } => {
|
||||
let layer = self.layer_mut(&layer_path)?;
|
||||
if let Some(shape) = layer.as_subpath_mut() {
|
||||
|
|
|
|||
|
|
@ -125,6 +125,9 @@ pub enum Operation {
|
|||
DeselectAllManipulatorPoints {
|
||||
layer_path: Vec<LayerId>,
|
||||
},
|
||||
SelectAllAnchors {
|
||||
layer_path: Vec<LayerId>,
|
||||
},
|
||||
DuplicateLayer {
|
||||
path: Vec<LayerId>,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ pub fn default_mapping() -> Mapping {
|
|||
entry!(PointerMove; refresh_keys=[Alt, Shift], action_dispatch=PathToolMessage::PointerMove { alt_mirror_angle: Alt, shift_mirror_distance: Shift }),
|
||||
entry!(KeyDown(Delete); action_dispatch=PathToolMessage::Delete),
|
||||
entry!(KeyDown(Backspace); action_dispatch=PathToolMessage::Delete),
|
||||
entry!(KeyUp(Lmb); action_dispatch=PathToolMessage::DragStop),
|
||||
entry!(KeyUp(Lmb); action_dispatch=PathToolMessage::DragStop { shift_mirror_distance: Shift }),
|
||||
entry!(DoubleClick; action_dispatch=PathToolMessage::InsertPoint),
|
||||
//
|
||||
// PenToolMessage
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ impl ShapeEditor {
|
|||
manipulator_group_id,
|
||||
manipulator_type: ManipulatorType::from_index(manipulator_point_index),
|
||||
};
|
||||
|
||||
points.push(point_info);
|
||||
responses.push_back(
|
||||
Operation::SelectManipulatorPoints {
|
||||
|
|
@ -187,6 +188,11 @@ impl ShapeEditor {
|
|||
self.iter(document).flat_map(|shape| shape.manipulator_groups().iter())
|
||||
}
|
||||
|
||||
// Sets the selected points to all points for the corresponding intersection
|
||||
pub fn select_all_anchors(&self, responses: &mut VecDeque<Message>, itersections: Vec<u64>) {
|
||||
responses.push_back(Operation::SelectAllAnchors { layer_path: itersections }.into());
|
||||
}
|
||||
|
||||
/// Provide the currently selected points by reference.
|
||||
pub fn selected_points<'a>(&'a self, document: &'a Document) -> impl Iterator<Item = &'a ManipulatorPoint> {
|
||||
self.selected_manipulator_groups(document).flat_map(|manipulator_group| manipulator_group.selected_points())
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::consts::{SELECTION_THRESHOLD, SELECTION_TOLERANCE};
|
||||
use crate::consts::{DRAG_THRESHOLD, SELECTION_THRESHOLD, SELECTION_TOLERANCE};
|
||||
use crate::messages::frontend::utility_types::MouseCursorIcon;
|
||||
use crate::messages::input_mapper::utility_types::input_keyboard::{Key, MouseMotion};
|
||||
use crate::messages::layout::utility_types::layout_widget::PropertyHolder;
|
||||
|
|
@ -6,6 +6,7 @@ use crate::messages::prelude::*;
|
|||
use crate::messages::tool::common_functionality::overlay_renderer::OverlayRenderer;
|
||||
use crate::messages::tool::common_functionality::shape_editor::{ManipulatorPointInfo, ShapeEditor};
|
||||
use crate::messages::tool::common_functionality::snapping::SnapManager;
|
||||
use crate::messages::tool::common_functionality::transformation_cage::axis_align_drag;
|
||||
use crate::messages::tool::utility_types::{EventToMessageMap, Fsm, ToolActionHandlerData, ToolMetadata, ToolTransition, ToolType};
|
||||
use crate::messages::tool::utility_types::{HintData, HintGroup, HintInfo};
|
||||
|
||||
|
|
@ -38,7 +39,9 @@ pub enum PathToolMessage {
|
|||
DragStart {
|
||||
add_to_selection: Key,
|
||||
},
|
||||
DragStop,
|
||||
DragStop {
|
||||
shift_mirror_distance: Key,
|
||||
},
|
||||
InsertPoint,
|
||||
PointerMove {
|
||||
alt_mirror_angle: Key,
|
||||
|
|
@ -109,6 +112,7 @@ struct PathToolData {
|
|||
snap_manager: SnapManager,
|
||||
|
||||
drag_start_pos: DVec2,
|
||||
previous_mouse_position: DVec2,
|
||||
alt_debounce: bool,
|
||||
}
|
||||
|
||||
|
|
@ -154,12 +158,12 @@ impl Fsm for PathToolFsmState {
|
|||
}
|
||||
// Mouse down
|
||||
(_, PathToolMessage::DragStart { add_to_selection }) => {
|
||||
let toggle_add_to_selection = input.keyboard.get(add_to_selection as usize);
|
||||
let shift_pressed = input.keyboard.get(add_to_selection as usize);
|
||||
|
||||
// Select the first point within the threshold (in pixels)
|
||||
if let Some(mut selected_points) = tool_data
|
||||
.shape_editor
|
||||
.select_point(&document.document_legacy, input.mouse.position, SELECTION_THRESHOLD, toggle_add_to_selection, responses)
|
||||
.select_point(&document.document_legacy, input.mouse.position, SELECTION_THRESHOLD, shift_pressed, responses)
|
||||
{
|
||||
responses.push_back(DocumentMessage::StartTransaction.into());
|
||||
|
||||
|
|
@ -186,8 +190,8 @@ impl Fsm for PathToolFsmState {
|
|||
|
||||
let include_handles = tool_data.shape_editor.selected_layers_ref();
|
||||
tool_data.snap_manager.add_all_document_handles(document, input, &include_handles, &[], &selected_points.points);
|
||||
|
||||
tool_data.drag_start_pos = input.mouse.position - selected_points.offset;
|
||||
tool_data.drag_start_pos = input.mouse.position;
|
||||
tool_data.previous_mouse_position = input.mouse.position - selected_points.offset;
|
||||
PathToolFsmState::Dragging
|
||||
}
|
||||
// We didn't find a point nearby, so consider selecting the nearest shape instead
|
||||
|
|
@ -198,19 +202,26 @@ impl Fsm for PathToolFsmState {
|
|||
.document_legacy
|
||||
.intersects_quad_root(Quad::from_box([input.mouse.position - selection_size, input.mouse.position + selection_size]), render_data);
|
||||
if !intersection.is_empty() {
|
||||
if toggle_add_to_selection {
|
||||
if shift_pressed {
|
||||
responses.push_back(DocumentMessage::AddSelectedLayers { additional_layers: intersection }.into());
|
||||
} else {
|
||||
// Selects the topmost layer when selecting intersecting shapes
|
||||
let top_most_intersection = intersection[intersection.len() - 1].clone();
|
||||
responses.push_back(
|
||||
DocumentMessage::SetSelectedLayers {
|
||||
replacement_selected_layers: intersection,
|
||||
replacement_selected_layers: vec![top_most_intersection.clone()],
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
tool_data.drag_start_pos = input.mouse.position;
|
||||
tool_data.previous_mouse_position = input.mouse.position;
|
||||
// Selects all the anchor points when clicking in a filled area of shape. If two shapes intersect we pick the topmost layer.
|
||||
tool_data.shape_editor.select_all_anchors(responses, top_most_intersection);
|
||||
return PathToolFsmState::Dragging;
|
||||
}
|
||||
} else {
|
||||
// Clear the previous selection if we didn't find anything
|
||||
if !input.keyboard.get(toggle_add_to_selection as usize) {
|
||||
if !input.keyboard.get(shift_pressed as usize) {
|
||||
responses.push_back(DocumentMessage::DeselectAllLayers.into());
|
||||
}
|
||||
}
|
||||
|
|
@ -240,12 +251,29 @@ impl Fsm for PathToolFsmState {
|
|||
|
||||
// Move the selected points by the mouse position
|
||||
let snapped_position = tool_data.snap_manager.snap_position(responses, document, input.mouse.position);
|
||||
tool_data.shape_editor.move_selected_points(snapped_position - tool_data.drag_start_pos, shift_pressed, responses);
|
||||
tool_data.drag_start_pos = snapped_position;
|
||||
tool_data
|
||||
.shape_editor
|
||||
.move_selected_points(snapped_position - tool_data.previous_mouse_position, shift_pressed, responses);
|
||||
tool_data.previous_mouse_position = snapped_position;
|
||||
PathToolFsmState::Dragging
|
||||
}
|
||||
// Mouse up
|
||||
(_, PathToolMessage::DragStop) => {
|
||||
(_, PathToolMessage::DragStop { shift_mirror_distance }) => {
|
||||
let selected_points = tool_data.shape_editor.selected_points(&document.document_legacy);
|
||||
let nearest_point = tool_data.shape_editor.find_nearest_point(&document.document_legacy, input.mouse.position, SELECTION_THRESHOLD);
|
||||
let shift_pressed = input.keyboard.get(shift_mirror_distance as usize);
|
||||
|
||||
if tool_data.drag_start_pos.distance(input.mouse.position) <= DRAG_THRESHOLD && !shift_pressed {
|
||||
for point in selected_points {
|
||||
if nearest_point == Some(point) {
|
||||
responses.push_back(DocumentMessage::DeselectAllManipulatorPoints.into());
|
||||
tool_data
|
||||
.shape_editor
|
||||
.select_point(&document.document_legacy, input.mouse.position, SELECTION_THRESHOLD, false, responses);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tool_data.snap_manager.cleanup(responses);
|
||||
PathToolFsmState::Ready
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue