Add path closing and segment extension to the Pen tool (#753)

* Close paths with pen tool

* Issue Z command always at end of path

* Small code review style changes

* Extending paths

* Fix mirror on extend path

* Code review tweaks

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube
2022-08-20 16:36:17 -07:00
committed by GitHub
co-authored by Keavon Chambers
parent a40b6a0aa1
commit d8b4055bcb
5 changed files with 327 additions and 108 deletions
+22
View File
@@ -787,6 +787,13 @@ impl Document {
}
Some([update_thumbnails_upstream(&layer_path), vec![DocumentChanged, LayerChanged { path: layer_path }]].concat())
}
Operation::PushFrontManipulatorGroup { layer_path, manipulator_group } => {
if let Ok(Some(shape)) = self.layer_mut(&layer_path).map(|layer| layer.as_subpath_mut()) {
shape.manipulator_groups_mut().push_front(manipulator_group);
self.mark_as_dirty(&layer_path)?;
}
Some([update_thumbnails_upstream(&layer_path), vec![DocumentChanged, LayerChanged { path: layer_path }]].concat())
}
Operation::RemoveManipulatorGroup { layer_path, id } => {
if let Ok(Some(shape)) = self.layer_mut(&layer_path).map(|layer| layer.as_subpath_mut()) {
shape.manipulator_groups_mut().remove(id);
@@ -959,6 +966,21 @@ impl Document {
self.mark_as_dirty(&layer_path)?;
Some([vec![DocumentChanged, LayerChanged { path: layer_path.clone() }], update_thumbnails_upstream(&layer_path)].concat())
}
Operation::SetManipulatorHandleMirroring {
layer_path,
id,
mirror_distance,
mirror_angle,
} => {
if let Ok(Some(shape)) = self.layer_mut(&layer_path).map(|layer| layer.as_subpath_mut()) {
if let Some(manipulator_group) = shape.manipulator_groups_mut().by_id_mut(id) {
manipulator_group.editor_state.mirror_distance_between_handles = mirror_distance;
manipulator_group.editor_state.mirror_angle_between_handles = mirror_angle;
self.mark_as_dirty(&layer_path)?;
}
}
Some([update_thumbnails_upstream(&layer_path), vec![DocumentChanged, LayerChanged { path: layer_path }]].concat())
}
Operation::SetSelectedHandleMirroring {
layer_path,
toggle_distance,
+2 -2
View File
@@ -34,7 +34,7 @@ impl<T> IdBackedVec<T> {
Some(self.next_id)
}
// Push an element to the end of the vector
/// Push an element to the end of the vector
pub fn push_end(&mut self, element: T) -> Option<ElementId> {
self.next_id += 1;
self.elements.push(element);
@@ -113,7 +113,7 @@ impl<T> IdBackedVec<T> {
}
/// Enumerate the ids and elements in this container `(&ElementId, &T)`
pub fn enumerate(&self) -> impl Iterator<Item = (&ElementId, &T)> {
pub fn enumerate(&self) -> std::iter::Zip<core::slice::Iter<u64>, core::slice::Iter<T>> {
self.element_ids.iter().zip(self.elements.iter())
}
+8 -5
View File
@@ -384,18 +384,21 @@ impl Subpath {
} else if last_out_handle.is_some() || first_in_handle.is_some() {
result.push('Q');
write_positions(&mut result, [last_out_handle, first_in_handle, first_in_anchor]);
} else {
result.push('Z');
}
} else if command == 'M' {
// Update the last moveto position
result.push('Z');
}
// Update the last moveto position
else if command == 'M' {
(first_in_handle, first_in_anchor) = (in_handle, anchor);
result.push(command);
write_positions(&mut result, [None, None, anchor]);
} else {
}
// Write other path commands (line to/quadratic to/cubic to)
else {
result.push(command);
write_positions(&mut result, [last_out_handle, in_handle, anchor]);
}
start_new_contour = command == 'Z';
last_out_handle = out_handle;
}
+10
View File
@@ -172,6 +172,10 @@ pub enum Operation {
layer_path: Vec<LayerId>,
manipulator_group: ManipulatorGroup,
},
PushFrontManipulatorGroup {
layer_path: Vec<LayerId>,
manipulator_group: ManipulatorGroup,
},
RemoveManipulatorGroup {
layer_path: Vec<LayerId>,
id: u64,
@@ -226,6 +230,12 @@ pub enum Operation {
path: Vec<LayerId>,
stroke: Stroke,
},
SetManipulatorHandleMirroring {
layer_path: Vec<LayerId>,
id: u64,
mirror_distance: bool,
mirror_angle: bool,
},
SetSelectedHandleMirroring {
layer_path: Vec<LayerId>,
toggle_distance: bool,