Rename graphic subtypes to remove their "data" and "group" suffixes (#2990)

* Rename VectorData to Vector

* Rename other VectorData* types to Vector*

* Move assorted data types out of vector_data.rs into misc.rs

* Rename vector_data.rs to vector_types.rs and remove the vector_types module folder

* Rename other references to "vector data"

* Remove label widgets for raster/vector/group to use "-" instead

* Rename RasterData to Raster

* Rename GraphicGroup to Group

* Fix migrations and rename graphic_element.rs -> graphic.rs

* Rename TaggedValue::ArtboardGroup -> TaggedValue::Artboard
This commit is contained in:
Keavon Chambers
2025-08-04 04:53:25 -07:00
committed by GitHub
parent 853c26cbc1
commit c98477d8ed
72 changed files with 1820 additions and 1901 deletions
@@ -11,6 +11,7 @@ use crate::messages::tool::common_functionality::snapping::SnapData;
use crate::messages::tool::common_functionality::snapping::SnapManager;
use crate::messages::tool::common_functionality::transformation_cage::*;
use graph_craft::document::NodeId;
use graphene_std::Artboard;
use graphene_std::renderer::Quad;
use graphene_std::table::Table;
@@ -337,8 +338,8 @@ impl Fsm for ArtboardToolFsmState {
responses.add(GraphOperationMessage::NewArtboard {
id,
artboard: graphene_std::Artboard {
graphic_group: Table::new(),
artboard: Artboard {
group: Table::new(),
label: String::from("Artboard"),
location: start.min(end).round().as_ivec2(),
dimensions: (start.round() - end.round()).abs().as_ivec2(),
@@ -360,9 +360,9 @@ mod test_freehand {
use crate::messages::tool::tool_messages::freehand_tool::FreehandOptionsUpdate;
use crate::test_utils::test_prelude::*;
use glam::{DAffine2, DVec2};
use graphene_std::vector::VectorData;
use graphene_std::vector::Vector;
async fn get_vector_data(editor: &mut EditorTestUtils) -> Vec<(VectorData, DAffine2)> {
async fn get_vector_and_transform_list(editor: &mut EditorTestUtils) -> Vec<(Vector, DAffine2)> {
let document = editor.active_document();
let layers = document.metadata().all_layers();
@@ -372,23 +372,22 @@ mod test_freehand {
// Only get layers with path nodes
let _ = graph_layer.upstream_visible_node_id_from_name_in_layer("Path")?;
let vector_data = document.network_interface.compute_modified_vector(layer)?;
let vector = document.network_interface.compute_modified_vector(layer)?;
let transform = document.metadata().transform_to_viewport(layer);
Some((vector_data, transform))
Some((vector, transform))
})
.collect()
}
fn verify_path_points(vector_data_list: &[(VectorData, DAffine2)], expected_captured_points: &[DVec2], tolerance: f64) -> Result<(), String> {
assert_eq!(vector_data_list.len(), 1, "there should be one vector data");
fn verify_path_points(vector_and_transform_list: &[(Vector, DAffine2)], expected_captured_points: &[DVec2], tolerance: f64) -> Result<(), String> {
assert_eq!(vector_and_transform_list.len(), 1, "There should be one row of Vector geometry");
let path_data = vector_data_list.iter().find(|(data, _)| data.point_domain.ids().len() > 0).ok_or("Could not find path data")?;
let (vector, transform) = vector_and_transform_list.iter().find(|(data, _)| data.point_domain.ids().len() > 0).ok_or("Could not find path data")?;
let (vector_data, transform) = path_data;
let point_count = vector_data.point_domain.ids().len();
let segment_count = vector_data.segment_domain.ids().len();
let point_count = vector.point_domain.ids().len();
let segment_count = vector.segment_domain.ids().len();
let actual_positions: Vec<DVec2> = vector_data.point_domain.positions().iter().map(|&position| transform.transform_point2(position)).collect();
let actual_positions: Vec<DVec2> = vector.point_domain.positions().iter().map(|&position| transform.transform_point2(position)).collect();
if segment_count != point_count - 1 {
return Err(format!("Expected segments to be one less than points, got {} segments for {} points", segment_count, point_count));
@@ -435,8 +434,8 @@ mod test_freehand {
let expected_captured_points = &mouse_points[1..];
editor.drag_path(&mouse_points, ModifierKeys::empty()).await;
let vector_data_list = get_vector_data(&mut editor).await;
verify_path_points(&vector_data_list, expected_captured_points, 1.).expect("Path points verification failed");
let vector_and_transform_list = get_vector_and_transform_list(&mut editor).await;
verify_path_points(&vector_and_transform_list, expected_captured_points, 1.).expect("Path points verification failed");
}
#[tokio::test]
@@ -468,12 +467,12 @@ mod test_freehand {
)
.await;
let initial_vector_data = get_vector_data(&mut editor).await;
assert!(!initial_vector_data.is_empty(), "No vector data found after initial drawing");
let initial_vector_and_transform_list = get_vector_and_transform_list(&mut editor).await;
assert!(!initial_vector_and_transform_list.is_empty(), "No Vector geometry found after initial drawing");
let (initial_data, transform) = &initial_vector_data[0];
let initial_point_count = initial_data.point_domain.ids().len();
let initial_segment_count = initial_data.segment_domain.ids().len();
let (initial_vector, initial_transform) = &initial_vector_and_transform_list[0];
let initial_point_count = initial_vector.point_domain.ids().len();
let initial_segment_count = initial_vector.segment_domain.ids().len();
assert!(initial_point_count >= 2, "Expected at least 2 points in initial path, found {}", initial_point_count);
assert_eq!(
@@ -484,15 +483,15 @@ mod test_freehand {
initial_segment_count
);
let extendable_points = initial_data.extendable_points(false).collect::<Vec<_>>();
let extendable_points = initial_vector.extendable_points(false).collect::<Vec<_>>();
assert!(!extendable_points.is_empty(), "No extendable points found in the path");
let endpoint_id = extendable_points[0];
let endpoint_pos_option = initial_data.point_domain.position_from_id(endpoint_id);
let endpoint_pos_option = initial_vector.point_domain.position_from_id(endpoint_id);
assert!(endpoint_pos_option.is_some(), "Could not find position for endpoint");
let endpoint_pos = endpoint_pos_option.unwrap();
let endpoint_viewport_pos = transform.transform_point2(endpoint_pos);
let endpoint_viewport_pos = initial_transform.transform_point2(endpoint_pos);
assert!(endpoint_viewport_pos.is_finite(), "Endpoint position is not finite");
@@ -527,12 +526,12 @@ mod test_freehand {
)
.await;
let extended_vector_data = get_vector_data(&mut editor).await;
assert!(!extended_vector_data.is_empty(), "No vector data found after extension");
let extended_vector_and_transform = get_vector_and_transform_list(&mut editor).await;
assert!(!extended_vector_and_transform.is_empty(), "No Vector geometry found after extension");
let (extended_data, _) = &extended_vector_data[0];
let extended_point_count = extended_data.point_domain.ids().len();
let extended_segment_count = extended_data.segment_domain.ids().len();
let (extended_vector, _) = &extended_vector_and_transform[0];
let extended_point_count = extended_vector.point_domain.ids().len();
let extended_segment_count = extended_vector.segment_domain.ids().len();
assert!(
extended_point_count > initial_point_count,
@@ -585,12 +584,12 @@ mod test_freehand {
)
.await;
let initial_vector_data = get_vector_data(&mut editor).await;
assert!(!initial_vector_data.is_empty(), "No vector data found after initial drawing");
let initial_vector_and_transform = get_vector_and_transform_list(&mut editor).await;
assert!(!initial_vector_and_transform.is_empty(), "No vector geometry found after initial drawing");
let (initial_data, _) = &initial_vector_data[0];
let initial_point_count = initial_data.point_domain.ids().len();
let initial_segment_count = initial_data.segment_domain.ids().len();
let (initial_vector, _) = &initial_vector_and_transform[0];
let initial_point_count = initial_vector.point_domain.ids().len();
let initial_segment_count = initial_vector.segment_domain.ids().len();
let existing_layer_id = {
let document = editor.active_document();
@@ -636,8 +635,8 @@ mod test_freehand {
)
.await;
let final_vector_data = get_vector_data(&mut editor).await;
assert!(!final_vector_data.is_empty(), "No vector data found after second drawing");
let final_vector_and_transform = get_vector_and_transform_list(&mut editor).await;
assert!(!final_vector_and_transform.is_empty(), "No vector geometry found after second drawing");
// Verify we still have only one layer
let layer_count = {
@@ -646,9 +645,9 @@ mod test_freehand {
};
assert_eq!(layer_count, 1, "Expected only one layer after drawing with Shift key");
let (final_data, _) = &final_vector_data[0];
let final_point_count = final_data.point_domain.ids().len();
let final_segment_count = final_data.segment_domain.ids().len();
let (final_vector, _) = &final_vector_and_transform[0];
let final_point_count = final_vector.point_domain.ids().len();
let final_segment_count = final_vector.segment_domain.ids().len();
assert!(
final_point_count > initial_point_count,
@@ -27,8 +27,8 @@ use graphene_std::renderer::Quad;
use graphene_std::transform::ReferencePoint;
use graphene_std::uuid::NodeId;
use graphene_std::vector::click_target::ClickTargetType;
use graphene_std::vector::{HandleExt, HandleId, NoHashBuilder, SegmentId, VectorData};
use graphene_std::vector::{ManipulatorPointId, PointId, VectorModificationType};
use graphene_std::vector::misc::{HandleId, ManipulatorPointId};
use graphene_std::vector::{HandleExt, NoHashBuilder, PointId, SegmentId, Vector, VectorModificationType};
use std::vec;
#[derive(Default, ExtractField)]
@@ -285,7 +285,7 @@ impl LayoutHolder for PathTool {
.selected_index(Some(self.options.path_overlay_mode as u32))
.widget_holder();
// Works only if a single layer is selected and its type is vectordata
// Works only if a single layer is selected and its type is Vector
let path_node_button = TextButton::new("Make Path Editable")
.icon(Some("NodeShape".into()))
.tooltip("Make Path Editable")
@@ -619,10 +619,10 @@ impl PathToolData {
self.can_toggle_colinearity = match &selection_status {
SelectionStatus::None => false,
SelectionStatus::One(single_selected_point) => {
let vector_data = document.network_interface.compute_modified_vector(single_selected_point.layer).unwrap();
if single_selected_point.id.get_handle_pair(&vector_data).is_some() {
let anchor = single_selected_point.id.get_anchor(&vector_data).expect("Cannot find connected anchor");
vector_data.all_connected(anchor).count() <= 2
let vector = document.network_interface.compute_modified_vector(single_selected_point.layer).unwrap();
if single_selected_point.id.get_handle_pair(&vector).is_some() {
let anchor = single_selected_point.id.get_anchor(&vector).expect("Cannot find connected anchor");
vector.all_connected(anchor).count() <= 2
} else {
false
}
@@ -761,13 +761,13 @@ impl PathToolData {
if handle_drag_from_anchor {
if let Some((layer, point)) = shape_editor.find_nearest_point_indices(&document.network_interface, input.mouse.position, SELECTION_THRESHOLD) {
// Check that selected point is an anchor
if let (Some(point_id), Some(vector_data)) = (point.as_anchor(), document.network_interface.compute_modified_vector(layer)) {
let handles = vector_data.all_connected(point_id).collect::<Vec<_>>();
if let (Some(point_id), Some(vector)) = (point.as_anchor(), document.network_interface.compute_modified_vector(layer)) {
let handles = vector.all_connected(point_id).collect::<Vec<_>>();
self.alt_clicked_on_anchor = true;
for handle in &handles {
let modification_type = handle.set_relative_position(DVec2::ZERO);
responses.add(GraphOperationMessage::Vector { layer, modification_type });
for &handles in &vector_data.colinear_manipulators {
for &handles in &vector.colinear_manipulators {
if handles.contains(handle) {
let modification_type = VectorModificationType::SetG1Continuous { handles, enabled: false };
responses.add(GraphOperationMessage::Vector { layer, modification_type });
@@ -783,16 +783,16 @@ impl PathToolData {
}
}
if let Some((Some(point), Some(vector_data))) = shape_editor
if let Some((Some(point), Some(vector))) = shape_editor
.find_nearest_point_indices(&document.network_interface, input.mouse.position, SELECTION_THRESHOLD)
.map(|(layer, point)| (point.as_anchor(), document.network_interface.compute_modified_vector(layer)))
{
let handles = vector_data
let handles = vector
.all_connected(point)
.filter(|handle| handle.length(&vector_data) < 1e-6)
.filter(|handle| handle.length(&vector) < 1e-6)
.map(|handle| handle.to_manipulator_point())
.collect::<Vec<_>>();
let endpoint = vector_data.extendable_points(false).any(|anchor| point == anchor);
let endpoint = vector.extendable_points(false).any(|anchor| point == anchor);
if drag_zero_handle && (handles.len() == 1 && !endpoint) {
shape_editor.deselect_all_points();
@@ -883,27 +883,25 @@ impl PathToolData {
let mut manipulators = HashMap::with_hasher(NoHashBuilder);
let mut unselected = Vec::new();
for (&layer, state) in &shape_editor.selected_shape_state {
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
continue;
};
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { continue };
let transform = document.metadata().transform_to_document_if_feeds(layer, &document.network_interface);
let mut layer_manipulators = HashSet::with_hasher(NoHashBuilder);
for point in state.selected_points() {
let Some(anchor) = point.get_anchor(&vector_data) else { continue };
let Some(anchor) = point.get_anchor(&vector) else { continue };
layer_manipulators.insert(anchor);
let Some([handle1, handle2]) = point.get_handle_pair(&vector_data) else { continue };
let Some([handle1, handle2]) = point.get_handle_pair(&vector) else { continue };
let Some(handle) = point.as_handle() else { continue };
// Check which handle is selected and which is opposite
let opposite = if handle == handle1 { handle2 } else { handle1 };
self.opposite_handle_position = if self.opposite_handle_position.is_none() {
opposite.to_manipulator_point().get_position(&vector_data)
opposite.to_manipulator_point().get_position(&vector)
} else {
self.opposite_handle_position
};
}
for (&id, &position) in vector_data.point_domain.ids().iter().zip(vector_data.point_domain.positions()) {
for (&id, &position) in vector.point_domain.ids().iter().zip(vector.point_domain.positions()) {
if layer_manipulators.contains(&id) {
continue;
}
@@ -956,17 +954,17 @@ impl PathToolData {
return false;
};
let Some(vector_data) = document.network_interface.compute_modified_vector(*layer) else {
let Some(vector) = document.network_interface.compute_modified_vector(*layer) else {
self.opposing_handle_lengths = Some(shape_editor.opposing_handle_lengths(document));
return false;
};
// Check if handle has a pair (to ignore handles of edges of open paths)
if let Some(handle_pair) = selected_handle_id.get_handle_pair(&vector_data) {
if let Some(handle_pair) = selected_handle_id.get_handle_pair(&vector) {
let opposite_handle_length = handle_pair.iter().filter(|&&h| h.to_manipulator_point() != selected_handle_id).find_map(|&h| {
let opp_handle_pos = h.to_manipulator_point().get_position(&vector_data)?;
let opp_anchor_id = h.to_manipulator_point().get_anchor(&vector_data)?;
let opp_anchor_pos = vector_data.point_domain.position_from_id(opp_anchor_id)?;
let opp_handle_pos = h.to_manipulator_point().get_position(&vector)?;
let opp_anchor_id = h.to_manipulator_point().get_anchor(&vector)?;
let opp_anchor_pos = vector.point_domain.position_from_id(opp_anchor_id)?;
Some((opp_handle_pos - opp_anchor_pos).length())
});
@@ -997,11 +995,11 @@ impl PathToolData {
let handle_id = selected_handle.to_manipulator_point();
let layer_to_document = document.metadata().transform_to_document_if_feeds(*layer, &document.network_interface);
let vector_data = document.network_interface.compute_modified_vector(*layer)?;
let vector = document.network_interface.compute_modified_vector(*layer)?;
let handle_position_local = selected_handle.to_manipulator_point().get_position(&vector_data)?;
let anchor_id = selected_handle.to_manipulator_point().get_anchor(&vector_data)?;
let anchor_position_local = vector_data.point_domain.position_from_id(anchor_id)?;
let handle_position_local = selected_handle.to_manipulator_point().get_position(&vector)?;
let anchor_id = selected_handle.to_manipulator_point().get_anchor(&vector)?;
let anchor_position_local = vector.point_domain.position_from_id(anchor_id)?;
let handle_position_document = layer_to_document.transform_point2(handle_position_local);
let anchor_position_document = layer_to_document.transform_point2(anchor_position_local);
@@ -1024,24 +1022,24 @@ impl PathToolData {
) -> f64 {
let current_angle = -handle_vector.angle_to(DVec2::X);
if let Some((vector_data, layer)) = shape_editor
if let Some((vector, layer)) = shape_editor
.selected_shape_state
.iter()
.next()
.and_then(|(layer, _)| document.network_interface.compute_modified_vector(*layer).map(|vector_data| (vector_data, layer)))
.and_then(|(layer, _)| document.network_interface.compute_modified_vector(*layer).map(|vector| (vector, layer)))
{
let adjacent_anchor = check_handle_over_adjacent_anchor(handle_id, &vector_data);
let adjacent_anchor = check_handle_over_adjacent_anchor(handle_id, &vector);
let mut required_angle = None;
// If the handle is dragged over one of its adjacent anchors while holding down the Ctrl key, compute the angle based on the tangent formed with the neighboring anchor points.
if adjacent_anchor.is_some() && lock_angle && !self.angle_locked {
let anchor = handle_id.get_anchor(&vector_data);
let (angle, anchor_position) = calculate_adjacent_anchor_tangent(handle_id, anchor, adjacent_anchor, &vector_data);
let anchor = handle_id.get_anchor(&vector);
let (angle, anchor_position) = calculate_adjacent_anchor_tangent(handle_id, anchor, adjacent_anchor, &vector);
let layer_to_document = document.metadata().transform_to_document_if_feeds(*layer, &document.network_interface);
self.adjacent_anchor_offset = handle_id
.get_anchor_position(&vector_data)
.get_anchor_position(&vector)
.and_then(|handle_anchor| anchor_position.map(|adjacent_anchor| layer_to_document.transform_point2(adjacent_anchor) - layer_to_document.transform_point2(handle_anchor)));
required_angle = angle;
@@ -1049,7 +1047,7 @@ impl PathToolData {
// If the handle is dragged near its adjacent anchors while holding down the Ctrl key, compute the angle using the tangent direction of neighboring segments.
if relative_vector.length() < 25. && lock_angle && !self.angle_locked {
required_angle = calculate_lock_angle(self, shape_editor, responses, document, &vector_data, handle_id, tangent_to_neighboring_tangents);
required_angle = calculate_lock_angle(self, shape_editor, responses, document, &vector, handle_id, tangent_to_neighboring_tangents);
}
// Finalize and apply angle locking if a valid target angle was determined.
@@ -1158,17 +1156,17 @@ impl PathToolData {
self.snapping_axis = None;
}
fn get_normalized_tangent(&mut self, point: PointId, segment: SegmentId, vector_data: &VectorData) -> Option<DVec2> {
let other_point = vector_data.other_point(segment, point)?;
let position = ManipulatorPointId::Anchor(point).get_position(vector_data)?;
fn get_normalized_tangent(&mut self, point: PointId, segment: SegmentId, vector: &Vector) -> Option<DVec2> {
let other_point = vector.other_point(segment, point)?;
let position = ManipulatorPointId::Anchor(point).get_position(vector)?;
let mut handles = vector_data.all_connected(other_point);
let mut handles = vector.all_connected(other_point);
let other_handle = handles.find(|handle| handle.segment == segment)?;
let target_position = if other_handle.length(vector_data) == 0. {
ManipulatorPointId::Anchor(other_point).get_position(vector_data)?
let target_position = if other_handle.length(vector) == 0. {
ManipulatorPointId::Anchor(other_point).get_position(vector)?
} else {
other_handle.to_manipulator_point().get_position(vector_data)?
other_handle.to_manipulator_point().get_position(vector)?
};
let tangent_vector = target_position - position;
@@ -1207,19 +1205,17 @@ impl PathToolData {
let Some(layer) = document.network_interface.selected_nodes().selected_layers(document.metadata()).next() else {
return false;
};
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
return false;
};
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { return false };
// Check that the handles of anchor point are also colinear
if !vector_data.colinear(*anchor) {
if !vector.colinear(*anchor) {
return false;
};
let Some(point_id) = anchor.as_anchor() else { return false };
let mut connected_segments = [None, None];
for (segment, bezier, start, end) in vector_data.segment_bezier_iter() {
for (segment, bezier, start, end) in vector.segment_bezier_iter() {
if start == point_id || end == point_id {
match (connected_segments[0], connected_segments[1]) {
(None, None) => connected_segments[0] = Some(SlidingSegmentData { segment_id: segment, bezier, start }),
@@ -1253,7 +1249,7 @@ impl PathToolData {
let anchor = sliding_point_info.anchor;
let layer = sliding_point_info.layer;
let Some(vector_data) = network_interface.compute_modified_vector(layer) else { return };
let Some(vector) = network_interface.compute_modified_vector(layer) else { return };
let transform = network_interface.document_metadata().transform_to_viewport_if_feeds(layer, network_interface);
let layer_pos = transform.inverse().transform_point2(target_position);
@@ -1272,12 +1268,12 @@ impl PathToolData {
};
// Move the anchor to the new position
let Some(current_position) = ManipulatorPointId::Anchor(anchor).get_position(&vector_data) else {
let Some(current_position) = ManipulatorPointId::Anchor(anchor).get_position(&vector) else {
return;
};
let delta = new_position - current_position;
shape_editor.move_anchor(anchor, &vector_data, delta, layer, None, responses);
shape_editor.move_anchor(anchor, &vector, delta, layer, None, responses);
// Make a split at the t_value
let [first, second] = closer_segment.bezier.split(TValue::Parametric(t_value));
@@ -1419,19 +1415,19 @@ impl PathToolData {
let Some(layer) = document.network_interface.selected_nodes().selected_layers(document.metadata()).next() else {
return;
};
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { return };
let Some(point_id) = shape_editor.selected_points().next().unwrap().get_anchor(&vector_data) else {
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { return };
let Some(point_id) = shape_editor.selected_points().next().unwrap().get_anchor(&vector) else {
return;
};
if vector_data.connected_count(point_id) == 2 {
let connected_segments: Vec<HandleId> = vector_data.all_connected(point_id).collect();
if vector.connected_count(point_id) == 2 {
let connected_segments: Vec<HandleId> = vector.all_connected(point_id).collect();
let segment1 = connected_segments[0];
let Some(tangent1) = self.get_normalized_tangent(point_id, segment1.segment, &vector_data) else {
let Some(tangent1) = self.get_normalized_tangent(point_id, segment1.segment, &vector) else {
return;
};
let segment2 = connected_segments[1];
let Some(tangent2) = self.get_normalized_tangent(point_id, segment2.segment, &vector_data) else {
let Some(tangent2) = self.get_normalized_tangent(point_id, segment2.segment, &vector) else {
return;
};
@@ -1565,11 +1561,11 @@ impl Fsm for PathToolFsmState {
let selected_layers = shape_editor.selected_layers().cloned().collect::<Vec<_>>();
for layer in selected_layers {
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue };
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { continue };
let selected_state = shape_editor.selected_shape_state.entry(layer).or_default();
for (segment, _, start, end) in vector_data.segment_bezier_iter() {
for (segment, _, start, end) in vector.segment_bezier_iter() {
if selected_state.is_segment_selected(segment) {
selected_state.select_point(ManipulatorPointId::Anchor(start));
selected_state.select_point(ManipulatorPointId::Anchor(end));
@@ -1610,11 +1606,11 @@ impl Fsm for PathToolFsmState {
let selected_layers = shape_editor.selected_layers().cloned().collect::<Vec<_>>();
for layer in selected_layers {
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue };
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { continue };
let selected_state = shape_editor.selected_shape_state.entry(layer).or_default();
for (segment, _, start, end) in vector_data.segment_bezier_iter() {
for (segment, _, start, end) in vector.segment_bezier_iter() {
let first_selected = selected_state.is_point_selected(ManipulatorPointId::Anchor(start));
let second_selected = selected_state.is_point_selected(ManipulatorPointId::Anchor(end));
if first_selected && second_selected {
@@ -1663,12 +1659,12 @@ impl Fsm for PathToolFsmState {
let mut segment_endpoints: HashMap<SegmentId, Vec<PointId>> = HashMap::new();
for layer in document.network_interface.selected_nodes().selected_layers(document.metadata()) {
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue };
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { continue };
// The points which are part of only one segment will be rendered
let mut selected_segments_by_point: HashMap<PointId, Vec<SegmentId>> = HashMap::new();
for (segment_id, _bezier, start, end) in vector_data.segment_bezier_iter() {
for (segment_id, _bezier, start, end) in vector.segment_bezier_iter() {
if selected_segments.contains(&segment_id) {
selected_segments_by_point.entry(start).or_default().push(segment_id);
selected_segments_by_point.entry(end).or_default().push(segment_id);
@@ -1721,8 +1717,8 @@ impl Fsm for PathToolFsmState {
);
let Some((layer, manipulator_point_id)) = nearest_visible_point_indices else { return };
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { return };
let Some(position) = manipulator_point_id.get_position(&vector_data) else {
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { return };
let Some(position) = manipulator_point_id.get_position(&vector) else {
error!("No position for hovered point");
return;
};
@@ -1847,10 +1843,10 @@ impl Fsm for PathToolFsmState {
};
for (layer, points) in points_inside {
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue };
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { continue };
for point in points {
let Some(position) = point.get_position(&vector_data) else { continue };
let Some(position) = point.get_position(&vector) else { continue };
let transform = document.metadata().transform_to_viewport(layer);
let position = transform.transform_point2(position);
@@ -1865,11 +1861,11 @@ impl Fsm for PathToolFsmState {
}
for (layer, segments) in segments_inside {
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue };
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { continue };
let transform = document.metadata().transform_to_viewport_if_feeds(layer, &document.network_interface);
for (segment, bezier, _, _) in vector_data.segment_bezier_iter() {
for (segment, bezier, _, _) in vector.segment_bezier_iter() {
if segments.contains(&segment) {
overlay_context.outline_overlay_bezier(bezier, transform);
}
@@ -2392,8 +2388,8 @@ impl Fsm for PathToolFsmState {
if !drag_occurred && !tool_data.molding_segment && ((point_mode && !segment_mode) || (segment_mode && tool_data.segment_editing_modifier)) {
if tool_data.delete_segment_pressed {
if let Some(vector_data) = document.network_interface.compute_modified_vector(segment.layer()) {
shape_editor.dissolve_segment(responses, segment.layer(), &vector_data, segment.segment(), segment.points());
if let Some(vector) = document.network_interface.compute_modified_vector(segment.layer()) {
shape_editor.dissolve_segment(responses, segment.layer(), &vector, segment.segment(), segment.points());
}
} else {
let is_segment_selected = shape_editor
@@ -2580,17 +2576,15 @@ impl Fsm for PathToolFsmState {
continue;
}
let Some(old_vector_data) = document.network_interface.compute_modified_vector(layer) else {
continue;
};
let Some(old_vector) = document.network_interface.compute_modified_vector(layer) else { continue };
// Also get the transform node that is applied on the layer if it exists
let transform = document.metadata().transform_to_document(layer);
let mut new_vector_data = VectorData::default();
let mut new_vector = Vector::default();
let mut selected_points_by_segment = HashSet::new();
old_vector_data
old_vector
.segment_bezier_iter()
.filter(|(segment, _, _, _)| layer_selection_state.is_segment_selected(*segment))
.for_each(|(_, _, start, end)| {
@@ -2599,16 +2593,16 @@ impl Fsm for PathToolFsmState {
});
// Add all the selected points
for (point, position) in old_vector_data.point_domain.iter() {
for (point, position) in old_vector.point_domain.iter() {
if layer_selection_state.is_point_selected(ManipulatorPointId::Anchor(point)) || selected_points_by_segment.contains(&point) {
new_vector_data.point_domain.push(point, position);
new_vector.point_domain.push(point, position);
}
}
let find_index = |id: PointId| new_vector_data.point_domain.iter().enumerate().find(|(_, (point_id, _))| *point_id == id).map(|(index, _)| index);
let find_index = |id: PointId| new_vector.point_domain.iter().enumerate().find(|(_, (point_id, _))| *point_id == id).map(|(index, _)| index);
// Add segments which have selected ends
for ((segment_id, bezier, start, end), stroke) in old_vector_data.segment_bezier_iter().zip(old_vector_data.segment_domain.stroke().iter()) {
for ((segment_id, bezier, start, end), stroke) in old_vector.segment_bezier_iter().zip(old_vector.segment_domain.stroke().iter()) {
let both_ends_selected = layer_selection_state.is_point_selected(ManipulatorPointId::Anchor(start)) && layer_selection_state.is_point_selected(ManipulatorPointId::Anchor(end));
let segment_selected = layer_selection_state.is_segment_selected(segment_id);
@@ -2618,17 +2612,17 @@ impl Fsm for PathToolFsmState {
error!("Point does not exist in point domain");
return PathToolFsmState::Ready;
};
new_vector_data.segment_domain.push(segment_id, start_index, end_index, bezier.handles, *stroke);
new_vector.segment_domain.push(segment_id, start_index, end_index, bezier.handles, *stroke);
}
}
for handles in old_vector_data.colinear_manipulators {
if new_vector_data.segment_domain.ids().contains(&handles[0].segment) && new_vector_data.segment_domain.ids().contains(&handles[1].segment) {
new_vector_data.colinear_manipulators.push(handles);
for handles in old_vector.colinear_manipulators {
if new_vector.segment_domain.ids().contains(&handles[0].segment) && new_vector.segment_domain.ids().contains(&handles[1].segment) {
new_vector.colinear_manipulators.push(handles);
}
}
buffer.push((layer, new_vector_data, transform));
buffer.push((layer, new_vector, transform));
}
if clipboard == Clipboard::Device {
@@ -2650,7 +2644,7 @@ impl Fsm for PathToolFsmState {
}
(_, PathToolMessage::Paste { data }) => {
// Deserialize the data
if let Ok(data) = serde_json::from_str::<Vec<(LayerNodeIdentifier, VectorData, DAffine2)>>(&data) {
if let Ok(data) = serde_json::from_str::<Vec<(LayerNodeIdentifier, Vector, DAffine2)>>(&data) {
shape_editor.deselect_all_points();
responses.add(DocumentMessage::AddTransaction);
let mut new_layers = Vec::new();
@@ -2690,7 +2684,7 @@ impl Fsm for PathToolFsmState {
layer
};
// Create new point ids and add those into the existing vector data
// Create new point ids and add those into the existing vector content
let mut points_map = HashMap::new();
for (point, position) in new_vector.point_domain.iter() {
let new_point_id = PointId::generate();
@@ -2701,7 +2695,7 @@ impl Fsm for PathToolFsmState {
responses.add(GraphOperationMessage::Vector { layer, modification_type });
}
// Create new segment ids and add the segments into the existing vector data
// Create new segment ids and add the segments into the existing vector content
let mut segments_map = HashMap::new();
for (segment_id, bezier, start, end) in new_vector.segment_bezier_iter() {
let new_segment_id = SegmentId::generate();
@@ -2777,13 +2771,13 @@ impl Fsm for PathToolFsmState {
if layer_selection_state.is_empty() {
continue;
}
let Some(old_vector_data) = document.network_interface.compute_modified_vector(layer) else {
let Some(old_vector) = document.network_interface.compute_modified_vector(layer) else {
continue;
};
// Add all the selected points
let mut selected_points_by_segment = HashSet::new();
old_vector_data
old_vector
.segment_bezier_iter()
.filter(|(segment, _, _, _)| layer_selection_state.is_segment_selected(*segment))
.for_each(|(_, _, start, end)| {
@@ -2792,7 +2786,7 @@ impl Fsm for PathToolFsmState {
});
let mut points_map = HashMap::new();
for (point, position) in old_vector_data.point_domain.iter() {
for (point, position) in old_vector.point_domain.iter() {
// TODO: Either the point is selected or it is an endpoint of a selected segment
if layer_selection_state.is_point_selected(ManipulatorPointId::Anchor(point)) || selected_points_by_segment.contains(&point) {
@@ -2808,7 +2802,7 @@ impl Fsm for PathToolFsmState {
let mut segments_map = HashMap::new();
for (segment_id, bezier, start, end) in old_vector_data.segment_bezier_iter() {
for (segment_id, bezier, start, end) in old_vector.segment_bezier_iter() {
let both_ends_selected = layer_selection_state.is_point_selected(ManipulatorPointId::Anchor(start)) && layer_selection_state.is_point_selected(ManipulatorPointId::Anchor(end));
let segment_selected = layer_selection_state.is_segment_selected(segment_id);
@@ -2830,7 +2824,7 @@ impl Fsm for PathToolFsmState {
}
}
for handles in old_vector_data.colinear_manipulators {
for handles in old_vector.colinear_manipulators {
let to_new_handle = |handle: HandleId| -> HandleId {
HandleId {
ty: handle.ty,
@@ -3104,13 +3098,13 @@ fn get_selection_status(network_interface: &NodeNetworkInterface, shape_state: &
let Some(layer) = selection_layers.find(|(_, v)| *v > 0).map(|(k, _)| k) else {
return SelectionStatus::None;
};
let Some(vector_data) = network_interface.compute_modified_vector(layer) else {
let Some(vector) = network_interface.compute_modified_vector(layer) else {
return SelectionStatus::None;
};
let Some(&point) = shape_state.selected_points().next() else {
return SelectionStatus::None;
};
let Some(local_position) = point.get_position(&vector_data) else {
let Some(local_position) = point.get_position(&vector) else {
return SelectionStatus::None;
};
@@ -3118,7 +3112,7 @@ fn get_selection_status(network_interface: &NodeNetworkInterface, shape_state: &
.document_metadata()
.transform_to_document_if_feeds(layer, network_interface)
.transform_point2(local_position);
let manipulator_angle = if vector_data.colinear(point) { ManipulatorAngle::Colinear } else { ManipulatorAngle::Free };
let manipulator_angle = if vector.colinear(point) { ManipulatorAngle::Colinear } else { ManipulatorAngle::Free };
return SelectionStatus::One(SingleSelectedPoint {
coordinates,
@@ -3143,40 +3137,40 @@ fn calculate_lock_angle(
shape_state: &mut ShapeState,
responses: &mut VecDeque<Message>,
document: &DocumentMessageHandler,
vector_data: &VectorData,
vector: &Vector,
handle_id: ManipulatorPointId,
tangent_to_neighboring_tangents: bool,
) -> Option<f64> {
let anchor = handle_id.get_anchor(vector_data)?;
let anchor_position = vector_data.point_domain.position_from_id(anchor);
let anchor = handle_id.get_anchor(vector)?;
let anchor_position = vector.point_domain.position_from_id(anchor);
let current_segment = handle_id.get_segment();
let points_connected = vector_data.connected_count(anchor);
let points_connected = vector.connected_count(anchor);
let (anchor_position, segment) = anchor_position.zip(current_segment)?;
if points_connected == 1 {
calculate_segment_angle(anchor, segment, vector_data, false)
calculate_segment_angle(anchor, segment, vector, false)
} else {
let opposite_handle = handle_id
.get_handle_pair(vector_data)
.get_handle_pair(vector)
.iter()
.flatten()
.find(|&h| h.to_manipulator_point() != handle_id)
.copied()
.map(|h| h.to_manipulator_point());
let opposite_handle_position = opposite_handle.and_then(|h| h.get_position(vector_data)).filter(|pos| (pos - anchor_position).length() > 1e-6);
let opposite_handle_position = opposite_handle.and_then(|h| h.get_position(vector)).filter(|pos| (pos - anchor_position).length() > 1e-6);
if let Some(opposite_pos) = opposite_handle_position {
if !vector_data.colinear_manipulators.iter().flatten().map(|h| h.to_manipulator_point()).any(|h| h == handle_id) {
if !vector.colinear_manipulators.iter().flatten().map(|h| h.to_manipulator_point()).any(|h| h == handle_id) {
shape_state.convert_selected_manipulators_to_colinear_handles(responses, document);
tool_data.temporary_colinear_handles = true;
}
Some(-(opposite_pos - anchor_position).angle_to(DVec2::X))
} else {
let angle_1 = vector_data
let angle_1 = vector
.adjacent_segment(&handle_id)
.and_then(|(_, adjacent_segment)| calculate_segment_angle(anchor, adjacent_segment, vector_data, false));
.and_then(|(_, adjacent_segment)| calculate_segment_angle(anchor, adjacent_segment, vector, false));
let angle_2 = calculate_segment_angle(anchor, segment, vector_data, false);
let angle_2 = calculate_segment_angle(anchor, segment, vector, false);
match (angle_1, angle_2) {
(Some(angle_1), Some(angle_2)) => {
@@ -3195,37 +3189,32 @@ fn calculate_lock_angle(
}
}
fn check_handle_over_adjacent_anchor(handle_id: ManipulatorPointId, vector_data: &VectorData) -> Option<PointId> {
let (anchor, handle_position) = handle_id.get_anchor(vector_data).zip(handle_id.get_position(vector_data))?;
fn check_handle_over_adjacent_anchor(handle_id: ManipulatorPointId, vector: &Vector) -> Option<PointId> {
let (anchor, handle_position) = handle_id.get_anchor(vector).zip(handle_id.get_position(vector))?;
let check_if_close = |point_id: &PointId| {
let Some(anchor_position) = vector_data.point_domain.position_from_id(*point_id) else {
let Some(anchor_position) = vector.point_domain.position_from_id(*point_id) else {
return false;
};
(anchor_position - handle_position).length() < 10.
};
vector_data.connected_points(anchor).find(check_if_close)
vector.connected_points(anchor).find(check_if_close)
}
fn calculate_adjacent_anchor_tangent(
currently_dragged_handle: ManipulatorPointId,
anchor: Option<PointId>,
adjacent_anchor: Option<PointId>,
vector_data: &VectorData,
) -> (Option<f64>, Option<DVec2>) {
fn calculate_adjacent_anchor_tangent(currently_dragged_handle: ManipulatorPointId, anchor: Option<PointId>, adjacent_anchor: Option<PointId>, vector: &Vector) -> (Option<f64>, Option<DVec2>) {
// Early return if no anchor or no adjacent anchors
let Some((dragged_handle_anchor, adjacent_anchor)) = anchor.zip(adjacent_anchor) else {
return (None, None);
};
let adjacent_anchor_position = vector_data.point_domain.position_from_id(adjacent_anchor);
let adjacent_anchor_position = vector.point_domain.position_from_id(adjacent_anchor);
let handles: Vec<_> = vector_data.all_connected(adjacent_anchor).filter(|handle| handle.length(vector_data) > 1e-6).collect();
let handles: Vec<_> = vector.all_connected(adjacent_anchor).filter(|handle| handle.length(vector) > 1e-6).collect();
match handles.len() {
0 => {
// Find non-shared segments
let non_shared_segment: Vec<_> = vector_data
let non_shared_segment: Vec<_> = vector
.segment_bezier_iter()
.filter_map(|(segment_id, _, start, end)| {
let touches_adjacent = start == adjacent_anchor || end == adjacent_anchor;
@@ -3237,7 +3226,7 @@ fn calculate_adjacent_anchor_tangent(
match non_shared_segment.first() {
Some(&segment) => {
let angle = calculate_segment_angle(adjacent_anchor, segment, vector_data, true);
let angle = calculate_segment_angle(adjacent_anchor, segment, vector, true);
(angle, adjacent_anchor_position)
}
None => (None, None),
@@ -3246,7 +3235,7 @@ fn calculate_adjacent_anchor_tangent(
1 => {
let segment = handles[0].segment;
let angle = calculate_segment_angle(adjacent_anchor, segment, vector_data, true);
let angle = calculate_segment_angle(adjacent_anchor, segment, vector, true);
(angle, adjacent_anchor_position)
}
@@ -3261,7 +3250,7 @@ fn calculate_adjacent_anchor_tangent(
};
let angle = shared_segment_handle
.get_position(vector_data)
.get_position(vector)
.zip(adjacent_anchor_position)
.map(|(handle, anchor)| -(handle - anchor).angle_to(DVec2::X));
@@ -3296,8 +3285,8 @@ fn update_dynamic_hints(
shape_editor.selected_points().next(),
document.network_interface.selected_nodes().selected_layers(document.metadata()).next(),
) {
if let Some(vector_data) = document.network_interface.compute_modified_vector(layer) {
single_colinear_anchor_selected = vector_data.colinear(*anchor)
if let Some(vector) = document.network_interface.compute_modified_vector(layer) {
single_colinear_anchor_selected = vector.colinear(*anchor)
}
}
}
@@ -3448,9 +3437,9 @@ fn update_dynamic_hints(
let handle1 = HandleId::primary(segment.segment());
let handle2 = HandleId::end(segment.segment());
if let Some(vector_data) = document.network_interface.compute_modified_vector(segment.layer()) {
let other_handle1 = vector_data.other_colinear_handle(handle1);
let other_handle2 = vector_data.other_colinear_handle(handle2);
if let Some(vector) = document.network_interface.compute_modified_vector(segment.layer()) {
let other_handle1 = vector.other_colinear_handle(handle1);
let other_handle2 = vector.other_colinear_handle(handle2);
if other_handle1.is_some() || other_handle2.is_some() {
has_colinear_anchors = true;
}
+109 -120
View File
@@ -14,8 +14,8 @@ use crate::messages::tool::common_functionality::utility_functions::{calculate_s
use bezier_rs::{Bezier, BezierHandles};
use graph_craft::document::NodeId;
use graphene_std::Color;
use graphene_std::vector::{HandleId, ManipulatorPointId, NoHashBuilder, SegmentId, StrokeId, VectorData};
use graphene_std::vector::{PointId, VectorModificationType};
use graphene_std::vector::misc::{HandleId, ManipulatorPointId};
use graphene_std::vector::{NoHashBuilder, PointId, SegmentId, StrokeId, Vector, VectorModificationType};
#[derive(Default, ExtractField)]
pub struct PenTool {
@@ -395,11 +395,11 @@ impl PenToolData {
}
/// Check whether target handle is primary, end, or `self.handle_end`
fn check_end_handle_type(&self, vector_data: &VectorData) -> TargetHandle {
fn check_end_handle_type(&self, vector: &Vector) -> TargetHandle {
match (self.handle_end, self.prior_segment_endpoint, self.prior_segment, self.path_closed) {
(Some(_), _, _, false) => TargetHandle::PreviewInHandle,
(None, Some(point), Some(segment), false) | (Some(_), Some(point), Some(segment), true) => {
if vector_data.segment_start_from_id(segment) == Some(point) {
if vector.segment_start_from_id(segment) == Some(point) {
TargetHandle::PriorOutHandle(segment)
} else {
TargetHandle::PriorInHandle(segment)
@@ -409,23 +409,23 @@ impl PenToolData {
}
}
fn check_grs_end_handle(&self, vector_data: &VectorData) -> TargetHandle {
fn check_grs_end_handle(&self, vector: &Vector) -> TargetHandle {
let Some(point) = self.latest_point().map(|point| point.id) else { return TargetHandle::None };
let Some(segment) = self.prior_segment else { return TargetHandle::None };
if vector_data.segment_start_from_id(segment) == Some(point) {
if vector.segment_start_from_id(segment) == Some(point) {
TargetHandle::PriorOutHandle(segment)
} else {
TargetHandle::PriorInHandle(segment)
}
}
fn get_opposite_handle_type(&self, handle_type: TargetHandle, vector_data: &VectorData) -> TargetHandle {
fn get_opposite_handle_type(&self, handle_type: TargetHandle, vector: &Vector) -> TargetHandle {
match handle_type {
TargetHandle::FuturePreviewOutHandle => self.check_end_handle_type(vector_data),
TargetHandle::FuturePreviewOutHandle => self.check_end_handle_type(vector),
TargetHandle::PreviewInHandle => match (self.path_closed, self.prior_segment_endpoint, self.prior_segment) {
(true, Some(point), Some(segment)) => {
if vector_data.segment_start_from_id(segment) == Some(point) {
if vector.segment_start_from_id(segment) == Some(point) {
TargetHandle::PriorOutHandle(segment)
} else {
TargetHandle::PriorInHandle(segment)
@@ -472,10 +472,10 @@ impl PenToolData {
}
}
fn target_handle_position(&self, handle_type: TargetHandle, vector_data: &VectorData) -> Option<DVec2> {
fn target_handle_position(&self, handle_type: TargetHandle, vector: &Vector) -> Option<DVec2> {
match handle_type {
TargetHandle::PriorOutHandle(segment) => ManipulatorPointId::PrimaryHandle(segment).get_position(vector_data),
TargetHandle::PriorInHandle(segment) => ManipulatorPointId::EndHandle(segment).get_position(vector_data),
TargetHandle::PriorOutHandle(segment) => ManipulatorPointId::PrimaryHandle(segment).get_position(vector),
TargetHandle::PriorInHandle(segment) => ManipulatorPointId::EndHandle(segment).get_position(vector),
TargetHandle::PreviewInHandle => self.handle_end,
TargetHandle::FuturePreviewOutHandle => Some(self.next_handle_start),
TargetHandle::None => None,
@@ -488,11 +488,11 @@ impl PenToolData {
return;
};
let Some(vector_data) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)) else {
let Some(vector) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)) else {
return;
};
match self.check_end_handle_type(&vector_data) {
match self.check_end_handle_type(&vector) {
TargetHandle::PriorInHandle(segment) => shape_state.deselect_point(ManipulatorPointId::EndHandle(segment)),
TargetHandle::PriorOutHandle(segment) => shape_state.deselect_point(ManipulatorPointId::PrimaryHandle(segment)),
_ => {}
@@ -518,18 +518,14 @@ impl PenToolData {
self.latest_points.len() == 1 && self.latest_point().is_some_and(|point| point.pos == self.next_point)
}
// When the vector data transform changes, the positions of the points must be recalculated.
// When the vector transform changes, the positions of the points must be recalculated.
fn recalculate_latest_points_position(&mut self, document: &DocumentMessageHandler) {
let selected_nodes = document.network_interface.selected_nodes();
let mut selected_layers = selected_nodes.selected_layers(document.metadata());
if let (Some(layer), None) = (selected_layers.next(), selected_layers.next()) {
let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else {
return;
};
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { return };
for point in &mut self.latest_points {
let Some(pos) = vector_data.point_domain.position_from_id(point.id) else {
continue;
};
let Some(pos) = vector.point_domain.position_from_id(point.id) else { continue };
point.pos = pos;
point.handle_start = point.pos;
}
@@ -549,7 +545,7 @@ impl PenToolData {
self.g1_continuous = true;
let document = snap_data.document;
self.next_handle_start = self.next_point;
let vector_data = document.network_interface.compute_modified_vector(layer).unwrap();
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
self.update_handle_type(TargetHandle::FuturePreviewOutHandle);
self.handle_mode = HandleMode::ColinearLocked;
@@ -565,7 +561,7 @@ impl PenToolData {
self.store_clicked_endpoint(document, &transform, snap_data.input, preferences);
if self.modifiers.lock_angle {
self.set_lock_angle(&vector_data, id, self.prior_segment);
self.set_lock_angle(&vector, id, self.prior_segment);
let last_segment = self.prior_segment;
let Some(point) = self.latest_point_mut() else { return };
point.in_segment = last_segment;
@@ -579,7 +575,7 @@ impl PenToolData {
}
// Closing path
let closing_path_on_point = self.close_path_on_point(snap_data, &vector_data, document, preferences, id, &transform);
let closing_path_on_point = self.close_path_on_point(snap_data, &vector, document, preferences, id, &transform);
if !closing_path_on_point && preferences.vector_meshes {
// Attempt to find nearest segment and close path on segment by creating an anchor point on it
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
@@ -600,24 +596,16 @@ impl PenToolData {
self.handle_mode = HandleMode::Free;
if let (true, Some(prior_endpoint)) = (self.modifiers.lock_angle, self.prior_segment_endpoint) {
self.set_lock_angle(&vector_data, prior_endpoint, self.prior_segment);
self.set_lock_angle(&vector, prior_endpoint, self.prior_segment);
self.switch_to_free_on_ctrl_release = true;
}
}
}
}
fn close_path_on_point(
&mut self,
snap_data: SnapData,
vector_data: &VectorData,
document: &DocumentMessageHandler,
preferences: &PreferencesMessageHandler,
id: PointId,
transform: &DAffine2,
) -> bool {
for id in vector_data.extendable_points(preferences.vector_meshes).filter(|&point| point != id) {
let Some(pos) = vector_data.point_domain.position_from_id(id) else { continue };
fn close_path_on_point(&mut self, snap_data: SnapData, vector: &Vector, document: &DocumentMessageHandler, preferences: &PreferencesMessageHandler, id: PointId, transform: &DAffine2) -> bool {
for id in vector.extendable_points(preferences.vector_meshes).filter(|&point| point != id) {
let Some(pos) = vector.point_domain.position_from_id(id) else { continue };
let transformed_distance_between_squared = transform.transform_point2(pos).distance_squared(transform.transform_point2(self.next_point));
let snap_point_tolerance_squared = crate::consts::SNAP_POINT_TOLERANCE.powi(2);
@@ -629,7 +617,7 @@ impl PenToolData {
self.store_clicked_endpoint(document, transform, snap_data.input, preferences);
self.handle_mode = HandleMode::Free;
if let (true, Some(prior_endpoint)) = (self.modifiers.lock_angle, self.prior_segment_endpoint) {
self.set_lock_angle(vector_data, prior_endpoint, self.prior_segment);
self.set_lock_angle(vector, prior_endpoint, self.prior_segment);
self.switch_to_free_on_ctrl_release = true;
}
return true;
@@ -662,11 +650,11 @@ impl PenToolData {
let selected_nodes = document.network_interface.selected_nodes();
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 vector_data = document.network_interface.compute_modified_vector(layer)?;
let vector = document.network_interface.compute_modified_vector(layer)?;
let start = self.latest_point()?.id;
let transform = document.metadata().document_to_viewport * transform;
for id in vector_data.extendable_points(preferences.vector_meshes).filter(|&point| point != start) {
let Some(pos) = vector_data.point_domain.position_from_id(id) else { continue };
for id in vector.extendable_points(preferences.vector_meshes).filter(|&point| point != start) {
let Some(pos) = vector.point_domain.position_from_id(id) else { continue };
let transformed_distance_between_squared = transform.transform_point2(pos).distance_squared(transform.transform_point2(next_point));
let snap_point_tolerance_squared = crate::consts::SNAP_POINT_TOLERANCE.powi(2);
if transformed_distance_between_squared < snap_point_tolerance_squared {
@@ -687,15 +675,15 @@ impl PenToolData {
// Store the segment
let id = SegmentId::generate();
if self.path_closed {
if let Some((handles, handle1_pos)) = match self.get_opposite_handle_type(TargetHandle::PreviewInHandle, &vector_data) {
if let Some((handles, handle1_pos)) = match self.get_opposite_handle_type(TargetHandle::PreviewInHandle, &vector) {
TargetHandle::PriorOutHandle(segment) => {
let handles = [HandleId::end(id), HandleId::primary(segment)];
let handle1_pos = handles[1].to_manipulator_point().get_position(&vector_data);
let handle1_pos = handles[1].to_manipulator_point().get_position(&vector);
handle1_pos.map(|pos| (handles, pos))
}
TargetHandle::PriorInHandle(segment) => {
let handles = [HandleId::end(id), HandleId::end(segment)];
let handle1_pos = handles[1].to_manipulator_point().get_position(&vector_data);
let handle1_pos = handles[1].to_manipulator_point().get_position(&vector);
handle1_pos.map(|pos| (handles, pos))
}
_ => None,
@@ -719,14 +707,14 @@ impl PenToolData {
// Mirror
if let Some((last_segment, last_point)) = self.latest_point().and_then(|point| point.in_segment).zip(self.latest_point()) {
let end = vector_data.segment_end_from_id(last_segment) == Some(last_point.id);
let end = vector.segment_end_from_id(last_segment) == Some(last_point.id);
let handles = if end {
[HandleId::end(last_segment), HandleId::primary(id)]
} else {
[HandleId::primary(last_segment), HandleId::primary(id)]
};
if let Some(h1) = handles[0].to_manipulator_point().get_position(&vector_data) {
if let Some(h1) = handles[0].to_manipulator_point().get_position(&vector) {
let angle = (h1 - last_point.pos).angle_to(last_point.handle_start - last_point.pos);
let pi = std::f64::consts::PI;
let colinear = (angle - pi).abs() < 1e-6 || (angle + pi).abs() < 1e-6;
@@ -758,13 +746,13 @@ impl PenToolData {
transform: &DAffine2,
snap_data: &SnapData<'_>,
mouse: &DVec2,
vector_data: &VectorData,
vector: &Vector,
input: &InputPreprocessorMessageHandler,
) -> Option<DVec2> {
let reference_handle = if self.path_closed { TargetHandle::PreviewInHandle } else { TargetHandle::FuturePreviewOutHandle };
let end_handle = self.get_opposite_handle_type(reference_handle, vector_data);
let end_handle_pos = self.target_handle_position(end_handle, vector_data);
let ref_pos = self.target_handle_position(reference_handle, vector_data)?;
let end_handle = self.get_opposite_handle_type(reference_handle, vector);
let end_handle_pos = self.target_handle_position(end_handle, vector);
let ref_pos = self.target_handle_position(reference_handle, vector)?;
let snap = &mut self.snap_manager;
let snap_data = SnapData::new_snap_cache(snap_data.document, input, &self.snap_cache);
@@ -826,7 +814,7 @@ impl PenToolData {
responses: &mut VecDeque<Message>,
) {
// Validate necessary data exists
let Some(vector_data) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)) else {
let Some(vector) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)) else {
return;
};
@@ -842,9 +830,9 @@ impl PenToolData {
let should_swap_to_start = !self.path_closed && !matches!(self.handle_type, TargetHandle::None | TargetHandle::FuturePreviewOutHandle);
if should_swap_to_opposite {
let opposite_type = self.get_opposite_handle_type(self.handle_type, &vector_data);
let opposite_type = self.get_opposite_handle_type(self.handle_type, &vector);
// Update offset
let Some(handle_pos) = self.target_handle_position(opposite_type, &vector_data) else {
let Some(handle_pos) = self.target_handle_position(opposite_type, &vector) else {
self.handle_swapped = false;
return;
};
@@ -894,7 +882,7 @@ impl PenToolData {
Some(PenToolFsmState::DraggingHandle(self.handle_mode))
}
fn move_anchor_and_handles(&mut self, delta: DVec2, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>, vector_data: &VectorData) {
fn move_anchor_and_handles(&mut self, delta: DVec2, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>, vector: &Vector) {
if self.handle_end.is_none() {
if let Some(latest_pt) = self.latest_point_mut() {
latest_pt.pos += delta;
@@ -912,10 +900,10 @@ impl PenToolData {
let reference_handle = if self.path_closed { TargetHandle::PreviewInHandle } else { TargetHandle::FuturePreviewOutHandle };
// Move the end handle
let end_handle_type = self.get_opposite_handle_type(reference_handle, vector_data);
let end_handle_type = self.get_opposite_handle_type(reference_handle, vector);
match end_handle_type {
TargetHandle::PriorInHandle(..) | TargetHandle::PriorOutHandle(..) => {
let Some(handle_pos) = self.target_handle_position(end_handle_type, vector_data) else { return };
let Some(handle_pos) = self.target_handle_position(end_handle_type, vector) else { return };
self.update_target_handle_pos(end_handle_type, self.next_point, responses, handle_pos + delta, layer);
}
_ => {}
@@ -934,13 +922,13 @@ impl PenToolData {
let colinear = (self.handle_mode == HandleMode::ColinearEquidistant && self.modifiers.break_handle) || (self.handle_mode == HandleMode::ColinearLocked && !self.modifiers.break_handle);
let document = snap_data.document;
let Some(layer) = layer else { return Some(PenToolFsmState::DraggingHandle(self.handle_mode)) };
let vector_data = document.network_interface.compute_modified_vector(layer)?;
let vector = document.network_interface.compute_modified_vector(layer)?;
let viewport_to_document = document.metadata().document_to_viewport.inverse();
let mut mouse_pos = mouse;
// Handles pressing Space to drag anchor and its handles
if self.modifiers.move_anchor_with_handles {
let Some(delta) = self.space_anchor_handle_snap(&viewport_to_document, &transform, &snap_data, &mouse, &vector_data, input) else {
let Some(delta) = self.space_anchor_handle_snap(&viewport_to_document, &transform, &snap_data, &mouse, &vector, input) else {
return Some(PenToolFsmState::DraggingHandle(self.handle_mode));
};
@@ -959,7 +947,7 @@ impl PenToolData {
};
}
self.move_anchor_and_handles(delta, layer, responses, &vector_data);
self.move_anchor_and_handles(delta, layer, responses, &vector);
responses.add(OverlaysMessage::Draw);
return Some(PenToolFsmState::DraggingHandle(self.handle_mode));
@@ -994,8 +982,8 @@ impl PenToolData {
match self.handle_mode {
HandleMode::ColinearLocked | HandleMode::ColinearEquidistant => {
self.g1_continuous = true;
self.apply_colinear_constraint(responses, layer, self.next_point, &vector_data);
self.adjust_handle_length(responses, layer, &vector_data);
self.apply_colinear_constraint(responses, layer, self.next_point, &vector);
self.adjust_handle_length(responses, layer, &vector);
}
HandleMode::Free => {
self.g1_continuous = false;
@@ -1006,7 +994,7 @@ impl PenToolData {
let Some(endpoint) = self.prior_segment_endpoint else {
return Some(PenToolFsmState::DraggingHandle(self.handle_mode));
};
self.set_lock_angle(&vector_data, endpoint, self.prior_segment);
self.set_lock_angle(&vector, endpoint, self.prior_segment);
self.switch_to_free_on_ctrl_release = true;
let last_segment = self.prior_segment;
if let Some(latest) = self.latest_point_mut() {
@@ -1020,19 +1008,19 @@ impl PenToolData {
}
/// Makes the opposite handle equidistant or locks its length.
fn adjust_handle_length(&mut self, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, vector_data: &VectorData) {
let opposite_handle_type = self.get_opposite_handle_type(self.handle_type, vector_data);
fn adjust_handle_length(&mut self, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, vector: &Vector) {
let opposite_handle_type = self.get_opposite_handle_type(self.handle_type, vector);
match self.handle_mode {
HandleMode::ColinearEquidistant => {
if self.modifiers.break_handle {
// Store handle for later restoration only when Alt is first pressed
if !self.alt_pressed {
self.previous_handle_end_pos = self.target_handle_position(opposite_handle_type, vector_data);
self.previous_handle_end_pos = self.target_handle_position(opposite_handle_type, vector);
self.alt_pressed = true;
}
// Set handle to opposite position of the other handle
let Some(new_position) = self.target_handle_position(self.handle_type, vector_data).map(|handle| self.next_point * 2. - handle) else {
let Some(new_position) = self.target_handle_position(self.handle_type, vector).map(|handle| self.next_point * 2. - handle) else {
return;
};
self.update_target_handle_pos(opposite_handle_type, self.next_point, responses, new_position, layer);
@@ -1047,7 +1035,7 @@ impl PenToolData {
}
HandleMode::ColinearLocked => {
if !self.modifiers.break_handle {
let Some(new_position) = self.target_handle_position(self.handle_type, vector_data).map(|handle| self.next_point * 2. - handle) else {
let Some(new_position) = self.target_handle_position(self.handle_type, vector).map(|handle| self.next_point * 2. - handle) else {
return;
};
self.update_target_handle_pos(opposite_handle_type, self.next_point, responses, new_position, layer);
@@ -1057,23 +1045,23 @@ impl PenToolData {
}
}
fn apply_colinear_constraint(&mut self, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, anchor_pos: DVec2, vector_data: &VectorData) {
let Some(handle) = self.target_handle_position(self.handle_type, vector_data) else {
return;
};
fn apply_colinear_constraint(&mut self, responses: &mut VecDeque<Message>, layer: LayerNodeIdentifier, anchor_pos: DVec2, vector: &Vector) {
let Some(handle) = self.target_handle_position(self.handle_type, vector) else { return };
if (anchor_pos - handle).length() < 1e-6 && self.modifiers.lock_angle {
return;
}
let Some(direction) = (anchor_pos - handle).try_normalize() else {
return;
};
let opposite_handle = self.get_opposite_handle_type(self.handle_type, vector_data);
let Some(handle_offset) = self.target_handle_position(opposite_handle, vector_data).map(|handle| (handle - anchor_pos).length()) else {
let Some(direction) = (anchor_pos - handle).try_normalize() else { return };
let opposite_handle = self.get_opposite_handle_type(self.handle_type, vector);
let Some(handle_offset) = self.target_handle_position(opposite_handle, vector).map(|handle| (handle - anchor_pos).length()) else {
return;
};
let new_handle_position = anchor_pos + handle_offset * direction;
self.update_target_handle_pos(opposite_handle, self.next_point, responses, new_handle_position, layer);
}
@@ -1086,10 +1074,10 @@ impl PenToolData {
let selected_nodes = document.network_interface.selected_nodes();
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 vector_data = document.network_interface.compute_modified_vector(layer)?;
let vector = document.network_interface.compute_modified_vector(layer)?;
let transform = document.metadata().document_to_viewport * transform;
for point in vector_data.extendable_points(preferences.vector_meshes) {
let Some(pos) = vector_data.point_domain.position_from_id(point) else { continue };
for point in vector.extendable_points(preferences.vector_meshes) {
let Some(pos) = vector.point_domain.position_from_id(point) else { continue };
let transformed_distance_between_squared = transform.transform_point2(pos).distance_squared(transform.transform_point2(self.next_point));
let snap_point_tolerance_squared = crate::consts::SNAP_POINT_TOLERANCE.powi(2);
if transformed_distance_between_squared < snap_point_tolerance_squared {
@@ -1217,11 +1205,11 @@ impl PenToolData {
if append {
if let Some((layer, point, _)) = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false, preferences) {
let vector_data = document.network_interface.compute_modified_vector(layer).unwrap();
let segment = vector_data.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
let segment = vector.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
if self.modifiers.lock_angle {
self.set_lock_angle(&vector_data, point, segment);
self.set_lock_angle(&vector, point, segment);
self.switch_to_free_on_ctrl_release = true;
}
}
@@ -1235,11 +1223,11 @@ impl PenToolData {
}
if let Some((layer, point, _position)) = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false, preferences) {
let vector_data = document.network_interface.compute_modified_vector(layer).unwrap();
let segment = vector_data.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
let segment = vector.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
self.handle_mode = HandleMode::Free;
if self.modifiers.lock_angle {
self.set_lock_angle(&vector_data, point, segment);
self.set_lock_angle(&vector, point, segment);
self.switch_to_free_on_ctrl_release = true;
}
}
@@ -1265,9 +1253,9 @@ impl PenToolData {
/// Perform extension of an existing path
fn extend_existing_path(&mut self, document: &DocumentMessageHandler, layer: LayerNodeIdentifier, point: PointId, position: DVec2) {
let vector_data = document.network_interface.compute_modified_vector(layer);
let (handle_start, in_segment) = if let Some(vector_data) = &vector_data {
vector_data
let vector = document.network_interface.compute_modified_vector(layer);
let (handle_start, in_segment) = if let Some(vector) = &vector {
vector
.segment_bezier_iter()
.find_map(|(segment_id, bezier, start, end)| {
let is_end = point == end;
@@ -1310,12 +1298,12 @@ impl PenToolData {
self.next_point = position;
self.next_handle_start = handle_start;
let vector_data = document.network_interface.compute_modified_vector(layer).unwrap();
let segment = vector_data.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
let segment = vector.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
self.handle_mode = HandleMode::Free;
if self.modifiers.lock_angle {
self.set_lock_angle(&vector_data, point, segment);
self.set_lock_angle(&vector, point, segment);
self.switch_to_free_on_ctrl_release = true;
}
}
@@ -1340,11 +1328,11 @@ impl PenToolData {
if let Some((layer, point, _position)) = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false, preferences) {
self.prior_segment_endpoint = Some(point);
self.prior_segment_layer = Some(layer);
let vector_data = document.network_interface.compute_modified_vector(layer).unwrap();
let segment = vector_data.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
let segment = vector.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
self.prior_segment = segment;
layer_manipulators.insert(point);
for (&id, &position) in vector_data.point_domain.ids().iter().zip(vector_data.point_domain.positions()) {
for (&id, &position) in vector.point_domain.ids().iter().zip(vector.point_domain.positions()) {
if id == point {
continue;
}
@@ -1355,8 +1343,8 @@ impl PenToolData {
}
}
fn set_lock_angle(&mut self, vector_data: &VectorData, anchor: PointId, segment: Option<SegmentId>) {
let anchor_position = vector_data.point_domain.position_from_id(anchor);
fn set_lock_angle(&mut self, vector: &Vector, anchor: PointId, segment: Option<SegmentId>) {
let anchor_position = vector.point_domain.position_from_id(anchor);
let Some((anchor_position, segment)) = anchor_position.zip(segment) else {
self.handle_mode = HandleMode::Free;
@@ -1365,7 +1353,7 @@ impl PenToolData {
match (self.handle_type, self.path_closed) {
(TargetHandle::FuturePreviewOutHandle, _) | (TargetHandle::PreviewInHandle, true) => {
if let Some(required_handle) = calculate_segment_angle(anchor, segment, vector_data, true) {
if let Some(required_handle) = calculate_segment_angle(anchor, segment, vector, true) {
self.angle = required_handle;
self.handle_mode = HandleMode::ColinearEquidistant;
}
@@ -1460,12 +1448,12 @@ impl Fsm for PenToolFsmState {
responses.add(TransformLayerMessage::BeginScalePen { last_point, handle });
}
let vector_data = document.network_interface.compute_modified_vector(layer).unwrap();
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
tool_data.previous_handle_start_pos = latest.handle_start;
let opposite_handle = tool_data.check_grs_end_handle(&vector_data);
tool_data.previous_handle_end_pos = tool_data.target_handle_position(opposite_handle, &vector_data);
let opposite_handle = tool_data.check_grs_end_handle(&vector);
tool_data.previous_handle_end_pos = tool_data.target_handle_position(opposite_handle, &vector);
let handle1 = latest_handle_start - latest_pos;
let Some(opposite_handle_pos) = tool_data.target_handle_position(opposite_handle, &vector_data) else {
let Some(opposite_handle_pos) = tool_data.target_handle_position(opposite_handle, &vector) else {
return PenToolFsmState::GRSHandle;
};
let handle2 = opposite_handle_pos - latest_pos;
@@ -1476,8 +1464,8 @@ impl Fsm for PenToolFsmState {
}
(PenToolFsmState::GRSHandle, PenToolMessage::FinalPosition { final_position }) => {
let Some(layer) = layer else { return PenToolFsmState::GRSHandle };
let vector_data = document.network_interface.compute_modified_vector(layer);
let Some(vector_data) = vector_data else { return PenToolFsmState::GRSHandle };
let vector = document.network_interface.compute_modified_vector(layer);
let Some(vector) = vector else { return PenToolFsmState::GRSHandle };
if let Some(latest_pt) = tool_data.latest_point_mut() {
let layer_space_to_viewport = document.metadata().transform_to_viewport(layer);
@@ -1489,8 +1477,8 @@ impl Fsm for PenToolFsmState {
let Some(latest) = tool_data.latest_point() else {
return PenToolFsmState::GRSHandle;
};
let opposite_handle = tool_data.check_grs_end_handle(&vector_data);
let Some(opposite_handle_pos) = tool_data.target_handle_position(opposite_handle, &vector_data) else {
let opposite_handle = tool_data.check_grs_end_handle(&vector);
let Some(opposite_handle_pos) = tool_data.target_handle_position(opposite_handle, &vector) else {
return PenToolFsmState::GRSHandle;
};
@@ -1531,8 +1519,8 @@ impl Fsm for PenToolFsmState {
tool_data.next_handle_start = input.mouse.position;
let Some(layer) = layer else { return PenToolFsmState::GRSHandle };
let vector_data = document.network_interface.compute_modified_vector(layer).unwrap();
let opposite_handle = tool_data.check_grs_end_handle(&vector_data);
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
let opposite_handle = tool_data.check_grs_end_handle(&vector);
let previous = tool_data.previous_handle_start_pos;
if let Some(latest) = tool_data.latest_point_mut() {
@@ -1722,10 +1710,10 @@ impl Fsm for PenToolFsmState {
let start = latest_point.id;
if let Some(layer) = layer
&& let Some(mut vector_data) = document.network_interface.compute_modified_vector(layer)
&& let Some(mut vector) = document.network_interface.compute_modified_vector(layer)
{
let closest_point = vector_data.extendable_points(preferences.vector_meshes).filter(|&id| id != start).find(|&id| {
vector_data.point_domain.position_from_id(id).map_or(false, |pos| {
let closest_point = vector.extendable_points(preferences.vector_meshes).filter(|&id| id != start).find(|&id| {
vector.point_domain.position_from_id(id).is_some_and(|pos| {
let dist_sq = transform.transform_point2(pos).distance_squared(transform.transform_point2(next_point));
dist_sq < crate::consts::SNAP_POINT_TOLERANCE.powi(2)
})
@@ -1734,21 +1722,21 @@ impl Fsm for PenToolFsmState {
// We have the point. Join the 2 vertices and check if any path is closed.
if let Some(end) = closest_point {
let segment_id = SegmentId::generate();
vector_data.push(segment_id, start, end, BezierHandles::Cubic { handle_start, handle_end }, StrokeId::ZERO);
vector.push(segment_id, start, end, BezierHandles::Cubic { handle_start, handle_end }, StrokeId::ZERO);
let grouped_segments = vector_data.auto_join_paths();
let grouped_segments = vector.auto_join_paths();
let closed_paths = grouped_segments.iter().filter(|path| path.is_closed() && path.contains(segment_id));
let subpaths: Vec<_> = closed_paths
.filter_map(|path| {
let segments = path.edges.iter().filter_map(|edge| {
vector_data
vector
.segment_domain
.iter()
.find(|(id, _, _, _)| id == &edge.id)
.map(|(_, start, end, bezier)| if start == edge.start { (bezier, start, end) } else { (bezier.reversed(), end, start) })
});
vector_data.subpath_from_segments_ignore_discontinuities(segments)
vector.subpath_from_segments_ignore_discontinuities(segments)
})
.collect();
@@ -1817,7 +1805,8 @@ impl Fsm for PenToolFsmState {
}
// Merge two layers if the point is connected to the end point of another path
// This might not be the correct solution to artboards being included as the other layer, which occurs due to the compute_modified_vector call in should_extend using the click targets for a layer instead of vector data.
// This might not be the correct solution to artboards being included as the other layer,
// which occurs due to the `compute_modified_vector` call in `should_extend` using the click targets for a layer instead of vector.
let layers = LayerNodeIdentifier::ROOT_PARENT
.descendants(document.metadata())
.filter(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[]));
@@ -1887,7 +1876,7 @@ impl Fsm for PenToolFsmState {
tool_data.toggle_colinear_debounce = true;
}
let Some(vector_data) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)) else {
let Some(vector) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)) else {
return self;
};
@@ -1901,7 +1890,7 @@ impl Fsm for PenToolFsmState {
document
.metadata()
.transform_to_viewport(layer)
.transform_point2(tool_data.target_handle_position(reference_handle, &vector_data).unwrap())
.transform_point2(tool_data.target_handle_position(reference_handle, &vector).unwrap())
});
tool_data.handle_start_offset = handle_start.map(|start| start - input.mouse.position);
tool_data.space_pressed = true;
@@ -2075,8 +2064,8 @@ impl Fsm for PenToolFsmState {
}
(PenToolFsmState::DraggingHandle(..), PenToolMessage::Confirm) => {
// Confirm to end path
if let Some((vector_data, layer)) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)).zip(layer) {
let single_point_in_layer = vector_data.point_domain.ids().len() == 1;
if let Some((vector, layer)) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)).zip(layer) {
let single_point_in_layer = vector.point_domain.ids().len() == 1;
tool_data.finish_placing_handle(SnapData::new(document, input), transform, preferences, responses);
let latest_points = tool_data.latest_points.len() == 1;
@@ -2129,8 +2118,8 @@ impl Fsm for PenToolFsmState {
}
}
(PenToolFsmState::PlacingAnchor, PenToolMessage::Abort) => {
let should_delete_layer = if let Some(vector_data) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)) {
vector_data.point_domain.ids().len() == 1
let should_delete_layer = if let Some(vector) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)) {
vector.point_domain.ids().len() == 1
} else {
false
};
@@ -548,15 +548,15 @@ mod test_spline_tool {
use crate::test_utils::test_prelude::*;
use glam::DAffine2;
use graphene_std::vector::PointId;
use graphene_std::vector::VectorData;
use graphene_std::vector::Vector;
fn assert_point_positions(vector_data: &VectorData, layer_to_viewport: DAffine2, expected_points: &[DVec2], epsilon: f64) {
let points_in_viewport: Vec<DVec2> = vector_data
fn assert_point_positions(vector: &Vector, layer_to_viewport: DAffine2, expected_points: &[DVec2], epsilon: f64) {
let points_in_viewport: Vec<DVec2> = vector
.point_domain
.ids()
.iter()
.filter_map(|&point_id| {
let position = vector_data.point_domain.position_from_id(point_id)?;
let position = vector.point_domain.position_from_id(point_id)?;
Some(layer_to_viewport.transform_point2(position))
})
.collect();
@@ -601,19 +601,19 @@ mod test_spline_tool {
let first_spline_node = find_spline(document, spline_layer).expect("Spline node not found in the layer");
let first_vector_data = document.network_interface.compute_modified_vector(spline_layer).expect("Vector data not found for the spline layer");
let first_vector = document.network_interface.compute_modified_vector(spline_layer).expect("Vector not found for the spline layer");
// Verify initial spline has correct number of points and segments
let initial_point_count = first_vector_data.point_domain.ids().len();
let initial_segment_count = first_vector_data.segment_domain.ids().len();
let initial_point_count = first_vector.point_domain.ids().len();
let initial_segment_count = first_vector.segment_domain.ids().len();
assert_eq!(initial_point_count, 3, "Expected 3 points in initial spline, found {}", initial_point_count);
assert_eq!(initial_segment_count, 2, "Expected 2 segments in initial spline, found {}", initial_segment_count);
let layer_to_viewport = document.metadata().transform_to_viewport(spline_layer);
let endpoints: Vec<(PointId, DVec2)> = first_vector_data
let endpoints: Vec<(PointId, DVec2)> = first_vector
.extendable_points(false)
.filter_map(|point_id| first_vector_data.point_domain.position_from_id(point_id).map(|pos| (point_id, layer_to_viewport.transform_point2(pos))))
.filter_map(|point_id| first_vector.point_domain.position_from_id(point_id).map(|pos| (point_id, layer_to_viewport.transform_point2(pos))))
.collect();
assert_eq!(endpoints.len(), 2, "Expected 2 endpoints in the initial spline");
@@ -632,14 +632,14 @@ mod test_spline_tool {
editor.press(Key::Enter, ModifierKeys::empty()).await;
let document = editor.active_document();
let extended_vector_data = document
let extended_vector = document
.network_interface
.compute_modified_vector(spline_layer)
.expect("Vector data not found for the extended spline layer");
.expect("Vector not found for the extended spline layer");
// Verify extended spline has correct number of points and segments
let extended_point_count = extended_vector_data.point_domain.ids().len();
let extended_segment_count = extended_vector_data.segment_domain.ids().len();
let extended_point_count = extended_vector.point_domain.ids().len();
let extended_segment_count = extended_vector.segment_domain.ids().len();
assert_eq!(extended_point_count, 5, "Expected 5 points in extended spline, found {}", extended_point_count);
assert_eq!(extended_segment_count, 4, "Expected 4 segments in extended spline, found {}", extended_segment_count);
@@ -653,7 +653,7 @@ mod test_spline_tool {
let all_expected_points = [initial_points[0], initial_points[1], initial_points[2], continuation_points[0], continuation_points[1]];
assert_point_positions(&extended_vector_data, layer_to_viewport, &all_expected_points, 1e-10);
assert_point_positions(&extended_vector, layer_to_viewport, &all_expected_points, 1e-10);
}
#[tokio::test]
@@ -688,14 +688,14 @@ mod test_spline_tool {
.selected_visible_and_unlocked_layers(network_interface)
.next()
.expect("Should have a selected layer");
let vector_data = network_interface.compute_modified_vector(layer).expect("Should have vector data");
let vector = network_interface.compute_modified_vector(layer).expect("Should have vector data");
let layer_to_viewport = document.metadata().transform_to_viewport(layer);
// Expected points in viewport coordinates
let expected_points = vec![DVec2::new(50., 50.), DVec2::new(100., 50.), DVec2::new(150., 100.)];
// Assert all points are correctly positioned
assert_point_positions(&vector_data, layer_to_viewport, &expected_points, 1e-10);
assert_point_positions(&vector, layer_to_viewport, &expected_points, 1e-10);
}
#[tokio::test]
@@ -728,14 +728,14 @@ mod test_spline_tool {
.selected_visible_and_unlocked_layers(network_interface)
.next()
.expect("Should have a selected layer");
let vector_data = network_interface.compute_modified_vector(layer).expect("Should have vector data");
let vector = network_interface.compute_modified_vector(layer).expect("Should have vector data");
let layer_to_viewport = document.metadata().transform_to_viewport(layer);
// Expected points in viewport coordinates
let expected_points = vec![DVec2::new(50., 50.), DVec2::new(100., 50.), DVec2::new(150., 100.)];
// Assert all points are correctly positioned
assert_point_positions(&vector_data, layer_to_viewport, &expected_points, 1e-10);
assert_point_positions(&vector, layer_to_viewport, &expected_points, 1e-10);
}
#[tokio::test]
@@ -766,14 +766,14 @@ mod test_spline_tool {
.selected_visible_and_unlocked_layers(network_interface)
.next()
.expect("Should have a selected layer");
let vector_data = network_interface.compute_modified_vector(layer).expect("Should have vector data");
let vector = network_interface.compute_modified_vector(layer).expect("Should have vector data");
let layer_to_viewport = document.metadata().transform_to_viewport(layer);
// Expected points in viewport coordinates
let expected_points = vec![DVec2::new(50., 50.), DVec2::new(100., 50.), DVec2::new(150., 100.)];
// Assert all points are correctly positioned
assert_point_positions(&vector_data, layer_to_viewport, &expected_points, 1e-10);
assert_point_positions(&vector, layer_to_viewport, &expected_points, 1e-10);
}
#[tokio::test]
@@ -805,14 +805,14 @@ mod test_spline_tool {
.selected_visible_and_unlocked_layers(network_interface)
.next()
.expect("Should have a selected layer");
let vector_data = network_interface.compute_modified_vector(layer).expect("Should have vector data");
let vector = network_interface.compute_modified_vector(layer).expect("Should have vector data");
let layer_to_viewport = document.metadata().transform_to_viewport(layer);
// Expected points in viewport coordinates
let expected_points = vec![DVec2::new(50., 50.), DVec2::new(100., 50.), DVec2::new(150., 100.)];
// Assert all points are correctly positioned
assert_point_positions(&vector_data, layer_to_viewport, &expected_points, 1e-10);
assert_point_positions(&vector, layer_to_viewport, &expected_points, 1e-10);
}
#[tokio::test]
@@ -845,17 +845,17 @@ mod test_spline_tool {
let spline_layer = layers.next().expect("Failed to find the spline layer");
assert!(find_spline(document, spline_layer).is_some(), "Spline node not found in the layer");
let vector_data = document.network_interface.compute_modified_vector(spline_layer).expect("Vector data not found for the spline layer");
let vector = document.network_interface.compute_modified_vector(spline_layer).expect("Vector not found for the spline layer");
// Verify we have the correct number of points and segments
let point_count = vector_data.point_domain.ids().len();
let segment_count = vector_data.segment_domain.ids().len();
let point_count = vector.point_domain.ids().len();
let segment_count = vector.segment_domain.ids().len();
assert_eq!(point_count, 3, "Expected 3 points in the spline, found {}", point_count);
assert_eq!(segment_count, 2, "Expected 2 segments in the spline, found {}", segment_count);
let layer_to_viewport = document.metadata().transform_to_viewport(spline_layer);
assert_point_positions(&vector_data, layer_to_viewport, &spline_points, 1e-10);
assert_point_positions(&vector, layer_to_viewport, &spline_points, 1e-10);
}
}