mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-07-08 00:05:00 +00:00
Clean up the Path tool's FSM to move segment molding state into the dragging state (#2835)
Cleanup molding segments state
This commit is contained in:
parent
49db963ce1
commit
8b0a27939e
1 changed files with 61 additions and 86 deletions
|
@ -362,12 +362,6 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for PathToo
|
||||||
Escape,
|
Escape,
|
||||||
RightClick
|
RightClick
|
||||||
),
|
),
|
||||||
PathToolFsmState::MoldingSegment => actions!(PathToolMessageDiscriminant;
|
|
||||||
PointerMove,
|
|
||||||
DragStop,
|
|
||||||
RightClick,
|
|
||||||
Escape,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -419,7 +413,6 @@ enum PathToolFsmState {
|
||||||
selection_shape: SelectionShapeType,
|
selection_shape: SelectionShapeType,
|
||||||
},
|
},
|
||||||
SlidingPoint,
|
SlidingPoint,
|
||||||
MoldingSegment,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -688,7 +681,7 @@ impl PathToolData {
|
||||||
self.molding_info = Some((pos1, pos2))
|
self.molding_info = Some((pos1, pos2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PathToolFsmState::MoldingSegment
|
PathToolFsmState::Dragging(self.dragging_state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If no other layers are selected and this is a single-click, then also select the layer (exception)
|
// If no other layers are selected and this is a single-click, then also select the layer (exception)
|
||||||
|
@ -1505,7 +1498,6 @@ impl Fsm for PathToolFsmState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::SlidingPoint => {}
|
Self::SlidingPoint => {}
|
||||||
Self::MoldingSegment => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
responses.add(PathToolMessage::SelectedPointUpdated);
|
responses.add(PathToolMessage::SelectedPointUpdated);
|
||||||
|
@ -1610,22 +1602,35 @@ impl Fsm for PathToolFsmState {
|
||||||
break_colinear_molding,
|
break_colinear_molding,
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
|
let selected_only_handles = !shape_editor.selected_points().any(|point| matches!(point, ManipulatorPointId::Anchor(_)));
|
||||||
tool_data.stored_selection = None;
|
tool_data.stored_selection = None;
|
||||||
let mut selected_only_handles = true;
|
|
||||||
|
|
||||||
let selected_points = shape_editor.selected_points();
|
|
||||||
|
|
||||||
for point in selected_points {
|
|
||||||
if matches!(point, ManipulatorPointId::Anchor(_)) {
|
|
||||||
selected_only_handles = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !tool_data.saved_points_before_handle_drag.is_empty() && (tool_data.drag_start_pos.distance(input.mouse.position) > DRAG_THRESHOLD) && (selected_only_handles) {
|
if !tool_data.saved_points_before_handle_drag.is_empty() && (tool_data.drag_start_pos.distance(input.mouse.position) > DRAG_THRESHOLD) && (selected_only_handles) {
|
||||||
tool_data.handle_drag_toggle = true;
|
tool_data.handle_drag_toggle = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tool_data.drag_start_pos.distance(input.mouse.position) > DRAG_THRESHOLD {
|
||||||
|
tool_data.molding_segment = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let break_molding = input.keyboard.get(break_colinear_molding as usize);
|
||||||
|
|
||||||
|
// Logic for molding segment
|
||||||
|
if let Some(segment) = &mut tool_data.segment {
|
||||||
|
if let Some(molding_segment_handles) = tool_data.molding_info {
|
||||||
|
tool_data.temporary_adjacent_handles_while_molding = segment.mold_handle_positions(
|
||||||
|
document,
|
||||||
|
responses,
|
||||||
|
molding_segment_handles,
|
||||||
|
input.mouse.position,
|
||||||
|
break_molding,
|
||||||
|
tool_data.temporary_adjacent_handles_while_molding,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PathToolFsmState::Dragging(tool_data.dragging_state);
|
||||||
|
}
|
||||||
|
|
||||||
let anchor_and_handle_toggled = input.keyboard.get(move_anchor_with_handles as usize);
|
let anchor_and_handle_toggled = input.keyboard.get(move_anchor_with_handles as usize);
|
||||||
let initial_press = anchor_and_handle_toggled && !tool_data.select_anchor_toggled;
|
let initial_press = anchor_and_handle_toggled && !tool_data.select_anchor_toggled;
|
||||||
let released_from_toggle = tool_data.select_anchor_toggled && !anchor_and_handle_toggled;
|
let released_from_toggle = tool_data.select_anchor_toggled && !anchor_and_handle_toggled;
|
||||||
|
@ -1701,29 +1706,6 @@ impl Fsm for PathToolFsmState {
|
||||||
tool_data.slide_point(input.mouse.position, responses, &document.network_interface, shape_editor);
|
tool_data.slide_point(input.mouse.position, responses, &document.network_interface, shape_editor);
|
||||||
PathToolFsmState::SlidingPoint
|
PathToolFsmState::SlidingPoint
|
||||||
}
|
}
|
||||||
(PathToolFsmState::MoldingSegment, PathToolMessage::PointerMove { break_colinear_molding, .. }) => {
|
|
||||||
if tool_data.drag_start_pos.distance(input.mouse.position) > DRAG_THRESHOLD {
|
|
||||||
tool_data.molding_segment = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let break_colinear_molding = input.keyboard.get(break_colinear_molding as usize);
|
|
||||||
|
|
||||||
// Logic for molding segment
|
|
||||||
if let Some(segment) = &mut tool_data.segment {
|
|
||||||
if let Some(molding_segment_handles) = tool_data.molding_info {
|
|
||||||
tool_data.temporary_adjacent_handles_while_molding = segment.mold_handle_positions(
|
|
||||||
document,
|
|
||||||
responses,
|
|
||||||
molding_segment_handles,
|
|
||||||
input.mouse.position,
|
|
||||||
break_colinear_molding,
|
|
||||||
tool_data.temporary_adjacent_handles_while_molding,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PathToolFsmState::MoldingSegment
|
|
||||||
}
|
|
||||||
(PathToolFsmState::Ready, PathToolMessage::PointerMove { delete_segment, .. }) => {
|
(PathToolFsmState::Ready, PathToolMessage::PointerMove { delete_segment, .. }) => {
|
||||||
tool_data.delete_segment_pressed = input.keyboard.get(delete_segment as usize);
|
tool_data.delete_segment_pressed = input.keyboard.get(delete_segment as usize);
|
||||||
|
|
||||||
|
@ -1855,6 +1837,9 @@ impl Fsm for PathToolFsmState {
|
||||||
tool_data.saved_points_before_handle_drag.clear();
|
tool_data.saved_points_before_handle_drag.clear();
|
||||||
tool_data.handle_drag_toggle = false;
|
tool_data.handle_drag_toggle = false;
|
||||||
}
|
}
|
||||||
|
tool_data.molding_info = None;
|
||||||
|
tool_data.molding_segment = false;
|
||||||
|
tool_data.temporary_adjacent_handles_while_molding = None;
|
||||||
tool_data.angle_locked = false;
|
tool_data.angle_locked = false;
|
||||||
responses.add(DocumentMessage::AbortTransaction);
|
responses.add(DocumentMessage::AbortTransaction);
|
||||||
tool_data.snap_manager.cleanup(responses);
|
tool_data.snap_manager.cleanup(responses);
|
||||||
|
@ -1872,17 +1857,6 @@ impl Fsm for PathToolFsmState {
|
||||||
|
|
||||||
PathToolFsmState::Ready
|
PathToolFsmState::Ready
|
||||||
}
|
}
|
||||||
(PathToolFsmState::MoldingSegment, PathToolMessage::Escape | PathToolMessage::RightClick) => {
|
|
||||||
// Undo the molding and go back to the state before
|
|
||||||
tool_data.molding_info = None;
|
|
||||||
tool_data.molding_segment = false;
|
|
||||||
tool_data.temporary_adjacent_handles_while_molding = None;
|
|
||||||
|
|
||||||
responses.add(DocumentMessage::AbortTransaction);
|
|
||||||
tool_data.snap_manager.cleanup(responses);
|
|
||||||
|
|
||||||
PathToolFsmState::Ready
|
|
||||||
}
|
|
||||||
// Mouse up
|
// Mouse up
|
||||||
(PathToolFsmState::Drawing { selection_shape }, PathToolMessage::DragStop { extend_selection, shrink_selection }) => {
|
(PathToolFsmState::Drawing { selection_shape }, PathToolMessage::DragStop { extend_selection, shrink_selection }) => {
|
||||||
let extend_selection = input.keyboard.get(extend_selection as usize);
|
let extend_selection = input.keyboard.get(extend_selection as usize);
|
||||||
|
@ -2598,7 +2572,40 @@ fn update_dynamic_hints(
|
||||||
dragging_hint_data.0.push(HintGroup(hold_group));
|
dragging_hint_data.0.push(HintGroup(hold_group));
|
||||||
}
|
}
|
||||||
|
|
||||||
dragging_hint_data
|
if tool_data.molding_segment {
|
||||||
|
let mut has_colinear_anchors = false;
|
||||||
|
|
||||||
|
if let Some(segment) = &tool_data.segment {
|
||||||
|
let handle1 = HandleId::primary(segment.segment());
|
||||||
|
let handle2 = HandleId::end(segment.segment());
|
||||||
|
|
||||||
|
if let Some(vector_data) = document.network_interface.compute_modified_vector(segment.layer()) {
|
||||||
|
let other_handle1 = vector_data.other_colinear_handle(handle1);
|
||||||
|
let other_handle2 = vector_data.other_colinear_handle(handle2);
|
||||||
|
if other_handle1.is_some() || other_handle2.is_some() {
|
||||||
|
has_colinear_anchors = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let handles_stored = if let Some(other_handles) = tool_data.temporary_adjacent_handles_while_molding {
|
||||||
|
other_handles[0].is_some() || other_handles[1].is_some()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
let molding_disable_possible = has_colinear_anchors || handles_stored;
|
||||||
|
|
||||||
|
let mut molding_hints = vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])];
|
||||||
|
|
||||||
|
if molding_disable_possible {
|
||||||
|
molding_hints.push(HintGroup(vec![HintInfo::keys([Key::Alt], "Break Colinear Handles")]));
|
||||||
|
}
|
||||||
|
|
||||||
|
HintData(molding_hints)
|
||||||
|
} else {
|
||||||
|
dragging_hint_data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PathToolFsmState::Drawing { .. } => HintData(vec![
|
PathToolFsmState::Drawing { .. } => HintData(vec![
|
||||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||||
|
@ -2608,38 +2615,6 @@ fn update_dynamic_hints(
|
||||||
HintInfo::keys([Key::Alt], "Subtract").prepend_plus(),
|
HintInfo::keys([Key::Alt], "Subtract").prepend_plus(),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
PathToolFsmState::MoldingSegment => {
|
|
||||||
let mut has_colinear_anchors = false;
|
|
||||||
|
|
||||||
if let Some(segment) = &tool_data.segment {
|
|
||||||
let handle1 = HandleId::primary(segment.segment());
|
|
||||||
let handle2 = HandleId::end(segment.segment());
|
|
||||||
|
|
||||||
if let Some(vector_data) = document.network_interface.compute_modified_vector(segment.layer()) {
|
|
||||||
let other_handle1 = vector_data.other_colinear_handle(handle1);
|
|
||||||
let other_handle2 = vector_data.other_colinear_handle(handle2);
|
|
||||||
if other_handle1.is_some() || other_handle2.is_some() {
|
|
||||||
has_colinear_anchors = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let handles_stored = if let Some(other_handles) = tool_data.temporary_adjacent_handles_while_molding {
|
|
||||||
other_handles[0].is_some() || other_handles[1].is_some()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
let molding_disable_possible = has_colinear_anchors || handles_stored;
|
|
||||||
|
|
||||||
let mut molding_hints = vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])];
|
|
||||||
|
|
||||||
if molding_disable_possible {
|
|
||||||
molding_hints.push(HintGroup(vec![HintInfo::keys([Key::Alt], "Break Colinear Handles")]));
|
|
||||||
}
|
|
||||||
|
|
||||||
HintData(molding_hints)
|
|
||||||
}
|
|
||||||
PathToolFsmState::SlidingPoint => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])]),
|
PathToolFsmState::SlidingPoint => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])]),
|
||||||
};
|
};
|
||||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue