Make the Pen tool extend an endpoint by starting with a colinear, equidistant handle (#2295)
* Fixed Pen extension having collienar handles * Reformat a little * handles being colinear for GRS --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
38e542e6c0
commit
cf2a071fb9
|
|
@ -690,25 +690,9 @@ impl PenToolData {
|
|||
self.handle_end = None;
|
||||
|
||||
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
||||
if let Some((layer, point, position)) = should_extend(document, viewport, tolerance, selected_nodes.selected_layers(document.metadata()), preferences) {
|
||||
// Perform extension of an existing path
|
||||
let in_segment = if self.modifiers.lock_angle { self.end_point_segment } else { None };
|
||||
self.add_point(LastPoint {
|
||||
id: point,
|
||||
pos: position,
|
||||
in_segment,
|
||||
handle_start: position,
|
||||
});
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![layer.to_node()] });
|
||||
self.next_point = position;
|
||||
self.next_handle_start = position;
|
||||
let vector_data = document.network_interface.compute_modified_vector(layer).unwrap();
|
||||
let segment = vector_data.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
|
||||
|
||||
if self.modifiers.lock_angle {
|
||||
self.set_lock_angle(&vector_data, point, segment);
|
||||
}
|
||||
|
||||
let extension_choice = should_extend(document, viewport, tolerance, selected_nodes.selected_layers(document.metadata()), preferences);
|
||||
if let Some((layer, point, position)) = extension_choice {
|
||||
self.extend_existing_path(document, layer, point, position, responses);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -759,6 +743,64 @@ impl PenToolData {
|
|||
responses.add(PenToolMessage::AddPointLayerPosition { layer, viewport });
|
||||
}
|
||||
|
||||
/// Perform extension of an existing path
|
||||
fn extend_existing_path(&mut self, document: &DocumentMessageHandler, layer: LayerNodeIdentifier, point: PointId, position: DVec2, responses: &mut VecDeque<Message>) {
|
||||
let vector_data = document.network_interface.compute_modified_vector(layer);
|
||||
let (handle_start, in_segment) = if let Some(vector_data) = &vector_data {
|
||||
vector_data
|
||||
.segment_bezier_iter()
|
||||
.find_map(|(segment_id, bezier, start, end)| {
|
||||
let is_end = point == end;
|
||||
let is_start = point == start;
|
||||
if !is_end && !is_start {
|
||||
return None;
|
||||
}
|
||||
|
||||
let handle = match bezier.handles {
|
||||
BezierHandles::Cubic { handle_start, handle_end, .. } => {
|
||||
if is_start {
|
||||
handle_start
|
||||
} else {
|
||||
handle_end
|
||||
}
|
||||
}
|
||||
BezierHandles::Quadratic { handle } => handle,
|
||||
_ => return None,
|
||||
};
|
||||
Some((segment_id, is_end, handle))
|
||||
})
|
||||
.map(|(segment_id, is_end, handle)| {
|
||||
let mirrored_handle = position * 2. - handle;
|
||||
let in_segment = if is_end { Some(segment_id) } else { None };
|
||||
(mirrored_handle, in_segment)
|
||||
})
|
||||
.unwrap_or_else(|| (position, None))
|
||||
} else {
|
||||
(position, None)
|
||||
};
|
||||
|
||||
let in_segment = if self.modifiers.lock_angle { self.end_point_segment } else { in_segment };
|
||||
|
||||
self.add_point(LastPoint {
|
||||
id: point,
|
||||
pos: position,
|
||||
in_segment,
|
||||
handle_start,
|
||||
});
|
||||
|
||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![layer.to_node()] });
|
||||
|
||||
self.next_point = position;
|
||||
self.next_handle_start = handle_start;
|
||||
let vector_data = document.network_interface.compute_modified_vector(layer).unwrap();
|
||||
let segment = vector_data.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
|
||||
|
||||
if self.modifiers.lock_angle {
|
||||
self.set_lock_angle(&vector_data, point, segment);
|
||||
}
|
||||
self.handle_mode = HandleMode::ColinearEquidistant;
|
||||
}
|
||||
|
||||
// Stores the segment and point ID of the clicked endpoint
|
||||
fn store_clicked_endpoint(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, preferences: &PreferencesMessageHandler) {
|
||||
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
||||
|
|
|
|||
Loading…
Reference in New Issue