Skip to content

Commit 514b894

Browse files
authored
Finish porting the point nodes to vector pool storage and apply Path node edits in linear time (#4735)
* Port the point nodes off the working form to weave the pool directly * Move quadratic handles and free points correctly under a point delta * Name a handle by its HandleId in the modification verbs * Apply a modification in linear passes over the working form
1 parent 347e6ac commit 514b894

7 files changed

Lines changed: 444 additions & 186 deletions

File tree

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

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -863,20 +863,6 @@ impl ShapeState {
863863
self.selected_shape_state.get(&layer).map(|state| &state.selected_segments)
864864
}
865865

866-
pub fn move_primary(&self, segment: SegmentId, delta: DVec2, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>) {
867-
responses.add(GraphOperationMessage::Vector {
868-
layer,
869-
modification_type: VectorModificationType::ApplyPrimaryDelta { segment, delta },
870-
});
871-
}
872-
873-
pub fn move_end(&self, segment: SegmentId, delta: DVec2, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>) {
874-
responses.add(GraphOperationMessage::Vector {
875-
layer,
876-
modification_type: VectorModificationType::ApplyEndDelta { segment, delta },
877-
});
878-
}
879-
880866
pub fn move_anchor(&self, point: PointId, vector: &VectorGeometry, delta: DVec2, layer: LayerNodeIdentifier, selected: Option<&SelectedLayerState>, responses: &mut VecDeque<Message>) {
881867
// Move anchor
882868
responses.add(GraphOperationMessage::Vector {
@@ -894,7 +880,10 @@ impl ShapeState {
894880
}
895881

896882
let relative_position = handle - point_to_dvec2(path_segment.start()) + delta;
897-
let modification_type = VectorModificationType::SetPrimaryHandle { segment, relative_position };
883+
let modification_type = VectorModificationType::SetHandlePosition {
884+
handle: HandleId::primary(segment),
885+
relative_position,
886+
};
898887

899888
responses.add(GraphOperationMessage::Vector { layer, modification_type });
900889
}
@@ -919,24 +908,20 @@ impl ShapeState {
919908
let transform = network_interface.document_metadata().transform_to_document_if_feeds(layer, network_interface).inverse();
920909
let position = transform.transform_point2(new_position);
921910
let current_position = vector.position_of(*point)?;
922-
let delta = position - current_position;
923911

924912
match *point {
925-
ManipulatorPointId::Anchor(point) => self.move_anchor(point, &vector, delta, layer, None, responses),
926-
ManipulatorPointId::PrimaryHandle(segment) => {
927-
self.move_primary(segment, delta, layer, responses);
928-
if let Some(handle) = point.as_handle()
929-
&& let Some(handles) = vector.colinear_pair_containing(handle)
930-
{
931-
let modification_type = VectorModificationType::SetG1Continuous { handles, enabled: false };
932-
responses.add(GraphOperationMessage::Vector { layer, modification_type });
933-
}
934-
}
935-
ManipulatorPointId::EndHandle(segment) => {
936-
self.move_end(segment, delta, layer, responses);
937-
if let Some(handle) = point.as_handle()
938-
&& let Some(handles) = vector.colinear_pair_containing(handle)
939-
{
913+
ManipulatorPointId::Anchor(anchor) => self.move_anchor(anchor, &vector, position - current_position, layer, None, responses),
914+
ManipulatorPointId::PrimaryHandle(_) | ManipulatorPointId::EndHandle(_) => {
915+
let handle = point.as_handle()?;
916+
917+
// Set by its offset from the anchor, since a delta has no stored offset to add onto until the Path node edits this handle
918+
let relative_position = position - vector.anchor_position_of(*point)?;
919+
responses.add(GraphOperationMessage::Vector {
920+
layer,
921+
modification_type: handle.set_relative_position(relative_position),
922+
});
923+
924+
if let Some(handles) = vector.colinear_pair_containing(handle) {
940925
let modification_type = VectorModificationType::SetG1Continuous { handles, enabled: false };
941926
responses.add(GraphOperationMessage::Vector { layer, modification_type });
942927
}
@@ -1587,11 +1572,7 @@ impl ShapeState {
15871572
responses.add(GraphOperationMessage::Vector { layer, modification_type });
15881573

15891574
// Update segment
1590-
let HandleId { ty, segment } = handle;
1591-
let modification_type = match ty {
1592-
graphene_std::vector::misc::HandleType::Primary => VectorModificationType::SetStartPoint { segment, id },
1593-
graphene_std::vector::misc::HandleType::End => VectorModificationType::SetEndPoint { segment, id },
1594-
};
1575+
let modification_type = VectorModificationType::SetEndpoint { handle, id };
15951576

15961577
responses.add(GraphOperationMessage::Vector { layer, modification_type });
15971578
}

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4113,4 +4113,36 @@ mod test_path_tool {
41134113

41144114
assert_eq!(pasted.colinear_pairs().len(), 2, "the pasted copy of the smooth anchor should be smooth too");
41154115
}
4116+
4117+
// The ellipse's handles come from its generator, so the first typed position is the Path node's first edit to the handle
4118+
#[tokio::test]
4119+
async fn a_typed_handle_position_moves_the_handle_there() {
4120+
let mut editor = EditorTestUtils::create();
4121+
editor.new_document().await;
4122+
editor.draw_ellipse(100., 100., 300., 200.).await;
4123+
let layer = editor.get_selected_layer().await.expect("the drawn ellipse should be selected");
4124+
4125+
let handle_in_document = |editor: &EditorTestUtils, handle: ManipulatorPointId| {
4126+
let document = editor.active_document();
4127+
let vector = document.network_interface.compute_modified_vector(layer).expect("the ellipse should have a vector");
4128+
let to_document = document.metadata().transform_to_document_if_feeds(layer, &document.network_interface);
4129+
to_document.transform_point2(vector.position_of(handle).expect("the handle should exist"))
4130+
};
4131+
4132+
let segment = {
4133+
let document = editor.active_document();
4134+
let vector = document.network_interface.compute_modified_vector(layer).expect("the ellipse should have a vector");
4135+
vector.segment_ids()[0]
4136+
};
4137+
let handle = ManipulatorPointId::PrimaryHandle(segment);
4138+
let before = handle_in_document(&editor, handle);
4139+
4140+
editor.select_tool(ToolType::Path).await;
4141+
editor.editor.dispatcher.message_handlers.tool_message_handler.shape_editor.select_point_by_layer_and_id(handle, layer);
4142+
editor.handle_message(PathToolMessage::SelectedPointUpdated).await;
4143+
editor.handle_message(PathToolMessage::SelectedPointXChanged { new_x: before.x + 5. }).await;
4144+
4145+
let after = handle_in_document(&editor, handle);
4146+
assert!(after.distance(before + DVec2::new(5., 0.)) < 1e-6, "the handle moved from {before} to {after}");
4147+
}
41164148
}

‎editor/src/messages/tool/tool_messages/pen_tool.rs‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -596,12 +596,18 @@ impl PenToolData {
596596
}
597597
TargetHandle::PriorInHandle(segment) => {
598598
let relative_position = delta - anchor_pos;
599-
let modification_type = VectorModificationType::SetEndHandle { segment, relative_position };
599+
let modification_type = VectorModificationType::SetHandlePosition {
600+
handle: HandleId::end(segment),
601+
relative_position,
602+
};
600603
responses.add(GraphOperationMessage::Vector { layer, modification_type });
601604
}
602605
TargetHandle::PriorOutHandle(segment) => {
603606
let relative_position = delta - anchor_pos;
604-
let modification_type = VectorModificationType::SetPrimaryHandle { segment, relative_position };
607+
let modification_type = VectorModificationType::SetHandlePosition {
608+
handle: HandleId::primary(segment),
609+
relative_position,
610+
};
605611
responses.add(GraphOperationMessage::Vector { layer, modification_type });
606612
}
607613
TargetHandle::None => {}

‎node-graph/libraries/vector-types/src/vector/flatten.rs‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,6 @@ impl WorkingVector {
124124

125125
vector.set_smooth_at_indices(paths, smooth_anchors, true);
126126
}
127-
128-
pub fn resolve_id(&self, id: PointId) -> Option<usize> {
129-
self.point_ids.iter().position(|&check_id| check_id == id)
130-
}
131127
}
132128

133129
// TODO: Eventually remove this document upgrade code

0 commit comments

Comments
 (0)