mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 23:38:06 +08:00
Remove update_dynamic_hints seperate function
This commit is contained in:
@@ -1596,7 +1596,7 @@ impl ShapeState {
|
||||
}
|
||||
|
||||
pub fn find_nearest_visible_point_indices(
|
||||
&mut self,
|
||||
&self,
|
||||
network_interface: &NodeNetworkInterface,
|
||||
mouse_position: DVec2,
|
||||
select_threshold: f64,
|
||||
|
||||
@@ -528,7 +528,7 @@ impl Fsm for ArtboardToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
ArtboardToolFsmState::Ready { .. } => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Draw Artboard")]),
|
||||
@@ -552,7 +552,7 @@ impl Fsm for ArtboardToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
if let Self::Ready { hovered: false } = self {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Crosshair });
|
||||
} else {
|
||||
|
||||
@@ -418,7 +418,7 @@ impl Fsm for BrushToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
BrushToolFsmState::Ready => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Draw")]),
|
||||
@@ -430,7 +430,7 @@ impl Fsm for BrushToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ impl Fsm for EyedropperToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
EyedropperToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::Lmb, "Sample to Primary"),
|
||||
@@ -138,7 +138,7 @@ impl Fsm for EyedropperToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let cursor = match *self {
|
||||
EyedropperToolFsmState::Ready => MouseCursorIcon::Default,
|
||||
EyedropperToolFsmState::SamplingPrimary | EyedropperToolFsmState::SamplingSecondary => MouseCursorIcon::None,
|
||||
|
||||
@@ -145,7 +145,7 @@ impl Fsm for FillToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
FillToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::Lmb, "Fill with Primary"),
|
||||
@@ -157,7 +157,7 @@ impl Fsm for FillToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ impl Fsm for FreehandToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
FreehandToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Polyline"),
|
||||
@@ -310,7 +310,7 @@ impl Fsm for FreehandToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -519,7 +519,7 @@ impl Fsm for GradientToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
GradientToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Gradient"),
|
||||
@@ -534,7 +534,7 @@ impl Fsm for GradientToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ impl Fsm for NavigateToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
NavigateToolFsmState::Ready | NavigateToolFsmState::ZoomOrClickZooming => HintData(vec![
|
||||
HintGroup(vec![
|
||||
@@ -169,7 +169,7 @@ impl Fsm for NavigateToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let cursor = match *self {
|
||||
NavigateToolFsmState::Ready => MouseCursorIcon::ZoomIn,
|
||||
NavigateToolFsmState::Tilting => MouseCursorIcon::Default,
|
||||
|
||||
@@ -1505,9 +1505,9 @@ impl Fsm for PathToolFsmState {
|
||||
tool_options: &Self::ToolOptions,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> Self {
|
||||
let ToolActionMessageContext { document, input, shape_editor, .. } = tool_action_data;
|
||||
self.update_hints(tool_data, tool_action_data, tool_options, responses);
|
||||
|
||||
update_dynamic_hints(self, responses, shape_editor, document, tool_data, tool_options, input.mouse.position);
|
||||
let ToolActionMessageContext { document, input, shape_editor, .. } = tool_action_data;
|
||||
|
||||
let ToolMessage::Path(event) = event else { return self };
|
||||
|
||||
@@ -3040,11 +3040,218 @@ impl Fsm for PathToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, _responses: &mut VecDeque<Message>) {
|
||||
// Moved logic to update_dynamic_hints
|
||||
fn update_hints(&self, tool_data: &Self::ToolData, ctx: &ToolActionMessageContext, tool_options: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let ToolActionMessageContext { document, shape_editor, input, .. } = ctx;
|
||||
|
||||
// Condinting based on currently selected segment if it has any one g1 continuous handle
|
||||
|
||||
let hint_data = match self {
|
||||
PathToolFsmState::Ready => {
|
||||
// Show point sliding hints only when there is an anchor with colinear handles selected
|
||||
let single_anchor_selected = shape_editor.selected_points().count() == 1 && shape_editor.selected_points().any(|point| matches!(point, ManipulatorPointId::Anchor(_)));
|
||||
let at_least_one_anchor_selected = shape_editor.selected_points().any(|point| matches!(point, ManipulatorPointId::Anchor(_)));
|
||||
let at_least_one_point_selected = shape_editor.selected_points().count() >= 1;
|
||||
|
||||
let mut single_colinear_anchor_selected = false;
|
||||
if single_anchor_selected {
|
||||
if let (Some(anchor), Some(layer)) = (
|
||||
shape_editor.selected_points().next(),
|
||||
document.network_interface.selected_nodes().selected_layers(document.metadata()).next(),
|
||||
) {
|
||||
if let Some(vector) = document.network_interface.compute_modified_vector(layer) {
|
||||
single_colinear_anchor_selected = vector.colinear(*anchor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut drag_selected_hints = vec![HintInfo::mouse(MouseMotion::LmbDrag, "Drag Selected")];
|
||||
let mut delete_selected_hints = vec![HintInfo::keys([Key::Delete], "Delete Selected")];
|
||||
|
||||
if at_least_one_anchor_selected {
|
||||
delete_selected_hints.push(HintInfo::keys([Key::Accel], "No Dissolve").prepend_plus());
|
||||
delete_selected_hints.push(HintInfo::keys([Key::Shift], "Cut Anchor").prepend_plus());
|
||||
}
|
||||
|
||||
if single_colinear_anchor_selected {
|
||||
drag_selected_hints.push(HintInfo::multi_keys([[Key::Control], [Key::Shift]], "Slide").prepend_plus());
|
||||
}
|
||||
|
||||
let segment_edit = tool_options.path_editing_mode.segment_editing_mode;
|
||||
let point_edit = tool_options.path_editing_mode.point_editing_mode;
|
||||
|
||||
let hovering_segment = tool_data.segment.is_some();
|
||||
let hovering_point = shape_editor
|
||||
.find_nearest_visible_point_indices(
|
||||
&document.network_interface,
|
||||
input.mouse.position,
|
||||
SELECTION_THRESHOLD,
|
||||
tool_options.path_overlay_mode,
|
||||
&tool_data.frontier_handles_info,
|
||||
)
|
||||
.is_some();
|
||||
|
||||
let mut hint_data = if hovering_segment {
|
||||
if segment_edit {
|
||||
// Hovering a segment in segment editing mode
|
||||
vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Select Segment"), HintInfo::keys([Key::Shift], "Extend").prepend_plus()]),
|
||||
HintGroup(vec![HintInfo::keys_and_mouse([Key::Control], MouseMotion::Lmb, "Insert Point on Segment")]),
|
||||
HintGroup(vec![HintInfo::keys_and_mouse([Key::Control], MouseMotion::LmbDrag, "Mold Segment")]),
|
||||
]
|
||||
} else {
|
||||
// Hovering a segment in point editing mode
|
||||
vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Insert Point on Segment")]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Mold Segment")]),
|
||||
HintGroup(vec![HintInfo::keys_and_mouse([Key::Alt], MouseMotion::Lmb, "Delete Segment")]),
|
||||
]
|
||||
}
|
||||
} else if hovering_point {
|
||||
if point_edit {
|
||||
// Hovering over a point in point editing mode
|
||||
vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::Lmb, "Select Point"),
|
||||
HintInfo::keys([Key::Shift], "Extend").prepend_plus(),
|
||||
])]
|
||||
} else {
|
||||
// Hovering over a point in segment selection mode (will select a nearby segment)
|
||||
vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::Lmb, "Select Segment"),
|
||||
HintInfo::keys([Key::Shift], "Extend").prepend_plus(),
|
||||
])]
|
||||
}
|
||||
} else {
|
||||
vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Select Area"),
|
||||
HintInfo::keys([Key::Control], "Lasso").prepend_plus(),
|
||||
])]
|
||||
};
|
||||
|
||||
if at_least_one_anchor_selected {
|
||||
// TODO: Dynamically show either "Smooth" or "Sharp" based on the current state
|
||||
hint_data.push(HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDouble, "Convert Anchor Point"),
|
||||
HintInfo::keys_and_mouse([Key::Alt], MouseMotion::Lmb, "To Sharp"),
|
||||
HintInfo::keys_and_mouse([Key::Alt], MouseMotion::LmbDrag, "To Smooth"),
|
||||
]));
|
||||
}
|
||||
|
||||
if at_least_one_point_selected {
|
||||
let mut groups = vec![
|
||||
HintGroup(drag_selected_hints),
|
||||
HintGroup(vec![HintInfo::multi_keys([[Key::KeyG], [Key::KeyR], [Key::KeyS]], "Grab/Rotate/Scale Selected")]),
|
||||
HintGroup(vec![HintInfo::arrow_keys("Nudge Selected"), HintInfo::keys([Key::Shift], "10x").prepend_plus()]),
|
||||
HintGroup(delete_selected_hints),
|
||||
];
|
||||
hint_data.append(&mut groups);
|
||||
}
|
||||
|
||||
HintData(hint_data)
|
||||
}
|
||||
PathToolFsmState::Dragging(dragging_state) => {
|
||||
let colinear = dragging_state.colinear;
|
||||
let mut dragging_hint_data = HintData(Vec::new());
|
||||
dragging_hint_data
|
||||
.0
|
||||
.push(HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]));
|
||||
|
||||
let drag_anchor = HintInfo::keys([Key::Space], "Drag Anchor");
|
||||
let toggle_group = match dragging_state.point_select_state {
|
||||
PointSelectState::HandleNoPair | PointSelectState::HandleWithPair => {
|
||||
let mut hints = vec![HintInfo::keys([Key::Tab], "Swap Dragged Handle")];
|
||||
hints.push(HintInfo::keys(
|
||||
[Key::KeyC],
|
||||
if colinear == ManipulatorAngle::Colinear {
|
||||
"Break Colinear Handles"
|
||||
} else {
|
||||
"Make Handles Colinear"
|
||||
},
|
||||
));
|
||||
hints
|
||||
}
|
||||
PointSelectState::Anchor => Vec::new(),
|
||||
};
|
||||
let hold_group = match dragging_state.point_select_state {
|
||||
PointSelectState::HandleNoPair => {
|
||||
let mut hints = vec![];
|
||||
if colinear != ManipulatorAngle::Free {
|
||||
hints.push(HintInfo::keys([Key::Alt], "Equidistant Handles"));
|
||||
}
|
||||
hints.push(HintInfo::keys([Key::Shift], "15° Increments"));
|
||||
hints.push(HintInfo::keys([Key::Control], "Lock Angle"));
|
||||
hints.push(drag_anchor);
|
||||
hints
|
||||
}
|
||||
PointSelectState::HandleWithPair => {
|
||||
let mut hints = vec![];
|
||||
if colinear != ManipulatorAngle::Free {
|
||||
hints.push(HintInfo::keys([Key::Alt], "Equidistant Handles"));
|
||||
}
|
||||
hints.push(HintInfo::keys([Key::Shift], "15° Increments"));
|
||||
hints.push(HintInfo::keys([Key::Control], "Lock Angle"));
|
||||
hints.push(drag_anchor);
|
||||
hints
|
||||
}
|
||||
PointSelectState::Anchor => Vec::new(),
|
||||
};
|
||||
|
||||
if !toggle_group.is_empty() {
|
||||
dragging_hint_data.0.push(HintGroup(toggle_group));
|
||||
}
|
||||
|
||||
if !hold_group.is_empty() {
|
||||
dragging_hint_data.0.push(HintGroup(hold_group));
|
||||
}
|
||||
|
||||
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) = document.network_interface.compute_modified_vector(segment.layer()) {
|
||||
let other_handle1 = vector.other_colinear_handle(handle1);
|
||||
let other_handle2 = vector.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![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Select Area"),
|
||||
HintInfo::keys([Key::Shift], "Extend").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "Subtract").prepend_plus(),
|
||||
]),
|
||||
]),
|
||||
PathToolFsmState::SlidingPoint => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])]),
|
||||
};
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
|
||||
}
|
||||
}
|
||||
@@ -3260,220 +3467,3 @@ fn calculate_adjacent_anchor_tangent(currently_dragged_handle: ManipulatorPointI
|
||||
_ => (None, None),
|
||||
}
|
||||
}
|
||||
|
||||
fn update_dynamic_hints(
|
||||
state: PathToolFsmState,
|
||||
responses: &mut VecDeque<Message>,
|
||||
shape_editor: &mut ShapeState,
|
||||
document: &DocumentMessageHandler,
|
||||
tool_data: &PathToolData,
|
||||
tool_options: &PathToolOptions,
|
||||
position: DVec2,
|
||||
) {
|
||||
// Condinting based on currently selected segment if it has any one g1 continuous handle
|
||||
|
||||
let hint_data = match state {
|
||||
PathToolFsmState::Ready => {
|
||||
// Show point sliding hints only when there is an anchor with colinear handles selected
|
||||
let single_anchor_selected = shape_editor.selected_points().count() == 1 && shape_editor.selected_points().any(|point| matches!(point, ManipulatorPointId::Anchor(_)));
|
||||
let at_least_one_anchor_selected = shape_editor.selected_points().any(|point| matches!(point, ManipulatorPointId::Anchor(_)));
|
||||
let at_least_one_point_selected = shape_editor.selected_points().count() >= 1;
|
||||
|
||||
let mut single_colinear_anchor_selected = false;
|
||||
if single_anchor_selected {
|
||||
if let (Some(anchor), Some(layer)) = (
|
||||
shape_editor.selected_points().next(),
|
||||
document.network_interface.selected_nodes().selected_layers(document.metadata()).next(),
|
||||
) {
|
||||
if let Some(vector) = document.network_interface.compute_modified_vector(layer) {
|
||||
single_colinear_anchor_selected = vector.colinear(*anchor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut drag_selected_hints = vec![HintInfo::mouse(MouseMotion::LmbDrag, "Drag Selected")];
|
||||
let mut delete_selected_hints = vec![HintInfo::keys([Key::Delete], "Delete Selected")];
|
||||
|
||||
if at_least_one_anchor_selected {
|
||||
delete_selected_hints.push(HintInfo::keys([Key::Accel], "No Dissolve").prepend_plus());
|
||||
delete_selected_hints.push(HintInfo::keys([Key::Shift], "Cut Anchor").prepend_plus());
|
||||
}
|
||||
|
||||
if single_colinear_anchor_selected {
|
||||
drag_selected_hints.push(HintInfo::multi_keys([[Key::Control], [Key::Shift]], "Slide").prepend_plus());
|
||||
}
|
||||
|
||||
let segment_edit = tool_options.path_editing_mode.segment_editing_mode;
|
||||
let point_edit = tool_options.path_editing_mode.point_editing_mode;
|
||||
|
||||
let hovering_segment = tool_data.segment.is_some();
|
||||
let hovering_point = shape_editor
|
||||
.find_nearest_visible_point_indices(
|
||||
&document.network_interface,
|
||||
position,
|
||||
SELECTION_THRESHOLD,
|
||||
tool_options.path_overlay_mode,
|
||||
&tool_data.frontier_handles_info,
|
||||
)
|
||||
.is_some();
|
||||
|
||||
let mut hint_data = if hovering_segment {
|
||||
if segment_edit {
|
||||
// Hovering a segment in segment editing mode
|
||||
vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Select Segment"), HintInfo::keys([Key::Shift], "Extend").prepend_plus()]),
|
||||
HintGroup(vec![HintInfo::keys_and_mouse([Key::Control], MouseMotion::Lmb, "Insert Point on Segment")]),
|
||||
HintGroup(vec![HintInfo::keys_and_mouse([Key::Control], MouseMotion::LmbDrag, "Mold Segment")]),
|
||||
]
|
||||
} else {
|
||||
// Hovering a segment in point editing mode
|
||||
vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Insert Point on Segment")]),
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Mold Segment")]),
|
||||
HintGroup(vec![HintInfo::keys_and_mouse([Key::Alt], MouseMotion::Lmb, "Delete Segment")]),
|
||||
]
|
||||
}
|
||||
} else if hovering_point {
|
||||
if point_edit {
|
||||
// Hovering over a point in point editing mode
|
||||
vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::Lmb, "Select Point"),
|
||||
HintInfo::keys([Key::Shift], "Extend").prepend_plus(),
|
||||
])]
|
||||
} else {
|
||||
// Hovering over a point in segment selection mode (will select a nearby segment)
|
||||
vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::Lmb, "Select Segment"),
|
||||
HintInfo::keys([Key::Shift], "Extend").prepend_plus(),
|
||||
])]
|
||||
}
|
||||
} else {
|
||||
vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Select Area"),
|
||||
HintInfo::keys([Key::Control], "Lasso").prepend_plus(),
|
||||
])]
|
||||
};
|
||||
|
||||
if at_least_one_anchor_selected {
|
||||
// TODO: Dynamically show either "Smooth" or "Sharp" based on the current state
|
||||
hint_data.push(HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDouble, "Convert Anchor Point"),
|
||||
HintInfo::keys_and_mouse([Key::Alt], MouseMotion::Lmb, "To Sharp"),
|
||||
HintInfo::keys_and_mouse([Key::Alt], MouseMotion::LmbDrag, "To Smooth"),
|
||||
]));
|
||||
}
|
||||
|
||||
if at_least_one_point_selected {
|
||||
let mut groups = vec![
|
||||
HintGroup(drag_selected_hints),
|
||||
HintGroup(vec![HintInfo::multi_keys([[Key::KeyG], [Key::KeyR], [Key::KeyS]], "Grab/Rotate/Scale Selected")]),
|
||||
HintGroup(vec![HintInfo::arrow_keys("Nudge Selected"), HintInfo::keys([Key::Shift], "10x").prepend_plus()]),
|
||||
HintGroup(delete_selected_hints),
|
||||
];
|
||||
hint_data.append(&mut groups);
|
||||
}
|
||||
|
||||
HintData(hint_data)
|
||||
}
|
||||
PathToolFsmState::Dragging(dragging_state) => {
|
||||
let colinear = dragging_state.colinear;
|
||||
let mut dragging_hint_data = HintData(Vec::new());
|
||||
dragging_hint_data
|
||||
.0
|
||||
.push(HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]));
|
||||
|
||||
let drag_anchor = HintInfo::keys([Key::Space], "Drag Anchor");
|
||||
let toggle_group = match dragging_state.point_select_state {
|
||||
PointSelectState::HandleNoPair | PointSelectState::HandleWithPair => {
|
||||
let mut hints = vec![HintInfo::keys([Key::Tab], "Swap Dragged Handle")];
|
||||
hints.push(HintInfo::keys(
|
||||
[Key::KeyC],
|
||||
if colinear == ManipulatorAngle::Colinear {
|
||||
"Break Colinear Handles"
|
||||
} else {
|
||||
"Make Handles Colinear"
|
||||
},
|
||||
));
|
||||
hints
|
||||
}
|
||||
PointSelectState::Anchor => Vec::new(),
|
||||
};
|
||||
let hold_group = match dragging_state.point_select_state {
|
||||
PointSelectState::HandleNoPair => {
|
||||
let mut hints = vec![];
|
||||
if colinear != ManipulatorAngle::Free {
|
||||
hints.push(HintInfo::keys([Key::Alt], "Equidistant Handles"));
|
||||
}
|
||||
hints.push(HintInfo::keys([Key::Shift], "15° Increments"));
|
||||
hints.push(HintInfo::keys([Key::Control], "Lock Angle"));
|
||||
hints.push(drag_anchor);
|
||||
hints
|
||||
}
|
||||
PointSelectState::HandleWithPair => {
|
||||
let mut hints = vec![];
|
||||
if colinear != ManipulatorAngle::Free {
|
||||
hints.push(HintInfo::keys([Key::Alt], "Equidistant Handles"));
|
||||
}
|
||||
hints.push(HintInfo::keys([Key::Shift], "15° Increments"));
|
||||
hints.push(HintInfo::keys([Key::Control], "Lock Angle"));
|
||||
hints.push(drag_anchor);
|
||||
hints
|
||||
}
|
||||
PointSelectState::Anchor => Vec::new(),
|
||||
};
|
||||
|
||||
if !toggle_group.is_empty() {
|
||||
dragging_hint_data.0.push(HintGroup(toggle_group));
|
||||
}
|
||||
|
||||
if !hold_group.is_empty() {
|
||||
dragging_hint_data.0.push(HintGroup(hold_group));
|
||||
}
|
||||
|
||||
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) = document.network_interface.compute_modified_vector(segment.layer()) {
|
||||
let other_handle1 = vector.other_colinear_handle(handle1);
|
||||
let other_handle2 = vector.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![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Select Area"),
|
||||
HintInfo::keys([Key::Shift], "Extend").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "Subtract").prepend_plus(),
|
||||
]),
|
||||
]),
|
||||
PathToolFsmState::SlidingPoint => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])]),
|
||||
};
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
@@ -2164,7 +2164,7 @@ impl Fsm for PenToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
PenToolFsmState::Ready | PenToolFsmState::GRSHandle => HintData(vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::Lmb, "Draw Path"),
|
||||
@@ -2226,7 +2226,7 @@ impl Fsm for PenToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1650,22 +1650,7 @@ impl Fsm for SelectToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn standard_tool_messages(&self, message: &ToolMessage, responses: &mut VecDeque<Message>) -> bool {
|
||||
// Check for standard hits or cursor events
|
||||
match message {
|
||||
ToolMessage::UpdateHints => {
|
||||
self.update_hints(responses);
|
||||
true
|
||||
}
|
||||
ToolMessage::UpdateCursor => {
|
||||
self.update_cursor(responses);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
match self {
|
||||
SelectToolFsmState::Ready { selection } => {
|
||||
let hint_data = HintData(vec![
|
||||
@@ -1752,7 +1737,7 @@ impl Fsm for SelectToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionMessageContext<'a>> for Shap
|
||||
}
|
||||
}
|
||||
|
||||
update_dynamic_hints(&self.fsm_state, responses, &self.tool_data);
|
||||
self.fsm_state.update_hints(&self.tool_data, context, &self.options, responses);
|
||||
self.send_layout(responses, LayoutTarget::ToolOptions);
|
||||
}
|
||||
|
||||
@@ -914,100 +914,96 @@ impl Fsm for ShapeToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, _responses: &mut VecDeque<Message>) {
|
||||
// Moved logic to update_dynamic_hints
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Crosshair });
|
||||
}
|
||||
}
|
||||
|
||||
fn update_dynamic_hints(state: &ShapeToolFsmState, responses: &mut VecDeque<Message>, tool_data: &ShapeToolData) {
|
||||
let hint_data = match state {
|
||||
ShapeToolFsmState::Ready(_) => {
|
||||
let hint_groups = match tool_data.current_shape {
|
||||
ShapeType::Polygon | ShapeType::Star => vec![
|
||||
HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Polygon"),
|
||||
HintInfo::keys([Key::Shift], "Constrain Regular").prepend_plus(),
|
||||
fn update_hints(&self, tool_data: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
ShapeToolFsmState::Ready(_) => {
|
||||
let hint_groups = match tool_data.current_shape {
|
||||
ShapeType::Polygon | ShapeType::Star => vec![
|
||||
HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Polygon"),
|
||||
HintInfo::keys([Key::Shift], "Constrain Regular").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
]),
|
||||
HintGroup(vec![HintInfo::multi_keys([[Key::BracketLeft], [Key::BracketRight]], "Decrease/Increase Sides")]),
|
||||
],
|
||||
ShapeType::Ellipse => vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Ellipse"),
|
||||
HintInfo::keys([Key::Shift], "Constrain Circular").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
])],
|
||||
ShapeType::Line => vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Line"),
|
||||
HintInfo::keys([Key::Shift], "15° Increments").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
HintInfo::keys([Key::Control], "Lock Angle").prepend_plus(),
|
||||
])],
|
||||
ShapeType::Rectangle => vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Rectangle"),
|
||||
HintInfo::keys([Key::Shift], "Constrain Square").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
])],
|
||||
ShapeType::Circle => vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Circle"),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
])],
|
||||
ShapeType::Arc => vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Arc"),
|
||||
HintInfo::keys([Key::Shift], "Constrain Arc").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
])],
|
||||
};
|
||||
HintData(hint_groups)
|
||||
}
|
||||
ShapeToolFsmState::Drawing(shape) => {
|
||||
let mut common_hint_group = vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])];
|
||||
let tool_hint_group = match shape {
|
||||
ShapeType::Polygon | ShapeType::Star | ShapeType::Arc => HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Regular"), HintInfo::keys([Key::Alt], "From Center")]),
|
||||
ShapeType::Rectangle => HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Square"), HintInfo::keys([Key::Alt], "From Center")]),
|
||||
ShapeType::Ellipse => HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Circular"), HintInfo::keys([Key::Alt], "From Center")]),
|
||||
ShapeType::Line => HintGroup(vec![
|
||||
HintInfo::keys([Key::Shift], "15° Increments"),
|
||||
HintInfo::keys([Key::Alt], "From Center"),
|
||||
HintInfo::keys([Key::Control], "Lock Angle"),
|
||||
]),
|
||||
HintGroup(vec![HintInfo::multi_keys([[Key::BracketLeft], [Key::BracketRight]], "Decrease/Increase Sides")]),
|
||||
],
|
||||
ShapeType::Ellipse => vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Ellipse"),
|
||||
HintInfo::keys([Key::Shift], "Constrain Circular").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
])],
|
||||
ShapeType::Line => vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Line"),
|
||||
HintInfo::keys([Key::Shift], "15° Increments").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
HintInfo::keys([Key::Control], "Lock Angle").prepend_plus(),
|
||||
])],
|
||||
ShapeType::Rectangle => vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Rectangle"),
|
||||
HintInfo::keys([Key::Shift], "Constrain Square").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
])],
|
||||
ShapeType::Circle => vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Circle"),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
])],
|
||||
ShapeType::Arc => vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Arc"),
|
||||
HintInfo::keys([Key::Shift], "Constrain Arc").prepend_plus(),
|
||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||
])],
|
||||
};
|
||||
HintData(hint_groups)
|
||||
}
|
||||
ShapeToolFsmState::Drawing(shape) => {
|
||||
let mut common_hint_group = vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])];
|
||||
let tool_hint_group = match shape {
|
||||
ShapeType::Polygon | ShapeType::Star | ShapeType::Arc => HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Regular"), HintInfo::keys([Key::Alt], "From Center")]),
|
||||
ShapeType::Rectangle => HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Square"), HintInfo::keys([Key::Alt], "From Center")]),
|
||||
ShapeType::Ellipse => HintGroup(vec![HintInfo::keys([Key::Shift], "Constrain Circular"), HintInfo::keys([Key::Alt], "From Center")]),
|
||||
ShapeType::Line => HintGroup(vec![
|
||||
ShapeType::Circle => HintGroup(vec![HintInfo::keys([Key::Alt], "From Center")]),
|
||||
};
|
||||
|
||||
if !tool_hint_group.0.is_empty() {
|
||||
common_hint_group.push(tool_hint_group);
|
||||
}
|
||||
|
||||
if matches!(shape, ShapeType::Polygon | ShapeType::Star) {
|
||||
common_hint_group.push(HintGroup(vec![HintInfo::multi_keys([[Key::BracketLeft], [Key::BracketRight]], "Decrease/Increase Sides")]));
|
||||
}
|
||||
|
||||
HintData(common_hint_group)
|
||||
}
|
||||
ShapeToolFsmState::DraggingLineEndpoints => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![
|
||||
HintInfo::keys([Key::Shift], "15° Increments"),
|
||||
HintInfo::keys([Key::Alt], "From Center"),
|
||||
HintInfo::keys([Key::Control], "Lock Angle"),
|
||||
]),
|
||||
ShapeType::Circle => HintGroup(vec![HintInfo::keys([Key::Alt], "From Center")]),
|
||||
};
|
||||
|
||||
if !tool_hint_group.0.is_empty() {
|
||||
common_hint_group.push(tool_hint_group);
|
||||
}
|
||||
|
||||
if matches!(shape, ShapeType::Polygon | ShapeType::Star) {
|
||||
common_hint_group.push(HintGroup(vec![HintInfo::multi_keys([[Key::BracketLeft], [Key::BracketRight]], "Decrease/Increase Sides")]));
|
||||
}
|
||||
|
||||
HintData(common_hint_group)
|
||||
}
|
||||
ShapeToolFsmState::DraggingLineEndpoints => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![
|
||||
HintInfo::keys([Key::Shift], "15° Increments"),
|
||||
HintInfo::keys([Key::Alt], "From Center"),
|
||||
HintInfo::keys([Key::Control], "Lock Angle"),
|
||||
]),
|
||||
]),
|
||||
ShapeToolFsmState::ResizingBounds => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Alt], "From Pivot"), HintInfo::keys([Key::Shift], "Preserve Aspect Ratio")]),
|
||||
]),
|
||||
ShapeToolFsmState::RotatingBounds => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "15° Increments")]),
|
||||
]),
|
||||
ShapeToolFsmState::SkewingBounds { .. } => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Control], "Unlock Slide")]),
|
||||
]),
|
||||
ShapeToolFsmState::ModifyingGizmo => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])]),
|
||||
};
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
ShapeToolFsmState::ResizingBounds => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Alt], "From Pivot"), HintInfo::keys([Key::Shift], "Preserve Aspect Ratio")]),
|
||||
]),
|
||||
ShapeToolFsmState::RotatingBounds => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Shift], "15° Increments")]),
|
||||
]),
|
||||
ShapeToolFsmState::SkewingBounds { .. } => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||
HintGroup(vec![HintInfo::keys([Key::Control], "Unlock Slide")]),
|
||||
]),
|
||||
ShapeToolFsmState::ModifyingGizmo => HintData(vec![HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()])]),
|
||||
};
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Crosshair });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,7 +450,7 @@ impl Fsm for SplineToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
SplineToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||
HintInfo::mouse(MouseMotion::Lmb, "Draw Spline"),
|
||||
@@ -467,7 +467,7 @@ impl Fsm for SplineToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -886,7 +886,7 @@ impl Fsm for TextToolFsmState {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let hint_data = match self {
|
||||
TextToolFsmState::Ready => HintData(vec![
|
||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Place Text")]),
|
||||
@@ -915,7 +915,7 @@ impl Fsm for TextToolFsmState {
|
||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
||||
}
|
||||
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
||||
fn update_cursor(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||
let cursor = match self {
|
||||
TextToolFsmState::Placing => MouseCursorIcon::Crosshair,
|
||||
_ => MouseCursorIcon::Text,
|
||||
|
||||
@@ -56,20 +56,27 @@ pub trait Fsm {
|
||||
fn transition(self, message: ToolMessage, tool_data: &mut Self::ToolData, transition_data: &mut ToolActionMessageContext, options: &Self::ToolOptions, responses: &mut VecDeque<Message>) -> Self;
|
||||
|
||||
/// Implementing this trait function lets a specific tool provide a list of hints (user input actions presently available) to draw in the footer bar.
|
||||
fn update_hints(&self, responses: &mut VecDeque<Message>);
|
||||
fn update_hints(&self, tool_data: &Self::ToolData, transition_data: &ToolActionMessageContext, options: &Self::ToolOptions, responses: &mut VecDeque<Message>);
|
||||
/// Implementing this trait function lets a specific tool set the current mouse cursor icon.
|
||||
fn update_cursor(&self, responses: &mut VecDeque<Message>);
|
||||
fn update_cursor(&self, tool_data: &Self::ToolData, transition_data: &ToolActionMessageContext, options: &Self::ToolOptions, responses: &mut VecDeque<Message>);
|
||||
|
||||
/// If this message is a standard tool message, process it and return true. Standard tool messages are those which are common across every tool.
|
||||
fn standard_tool_messages(&self, message: &ToolMessage, responses: &mut VecDeque<Message>) -> bool {
|
||||
fn standard_tool_messages(
|
||||
&self,
|
||||
message: &ToolMessage,
|
||||
tool_data: &Self::ToolData,
|
||||
transition_data: &ToolActionMessageContext,
|
||||
options: &Self::ToolOptions,
|
||||
responses: &mut VecDeque<Message>,
|
||||
) -> bool {
|
||||
// Check for standard hits or cursor events
|
||||
match message {
|
||||
ToolMessage::UpdateHints => {
|
||||
self.update_hints(responses);
|
||||
self.update_hints(tool_data, transition_data, options, responses);
|
||||
true
|
||||
}
|
||||
ToolMessage::UpdateCursor => {
|
||||
self.update_cursor(responses);
|
||||
self.update_cursor(tool_data, transition_data, options, responses);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
@@ -90,7 +97,7 @@ pub trait Fsm {
|
||||
Self: PartialEq + Sized + Copy,
|
||||
{
|
||||
// If this message is one of the standard tool messages, process it and exit early
|
||||
if self.standard_tool_messages(&message, responses) {
|
||||
if self.standard_tool_messages(&message, tool_data, transition_data, options, responses) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -100,9 +107,9 @@ pub trait Fsm {
|
||||
// Update state
|
||||
if *self != new_state {
|
||||
*self = new_state;
|
||||
self.update_hints(responses);
|
||||
self.update_hints(tool_data, transition_data, options, responses);
|
||||
if update_cursor_on_transition {
|
||||
self.update_cursor(responses);
|
||||
self.update_cursor(tool_data, transition_data, options, responses);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user