mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-30 21:08:12 +08:00
Add G/R/S to the Pen tool to control the outgoing segment handle (#2211)
* more_refactoring_solve_conflict * overlays-target-fix * Code review * select-broken-fix --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
co-authored by
Keavon Chambers
parent
96c57605b7
commit
9e2bda36b0
@@ -63,6 +63,8 @@ pub enum PenToolMessage {
|
||||
UpdateOptions(PenOptionsUpdate),
|
||||
RecalculateLatestPointsPosition,
|
||||
RemovePreviousHandle,
|
||||
GRS { grab: Key, rotate: Key, scale: Key },
|
||||
FinalPosition { final_position: DVec2 },
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
@@ -71,6 +73,7 @@ enum PenToolFsmState {
|
||||
Ready,
|
||||
DraggingHandle,
|
||||
PlacingAnchor,
|
||||
GRSHandle,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
@@ -162,13 +165,14 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for PenTool
|
||||
|
||||
fn actions(&self) -> ActionList {
|
||||
match self.fsm_state {
|
||||
PenToolFsmState::Ready => actions!(PenToolMessageDiscriminant;
|
||||
PenToolFsmState::Ready | PenToolFsmState::GRSHandle => actions!(PenToolMessageDiscriminant;
|
||||
Undo,
|
||||
DragStart,
|
||||
DragStop,
|
||||
Confirm,
|
||||
Abort,
|
||||
PointerMove,
|
||||
FinalPosition
|
||||
),
|
||||
PenToolFsmState::DraggingHandle | PenToolFsmState::PlacingAnchor => actions!(PenToolMessageDiscriminant;
|
||||
DragStart,
|
||||
@@ -177,6 +181,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for PenTool
|
||||
Confirm,
|
||||
Abort,
|
||||
RemovePreviousHandle,
|
||||
GRS,
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -223,6 +228,8 @@ struct PenToolData {
|
||||
modifiers: ModifierState,
|
||||
|
||||
buffering_merged_vector: bool,
|
||||
|
||||
before_grs_pos: DVec2,
|
||||
}
|
||||
impl PenToolData {
|
||||
fn latest_point(&self) -> Option<&LastPoint> {
|
||||
@@ -563,6 +570,72 @@ impl Fsm for PenToolFsmState {
|
||||
|
||||
let ToolMessage::Pen(event) = event else { return self };
|
||||
match (self, event) {
|
||||
(PenToolFsmState::PlacingAnchor | PenToolFsmState::GRSHandle, PenToolMessage::GRS { grab, rotate, scale }) => {
|
||||
let Some(latest) = tool_data.latest_point_mut() else { return PenToolFsmState::PlacingAnchor };
|
||||
let Some(layer) = layer else { return PenToolFsmState::PlacingAnchor };
|
||||
|
||||
if latest.handle_start != latest.pos {
|
||||
let viewport = document.metadata().transform_to_viewport(layer);
|
||||
let last_point = viewport.transform_point2(latest.pos);
|
||||
let handle = viewport.transform_point2(latest.handle_start);
|
||||
|
||||
if input.keyboard.key(grab) {
|
||||
responses.add(TransformLayerMessage::BeginGrabPen { last_point, handle });
|
||||
} else if input.keyboard.key(rotate) {
|
||||
responses.add(TransformLayerMessage::BeginRotatePen { last_point, handle });
|
||||
} else if input.keyboard.key(scale) {
|
||||
responses.add(TransformLayerMessage::BeginScalePen { last_point, handle });
|
||||
}
|
||||
|
||||
tool_data.before_grs_pos = latest.handle_start;
|
||||
}
|
||||
|
||||
PenToolFsmState::GRSHandle
|
||||
}
|
||||
(PenToolFsmState::GRSHandle, PenToolMessage::FinalPosition { final_position: final_pos }) => {
|
||||
let Some(layer) = layer else { return PenToolFsmState::GRSHandle };
|
||||
|
||||
if let Some(latest_pt) = tool_data.latest_point_mut() {
|
||||
let layer_space_to_viewport = document.metadata().transform_to_viewport(layer);
|
||||
let final_pos = layer_space_to_viewport.inverse().transform_point2(final_pos);
|
||||
latest_pt.handle_start = final_pos;
|
||||
}
|
||||
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
|
||||
PenToolFsmState::GRSHandle
|
||||
}
|
||||
(PenToolFsmState::GRSHandle, PenToolMessage::Confirm) => {
|
||||
tool_data.next_point = input.mouse.position;
|
||||
tool_data.next_handle_start = input.mouse.position;
|
||||
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
responses.add(PenToolMessage::PointerMove {
|
||||
snap_angle: Key::Control,
|
||||
break_handle: Key::Alt,
|
||||
lock_angle: Key::Shift,
|
||||
});
|
||||
|
||||
PenToolFsmState::PlacingAnchor
|
||||
}
|
||||
(PenToolFsmState::GRSHandle, PenToolMessage::Abort) => {
|
||||
tool_data.next_point = input.mouse.position;
|
||||
tool_data.next_handle_start = input.mouse.position;
|
||||
|
||||
let previous = tool_data.before_grs_pos;
|
||||
if let Some(latest) = tool_data.latest_point_mut() {
|
||||
latest.handle_start = previous;
|
||||
}
|
||||
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
responses.add(PenToolMessage::PointerMove {
|
||||
snap_angle: Key::Control,
|
||||
break_handle: Key::Alt,
|
||||
lock_angle: Key::Shift,
|
||||
});
|
||||
|
||||
PenToolFsmState::PlacingAnchor
|
||||
}
|
||||
(_, PenToolMessage::SelectionChanged) => {
|
||||
responses.add(OverlaysMessage::Draw);
|
||||
self
|
||||
@@ -814,7 +887,7 @@ impl Fsm for PenToolFsmState {
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
PenToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||
PenToolFsmState::Ready | PenToolFsmState::GRSHandle => HintData(vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::Lmb, "Draw Path"),
|
||||
// TODO: Only show this if a single layer is selected and it's of a valid type (e.g. a vector path but not raster or artboard)
|
||||
HintInfo::keys([Key::Shift], "Append to Selected Layer").prepend_plus(),
|
||||
|
||||
@@ -632,6 +632,7 @@ impl Fsm for SelectToolFsmState {
|
||||
&document.network_interface,
|
||||
None,
|
||||
&ToolType::Select,
|
||||
None
|
||||
);
|
||||
bounds.center_of_transformation = selected.mean_average_of_pivots();
|
||||
}
|
||||
@@ -660,6 +661,7 @@ impl Fsm for SelectToolFsmState {
|
||||
&document.network_interface,
|
||||
None,
|
||||
&ToolType::Select,
|
||||
None
|
||||
);
|
||||
|
||||
bounds.center_of_transformation = selected.mean_average_of_pivots();
|
||||
@@ -785,7 +787,16 @@ impl Fsm for SelectToolFsmState {
|
||||
}
|
||||
});
|
||||
let selected = &tool_data.layers_dragging;
|
||||
let mut selected = Selected::new(&mut bounds.original_transforms, &mut pivot, selected, responses, &document.network_interface, None, &ToolType::Select);
|
||||
let mut selected = Selected::new(
|
||||
&mut bounds.original_transforms,
|
||||
&mut pivot,
|
||||
selected,
|
||||
responses,
|
||||
&document.network_interface,
|
||||
None,
|
||||
&ToolType::Select,
|
||||
None,
|
||||
);
|
||||
|
||||
selected.apply_transformation(bounds.original_bound_transform * transformation * bounds.original_bound_transform.inverse());
|
||||
|
||||
@@ -833,6 +844,7 @@ impl Fsm for SelectToolFsmState {
|
||||
&document.network_interface,
|
||||
None,
|
||||
&ToolType::Select,
|
||||
None,
|
||||
);
|
||||
|
||||
selected.update_transforms(delta);
|
||||
|
||||
Reference in New Issue
Block a user