Skip to content

Commit 2b7e6e6

Browse files
committed
fix: use position-based lookup when joining paths from different layers
1 parent d604ef6 commit 2b7e6e6

File tree

2 files changed

+47
-34
lines changed

2 files changed

+47
-34
lines changed

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

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -462,26 +462,28 @@ impl ShapeState {
462462
} else {
463463
// Different layers: merge first, then create segment
464464

465-
// Get the indices of the selected points in their respective vectors
466-
let start_index = document.network_interface.compute_modified_vector(layer1)
467-
.and_then(|v| v.point_domain.resolve_id(start_point));
468-
let end_index = document.network_interface.compute_modified_vector(layer2)
469-
.and_then(|v| v.point_domain.resolve_id(end_point));
470-
471-
// Get the number of points in layer1 (this will be the offset for layer2 points after merge)
472-
let layer1_point_count = document.network_interface.compute_modified_vector(layer1)
473-
.map(|v| v.point_domain.ids().len());
474-
475-
if let (Some(start_idx), Some(end_idx), Some(point_offset)) = (start_index, end_index, layer1_point_count) {
476-
// Merge the layers
465+
// Get the local positions of the selected points
466+
let start_local_pos = document.network_interface.compute_modified_vector(layer1)
467+
.and_then(|v| v.point_domain.position_from_id(start_point));
468+
let end_local_pos = document.network_interface.compute_modified_vector(layer2)
469+
.and_then(|v| v.point_domain.position_from_id(end_point));
470+
471+
// Transform to document/world space
472+
let start_transform = document.metadata().transform_to_document(layer1);
473+
let end_transform = document.metadata().transform_to_document(layer2);
474+
475+
if let (Some(start_local), Some(end_local)) = (start_local_pos, end_local_pos) {
476+
let start_pos = start_transform.transform_point2(start_local);
477+
let end_pos = end_transform.transform_point2(end_local);
478+
477479
merge_layers(document, layer1, layer2, responses);
478480

479-
// After the graph runs and the merge is complete, restore selection and close path
481+
// Connect the points
480482
responses.add(DeferMessage::AfterGraphRun {
481-
messages: vec![ToolMessage::Path(PathToolMessage::RestoreSelectionAndClosePath {
483+
messages: vec![ToolMessage::Path(PathToolMessage::ConnectPointsByPosition {
482484
layer: layer1,
483-
start_index: start_idx,
484-
end_index: end_idx + point_offset,
485+
start_position: start_pos,
486+
end_position: end_pos,
485487
}).into()],
486488
});
487489
}

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

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ pub enum PathToolMessage {
7373
},
7474
Escape,
7575
ClosePath,
76-
RestoreSelectionAndClosePath {
76+
ConnectPointsByPosition {
7777
layer: LayerNodeIdentifier,
78-
start_index: usize,
79-
end_index: usize,
78+
start_position: DVec2,
79+
end_position: DVec2,
8080
},
8181
DoubleClick {
8282
extend_selection: Key,
@@ -2674,32 +2674,43 @@ impl Fsm for PathToolFsmState {
26742674

26752675
self
26762676
}
2677-
(_, PathToolMessage::RestoreSelectionAndClosePath { layer, start_index, end_index }) => {
2677+
(_, PathToolMessage::ConnectPointsByPosition { layer, start_position, end_position }) => {
26782678
// Get the merged vector
26792679
let Some(vector) = document.network_interface.compute_modified_vector(layer) else {
26802680
return self;
26812681
};
26822682

2683-
// Get the point IDs at the calculated indices
2683+
// Find points by their positions (with small tolerance for floating point comparison)
2684+
const POSITION_TOLERANCE: f64 = 0.01;
2685+
2686+
let positions = vector.point_domain.positions();
26842687
let point_ids = vector.point_domain.ids();
26852688

2686-
if start_index >= point_ids.len() || end_index >= point_ids.len() {
2687-
return self;
2688-
}
2689+
let mut start_point_id = None;
2690+
let mut end_point_id = None;
26892691

2690-
let start_point_id = point_ids[start_index];
2691-
let end_point_id = point_ids[end_index];
2692+
for (i, &pos) in positions.iter().enumerate() {
2693+
if start_point_id.is_none() && (pos - start_position).length() < POSITION_TOLERANCE {
2694+
start_point_id = Some(point_ids[i]);
2695+
}
2696+
if end_point_id.is_none() && (pos - end_position).length() < POSITION_TOLERANCE {
2697+
end_point_id = Some(point_ids[i]);
2698+
}
2699+
if start_point_id.is_some() && end_point_id.is_some() {
2700+
break;
2701+
}
2702+
}
26922703

2693-
// Clear existing selection and select the merged layer
2694-
shape_editor.deselect_all_points();
2695-
shape_editor.set_selected_layers(vec![layer]);
2704+
if let (Some(start_id), Some(end_id)) = (start_point_id, end_point_id) {
2705+
// Clear existing selection
2706+
shape_editor.deselect_all_points();
2707+
shape_editor.set_selected_layers(vec![layer]);
26962708

2697-
// Select the two points
2698-
shape_editor.select_point_by_layer_and_id(ManipulatorPointId::Anchor(start_point_id), layer);
2699-
shape_editor.select_point_by_layer_and_id(ManipulatorPointId::Anchor(end_point_id), layer);
2709+
shape_editor.select_point_by_layer_and_id(ManipulatorPointId::Anchor(start_id), layer);
2710+
shape_editor.select_point_by_layer_and_id(ManipulatorPointId::Anchor(end_id), layer);
27002711

2701-
// Now call ClosePath which will see the selection and create the segment
2702-
responses.add(PathToolMessage::ClosePath);
2712+
responses.add(PathToolMessage::ClosePath);
2713+
}
27032714

27042715
self
27052716
}

0 commit comments

Comments
 (0)