Promote vector meshes from experimental by removing it from preferences
This commit is contained in:
parent
e73e524f3d
commit
123108c813
|
|
@ -256,29 +256,6 @@ impl PreferencesDialogMessageHandler {
|
||||||
.widget_instance(),
|
.widget_instance(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let checkbox_id = CheckboxId::new();
|
|
||||||
let vector_mesh_description = "
|
|
||||||
Allow the Pen tool to produce branching geometry, where more than two segments may be connected to one anchor point.\n\
|
|
||||||
\n\
|
|
||||||
Currently, vector meshes do not properly render strokes (branching joins) and fills (multiple regions).
|
|
||||||
"
|
|
||||||
.trim();
|
|
||||||
let vector_meshes = vec![
|
|
||||||
Separator::new(SeparatorType::Unrelated).widget_instance(),
|
|
||||||
Separator::new(SeparatorType::Unrelated).widget_instance(),
|
|
||||||
CheckboxInput::new(preferences.vector_meshes)
|
|
||||||
.tooltip_label("Vector Meshes")
|
|
||||||
.tooltip_description(vector_mesh_description)
|
|
||||||
.on_update(|checkbox_input: &CheckboxInput| PreferencesMessage::VectorMeshes { enabled: checkbox_input.checked }.into())
|
|
||||||
.for_label(checkbox_id)
|
|
||||||
.widget_instance(),
|
|
||||||
TextLabel::new("Vector Meshes")
|
|
||||||
.tooltip_label("Vector Meshes")
|
|
||||||
.tooltip_description(vector_mesh_description)
|
|
||||||
.for_checkbox(checkbox_id)
|
|
||||||
.widget_instance(),
|
|
||||||
];
|
|
||||||
|
|
||||||
let checkbox_id = CheckboxId::new();
|
let checkbox_id = CheckboxId::new();
|
||||||
let brush_tool_description = "
|
let brush_tool_description = "
|
||||||
Enable the Brush tool to support basic raster-based layer painting.\n\
|
Enable the Brush tool to support basic raster-based layer painting.\n\
|
||||||
|
|
@ -304,7 +281,7 @@ impl PreferencesDialogMessageHandler {
|
||||||
.widget_instance(),
|
.widget_instance(),
|
||||||
];
|
];
|
||||||
|
|
||||||
rows.extend_from_slice(&[header, node_graph_wires_label, graph_wire_style, use_vello, vector_meshes, brush_tool]);
|
rows.extend_from_slice(&[header, node_graph_wires_label, graph_wire_style, use_vello, brush_tool]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout(rows.into_iter().map(|r| LayoutGroup::Row { widgets: r }).collect())
|
Layout(rows.into_iter().map(|r| LayoutGroup::Row { widgets: r }).collect())
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use crate::consts::HIDE_HANDLE_DISTANCE;
|
||||||
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
||||||
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
|
use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface;
|
||||||
use crate::messages::tool::common_functionality::shape_editor::{SelectedLayerState, ShapeState};
|
use crate::messages::tool::common_functionality::shape_editor::{SelectedLayerState, ShapeState};
|
||||||
use crate::messages::tool::tool_messages::tool_prelude::{DocumentMessageHandler, PreferencesMessageHandler};
|
use crate::messages::tool::tool_messages::tool_prelude::DocumentMessageHandler;
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use graphene_std::subpath::{Bezier, BezierHandles};
|
use graphene_std::subpath::{Bezier, BezierHandles};
|
||||||
use graphene_std::text::{Font, FontCache, TextAlign, TextContext, TypesettingConfig};
|
use graphene_std::text::{Font, FontCache, TextAlign, TextContext, TypesettingConfig};
|
||||||
|
|
@ -200,7 +200,7 @@ pub fn path_overlays(document: &DocumentMessageHandler, draw_handles: DrawHandle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path_endpoint_overlays(document: &DocumentMessageHandler, shape_editor: &mut ShapeState, overlay_context: &mut OverlayContext, preferences: &PreferencesMessageHandler) {
|
pub fn path_endpoint_overlays(document: &DocumentMessageHandler, shape_editor: &mut ShapeState, overlay_context: &mut OverlayContext) {
|
||||||
if !overlay_context.visibility_settings.anchors() {
|
if !overlay_context.visibility_settings.anchors() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -213,7 +213,7 @@ pub fn path_endpoint_overlays(document: &DocumentMessageHandler, shape_editor: &
|
||||||
let selected = shape_editor.selected_shape_state.get(&layer);
|
let selected = shape_editor.selected_shape_state.get(&layer);
|
||||||
let is_selected = |selected: Option<&SelectedLayerState>, point: ManipulatorPointId| selected.is_some_and(|selected| selected.is_point_selected(point));
|
let is_selected = |selected: Option<&SelectedLayerState>, point: ManipulatorPointId| selected.is_some_and(|selected| selected.is_point_selected(point));
|
||||||
|
|
||||||
for point in vector.extendable_points(preferences.vector_meshes) {
|
for point in vector.extendable_points() {
|
||||||
let Some(position) = vector.point_domain.position_from_id(point) else { continue };
|
let Some(position) = vector.point_domain.position_from_id(point) else { continue };
|
||||||
let position = transform.transform_point2(position);
|
let position = transform.transform_point2(position);
|
||||||
overlay_context.manipulator_anchor(position, is_selected(selected, ManipulatorPointId::Anchor(point)), None);
|
overlay_context.manipulator_anchor(position, is_selected(selected, ManipulatorPointId::Anchor(point)), None);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ pub enum PreferencesMessage {
|
||||||
// Per-preference messages
|
// Per-preference messages
|
||||||
UseVello { use_vello: bool },
|
UseVello { use_vello: bool },
|
||||||
SelectionMode { selection_mode: SelectionMode },
|
SelectionMode { selection_mode: SelectionMode },
|
||||||
VectorMeshes { enabled: bool },
|
|
||||||
BrushTool { enabled: bool },
|
BrushTool { enabled: bool },
|
||||||
ModifyLayout { zoom_with_scroll: bool },
|
ModifyLayout { zoom_with_scroll: bool },
|
||||||
GraphWireStyle { style: GraphWireStyle },
|
GraphWireStyle { style: GraphWireStyle },
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ pub struct PreferencesMessageHandler {
|
||||||
pub selection_mode: SelectionMode,
|
pub selection_mode: SelectionMode,
|
||||||
pub zoom_with_scroll: bool,
|
pub zoom_with_scroll: bool,
|
||||||
pub use_vello: bool,
|
pub use_vello: bool,
|
||||||
pub vector_meshes: bool,
|
|
||||||
pub brush_tool: bool,
|
pub brush_tool: bool,
|
||||||
pub graph_wire_style: GraphWireStyle,
|
pub graph_wire_style: GraphWireStyle,
|
||||||
pub viewport_zoom_wheel_rate: f64,
|
pub viewport_zoom_wheel_rate: f64,
|
||||||
|
|
@ -46,7 +45,6 @@ impl Default for PreferencesMessageHandler {
|
||||||
selection_mode: SelectionMode::Touched,
|
selection_mode: SelectionMode::Touched,
|
||||||
zoom_with_scroll: matches!(MappingVariant::default(), MappingVariant::ZoomWithScroll),
|
zoom_with_scroll: matches!(MappingVariant::default(), MappingVariant::ZoomWithScroll),
|
||||||
use_vello: EditorPreferences::default().use_vello,
|
use_vello: EditorPreferences::default().use_vello,
|
||||||
vector_meshes: false,
|
|
||||||
brush_tool: false,
|
brush_tool: false,
|
||||||
graph_wire_style: GraphWireStyle::default(),
|
graph_wire_style: GraphWireStyle::default(),
|
||||||
viewport_zoom_wheel_rate: VIEWPORT_ZOOM_WHEEL_RATE,
|
viewport_zoom_wheel_rate: VIEWPORT_ZOOM_WHEEL_RATE,
|
||||||
|
|
@ -87,9 +85,6 @@ impl MessageHandler<PreferencesMessage, PreferencesMessageContext<'_>> for Prefe
|
||||||
responses.add(PortfolioMessage::UpdateVelloPreference);
|
responses.add(PortfolioMessage::UpdateVelloPreference);
|
||||||
responses.add(PortfolioMessage::EditorPreferences);
|
responses.add(PortfolioMessage::EditorPreferences);
|
||||||
}
|
}
|
||||||
PreferencesMessage::VectorMeshes { enabled } => {
|
|
||||||
self.vector_meshes = enabled;
|
|
||||||
}
|
|
||||||
PreferencesMessage::BrushTool { enabled } => {
|
PreferencesMessage::BrushTool { enabled } => {
|
||||||
self.brush_tool = enabled;
|
self.brush_tool = enabled;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -421,7 +421,7 @@ impl ShapeState {
|
||||||
(point.as_handle().is_some() && self.ignore_handles) || (point.as_anchor().is_some() && self.ignore_anchors)
|
(point.as_handle().is_some() && self.ignore_handles) || (point.as_anchor().is_some() && self.ignore_anchors)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close_selected_path(&self, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>, vector_meshes: bool) {
|
pub fn close_selected_path(&self, document: &DocumentMessageHandler, responses: &mut VecDeque<Message>) {
|
||||||
// First collect all selected anchor points across all layers
|
// First collect all selected anchor points across all layers
|
||||||
let all_selected_points: Vec<(LayerNodeIdentifier, PointId)> = self
|
let all_selected_points: Vec<(LayerNodeIdentifier, PointId)> = self
|
||||||
.selected_shape_state
|
.selected_shape_state
|
||||||
|
|
@ -446,14 +446,6 @@ impl ShapeState {
|
||||||
let (layer1, start_point) = all_selected_points[0];
|
let (layer1, start_point) = all_selected_points[0];
|
||||||
let (layer2, end_point) = all_selected_points[1];
|
let (layer2, end_point) = all_selected_points[1];
|
||||||
|
|
||||||
let Some(vector1) = document.network_interface.compute_modified_vector(layer1) else { return };
|
|
||||||
let Some(vector2) = document.network_interface.compute_modified_vector(layer2) else { return };
|
|
||||||
|
|
||||||
// If vector meshes is not selected then only for endpoints, otherwise normally applicable
|
|
||||||
if !vector_meshes && (vector1.all_connected(start_point).count() != 1 || vector2.all_connected(end_point).count() != 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if layer1 == layer2 {
|
if layer1 == layer2 {
|
||||||
if start_point == end_point {
|
if start_point == end_point {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,8 @@ use graphene_std::vector::{HandleExt, PointId, SegmentId, Vector, VectorModifica
|
||||||
use kurbo::{CubicBez, DEFAULT_ACCURACY, Line, ParamCurve, PathSeg, Point, QuadBez, Shape};
|
use kurbo::{CubicBez, DEFAULT_ACCURACY, Line, ParamCurve, PathSeg, Point, QuadBez, Shape};
|
||||||
|
|
||||||
/// Determines if a path should be extended. Goal in viewport space. Returns the path and if it is extending from the start, if applicable.
|
/// Determines if a path should be extended. Goal in viewport space. Returns the path and if it is extending from the start, if applicable.
|
||||||
pub fn should_extend(
|
pub fn should_extend(document: &DocumentMessageHandler, goal: DVec2, tolerance: f64, layers: impl Iterator<Item = LayerNodeIdentifier>) -> Option<(LayerNodeIdentifier, PointId, DVec2)> {
|
||||||
document: &DocumentMessageHandler,
|
closest_point(document, goal, tolerance, layers, |_| false)
|
||||||
goal: DVec2,
|
|
||||||
tolerance: f64,
|
|
||||||
layers: impl Iterator<Item = LayerNodeIdentifier>,
|
|
||||||
preferences: &PreferencesMessageHandler,
|
|
||||||
) -> Option<(LayerNodeIdentifier, PointId, DVec2)> {
|
|
||||||
closest_point(document, goal, tolerance, layers, |_| false, preferences)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine the closest point to the goal point under max_distance.
|
/// Determine the closest point to the goal point under max_distance.
|
||||||
|
|
@ -40,7 +34,6 @@ pub fn closest_point<T>(
|
||||||
max_distance: f64,
|
max_distance: f64,
|
||||||
layers: impl Iterator<Item = LayerNodeIdentifier>,
|
layers: impl Iterator<Item = LayerNodeIdentifier>,
|
||||||
exclude: T,
|
exclude: T,
|
||||||
preferences: &PreferencesMessageHandler,
|
|
||||||
) -> Option<(LayerNodeIdentifier, PointId, DVec2)>
|
) -> Option<(LayerNodeIdentifier, PointId, DVec2)>
|
||||||
where
|
where
|
||||||
T: Fn(PointId) -> bool,
|
T: Fn(PointId) -> bool,
|
||||||
|
|
@ -50,7 +43,7 @@ where
|
||||||
for layer in layers {
|
for layer in layers {
|
||||||
let viewspace = document.metadata().transform_to_viewport(layer);
|
let viewspace = document.metadata().transform_to_viewport(layer);
|
||||||
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { continue };
|
let Some(vector) = document.network_interface.compute_modified_vector(layer) else { continue };
|
||||||
for id in vector.extendable_points(preferences.vector_meshes) {
|
for id in vector.extendable_points() {
|
||||||
if exclude(id) {
|
if exclude(id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -236,7 +236,6 @@ impl Fsm for FreehandToolFsmState {
|
||||||
global_tool_data,
|
global_tool_data,
|
||||||
input,
|
input,
|
||||||
shape_editor,
|
shape_editor,
|
||||||
preferences,
|
|
||||||
viewport,
|
viewport,
|
||||||
..
|
..
|
||||||
} = tool_action_data;
|
} = tool_action_data;
|
||||||
|
|
@ -244,7 +243,7 @@ impl Fsm for FreehandToolFsmState {
|
||||||
let ToolMessage::Freehand(event) = event else { return self };
|
let ToolMessage::Freehand(event) = event else { return self };
|
||||||
match (self, event) {
|
match (self, event) {
|
||||||
(_, FreehandToolMessage::Overlays { context: mut overlay_context }) => {
|
(_, FreehandToolMessage::Overlays { context: mut overlay_context }) => {
|
||||||
path_endpoint_overlays(document, shape_editor, &mut overlay_context, tool_action_data.preferences);
|
path_endpoint_overlays(document, shape_editor, &mut overlay_context);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
@ -258,7 +257,7 @@ impl Fsm for FreehandToolFsmState {
|
||||||
// Extend an endpoint of the selected path
|
// Extend an endpoint of the selected path
|
||||||
let selected_nodes = document.network_interface.selected_nodes();
|
let selected_nodes = document.network_interface.selected_nodes();
|
||||||
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
||||||
if let Some((layer, point, position)) = should_extend(document, input.mouse.position, tolerance, selected_nodes.selected_layers(document.metadata()), preferences) {
|
if let Some((layer, point, position)) = should_extend(document, input.mouse.position, tolerance, selected_nodes.selected_layers(document.metadata())) {
|
||||||
tool_data.layer = Some(layer);
|
tool_data.layer = Some(layer);
|
||||||
tool_data.end_point = Some((position, point));
|
tool_data.end_point = Some((position, point));
|
||||||
|
|
||||||
|
|
@ -519,7 +518,7 @@ mod test_freehand {
|
||||||
initial_segment_count
|
initial_segment_count
|
||||||
);
|
);
|
||||||
|
|
||||||
let extendable_points = initial_vector.extendable_points(false).collect::<Vec<_>>();
|
let extendable_points = initial_vector.extendable_points().collect::<Vec<_>>();
|
||||||
assert!(!extendable_points.is_empty(), "No extendable points found in the path");
|
assert!(!extendable_points.is_empty(), "No extendable points found in the path");
|
||||||
|
|
||||||
let endpoint_id = extendable_points[0];
|
let endpoint_id = extendable_points[0];
|
||||||
|
|
|
||||||
|
|
@ -823,7 +823,7 @@ impl PathToolData {
|
||||||
.filter(|handle| handle.length(&vector) < 1e-6)
|
.filter(|handle| handle.length(&vector) < 1e-6)
|
||||||
.map(|handle| handle.to_manipulator_point())
|
.map(|handle| handle.to_manipulator_point())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let endpoint = vector.extendable_points(false).any(|anchor| point == anchor);
|
let endpoint = vector.extendable_points_no_vector_meshes().any(|anchor| point == anchor);
|
||||||
|
|
||||||
if drag_zero_handle && (handles.len() == 1 && !endpoint) {
|
if drag_zero_handle && (handles.len() == 1 && !endpoint) {
|
||||||
shape_editor.deselect_all_points();
|
shape_editor.deselect_all_points();
|
||||||
|
|
@ -2662,7 +2662,7 @@ impl Fsm for PathToolFsmState {
|
||||||
}
|
}
|
||||||
(_, PathToolMessage::ClosePath) => {
|
(_, PathToolMessage::ClosePath) => {
|
||||||
responses.add(DocumentMessage::AddTransaction);
|
responses.add(DocumentMessage::AddTransaction);
|
||||||
shape_editor.close_selected_path(document, responses, tool_action_data.preferences.vector_meshes);
|
shape_editor.close_selected_path(document, responses);
|
||||||
responses.add(DocumentMessage::EndTransaction);
|
responses.add(DocumentMessage::EndTransaction);
|
||||||
|
|
||||||
responses.add(OverlaysMessage::Draw);
|
responses.add(OverlaysMessage::Draw);
|
||||||
|
|
|
||||||
|
|
@ -589,15 +589,7 @@ impl PenToolData {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the user places the anchor on top of the previous anchor, it becomes sharp and the outgoing handle may be dragged.
|
/// If the user places the anchor on top of the previous anchor, it becomes sharp and the outgoing handle may be dragged.
|
||||||
fn bend_from_previous_point(
|
fn bend_from_previous_point(&mut self, snap_data: SnapData, transform: DAffine2, layer: LayerNodeIdentifier, shape_editor: &mut ShapeState, responses: &mut VecDeque<Message>) {
|
||||||
&mut self,
|
|
||||||
snap_data: SnapData,
|
|
||||||
transform: DAffine2,
|
|
||||||
layer: LayerNodeIdentifier,
|
|
||||||
preferences: &PreferencesMessageHandler,
|
|
||||||
shape_editor: &mut ShapeState,
|
|
||||||
responses: &mut VecDeque<Message>,
|
|
||||||
) {
|
|
||||||
self.g1_continuous = true;
|
self.g1_continuous = true;
|
||||||
let document = snap_data.document;
|
let document = snap_data.document;
|
||||||
self.next_handle_start = self.next_point;
|
self.next_handle_start = self.next_point;
|
||||||
|
|
@ -614,7 +606,7 @@ impl PenToolData {
|
||||||
self.handle_end = None;
|
self.handle_end = None;
|
||||||
self.handle_mode = HandleMode::Free;
|
self.handle_mode = HandleMode::Free;
|
||||||
|
|
||||||
self.store_clicked_endpoint(document, &transform, snap_data.input, snap_data.viewport, preferences);
|
self.store_clicked_endpoint(document, &transform, snap_data.input, snap_data.viewport);
|
||||||
|
|
||||||
if self.modifiers.lock_angle {
|
if self.modifiers.lock_angle {
|
||||||
self.set_lock_angle(&vector, id, self.prior_segment);
|
self.set_lock_angle(&vector, id, self.prior_segment);
|
||||||
|
|
@ -631,8 +623,8 @@ impl PenToolData {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Closing path
|
// Closing path
|
||||||
let closing_path_on_point = self.close_path_on_point(snap_data, &vector, document, preferences, id, &transform);
|
let closing_path_on_point = self.close_path_on_point(snap_data, &vector, document, id, &transform);
|
||||||
if !closing_path_on_point && preferences.vector_meshes {
|
if !closing_path_on_point {
|
||||||
// Attempt to find nearest segment and close path on segment by creating an anchor point on it
|
// Attempt to find nearest segment and close path on segment by creating an anchor point on it
|
||||||
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
||||||
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, transform.transform_point2(self.next_point), tolerance) {
|
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, transform.transform_point2(self.next_point), tolerance) {
|
||||||
|
|
@ -659,8 +651,8 @@ impl PenToolData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close_path_on_point(&mut self, snap_data: SnapData, vector: &Vector, document: &DocumentMessageHandler, preferences: &PreferencesMessageHandler, id: PointId, transform: &DAffine2) -> bool {
|
fn close_path_on_point(&mut self, snap_data: SnapData, vector: &Vector, document: &DocumentMessageHandler, id: PointId, transform: &DAffine2) -> bool {
|
||||||
for id in vector.extendable_points(preferences.vector_meshes).filter(|&point| point != id) {
|
for id in vector.extendable_points().filter(|&point| point != id) {
|
||||||
let Some(pos) = vector.point_domain.position_from_id(id) else { continue };
|
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 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);
|
let snap_point_tolerance_squared = crate::consts::SNAP_POINT_TOLERANCE.powi(2);
|
||||||
|
|
@ -670,7 +662,7 @@ impl PenToolData {
|
||||||
self.handle_end_offset = None;
|
self.handle_end_offset = None;
|
||||||
self.path_closed = true;
|
self.path_closed = true;
|
||||||
self.next_handle_start = self.next_point;
|
self.next_handle_start = self.next_point;
|
||||||
self.store_clicked_endpoint(document, transform, snap_data.input, snap_data.viewport, preferences);
|
self.store_clicked_endpoint(document, transform, snap_data.input, snap_data.viewport);
|
||||||
self.handle_mode = HandleMode::Free;
|
self.handle_mode = HandleMode::Free;
|
||||||
if let (true, Some(prior_endpoint)) = (self.modifiers.lock_angle, self.prior_segment_endpoint) {
|
if let (true, Some(prior_endpoint)) = (self.modifiers.lock_angle, self.prior_segment_endpoint) {
|
||||||
self.set_lock_angle(vector, prior_endpoint, self.prior_segment);
|
self.set_lock_angle(vector, prior_endpoint, self.prior_segment);
|
||||||
|
|
@ -682,7 +674,7 @@ impl PenToolData {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish_placing_handle(&mut self, snap_data: SnapData, transform: DAffine2, preferences: &PreferencesMessageHandler, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
|
fn finish_placing_handle(&mut self, snap_data: SnapData, transform: DAffine2, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
|
||||||
let document = snap_data.document;
|
let document = snap_data.document;
|
||||||
let next_handle_start = self.next_handle_start;
|
let next_handle_start = self.next_handle_start;
|
||||||
let handle_start = self.latest_point()?.handle_start;
|
let handle_start = self.latest_point()?.handle_start;
|
||||||
|
|
@ -693,12 +685,12 @@ impl PenToolData {
|
||||||
let Some(handle_end) = self.handle_end else {
|
let Some(handle_end) = self.handle_end else {
|
||||||
responses.add(DocumentMessage::EndTransaction);
|
responses.add(DocumentMessage::EndTransaction);
|
||||||
self.handle_end = Some(next_handle_start);
|
self.handle_end = Some(next_handle_start);
|
||||||
self.place_anchor(snap_data, transform, mouse, preferences, responses);
|
self.place_anchor(snap_data, transform, mouse, responses);
|
||||||
self.latest_point_mut()?.handle_start = next_handle_start;
|
self.latest_point_mut()?.handle_start = next_handle_start;
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let next_point = self.next_point;
|
let next_point = self.next_point;
|
||||||
self.place_anchor(snap_data, transform, mouse, preferences, responses);
|
self.place_anchor(snap_data, transform, mouse, responses);
|
||||||
let handles = [handle_start - self.latest_point()?.pos, handle_end - next_point].map(Some);
|
let handles = [handle_start - self.latest_point()?.pos, handle_end - next_point].map(Some);
|
||||||
|
|
||||||
// Get close path
|
// Get close path
|
||||||
|
|
@ -709,7 +701,7 @@ impl PenToolData {
|
||||||
let vector = document.network_interface.compute_modified_vector(layer)?;
|
let vector = document.network_interface.compute_modified_vector(layer)?;
|
||||||
let start = self.latest_point()?.id;
|
let start = self.latest_point()?.id;
|
||||||
let transform = document.metadata().document_to_viewport * transform;
|
let transform = document.metadata().document_to_viewport * transform;
|
||||||
for id in vector.extendable_points(preferences.vector_meshes).filter(|&point| point != start) {
|
for id in vector.extendable_points().filter(|&point| point != start) {
|
||||||
let Some(pos) = vector.point_domain.position_from_id(id) else { continue };
|
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 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);
|
let snap_point_tolerance_squared = crate::consts::SNAP_POINT_TOLERANCE.powi(2);
|
||||||
|
|
@ -1123,7 +1115,7 @@ impl PenToolData {
|
||||||
self.update_target_handle_pos(opposite_handle, self.next_point, responses, new_handle_position, layer);
|
self.update_target_handle_pos(opposite_handle, self.next_point, responses, new_handle_position, layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn place_anchor(&mut self, snap_data: SnapData, transform: DAffine2, mouse: DVec2, preferences: &PreferencesMessageHandler, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
|
fn place_anchor(&mut self, snap_data: SnapData, transform: DAffine2, mouse: DVec2, responses: &mut VecDeque<Message>) -> Option<PenToolFsmState> {
|
||||||
let document = snap_data.document;
|
let document = snap_data.document;
|
||||||
|
|
||||||
let relative = if self.path_closed { None } else { self.latest_point().map(|point| point.pos) };
|
let relative = if self.path_closed { None } else { self.latest_point().map(|point| point.pos) };
|
||||||
|
|
@ -1134,7 +1126,7 @@ impl PenToolData {
|
||||||
let layer = selected_layers.next().filter(|_| selected_layers.next().is_none()).or(self.current_layer)?;
|
let layer = selected_layers.next().filter(|_| selected_layers.next().is_none()).or(self.current_layer)?;
|
||||||
let vector = document.network_interface.compute_modified_vector(layer)?;
|
let vector = document.network_interface.compute_modified_vector(layer)?;
|
||||||
let transform = document.metadata().document_to_viewport * transform;
|
let transform = document.metadata().document_to_viewport * transform;
|
||||||
for point in vector.extendable_points(preferences.vector_meshes) {
|
for point in vector.extendable_points() {
|
||||||
let Some(pos) = vector.point_domain.position_from_id(point) else { continue };
|
let Some(pos) = vector.point_domain.position_from_id(point) else { continue };
|
||||||
let transformed_distance_between_squared = transform.transform_point2(pos).distance_squared(transform.transform_point2(self.next_point));
|
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);
|
let snap_point_tolerance_squared = crate::consts::SNAP_POINT_TOLERANCE.powi(2);
|
||||||
|
|
@ -1230,7 +1222,6 @@ impl PenToolData {
|
||||||
responses: &mut VecDeque<Message>,
|
responses: &mut VecDeque<Message>,
|
||||||
tool_options: &PenOptions,
|
tool_options: &PenOptions,
|
||||||
append: bool,
|
append: bool,
|
||||||
preferences: &PreferencesMessageHandler,
|
|
||||||
shape_editor: &mut ShapeState,
|
shape_editor: &mut ShapeState,
|
||||||
) {
|
) {
|
||||||
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
||||||
|
|
@ -1242,14 +1233,12 @@ impl PenToolData {
|
||||||
self.handle_end = None;
|
self.handle_end = None;
|
||||||
|
|
||||||
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
||||||
let extension_choice = should_extend(document, viewport_vec, tolerance, selected_nodes.selected_layers(document.metadata()), preferences);
|
let extension_choice = should_extend(document, viewport_vec, tolerance, selected_nodes.selected_layers(document.metadata()));
|
||||||
if let Some((layer, point, position)) = extension_choice {
|
if let Some((layer, point, position)) = extension_choice {
|
||||||
self.current_layer = Some(layer);
|
self.current_layer = Some(layer);
|
||||||
self.extend_existing_path(document, layer, point, position);
|
self.extend_existing_path(document, layer, point, position);
|
||||||
return;
|
return;
|
||||||
} else if preferences.vector_meshes
|
} else if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport_vec, tolerance) {
|
||||||
&& let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport_vec, tolerance)
|
|
||||||
{
|
|
||||||
let (point, segments) = closest_segment.adjusted_insert(responses);
|
let (point, segments) = closest_segment.adjusted_insert(responses);
|
||||||
let layer = closest_segment.layer();
|
let layer = closest_segment.layer();
|
||||||
let position = closest_segment.closest_point_document();
|
let position = closest_segment.closest_point_document();
|
||||||
|
|
@ -1264,7 +1253,7 @@ impl PenToolData {
|
||||||
}
|
}
|
||||||
|
|
||||||
if append {
|
if append {
|
||||||
if let Some((layer, point, _)) = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false, preferences) {
|
if let Some((layer, point, _)) = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false) {
|
||||||
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
|
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
|
||||||
let segment = vector.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
|
let segment = vector.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
|
||||||
|
|
||||||
|
|
@ -1282,7 +1271,7 @@ impl PenToolData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((layer, point, _position)) = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false, preferences) {
|
if let Some((layer, point, _position)) = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false) {
|
||||||
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
|
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
|
||||||
let segment = vector.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
|
let segment = vector.all_connected(point).collect::<Vec<_>>().first().map(|s| s.segment);
|
||||||
self.handle_mode = HandleMode::Free;
|
self.handle_mode = HandleMode::Free;
|
||||||
|
|
@ -1366,14 +1355,7 @@ impl PenToolData {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stores the segment and point ID of the clicked endpoint
|
// Stores the segment and point ID of the clicked endpoint
|
||||||
fn store_clicked_endpoint(
|
fn store_clicked_endpoint(&mut self, document: &DocumentMessageHandler, transform: &DAffine2, input: &InputPreprocessorMessageHandler, viewport: &ViewportMessageHandler) {
|
||||||
&mut self,
|
|
||||||
document: &DocumentMessageHandler,
|
|
||||||
transform: &DAffine2,
|
|
||||||
input: &InputPreprocessorMessageHandler,
|
|
||||||
viewport: &ViewportMessageHandler,
|
|
||||||
preferences: &PreferencesMessageHandler,
|
|
||||||
) {
|
|
||||||
let mut manipulators = HashMap::with_hasher(NoHashBuilder);
|
let mut manipulators = HashMap::with_hasher(NoHashBuilder);
|
||||||
let mut unselected = Vec::new();
|
let mut unselected = Vec::new();
|
||||||
let mut layer_manipulators = HashSet::with_hasher(NoHashBuilder);
|
let mut layer_manipulators = HashSet::with_hasher(NoHashBuilder);
|
||||||
|
|
@ -1389,7 +1371,7 @@ impl PenToolData {
|
||||||
self.prior_segment_layer = None;
|
self.prior_segment_layer = None;
|
||||||
self.prior_segments = None;
|
self.prior_segments = None;
|
||||||
|
|
||||||
if let Some((layer, point, _position)) = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false, preferences) {
|
if let Some((layer, point, _position)) = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false) {
|
||||||
self.prior_segment_endpoint = Some(point);
|
self.prior_segment_endpoint = Some(point);
|
||||||
self.prior_segment_layer = Some(layer);
|
self.prior_segment_layer = Some(layer);
|
||||||
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
|
let vector = document.network_interface.compute_modified_vector(layer).unwrap();
|
||||||
|
|
@ -1468,7 +1450,6 @@ impl Fsm for PenToolFsmState {
|
||||||
global_tool_data,
|
global_tool_data,
|
||||||
input,
|
input,
|
||||||
shape_editor,
|
shape_editor,
|
||||||
preferences,
|
|
||||||
viewport,
|
viewport,
|
||||||
..
|
..
|
||||||
} = tool_action_data;
|
} = tool_action_data;
|
||||||
|
|
@ -1630,11 +1611,8 @@ impl Fsm for PenToolFsmState {
|
||||||
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
||||||
let viewport_vec = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
let viewport_vec = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||||
|
|
||||||
let close_to_point = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false, preferences).is_some();
|
let close_to_point = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false).is_some();
|
||||||
if preferences.vector_meshes
|
if !close_to_point && let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport_vec, tolerance) {
|
||||||
&& !close_to_point
|
|
||||||
&& let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport_vec, tolerance)
|
|
||||||
{
|
|
||||||
let pos = closest_segment.closest_point_to_viewport();
|
let pos = closest_segment.closest_point_to_viewport();
|
||||||
let perp = closest_segment.calculate_perp(document);
|
let perp = closest_segment.calculate_perp(document);
|
||||||
overlay_context.manipulator_anchor(pos, true, None);
|
overlay_context.manipulator_anchor(pos, true, None);
|
||||||
|
|
@ -1689,10 +1667,8 @@ impl Fsm for PenToolFsmState {
|
||||||
}
|
}
|
||||||
// If a vector mesh then there can be more than one prior segments
|
// If a vector mesh then there can be more than one prior segments
|
||||||
else if let Some(segments) = tool_data.prior_segments.clone() {
|
else if let Some(segments) = tool_data.prior_segments.clone() {
|
||||||
if preferences.vector_meshes {
|
let selected_anchors_data = HashMap::from([(layer, segments)]);
|
||||||
let selected_anchors_data = HashMap::from([(layer, segments)]);
|
path_overlays(document, DrawHandles::SelectedAnchors(selected_anchors_data), shape_editor, &mut overlay_context);
|
||||||
path_overlays(document, DrawHandles::SelectedAnchors(selected_anchors_data), shape_editor, &mut overlay_context);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
path_overlays(document, DrawHandles::None, shape_editor, &mut overlay_context);
|
path_overlays(document, DrawHandles::None, shape_editor, &mut overlay_context);
|
||||||
};
|
};
|
||||||
|
|
@ -1755,12 +1731,12 @@ impl Fsm for PenToolFsmState {
|
||||||
overlay_context.manipulator_anchor(next_anchor, false, None);
|
overlay_context.manipulator_anchor(next_anchor, false, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self == PenToolFsmState::PlacingAnchor && preferences.vector_meshes {
|
if self == PenToolFsmState::PlacingAnchor {
|
||||||
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
let tolerance = crate::consts::SNAP_POINT_TOLERANCE;
|
||||||
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
let point = SnapCandidatePoint::handle(document.metadata().document_to_viewport.inverse().transform_point2(input.mouse.position));
|
||||||
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
||||||
let viewport = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
let viewport = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||||
let close_to_point = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false, preferences).is_some();
|
let close_to_point = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false).is_some();
|
||||||
if !close_to_point && let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport, tolerance) {
|
if !close_to_point && let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport, tolerance) {
|
||||||
let pos = closest_segment.closest_point_to_viewport();
|
let pos = closest_segment.closest_point_to_viewport();
|
||||||
let perp = closest_segment.calculate_perp(document);
|
let perp = closest_segment.calculate_perp(document);
|
||||||
|
|
@ -1779,7 +1755,7 @@ impl Fsm for PenToolFsmState {
|
||||||
if let Some(layer) = layer
|
if let Some(layer) = layer
|
||||||
&& let Some(mut vector) = document.network_interface.compute_modified_vector(layer)
|
&& let Some(mut vector) = document.network_interface.compute_modified_vector(layer)
|
||||||
{
|
{
|
||||||
let closest_point = vector.extendable_points(preferences.vector_meshes).filter(|&id| id != start).find(|&id| {
|
let closest_point = vector.extendable_points().filter(|&id| id != start).find(|&id| {
|
||||||
vector.point_domain.position_from_id(id).is_some_and(|pos| {
|
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));
|
let dist_sq = transform.transform_point2(pos).distance_squared(transform.transform_point2(next_point));
|
||||||
dist_sq < crate::consts::SNAP_POINT_TOLERANCE.powi(2)
|
dist_sq < crate::consts::SNAP_POINT_TOLERANCE.powi(2)
|
||||||
|
|
@ -1835,8 +1811,8 @@ impl Fsm for PenToolFsmState {
|
||||||
// Get the closest point and the segment it is on
|
// Get the closest point and the segment it is on
|
||||||
let append = input.keyboard.key(append_to_selected);
|
let append = input.keyboard.key(append_to_selected);
|
||||||
|
|
||||||
tool_data.store_clicked_endpoint(document, &transform, input, viewport, preferences);
|
tool_data.store_clicked_endpoint(document, &transform, input, viewport);
|
||||||
tool_data.create_initial_point(document, input, viewport, responses, tool_options, append, preferences, shape_editor);
|
tool_data.create_initial_point(document, input, viewport, responses, tool_options, append, shape_editor);
|
||||||
|
|
||||||
// Enter the dragging handle state while the mouse is held down, allowing the user to move the mouse and position the handle
|
// Enter the dragging handle state while the mouse is held down, allowing the user to move the mouse and position the handle
|
||||||
PenToolFsmState::DraggingHandle(tool_data.handle_mode)
|
PenToolFsmState::DraggingHandle(tool_data.handle_mode)
|
||||||
|
|
@ -1860,8 +1836,8 @@ impl Fsm for PenToolFsmState {
|
||||||
if let Some(layer) = layer {
|
if let Some(layer) = layer {
|
||||||
tool_data.buffering_merged_vector = false;
|
tool_data.buffering_merged_vector = false;
|
||||||
tool_data.handle_mode = HandleMode::ColinearLocked;
|
tool_data.handle_mode = HandleMode::ColinearLocked;
|
||||||
tool_data.bend_from_previous_point(SnapData::new(document, input, viewport), transform, layer, preferences, shape_editor, responses);
|
tool_data.bend_from_previous_point(SnapData::new(document, input, viewport), transform, layer, shape_editor, responses);
|
||||||
tool_data.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, preferences, responses);
|
tool_data.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, responses);
|
||||||
}
|
}
|
||||||
tool_data.buffering_merged_vector = false;
|
tool_data.buffering_merged_vector = false;
|
||||||
PenToolFsmState::DraggingHandle(tool_data.handle_mode)
|
PenToolFsmState::DraggingHandle(tool_data.handle_mode)
|
||||||
|
|
@ -1876,7 +1852,7 @@ impl Fsm for PenToolFsmState {
|
||||||
let layers = LayerNodeIdentifier::ROOT_PARENT
|
let layers = LayerNodeIdentifier::ROOT_PARENT
|
||||||
.descendants(document.metadata())
|
.descendants(document.metadata())
|
||||||
.filter(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[]));
|
.filter(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[]));
|
||||||
if let Some((other_layer, _, _)) = should_extend(document, viewport_vec, crate::consts::SNAP_POINT_TOLERANCE, layers, preferences) {
|
if let Some((other_layer, _, _)) = should_extend(document, viewport_vec, crate::consts::SNAP_POINT_TOLERANCE, layers) {
|
||||||
let selected_nodes = document.network_interface.selected_nodes();
|
let selected_nodes = document.network_interface.selected_nodes();
|
||||||
let mut selected_layers = selected_nodes.selected_layers(document.metadata());
|
let mut selected_layers = selected_nodes.selected_layers(document.metadata());
|
||||||
if let Some(current_layer) = selected_layers
|
if let Some(current_layer) = selected_layers
|
||||||
|
|
@ -1906,7 +1882,7 @@ impl Fsm for PenToolFsmState {
|
||||||
(PenToolFsmState::DraggingHandle(_), PenToolMessage::DragStop) => {
|
(PenToolFsmState::DraggingHandle(_), PenToolMessage::DragStop) => {
|
||||||
tool_data.cleanup_target_selections(shape_editor, layer, document, responses);
|
tool_data.cleanup_target_selections(shape_editor, layer, document, responses);
|
||||||
tool_data
|
tool_data
|
||||||
.finish_placing_handle(SnapData::new(document, input, viewport), transform, preferences, responses)
|
.finish_placing_handle(SnapData::new(document, input, viewport), transform, responses)
|
||||||
.unwrap_or(PenToolFsmState::PlacingAnchor)
|
.unwrap_or(PenToolFsmState::PlacingAnchor)
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
|
|
@ -2025,7 +2001,7 @@ impl Fsm for PenToolFsmState {
|
||||||
move_anchor_with_handles: input.keyboard.key(move_anchor_with_handles),
|
move_anchor_with_handles: input.keyboard.key(move_anchor_with_handles),
|
||||||
};
|
};
|
||||||
let state = tool_data
|
let state = tool_data
|
||||||
.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, preferences, responses)
|
.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, responses)
|
||||||
.unwrap_or(PenToolFsmState::Ready);
|
.unwrap_or(PenToolFsmState::Ready);
|
||||||
|
|
||||||
// Auto-panning
|
// Auto-panning
|
||||||
|
|
@ -2132,7 +2108,7 @@ impl Fsm for PenToolFsmState {
|
||||||
// Confirm to end path
|
// Confirm to end path
|
||||||
if let Some((vector, layer)) = layer.and_then(|layer| document.network_interface.compute_modified_vector(layer)).zip(layer) {
|
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;
|
let single_point_in_layer = vector.point_domain.ids().len() == 1;
|
||||||
tool_data.finish_placing_handle(SnapData::new(document, input, viewport), transform, preferences, responses);
|
tool_data.finish_placing_handle(SnapData::new(document, input, viewport), transform, responses);
|
||||||
let latest_points = tool_data.latest_points.len() == 1;
|
let latest_points = tool_data.latest_points.len() == 1;
|
||||||
|
|
||||||
if latest_points && single_point_in_layer {
|
if latest_points && single_point_in_layer {
|
||||||
|
|
@ -2179,7 +2155,7 @@ impl Fsm for PenToolFsmState {
|
||||||
PenToolFsmState::Ready
|
PenToolFsmState::Ready
|
||||||
} else {
|
} else {
|
||||||
tool_data
|
tool_data
|
||||||
.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, preferences, responses)
|
.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, responses)
|
||||||
.unwrap_or(PenToolFsmState::Ready)
|
.unwrap_or(PenToolFsmState::Ready)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2210,7 +2186,7 @@ impl Fsm for PenToolFsmState {
|
||||||
if tool_data.point_index > 0 {
|
if tool_data.point_index > 0 {
|
||||||
tool_data.point_index -= 1;
|
tool_data.point_index -= 1;
|
||||||
tool_data
|
tool_data
|
||||||
.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, preferences, responses)
|
.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, responses)
|
||||||
.unwrap_or(PenToolFsmState::PlacingAnchor)
|
.unwrap_or(PenToolFsmState::PlacingAnchor)
|
||||||
} else {
|
} else {
|
||||||
responses.add(PenToolMessage::Abort);
|
responses.add(PenToolMessage::Abort);
|
||||||
|
|
@ -2219,7 +2195,7 @@ impl Fsm for PenToolFsmState {
|
||||||
}
|
}
|
||||||
(_, PenToolMessage::Redo) => {
|
(_, PenToolMessage::Redo) => {
|
||||||
tool_data.point_index = (tool_data.point_index + 1).min(tool_data.latest_points.len().saturating_sub(1));
|
tool_data.point_index = (tool_data.point_index + 1).min(tool_data.latest_points.len().saturating_sub(1));
|
||||||
tool_data.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, preferences, responses);
|
tool_data.place_anchor(SnapData::new(document, input, viewport), transform, input.mouse.position, responses);
|
||||||
match tool_data.point_index {
|
match tool_data.point_index {
|
||||||
0 => PenToolFsmState::Ready,
|
0 => PenToolFsmState::Ready,
|
||||||
_ => PenToolFsmState::PlacingAnchor,
|
_ => PenToolFsmState::PlacingAnchor,
|
||||||
|
|
|
||||||
|
|
@ -556,7 +556,6 @@ impl Fsm for ShapeToolFsmState {
|
||||||
document,
|
document,
|
||||||
global_tool_data,
|
global_tool_data,
|
||||||
input,
|
input,
|
||||||
preferences,
|
|
||||||
shape_editor,
|
shape_editor,
|
||||||
viewport,
|
viewport,
|
||||||
..
|
..
|
||||||
|
|
@ -762,7 +761,6 @@ impl Fsm for ShapeToolFsmState {
|
||||||
SNAP_POINT_TOLERANCE,
|
SNAP_POINT_TOLERANCE,
|
||||||
document.network_interface.selected_nodes().selected_visible_and_unlocked_layers(&document.network_interface),
|
document.network_interface.selected_nodes().selected_visible_and_unlocked_layers(&document.network_interface),
|
||||||
|_| false,
|
|_| false,
|
||||||
preferences,
|
|
||||||
) && clicked_on_line_endpoints(layer, document, input, tool_data)
|
) && clicked_on_line_endpoints(layer, document, input, tool_data)
|
||||||
&& !input.keyboard.key(Key::Control)
|
&& !input.keyboard.key(Key::Control)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -294,7 +294,6 @@ impl Fsm for SplineToolFsmState {
|
||||||
global_tool_data,
|
global_tool_data,
|
||||||
input,
|
input,
|
||||||
shape_editor,
|
shape_editor,
|
||||||
preferences,
|
|
||||||
viewport,
|
viewport,
|
||||||
..
|
..
|
||||||
} = tool_action_data;
|
} = tool_action_data;
|
||||||
|
|
@ -303,7 +302,7 @@ impl Fsm for SplineToolFsmState {
|
||||||
match (self, event) {
|
match (self, event) {
|
||||||
(_, SplineToolMessage::CanvasTransformed) => self,
|
(_, SplineToolMessage::CanvasTransformed) => self,
|
||||||
(_, SplineToolMessage::Overlays { context: mut overlay_context }) => {
|
(_, SplineToolMessage::Overlays { context: mut overlay_context }) => {
|
||||||
path_endpoint_overlays(document, shape_editor, &mut overlay_context, preferences);
|
path_endpoint_overlays(document, shape_editor, &mut overlay_context);
|
||||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
tool_data.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
@ -351,7 +350,7 @@ impl Fsm for SplineToolFsmState {
|
||||||
.filter(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[]));
|
.filter(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[]));
|
||||||
|
|
||||||
// Extend an endpoint of the selected path
|
// Extend an endpoint of the selected path
|
||||||
if let Some((layer, point, position)) = should_extend(document, viewport_vec, SNAP_POINT_TOLERANCE, layers, preferences) {
|
if let Some((layer, point, position)) = should_extend(document, viewport_vec, SNAP_POINT_TOLERANCE, layers) {
|
||||||
if find_spline(document, layer).is_some() {
|
if find_spline(document, layer).is_some() {
|
||||||
// If the point is the part of Spline then we extend it.
|
// If the point is the part of Spline then we extend it.
|
||||||
tool_data.current_layer = Some(layer);
|
tool_data.current_layer = Some(layer);
|
||||||
|
|
@ -417,7 +416,7 @@ impl Fsm for SplineToolFsmState {
|
||||||
extend_spline(tool_data, false, responses);
|
extend_spline(tool_data, false, responses);
|
||||||
tool_data.preview_point = preview_point;
|
tool_data.preview_point = preview_point;
|
||||||
|
|
||||||
if try_merging_lastest_endpoint(document, tool_data, preferences).is_some() {
|
if try_merging_lastest_endpoint(document, tool_data).is_some() {
|
||||||
responses.add(SplineToolMessage::Confirm);
|
responses.add(SplineToolMessage::Confirm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -427,7 +426,7 @@ impl Fsm for SplineToolFsmState {
|
||||||
(SplineToolFsmState::Drawing, SplineToolMessage::PointerMove) => {
|
(SplineToolFsmState::Drawing, SplineToolMessage::PointerMove) => {
|
||||||
let Some(layer) = tool_data.current_layer else { return SplineToolFsmState::Ready };
|
let Some(layer) = tool_data.current_layer else { return SplineToolFsmState::Ready };
|
||||||
let ignore = |cp: PointId| tool_data.preview_point.is_some_and(|pp| pp == cp) || tool_data.points.last().is_some_and(|(ep, _)| *ep == cp);
|
let ignore = |cp: PointId| tool_data.preview_point.is_some_and(|pp| pp == cp) || tool_data.points.last().is_some_and(|(ep, _)| *ep == cp);
|
||||||
let join_point = closest_point(document, input.mouse.position, PATH_JOIN_THRESHOLD, vec![layer].into_iter(), ignore, preferences);
|
let join_point = closest_point(document, input.mouse.position, PATH_JOIN_THRESHOLD, vec![layer].into_iter(), ignore);
|
||||||
|
|
||||||
// Endpoints snapping
|
// Endpoints snapping
|
||||||
if let Some((_, _, point)) = join_point {
|
if let Some((_, _, point)) = join_point {
|
||||||
|
|
@ -511,7 +510,7 @@ impl Fsm for SplineToolFsmState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_merging_lastest_endpoint(document: &DocumentMessageHandler, tool_data: &mut SplineToolData, preferences: &PreferencesMessageHandler) -> Option<()> {
|
fn try_merging_lastest_endpoint(document: &DocumentMessageHandler, tool_data: &mut SplineToolData) -> Option<()> {
|
||||||
if tool_data.points.len() < 2 {
|
if tool_data.points.len() < 2 {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
@ -526,7 +525,7 @@ fn try_merging_lastest_endpoint(document: &DocumentMessageHandler, tool_data: &m
|
||||||
let exclude = |p: PointId| preview_point.is_some_and(|pp| pp == p) || *last_endpoint == p;
|
let exclude = |p: PointId| preview_point.is_some_and(|pp| pp == p) || *last_endpoint == p;
|
||||||
let position = document.metadata().transform_to_viewport(current_layer).transform_point2(*last_endpoint_position);
|
let position = document.metadata().transform_to_viewport(current_layer).transform_point2(*last_endpoint_position);
|
||||||
|
|
||||||
let (layer, endpoint, _) = closest_point(document, position, PATH_JOIN_THRESHOLD, layers, exclude, preferences)?;
|
let (layer, endpoint, _) = closest_point(document, position, PATH_JOIN_THRESHOLD, layers, exclude)?;
|
||||||
tool_data.merge_layers.insert(layer);
|
tool_data.merge_layers.insert(layer);
|
||||||
tool_data.merge_endpoints.push((EndpointPosition::End, endpoint));
|
tool_data.merge_endpoints.push((EndpointPosition::End, endpoint));
|
||||||
|
|
||||||
|
|
@ -647,7 +646,7 @@ mod test_spline_tool {
|
||||||
let layer_to_viewport = document.metadata().transform_to_viewport(spline_layer);
|
let layer_to_viewport = document.metadata().transform_to_viewport(spline_layer);
|
||||||
|
|
||||||
let endpoints: Vec<(PointId, DVec2)> = first_vector
|
let endpoints: Vec<(PointId, DVec2)> = first_vector
|
||||||
.extendable_points(false)
|
.extendable_points_no_vector_meshes()
|
||||||
.filter_map(|point_id| first_vector.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();
|
.collect();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -366,10 +366,20 @@ impl<Upstream> Vector<Upstream> {
|
||||||
|
|
||||||
/// Points that can be extended from.
|
/// Points that can be extended from.
|
||||||
///
|
///
|
||||||
/// This is usually only points with exactly one connection unless vector meshes are enabled.
|
/// This may be points with more than one connection because of vector meshes.
|
||||||
pub fn extendable_points(&self, vector_meshes: bool) -> impl Iterator<Item = PointId> + '_ {
|
pub fn extendable_points(&self) -> impl Iterator<Item = PointId> + '_ {
|
||||||
let point_ids = self.point_domain.ids().iter().enumerate();
|
self.point_domain.ids().iter().copied()
|
||||||
point_ids.filter(move |(index, _)| vector_meshes || self.segment_domain.connected_count(*index) == 1).map(|(_, &id)| id)
|
}
|
||||||
|
|
||||||
|
// TODO: Avoid needing this special function that's used in only one place. See: <https://github.com/GraphiteEditor/Graphite/commit/6e7f218068a55cc22659ee2cf4f0f2cf26d37774#r173283173>
|
||||||
|
/// Points that can be extended from.
|
||||||
|
///
|
||||||
|
/// This includes only points with exactly one connection because vector meshes are ignored.
|
||||||
|
pub fn extendable_points_no_vector_meshes(&self) -> impl Iterator<Item = PointId> + '_ {
|
||||||
|
self.extendable_points()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|&(index, _)| self.segment_domain.connected_count(index) == 1)
|
||||||
|
.map(|(_, id)| id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes if all the connected handles are colinear for an anchor, or if that handle is colinear for a handle.
|
/// Computes if all the connected handles are colinear for an anchor, or if that handle is colinear for a handle.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue