Fix the Pen tool preview segment disappearing during repeated undo (#3791)

* fix preview line to be visible on multiple undo

* fixed regression issue for last anchor

* Remove unneeded preview-state resync from the Pen tool undo handler

* Prevent a transient vector gap from ending the Pen tool drawing session

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Vatsal Kumar
2026-06-08 11:46:10 -07:00
committed by GitHub
co-authored by Keavon Chambers
parent 2835c3b536
commit cc7d700bfd
@@ -1133,7 +1133,11 @@ impl PenToolData {
let selected_nodes = document.network_interface.selected_nodes(); let selected_nodes = document.network_interface.selected_nodes();
let mut selected_layers = selected_nodes.selected_layers(document.metadata()); let mut selected_layers = selected_nodes.selected_layers(document.metadata());
let layer = selected_layers.next().filter(|_| selected_layers.next().is_none()).or(self.current_layer)?; let layer = selected_layers.next().filter(|_| selected_layers.next().is_none()).or(self.current_layer)?;
let vector = document.network_interface.compute_modified_vector(layer)?;
// The modified vector can be momentarily unavailable while the node graph re-evaluates after a document undo.
// Snapping onto an existing point is only a convenience, so skip it when the vector is missing rather than
// returning `None`, which would let a caller like PointerMove's `unwrap_or(Ready)` end the session.
if let Some(vector) = document.network_interface.compute_modified_vector(layer) {
let transform = document.metadata().document_to_viewport * transform; let transform = document.metadata().document_to_viewport * transform;
for point in vector.anchor_points() { for point in vector.anchor_points() {
let Some(pos) = vector.point_domain.position_from_id(point) else { continue }; let Some(pos) = vector.point_domain.position_from_id(point) else { continue };
@@ -1143,6 +1147,8 @@ impl PenToolData {
self.next_point = pos; self.next_point = pos;
} }
} }
}
if let Some(handle_end) = self.handle_end.as_mut() { if let Some(handle_end) = self.handle_end.as_mut() {
*handle_end = self.next_point; *handle_end = self.next_point;
self.next_handle_start = self.next_point; self.next_handle_start = self.next_point;
@@ -1979,9 +1985,9 @@ impl Fsm for PenToolFsmState {
tool_data.angle_locked = false; tool_data.angle_locked = false;
} }
let state = tool_data // A pointer move must never end the path: keep dragging if the handle can't be resolved this frame
.drag_handle(snap_data, transform, input.mouse.position, responses, layer, input, viewport) // (the vector is briefly unavailable while the graph re-evaluates after an undo)
.unwrap_or(PenToolFsmState::Ready); let state = tool_data.drag_handle(snap_data, transform, input.mouse.position, responses, layer, input, viewport).unwrap_or(self);
if tool_data.handle_swapped { if tool_data.handle_swapped {
responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::None }); responses.add(FrontendMessage::UpdateMouseCursor { cursor: MouseCursorIcon::None });
@@ -2029,9 +2035,10 @@ impl Fsm for PenToolFsmState {
colinear: input.keyboard.key(colinear), colinear: input.keyboard.key(colinear),
move_anchor_with_handles: input.keyboard.key(move_anchor_with_handles), move_anchor_with_handles: input.keyboard.key(move_anchor_with_handles),
}; };
// A pointer move must never end the path: keep placing if the anchor can't be resolved this frame
let state = tool_data let state = tool_data
.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, responses) .place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, responses)
.unwrap_or(PenToolFsmState::Ready); .unwrap_or(self);
// Auto-panning // Auto-panning
let messages = [ let messages = [