mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-05 10:48:12 +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(
|
pub fn find_nearest_visible_point_indices(
|
||||||
&mut self,
|
&self,
|
||||||
network_interface: &NodeNetworkInterface,
|
network_interface: &NodeNetworkInterface,
|
||||||
mouse_position: DVec2,
|
mouse_position: DVec2,
|
||||||
select_threshold: f64,
|
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 {
|
let hint_data = match self {
|
||||||
ArtboardToolFsmState::Ready { .. } => HintData(vec![
|
ArtboardToolFsmState::Ready { .. } => HintData(vec![
|
||||||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Draw Artboard")]),
|
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Draw Artboard")]),
|
||||||
@@ -552,7 +552,7 @@ impl Fsm for ArtboardToolFsmState {
|
|||||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
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 {
|
if let Self::Ready { hovered: false } = self {
|
||||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Crosshair });
|
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Crosshair });
|
||||||
} else {
|
} 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 {
|
let hint_data = match self {
|
||||||
BrushToolFsmState::Ready => HintData(vec![
|
BrushToolFsmState::Ready => HintData(vec![
|
||||||
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Draw")]),
|
HintGroup(vec![HintInfo::mouse(MouseMotion::LmbDrag, "Draw")]),
|
||||||
@@ -430,7 +430,7 @@ impl Fsm for BrushToolFsmState {
|
|||||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
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 });
|
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 {
|
let hint_data = match self {
|
||||||
EyedropperToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
EyedropperToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||||
HintInfo::mouse(MouseMotion::Lmb, "Sample to Primary"),
|
HintInfo::mouse(MouseMotion::Lmb, "Sample to Primary"),
|
||||||
@@ -138,7 +138,7 @@ impl Fsm for EyedropperToolFsmState {
|
|||||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
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 {
|
let cursor = match *self {
|
||||||
EyedropperToolFsmState::Ready => MouseCursorIcon::Default,
|
EyedropperToolFsmState::Ready => MouseCursorIcon::Default,
|
||||||
EyedropperToolFsmState::SamplingPrimary | EyedropperToolFsmState::SamplingSecondary => MouseCursorIcon::None,
|
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 {
|
let hint_data = match self {
|
||||||
FillToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
FillToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||||
HintInfo::mouse(MouseMotion::Lmb, "Fill with Primary"),
|
HintInfo::mouse(MouseMotion::Lmb, "Fill with Primary"),
|
||||||
@@ -157,7 +157,7 @@ impl Fsm for FillToolFsmState {
|
|||||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
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 });
|
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 {
|
let hint_data = match self {
|
||||||
FreehandToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
FreehandToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Polyline"),
|
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Polyline"),
|
||||||
@@ -310,7 +310,7 @@ impl Fsm for FreehandToolFsmState {
|
|||||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
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 });
|
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 {
|
let hint_data = match self {
|
||||||
GradientToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
GradientToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Gradient"),
|
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Gradient"),
|
||||||
@@ -534,7 +534,7 @@ impl Fsm for GradientToolFsmState {
|
|||||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
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 });
|
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 {
|
let hint_data = match self {
|
||||||
NavigateToolFsmState::Ready | NavigateToolFsmState::ZoomOrClickZooming => HintData(vec![
|
NavigateToolFsmState::Ready | NavigateToolFsmState::ZoomOrClickZooming => HintData(vec![
|
||||||
HintGroup(vec![
|
HintGroup(vec![
|
||||||
@@ -169,7 +169,7 @@ impl Fsm for NavigateToolFsmState {
|
|||||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
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 {
|
let cursor = match *self {
|
||||||
NavigateToolFsmState::Ready => MouseCursorIcon::ZoomIn,
|
NavigateToolFsmState::Ready => MouseCursorIcon::ZoomIn,
|
||||||
NavigateToolFsmState::Tilting => MouseCursorIcon::Default,
|
NavigateToolFsmState::Tilting => MouseCursorIcon::Default,
|
||||||
|
|||||||
@@ -1505,9 +1505,9 @@ impl Fsm for PathToolFsmState {
|
|||||||
tool_options: &Self::ToolOptions,
|
tool_options: &Self::ToolOptions,
|
||||||
responses: &mut VecDeque<Message>,
|
responses: &mut VecDeque<Message>,
|
||||||
) -> Self {
|
) -> 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 };
|
let ToolMessage::Path(event) = event else { return self };
|
||||||
|
|
||||||
@@ -3040,11 +3040,218 @@ impl Fsm for PathToolFsmState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_hints(&self, _responses: &mut VecDeque<Message>) {
|
fn update_hints(&self, tool_data: &Self::ToolData, ctx: &ToolActionMessageContext, tool_options: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||||
// Moved logic to update_dynamic_hints
|
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 });
|
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Default });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3260,220 +3467,3 @@ fn calculate_adjacent_anchor_tangent(currently_dragged_handle: ManipulatorPointI
|
|||||||
_ => (None, None),
|
_ => (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 {
|
let hint_data = match self {
|
||||||
PenToolFsmState::Ready | PenToolFsmState::GRSHandle => HintData(vec![HintGroup(vec![
|
PenToolFsmState::Ready | PenToolFsmState::GRSHandle => HintData(vec![HintGroup(vec![
|
||||||
HintInfo::mouse(MouseMotion::Lmb, "Draw Path"),
|
HintInfo::mouse(MouseMotion::Lmb, "Draw Path"),
|
||||||
@@ -2226,7 +2226,7 @@ impl Fsm for PenToolFsmState {
|
|||||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
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 });
|
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 {
|
fn update_hints(&self, _: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||||
// 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>) {
|
|
||||||
match self {
|
match self {
|
||||||
SelectToolFsmState::Ready { selection } => {
|
SelectToolFsmState::Ready { selection } => {
|
||||||
let hint_data = HintData(vec![
|
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 });
|
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);
|
self.send_layout(responses, LayoutTarget::ToolOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -914,100 +914,96 @@ impl Fsm for ShapeToolFsmState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_hints(&self, _responses: &mut VecDeque<Message>) {
|
fn update_hints(&self, tool_data: &Self::ToolData, _: &ToolActionMessageContext, _: &Self::ToolOptions, responses: &mut VecDeque<Message>) {
|
||||||
// Moved logic to update_dynamic_hints
|
let hint_data = match self {
|
||||||
}
|
ShapeToolFsmState::Ready(_) => {
|
||||||
|
let hint_groups = match tool_data.current_shape {
|
||||||
fn update_cursor(&self, responses: &mut VecDeque<Message>) {
|
ShapeType::Polygon | ShapeType::Star => vec![
|
||||||
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::Crosshair });
|
HintGroup(vec![
|
||||||
}
|
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Polygon"),
|
||||||
}
|
HintInfo::keys([Key::Shift], "Constrain Regular").prepend_plus(),
|
||||||
|
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
||||||
fn update_dynamic_hints(state: &ShapeToolFsmState, responses: &mut VecDeque<Message>, tool_data: &ShapeToolData) {
|
]),
|
||||||
let hint_data = match state {
|
HintGroup(vec![HintInfo::multi_keys([[Key::BracketLeft], [Key::BracketRight]], "Decrease/Increase Sides")]),
|
||||||
ShapeToolFsmState::Ready(_) => {
|
],
|
||||||
let hint_groups = match tool_data.current_shape {
|
ShapeType::Ellipse => vec![HintGroup(vec![
|
||||||
ShapeType::Polygon | ShapeType::Star => vec![
|
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Ellipse"),
|
||||||
HintGroup(vec![
|
HintInfo::keys([Key::Shift], "Constrain Circular").prepend_plus(),
|
||||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Polygon"),
|
|
||||||
HintInfo::keys([Key::Shift], "Constrain Regular").prepend_plus(),
|
|
||||||
HintInfo::keys([Key::Alt], "From Center").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::Circle => HintGroup(vec![HintInfo::keys([Key::Alt], "From Center")]),
|
||||||
],
|
};
|
||||||
ShapeType::Ellipse => vec![HintGroup(vec![
|
|
||||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Ellipse"),
|
if !tool_hint_group.0.is_empty() {
|
||||||
HintInfo::keys([Key::Shift], "Constrain Circular").prepend_plus(),
|
common_hint_group.push(tool_hint_group);
|
||||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
}
|
||||||
])],
|
|
||||||
ShapeType::Line => vec![HintGroup(vec![
|
if matches!(shape, ShapeType::Polygon | ShapeType::Star) {
|
||||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Line"),
|
common_hint_group.push(HintGroup(vec![HintInfo::multi_keys([[Key::BracketLeft], [Key::BracketRight]], "Decrease/Increase Sides")]));
|
||||||
HintInfo::keys([Key::Shift], "15° Increments").prepend_plus(),
|
}
|
||||||
HintInfo::keys([Key::Alt], "From Center").prepend_plus(),
|
|
||||||
HintInfo::keys([Key::Control], "Lock Angle").prepend_plus(),
|
HintData(common_hint_group)
|
||||||
])],
|
}
|
||||||
ShapeType::Rectangle => vec![HintGroup(vec![
|
ShapeToolFsmState::DraggingLineEndpoints => HintData(vec![
|
||||||
HintInfo::mouse(MouseMotion::LmbDrag, "Draw Rectangle"),
|
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
|
||||||
HintInfo::keys([Key::Shift], "Constrain Square").prepend_plus(),
|
HintGroup(vec![
|
||||||
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::Shift], "15° Increments"),
|
||||||
HintInfo::keys([Key::Alt], "From Center"),
|
HintInfo::keys([Key::Alt], "From Center"),
|
||||||
HintInfo::keys([Key::Control], "Lock Angle"),
|
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![
|
||||||
ShapeToolFsmState::ResizingBounds => 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()]),
|
HintGroup(vec![HintInfo::keys([Key::Alt], "From Pivot"), HintInfo::keys([Key::Shift], "Preserve Aspect Ratio")]),
|
||||||
HintGroup(vec![HintInfo::keys([Key::Alt], "From Pivot"), HintInfo::keys([Key::Shift], "Preserve Aspect Ratio")]),
|
]),
|
||||||
]),
|
ShapeToolFsmState::RotatingBounds => HintData(vec![
|
||||||
ShapeToolFsmState::RotatingBounds => 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()]),
|
HintGroup(vec![HintInfo::keys([Key::Shift], "15° Increments")]),
|
||||||
HintGroup(vec![HintInfo::keys([Key::Shift], "15° Increments")]),
|
]),
|
||||||
]),
|
ShapeToolFsmState::SkewingBounds { .. } => HintData(vec![
|
||||||
ShapeToolFsmState::SkewingBounds { .. } => 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()]),
|
HintGroup(vec![HintInfo::keys([Key::Control], "Unlock Slide")]),
|
||||||
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()])]),
|
||||||
ShapeToolFsmState::ModifyingGizmo => 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 });
|
}
|
||||||
|
|
||||||
|
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 {
|
let hint_data = match self {
|
||||||
SplineToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
SplineToolFsmState::Ready => HintData(vec![HintGroup(vec![
|
||||||
HintInfo::mouse(MouseMotion::Lmb, "Draw Spline"),
|
HintInfo::mouse(MouseMotion::Lmb, "Draw Spline"),
|
||||||
@@ -467,7 +467,7 @@ impl Fsm for SplineToolFsmState {
|
|||||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
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 });
|
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 {
|
let hint_data = match self {
|
||||||
TextToolFsmState::Ready => HintData(vec![
|
TextToolFsmState::Ready => HintData(vec![
|
||||||
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Place Text")]),
|
HintGroup(vec![HintInfo::mouse(MouseMotion::Lmb, "Place Text")]),
|
||||||
@@ -915,7 +915,7 @@ impl Fsm for TextToolFsmState {
|
|||||||
responses.add(FrontendMessage::UpdateInputHints { hint_data });
|
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 {
|
let cursor = match self {
|
||||||
TextToolFsmState::Placing => MouseCursorIcon::Crosshair,
|
TextToolFsmState::Placing => MouseCursorIcon::Crosshair,
|
||||||
_ => MouseCursorIcon::Text,
|
_ => 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;
|
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.
|
/// 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.
|
/// 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.
|
/// 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
|
// Check for standard hits or cursor events
|
||||||
match message {
|
match message {
|
||||||
ToolMessage::UpdateHints => {
|
ToolMessage::UpdateHints => {
|
||||||
self.update_hints(responses);
|
self.update_hints(tool_data, transition_data, options, responses);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
ToolMessage::UpdateCursor => {
|
ToolMessage::UpdateCursor => {
|
||||||
self.update_cursor(responses);
|
self.update_cursor(tool_data, transition_data, options, responses);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
@@ -90,7 +97,7 @@ pub trait Fsm {
|
|||||||
Self: PartialEq + Sized + Copy,
|
Self: PartialEq + Sized + Copy,
|
||||||
{
|
{
|
||||||
// If this message is one of the standard tool messages, process it and exit early
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,9 +107,9 @@ pub trait Fsm {
|
|||||||
// Update state
|
// Update state
|
||||||
if *self != new_state {
|
if *self != new_state {
|
||||||
*self = new_state;
|
*self = new_state;
|
||||||
self.update_hints(responses);
|
self.update_hints(tool_data, transition_data, options, responses);
|
||||||
if update_cursor_on_transition {
|
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