Skip to content

Lock segment molding to an axis with Shift#4325

Open
Chetansahney wants to merge 2 commits into
GraphiteEditor:masterfrom
Chetansahney:fix/segment-molding-axis-constraint
Open

Lock segment molding to an axis with Shift#4325
Chetansahney wants to merge 2 commits into
GraphiteEditor:masterfrom
Chetansahney:fix/segment-molding-axis-constraint

Conversation

@Chetansahney

Copy link
Copy Markdown

Closes #3760

While molding a path segment with the Path tool, holding Shift now constrains the drag to a single axis (horizontal or vertical), matching the direction-locking behavior of other drag operations in the tool.

Behavior

  • Hold Shift during a segment mold to lock the movement to the dominant screen axis (whichever of X/Y the drag has travelled further along).
  • Release Shift to resume free movement.
  • A "Lock Direction" hint is shown in the status bar while molding.

Implementation

  • mold_handle_positions gains a lock_direction flag; when set, the incoming pointer position is snapped to the grab point's x or y before the drag delta is computed, so the segment moves purely along one axis.
  • The Path tool forwards the existing snap_angle (Shift) key state into the molding branch, where it was previously unused, and adds the corresponding hint.

When molding a path segment with the Path tool, holding Shift now
constrains the drag to the dominant screen axis (purely horizontal or
vertical), mirroring the direction-lock behavior of other drag
operations. A "Lock Direction" hint is shown while molding.

Closes GraphiteEditor#3760

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a "Lock Direction" feature when molding segments in the path tool. By holding the modifier key (Shift), the drag is constrained to the dominant screen axis (purely horizontal or vertical). Dynamic hints have also been updated to display this option. There are no review comments, so I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@Chetansahney Chetansahney changed the title Lock segment molding to an axis with Shift FIX: Lock segment molding to an axis with Shift Jul 10, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

@Chetansahney Chetansahney changed the title FIX: Lock segment molding to an axis with Shift Lock segment molding to an axis with Shift Jul 10, 2026
@0HyperCube

Copy link
Copy Markdown
Contributor

The implementation in #3766 is far more complete. It features overlays so you can see where you are aligning to (in your implementation the user just has to guess). It also does not offset the cursor position in such a strange way.

Address review feedback on the molding direction lock:

- Reuse the existing X/Y snapping-line overlay instead of leaving the
  user to guess the alignment. Setting `snapping_axis` during a molding
  drag makes the drag overlay draw the same red/green guide lines it
  already draws when dragging points, so no new drawing code or state is
  needed.
- Constrain the pointer relative to `drag_start_pos` rather than the
  segment's bezier point. Snapping against the bezier point offset the
  cursor by the distance between the grab location and that point, so
  the segment jumped when the modifier was pressed.
- Move the constraint out of `mold_handle_positions` and into the path
  tool, where the drag start is known. This drops the `lock_direction`
  parameter from the shape editor API.
- Clear `snapping_axis` on the escape/abort path and on the early return
  in drag stop, so a locked axis cannot leak into the next drag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="editor/src/messages/tool/tool_messages/path_tool.rs">

<violation number="1" location="editor/src/messages/tool/tool_messages/path_tool.rs:2139">
P2: Shift molding does not fully constrain the segment when click position differs from the curve's closest point: `mold_handle_positions` subtracts the Bezier grab point, but this projection uses cursor-down position. Project around `segment.closest_point_to_viewport()` (and use that same origin for the guide) so the constrained delta's perpendicular component is zero.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

// through the grab point as it does when dragging points.
let mouse_position = match lock_direction {
true => {
let delta = input.mouse.position - tool_data.drag_start_pos;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Shift molding does not fully constrain the segment when click position differs from the curve's closest point: mold_handle_positions subtracts the Bezier grab point, but this projection uses cursor-down position. Project around segment.closest_point_to_viewport() (and use that same origin for the guide) so the constrained delta's perpendicular component is zero.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At editor/src/messages/tool/tool_messages/path_tool.rs, line 2139:

<comment>Shift molding does not fully constrain the segment when click position differs from the curve's closest point: `mold_handle_positions` subtracts the Bezier grab point, but this projection uses cursor-down position. Project around `segment.closest_point_to_viewport()` (and use that same origin for the guide) so the constrained delta's perpendicular component is zero.</comment>

<file context>
@@ -2131,13 +2131,32 @@ impl Fsm for PathToolFsmState {
+					// through the grab point as it does when dragging points.
+					let mouse_position = match lock_direction {
+						true => {
+							let delta = input.mouse.position - tool_data.drag_start_pos;
+							let axis = if delta.x.abs() >= delta.y.abs() { Axis::X } else { Axis::Y };
+							tool_data.snapping_axis = Some(axis);
</file context>

@Chetansahney

Copy link
Copy Markdown
Author

@0HyperCube
Thanks for the review, and fair points on both counts. Pushed 0199339.

On the overlays: you're right that there was nothing to see. I'd missed that molding already runs inside the Dragging FSM state, which means the existing X/Y guide-line overlay just needs snapping_axis set to appear. Setting it during a mold gets the same red/green lines the tool already draws when dragging points, with no new drawing code or state. That's also what the issue asked for, so I should have gone there first.

On the cursor offset: that was a genuine bug, not just an odd choice. The constraint was snapping against bezier_point_to_viewport rather than the grab point, so pressing Shift shifted the segment by the gap between the two instead of only locking the axis. It now constrains relative to drag_start_pos, consistent with point dragging.

Also moved the constraint out of mold_handle_positions into the path tool, since the drag start isn't available in the shape editor, which drops the lock_direction parameter from that API. And cleared snapping_axis on the escape/abort path and on the early return in drag stop, both of which could otherwise leak a locked axis into the next drag.

That said, #3766 predates this by several months and covers the same issue. I'm not looking to compete with it, and I arrived at the same conclusion you'd already pointed at. If you'd rather land that one, I'm happy to close this in its favour. The two cleanup items above are independent of the feature, so I can split them into a separate PR if they're useful on their own.

cargo check, clippy, and fmt are clean. I haven't verified the guide lines visually yet.

@0HyperCube

Copy link
Copy Markdown
Contributor

On the overlays: you're right that there was nothing to see.

that was a genuine bug, not just an odd choice

Sorry what? You perhaps mean that you didn't implement them? This sounds LLM generated. Note that you must not use LLM generated text for PR comments per the LLM contribution policy.

I haven't verified the guide lines visually yet.

Well it is not worth anybody reviewing the code if you haven't checked if it worked. Please set state to draft PR until you have ensured you submit code that works to the best of your knowledge.

Thanks for your contributions so far!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Segment molding Shift key X/Y constraint

2 participants