Skip to content

Commit 82df4fe

Browse files
committed
fix: tidy up dynamic tool hints
switch colinear to V
1 parent 67717bb commit 82df4fe

File tree

3 files changed

+102
-56
lines changed

3 files changed

+102
-56
lines changed

editor/src/messages/input_mapper/input_mappings.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ pub fn input_mappings() -> Mapping {
211211
entry!(KeyDown(KeyG); action_dispatch=PathToolMessage::GRS { key: KeyG }),
212212
entry!(KeyDown(KeyR); action_dispatch=PathToolMessage::GRS { key: KeyR }),
213213
entry!(KeyDown(KeyS); action_dispatch=PathToolMessage::GRS { key: KeyS }),
214-
entry!(PointerMove; refresh_keys=[Alt, Shift, Space], action_dispatch=PathToolMessage::PointerMove { alt: Alt, shift: Shift, move_anchor_and_handles: Space}),
214+
entry!(PointerMove; refresh_keys=[KeyV, Shift, Space], action_dispatch=PathToolMessage::PointerMove { alt:KeyV, shift: Shift, move_anchor_and_handles: Space}),
215215
entry!(KeyDown(Delete); action_dispatch=PathToolMessage::Delete),
216216
entry!(KeyDown(KeyA); modifiers=[Accel], action_dispatch=PathToolMessage::SelectAllAnchors),
217217
entry!(KeyDown(KeyA); modifiers=[Accel, Shift], action_dispatch=PathToolMessage::DeselectAllPoints),

editor/src/messages/tool/common_functionality/shape_editor.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::messages::portfolio::document::utility_types::document_metadata::{Doc
44
use crate::messages::portfolio::document::utility_types::misc::{GeometrySnapSource, SnapSource};
55
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
66
use crate::messages::prelude::*;
7+
use crate::messages::tool::tool_messages::path_tool::PointSelectState;
78

89
use bezier_rs::{Bezier, BezierHandles, TValue};
910
use graphene_core::transform::Transform;
@@ -1060,12 +1061,34 @@ impl ShapeState {
10601061
_ => self.sorted_selected_layers(network_interface.document_metadata()).find_map(closest_seg),
10611062
}
10621063
}
1064+
pub fn get_dragging_state(&self, network_interface: &NodeNetworkInterface) -> PointSelectState {
1065+
for &layer in self.selected_shape_state.keys() {
1066+
let Some(vector_data) = network_interface.compute_modified_vector(layer) else {
1067+
continue;
1068+
};
1069+
1070+
for point in self.selected_points() {
1071+
if let Some(_) = point.as_anchor() {
1072+
return PointSelectState::Anchor;
1073+
}
1074+
if let Some(_) = point.get_handle_pair(&vector_data) {
1075+
return PointSelectState::HandleWithPair;
1076+
}
1077+
}
1078+
}
1079+
return PointSelectState::HandleNoPair;
1080+
}
10631081

1064-
/// Returns true if atleast one handle is selected
1065-
pub fn handle_selected(&mut self) -> bool {
1066-
for point in self.selected_points() {
1067-
if let Some(_) = point.as_handle() {
1068-
return true;
1082+
/// Returns true if atleast one handle with pair is selected
1083+
pub fn handle_with_pair_selected(&mut self, network_interface: &NodeNetworkInterface) -> bool {
1084+
for &layer in self.selected_shape_state.keys() {
1085+
let Some(vector_data) = network_interface.compute_modified_vector(layer) else {
1086+
continue;
1087+
};
1088+
for point in self.selected_points() {
1089+
if let Some(_) = point.get_handle_pair(&vector_data) {
1090+
return true;
1091+
}
10691092
}
10701093
}
10711094
return false;

editor/src/messages/tool/tool_messages/path_tool.rs

Lines changed: 73 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -77,24 +77,6 @@ pub enum PathToolMessage {
7777
AlternateSelectedHandles,
7878
}
7979

80-
fn handle_hint_data() -> HintData {
81-
return HintData(vec![
82-
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
83-
HintGroup(vec![
84-
// TODO: Switch this to the "S" key. Also, make the hint dynamically say "Make Colinear" or "Make Not Colinear" based on its current state. And only
85-
// TODO: show this hint if a handle (not an anchor) is being dragged, and disable that shortcut so it can't be pressed even with the hint not shown.
86-
HintInfo::keys([Key::Alt], "Toggle Colinear Handles"),
87-
// TODO: Switch this to the "Alt" key (since it's equivalent to the "From Center" modifier when drawing a line). And show this only when a handle is being dragged.
88-
HintInfo::keys([Key::Shift], "Equidistant Handles"),
89-
HintInfo::keys([Key::Tab], "Select Opposite Handles"), //TODO: only show when handle selected
90-
// TODO: Add "Snap 15°" modifier with the "Shift" key (only when a handle is being dragged).
91-
// TODO: Add "Lock Angle" modifier with the "Ctrl" key (only when a handle is being dragged).
92-
// TODO: Add "Snap 15°" modifier with the "Shift" key (only when a handle is being dragged).
93-
// TODO: Add "Lock Angle" modifier with the "Ctrl" key (only when a handle is being dragged).
94-
HintInfo::keys([Key::Space], "Drag anchor"),
95-
]),
96-
]);
97-
}
9880
impl ToolMetadata for PathTool {
9981
fn icon_name(&self) -> String {
10082
"VectorPathTool".into()
@@ -191,7 +173,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for PathToo
191173

192174
match message {
193175
ToolMessage::Path(PathToolMessage::AlternateSelectedHandles) => {
194-
if tool_data.shape_editor.handle_selected() {
176+
if tool_data.shape_editor.handle_with_pair_selected(&tool_data.document.network_interface) {
195177
tool_data.shape_editor.alternate_selected_handles(&tool_data.document.network_interface);
196178
responses.add(PathToolMessage::SelectedPointUpdated);
197179
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::None });
@@ -222,7 +204,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionHandlerData<'a>> for PathToo
222204
BreakPath,
223205
DeleteAndBreakPath,
224206
),
225-
PathToolFsmState::Dragging => actions!(PathToolMessageDiscriminant;
207+
PathToolFsmState::Dragging(_) => actions!(PathToolMessageDiscriminant;
226208
Escape,
227209
RightClick,
228210
FlipSmoothSharp,
@@ -267,12 +249,25 @@ impl ToolTransition for PathTool {
267249
}
268250
}
269251
}
252+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
253+
pub struct DraggingState {
254+
point_select_state: PointSelectState,
255+
colinear: bool,
256+
}
257+
258+
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
259+
pub enum PointSelectState {
260+
HandleWithPair,
261+
#[default]
262+
HandleNoPair,
263+
Anchor,
264+
}
270265

271266
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
272267
enum PathToolFsmState {
273268
#[default]
274269
Ready,
275-
Dragging,
270+
Dragging(DraggingState),
276271
DrawingBox,
277272
InsertPoint,
278273
}
@@ -298,12 +293,13 @@ struct PathToolData {
298293
auto_panning: AutoPanning,
299294
saved_points_before_anchor_select_toggle: Vec<ManipulatorPointId>,
300295
select_anchor_toggled: bool,
296+
dragging_state: DraggingState,
301297
}
302298

303299
impl PathToolData {
304300
fn save_points_before_anchor_toggle(&mut self, points: Vec<ManipulatorPointId>) -> PathToolFsmState {
305301
self.saved_points_before_anchor_select_toggle = points;
306-
PathToolFsmState::Dragging
302+
PathToolFsmState::Dragging(self.dragging_state)
307303
}
308304

309305
fn remove_saved_points(&mut self) {
@@ -380,7 +376,7 @@ impl PathToolData {
380376
self.start_dragging_point(selected_points, input, document, shape_editor);
381377
responses.add(OverlaysMessage::Draw);
382378
}
383-
PathToolFsmState::Dragging
379+
PathToolFsmState::Dragging(self.dragging_state)
384380
}
385381
// We didn't find a point nearby, so now we'll try to add a point into the closest path segment
386382
else if let Some(closed_segment) = shape_editor.upper_closest_segment(&document.network_interface, input.mouse.position, SELECTION_TOLERANCE) {
@@ -404,7 +400,11 @@ impl PathToolData {
404400
shape_editor.select_connected_anchors(document, layer, input.mouse.position);
405401

406402
responses.add(DocumentMessage::StartTransaction);
407-
PathToolFsmState::Dragging
403+
PathToolFsmState::Dragging(self.dragging_state)
404+
// PathToolFsmState::Dragging {
405+
// dragging_state: self.dragging_state,
406+
// colinear: self.colinear,
407+
// }
408408
}
409409
// Start drawing a box
410410
else {
@@ -513,7 +513,7 @@ impl Fsm for PathToolFsmState {
513513

514514
overlay_context.quad(Quad::from_box([tool_data.drag_start_pos, tool_data.previous_mouse_position]), Some(&("#".to_string() + &fill_color)));
515515
}
516-
Self::Dragging => {
516+
Self::Dragging(_) => {
517517
tool_data.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context);
518518
}
519519
Self::InsertPoint => {
@@ -579,7 +579,7 @@ impl Fsm for PathToolFsmState {
579579

580580
PathToolFsmState::DrawingBox
581581
}
582-
(PathToolFsmState::Dragging, PathToolMessage::PointerMove { alt, shift, move_anchor_and_handles }) => {
582+
(PathToolFsmState::Dragging { .. }, PathToolMessage::PointerMove { alt, shift, move_anchor_and_handles }) => {
583583
let anchor_and_handle_toggled = input.keyboard.get(move_anchor_and_handles as usize);
584584
let initial_press = anchor_and_handle_toggled && !tool_data.select_anchor_toggled;
585585
let released_from_toggle = tool_data.select_anchor_toggled && !anchor_and_handle_toggled;
@@ -610,7 +610,7 @@ impl Fsm for PathToolFsmState {
610610
];
611611
tool_data.auto_panning.setup_by_mouse_position(input, &messages, responses);
612612

613-
PathToolFsmState::Dragging
613+
PathToolFsmState::Dragging(tool_data.dragging_state)
614614
}
615615
(PathToolFsmState::DrawingBox, PathToolMessage::PointerOutsideViewport { .. }) => {
616616
// Auto-panning
@@ -620,14 +620,14 @@ impl Fsm for PathToolFsmState {
620620

621621
PathToolFsmState::DrawingBox
622622
}
623-
(PathToolFsmState::Dragging, PathToolMessage::PointerOutsideViewport { shift, .. }) => {
623+
(PathToolFsmState::Dragging(dragging_state), PathToolMessage::PointerOutsideViewport { shift, .. }) => {
624624
// Auto-panning
625625
if tool_data.auto_panning.shift_viewport(input, responses).is_some() {
626626
let shift_state = input.keyboard.get(shift as usize);
627627
tool_data.drag(shift_state, shape_editor, document, input, responses);
628628
}
629629

630-
PathToolFsmState::Dragging
630+
PathToolFsmState::Dragging(dragging_state)
631631
}
632632
(state, PathToolMessage::PointerOutsideViewport { alt, shift, move_anchor_and_handles }) => {
633633
// Auto-panning
@@ -651,7 +651,7 @@ impl Fsm for PathToolFsmState {
651651

652652
PathToolFsmState::Ready
653653
}
654-
(PathToolFsmState::Dragging, PathToolMessage::Escape | PathToolMessage::RightClick) => {
654+
(PathToolFsmState::Dragging { .. }, PathToolMessage::Escape | PathToolMessage::RightClick) => {
655655
responses.add(DocumentMessage::AbortTransaction);
656656
tool_data.snap_manager.cleanup(responses);
657657
PathToolFsmState::Ready
@@ -760,10 +760,15 @@ impl Fsm for PathToolFsmState {
760760
PathToolFsmState::Ready
761761
}
762762
(_, PathToolMessage::SelectedPointUpdated) => {
763-
if shape_editor.handle_selected() {
764-
responses.add(FrontendMessage::UpdateInputHints { hint_data: handle_hint_data() });
765-
}
766-
763+
let colinear = match shape_editor.selected_manipulator_angles(&document.network_interface) {
764+
ManipulatorAngle::Colinear => true,
765+
ManipulatorAngle::Free => false,
766+
ManipulatorAngle::Mixed => true,
767+
};
768+
tool_data.dragging_state = DraggingState {
769+
point_select_state: shape_editor.get_dragging_state(&document.network_interface),
770+
colinear,
771+
};
767772
tool_data.selection_status = get_selection_status(&document.network_interface, shape_editor);
768773
self
769774
}
@@ -802,22 +807,40 @@ impl Fsm for PathToolFsmState {
802807
HintInfo::keys([Key::Shift], "Break Anchor").prepend_plus(),
803808
]),
804809
]),
805-
PathToolFsmState::Dragging => HintData(vec![
806-
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
807-
HintGroup(vec![
808-
// TODO: Switch this to the "S" key. Also, make the hint dynamically say "Make Colinear" or "Make Not Colinear" based on its current state. And only
809-
// TODO: show this hint if a handle (not an anchor) is being dragged, and disable that shortcut so it can't be pressed even with the hint not shown.
810-
HintInfo::keys([Key::Alt], "Toggle Colinear Handles"),
811-
// TODO: Switch this to the "Alt" key (since it's equivalent to the "From Center" modifier when drawing a line). And show this only when a handle is being dragged.
812-
HintInfo::keys([Key::Shift], "Equidistant Handles"),
813-
// HintInfo::keys([Key::Tab], "Select Opposite Handles"), //TODO: only show when handle selected
814-
// TODO: Add "Snap 15°" modifier with the "Shift" key (only when a handle is being dragged).
815-
// TODO: Add "Lock Angle" modifier with the "Ctrl" key (only when a handle is being dragged).
816-
// TODO: Add "Snap 15°" modifier with the "Shift" key (only when a handle is being dragged).
817-
// TODO: Add "Lock Angle" modifier with the "Ctrl" key (only when a handle is being dragged).
818-
HintInfo::keys([Key::Space], "Drag anchor"),
819-
]),
820-
]),
810+
PathToolFsmState::Dragging(dragging_state) => {
811+
let colinear = dragging_state.colinear;
812+
debug!("STATE: {:?}", &dragging_state);
813+
let mut dragging_hint_data = HintData(Vec::new());
814+
dragging_hint_data
815+
.0
816+
.push(HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]));
817+
818+
let point_select_state_hint_group: HintGroup = match dragging_state.point_select_state {
819+
PointSelectState::HandleNoPair => HintGroup(vec![HintInfo::keys([Key::Space], "Drag anchor")]),
820+
PointSelectState::HandleWithPair => {
821+
if colinear {
822+
HintGroup(vec![
823+
HintInfo::keys([Key::Space], "Drag anchor"),
824+
HintInfo::keys([Key::Tab], "Select Opposite Handles"),
825+
HintInfo::keys([Key::Shift], "Equidistant Handles"),
826+
HintInfo::keys([Key::KeyV], "Disable Colinear Handles"),
827+
])
828+
} else {
829+
HintGroup(vec![HintInfo::keys([Key::Space], "Drag anchor"), HintInfo::keys([Key::KeyV], "Toggle Colinear Handles")])
830+
}
831+
}
832+
PointSelectState::Anchor => HintGroup(vec![]),
833+
};
834+
835+
dragging_hint_data.0.push(point_select_state_hint_group);
836+
dragging_hint_data
837+
838+
// TODO: Switch this to the "Alt" key (since it's equivalent to the "From Center" modifier when drawing a line). And show this only when a handle is being dragged.
839+
// TODO: Add "Snap 15°" modifier with the "Shift" key (only when a handle is being dragged).
840+
// TODO: Add "Lock Angle" modifier with the "Ctrl" key (only when a handle is being dragged).
841+
// TODO: Add "Snap 15°" modifier with the "Shift" key (only when a handle is being dragged).
842+
// TODO: Add "Lock Angle" modifier with the "Ctrl" key (only when a handle is being dragged).
843+
}
821844
PathToolFsmState::DrawingBox => HintData(vec![
822845
HintGroup(vec![HintInfo::mouse(MouseMotion::Rmb, ""), HintInfo::keys([Key::Escape], "Cancel").prepend_slash()]),
823846
HintGroup(vec![

0 commit comments

Comments
 (0)