From 2c6c13e239a40e238e9365e3f35d880a06328b3c Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Tue, 11 Feb 2025 21:40:48 -0800 Subject: [PATCH] Code review --- .../document/overlays/utility_functions.rs | 114 ++++++++---------- .../document/overlays/utility_types.rs | 3 +- .../messages/tool/tool_messages/path_tool.rs | 95 +++++++-------- .../messages/tool/tool_messages/pen_tool.rs | 43 ++++--- node-graph/gcore/src/vector/vector_data.rs | 2 +- 5 files changed, 119 insertions(+), 138 deletions(-) diff --git a/editor/src/messages/portfolio/document/overlays/utility_functions.rs b/editor/src/messages/portfolio/document/overlays/utility_functions.rs index 7ce0171610..d9af75f7a4 100644 --- a/editor/src/messages/portfolio/document/overlays/utility_functions.rs +++ b/editor/src/messages/portfolio/document/overlays/utility_functions.rs @@ -4,10 +4,10 @@ use crate::messages::tool::common_functionality::shape_editor::{SelectedLayerSta use crate::messages::tool::tool_messages::tool_prelude::{DocumentMessageHandler, PreferencesMessageHandler}; use graphene_core::vector::ManipulatorPointId; +use graphene_std::vector::{PointId, SegmentId}; -use bezier_rs::Bezier; +use bezier_rs::{Bezier, BezierHandles}; use glam::{DAffine2, DVec2}; -use graphene_std::vector::{PointId, SegmentId}; use wasm_bindgen::JsCast; pub fn overlay_canvas_element() -> Option { @@ -25,64 +25,54 @@ pub fn overlay_canvas_context() -> web_sys::CanvasRenderingContext2d { create_context().expect("Failed to get canvas context") } -pub fn get_selected_segments(document: &DocumentMessageHandler, shape_editor: &mut ShapeState) -> Vec { +pub fn selected_segments(document: &DocumentMessageHandler, shape_editor: &mut ShapeState) -> Vec { let selected_points = shape_editor.selected_points(); - let selected_anchors: Vec = selected_points + let selected_anchors = selected_points .filter_map(|point_id| if let ManipulatorPointId::Anchor(p) = point_id { Some(*p) } else { None }) - .collect(); - //Collect the segments whose handles are selected - let mut selected_segments: Vec = shape_editor + .collect::>(); + + // Collect the segments whose handles are selected + let mut selected_segments = shape_editor .selected_points() - .filter_map(|point_id| { - if let ManipulatorPointId::EndHandle(segment_id) = point_id { - Some(*segment_id) - } else if let ManipulatorPointId::PrimaryHandle(segment_id) = point_id { - Some(*segment_id) - } else { - None - } + .filter_map(|point_id| match point_id { + ManipulatorPointId::PrimaryHandle(segment_id) | ManipulatorPointId::EndHandle(segment_id) => Some(*segment_id), + ManipulatorPointId::Anchor(_) => None, }) - .collect(); + .collect::>(); - //TODO: Currently if there are two duplicate layers, both of their segments get overlays + // TODO: Currently if there are two duplicate layers, both of their segments get overlays // Adding segments which are are connected to selected anchors for layer in document.network_interface.selected_nodes(&[]).unwrap().selected_layers(document.metadata()) { - let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { - continue; - }; + let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue }; + for (segment_id, _bezier, start, end) in vector_data.segment_bezier_iter() { if selected_anchors.contains(&start) || selected_anchors.contains(&end) { selected_segments.push(segment_id); } } } + selected_segments } -fn overlay_bezier_handles( - segment_id: SegmentId, - bezier: Bezier, - transform: DAffine2, - overlay_context: &mut OverlayContext, - selected: Option<&SelectedLayerState>, - is_selected: impl Fn(Option<&SelectedLayerState>, ManipulatorPointId) -> bool, -) { +fn overlay_bezier_handles(bezier: Bezier, segment_id: SegmentId, transform: DAffine2, is_selected: impl Fn(ManipulatorPointId) -> bool, overlay_context: &mut OverlayContext) { let bezier = bezier.apply_transformation(|point| transform.transform_point2(point)); let not_under_anchor = |position: DVec2, anchor: DVec2| position.distance_squared(anchor) >= HIDE_HANDLE_DISTANCE * HIDE_HANDLE_DISTANCE; + match bezier.handles { - bezier_rs::BezierHandles::Quadratic { handle } if not_under_anchor(handle, bezier.start) && not_under_anchor(handle, bezier.end) => { + BezierHandles::Quadratic { handle } if not_under_anchor(handle, bezier.start) && not_under_anchor(handle, bezier.end) => { overlay_context.line(handle, bezier.start, None); overlay_context.line(handle, bezier.end, None); - overlay_context.manipulator_handle(handle, is_selected(selected, ManipulatorPointId::PrimaryHandle(segment_id)), None); + overlay_context.manipulator_handle(handle, is_selected(ManipulatorPointId::PrimaryHandle(segment_id)), None); } - bezier_rs::BezierHandles::Cubic { handle_start, handle_end } => { + BezierHandles::Cubic { handle_start, handle_end } => { if not_under_anchor(handle_start, bezier.start) { overlay_context.line(handle_start, bezier.start, None); - overlay_context.manipulator_handle(handle_start, is_selected(selected, ManipulatorPointId::PrimaryHandle(segment_id)), None); + overlay_context.manipulator_handle(handle_start, is_selected(ManipulatorPointId::PrimaryHandle(segment_id)), None); } if not_under_anchor(handle_end, bezier.end) { overlay_context.line(handle_end, bezier.end, None); - overlay_context.manipulator_handle(handle_end, is_selected(selected, ManipulatorPointId::EndHandle(segment_id)), None); + overlay_context.manipulator_handle(handle_end, is_selected(ManipulatorPointId::EndHandle(segment_id)), None); } } _ => {} @@ -90,59 +80,54 @@ fn overlay_bezier_handles( } pub fn overlay_bezier_handle_specific_point( - segment_id: SegmentId, bezier: Bezier, - start: PointId, - end: PointId, + segment_id: SegmentId, + (start, end): (PointId, PointId), + point_to_render: PointId, transform: DAffine2, + is_selected: impl Fn(ManipulatorPointId) -> bool, overlay_context: &mut OverlayContext, - selected: Option<&SelectedLayerState>, - is_selected: impl Fn(Option<&SelectedLayerState>, ManipulatorPointId) -> bool, - point_to_render: PointId, ) { let bezier = bezier.apply_transformation(|point| transform.transform_point2(point)); let not_under_anchor = |position: DVec2, anchor: DVec2| position.distance_squared(anchor) >= HIDE_HANDLE_DISTANCE * HIDE_HANDLE_DISTANCE; + match bezier.handles { - bezier_rs::BezierHandles::Quadratic { handle } if not_under_anchor(handle, bezier.start) && not_under_anchor(handle, bezier.end) => { - if start == point_to_render { - //review this - overlay_context.line(handle, bezier.start, None); - } else { - overlay_context.line(handle, bezier.end, None); + BezierHandles::Quadratic { handle } => { + if not_under_anchor(handle, bezier.start) && not_under_anchor(handle, bezier.end) { + let end = if start == point_to_render { bezier.start } else { bezier.end }; + overlay_context.line(handle, end, None); + overlay_context.manipulator_handle(handle, is_selected(ManipulatorPointId::PrimaryHandle(segment_id)), None); } - overlay_context.manipulator_handle(handle, is_selected(selected, ManipulatorPointId::PrimaryHandle(segment_id)), None); } - bezier_rs::BezierHandles::Cubic { handle_start, handle_end } => { + BezierHandles::Cubic { handle_start, handle_end } => { if not_under_anchor(handle_start, bezier.start) && (point_to_render == start) { overlay_context.line(handle_start, bezier.start, None); - overlay_context.manipulator_handle(handle_start, is_selected(selected, ManipulatorPointId::PrimaryHandle(segment_id)), None); + overlay_context.manipulator_handle(handle_start, is_selected(ManipulatorPointId::PrimaryHandle(segment_id)), None); } if not_under_anchor(handle_end, bezier.end) && (point_to_render == end) { overlay_context.line(handle_end, bezier.end, None); - overlay_context.manipulator_handle(handle_end, is_selected(selected, ManipulatorPointId::EndHandle(segment_id)), None); + overlay_context.manipulator_handle(handle_end, is_selected(ManipulatorPointId::EndHandle(segment_id)), None); } } _ => {} } } -pub fn path_overlays(document: &DocumentMessageHandler, shape_editor: &mut ShapeState, overlay_context: &mut OverlayContext, draw_handles: DrawHandles) { +pub fn path_overlays(document: &DocumentMessageHandler, draw_handles: DrawHandles, shape_editor: &mut ShapeState, overlay_context: &mut OverlayContext) { for layer in document.network_interface.selected_nodes(&[]).unwrap().selected_layers(document.metadata()) { - let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { - continue; - }; - //let document_to_viewport = document.navigation_handler.calculate_offset_transform(overlay_context.size / 2., &document.document_ptz); + let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue }; let transform = document.metadata().transform_to_viewport(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_selected(point)); overlay_context.outline_vector(&vector_data, transform); - let opposite_handles_data: Vec<(PointId, SegmentId)> = shape_editor.selected_points().filter_map(|point_id| vector_data.get_adjacent_segment(point_id)).collect(); + let selected = shape_editor.selected_shape_state.get(&layer); + let is_selected = |point: ManipulatorPointId| selected.is_some_and(|selected| selected.is_selected(point)); + + let opposite_handles_data: Vec<(PointId, SegmentId)> = shape_editor.selected_points().filter_map(|point_id| vector_data.adjacent_segment(point_id)).collect(); match draw_handles { DrawHandles::All => { vector_data.segment_bezier_iter().for_each(|(segment_id, bezier, _start, _end)| { - overlay_bezier_handles(segment_id, bezier, transform, overlay_context, selected, is_selected); + overlay_bezier_handles(bezier, segment_id, transform, is_selected, overlay_context); }); } DrawHandles::SelectedAnchors(ref selected_segments) => { @@ -150,26 +135,25 @@ pub fn path_overlays(document: &DocumentMessageHandler, shape_editor: &mut Shape .segment_bezier_iter() .filter(|(segment_id, ..)| selected_segments.contains(segment_id)) .for_each(|(segment_id, bezier, _start, _end)| { - overlay_bezier_handles(segment_id, bezier, transform, overlay_context, selected, is_selected); + overlay_bezier_handles(bezier, segment_id, transform, is_selected, overlay_context); }); for (segment_id, bezier, start, end) in vector_data.segment_bezier_iter() { if let Some((corresponding_anchor, _)) = opposite_handles_data.iter().find(|(_, adj_segment_id)| adj_segment_id == &segment_id) { - overlay_bezier_handle_specific_point(segment_id, bezier, start, end, transform, overlay_context, selected, is_selected, *corresponding_anchor); + overlay_bezier_handle_specific_point(bezier, segment_id, (start, end), *corresponding_anchor, transform, is_selected, overlay_context); } } } - DrawHandles::FrontierHandles(ref segment_endpoints) => { vector_data .segment_bezier_iter() - .filter(|(segment_id, ..)| segment_endpoints.contains_key(&segment_id)) + .filter(|(segment_id, ..)| segment_endpoints.contains_key(segment_id)) .for_each(|(segment_id, bezier, start, end)| { if segment_endpoints.get(&segment_id).unwrap().len() == 1 { let point_to_render = segment_endpoints.get(&segment_id).unwrap()[0]; - overlay_bezier_handle_specific_point(segment_id, bezier, start, end, transform, overlay_context, selected, is_selected, point_to_render); + overlay_bezier_handle_specific_point(bezier, segment_id, (start, end), point_to_render, transform, is_selected, overlay_context); } else { - overlay_bezier_handles(segment_id, bezier, transform, overlay_context, selected, is_selected); + overlay_bezier_handles(bezier, segment_id, transform, is_selected, overlay_context); } }); } @@ -177,7 +161,7 @@ pub fn path_overlays(document: &DocumentMessageHandler, shape_editor: &mut Shape } for (&id, &position) in vector_data.point_domain.ids().iter().zip(vector_data.point_domain.positions()) { - overlay_context.manipulator_anchor(transform.transform_point2(position), is_selected(selected, ManipulatorPointId::Anchor(id)), None); + overlay_context.manipulator_anchor(transform.transform_point2(position), is_selected(ManipulatorPointId::Anchor(id)), None); } } } diff --git a/editor/src/messages/portfolio/document/overlays/utility_types.rs b/editor/src/messages/portfolio/document/overlays/utility_types.rs index 10e7b3287e..a16eda48c4 100644 --- a/editor/src/messages/portfolio/document/overlays/utility_types.rs +++ b/editor/src/messages/portfolio/document/overlays/utility_types.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use super::utility_functions::overlay_canvas_context; use crate::consts::{ COLOR_OVERLAY_BLUE, COLOR_OVERLAY_TRANSPARENT, COLOR_OVERLAY_WHITE, COLOR_OVERLAY_YELLOW, MANIPULATOR_GROUP_MARKER_SIZE, PIVOT_CROSSHAIR_LENGTH, PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER, @@ -13,6 +11,7 @@ use graphene_std::vector::{PointId, SegmentId, VectorData}; use core::borrow::Borrow; use core::f64::consts::TAU; use glam::{DAffine2, DVec2}; +use std::collections::HashMap; use wasm_bindgen::JsValue; pub type OverlayProvider = fn(OverlayContext) -> Message; diff --git a/editor/src/messages/tool/tool_messages/path_tool.rs b/editor/src/messages/tool/tool_messages/path_tool.rs index a1cc2d8a3c..a87fccbfcb 100644 --- a/editor/src/messages/tool/tool_messages/path_tool.rs +++ b/editor/src/messages/tool/tool_messages/path_tool.rs @@ -3,7 +3,7 @@ use super::tool_prelude::*; use crate::consts::{ COLOR_OVERLAY_BLUE, DRAG_DIRECTION_MODE_DETERMINATION_THRESHOLD, DRAG_THRESHOLD, HANDLE_ROTATE_SNAP_ANGLE, INSERT_POINT_ON_SEGMENT_TOO_FAR_DISTANCE, SELECTION_THRESHOLD, SELECTION_TOLERANCE, }; -use crate::messages::portfolio::document::overlays::utility_functions::{get_selected_segments, path_overlays}; +use crate::messages::portfolio::document::overlays::utility_functions::{path_overlays, selected_segments}; use crate::messages::portfolio::document::overlays::utility_types::{DrawHandles, OverlayContext}; use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::portfolio::document::utility_types::network_interface::NodeNetworkInterface; @@ -27,18 +27,11 @@ pub struct PathTool { options: PathToolOptions, } +#[derive(Default)] pub struct PathToolOptions { path_overlay_mode: PathOverlayMode, } -impl Default for PathToolOptions { - fn default() -> Self { - Self { - path_overlay_mode: PathOverlayMode::SelectedPointHandles, - } - } -} - #[impl_message(Message, ToolMessage, Path)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)] pub enum PathToolMessage { @@ -105,9 +98,10 @@ pub enum PathToolMessage { UpdateOptions(PathOptionsUpdate), } -#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)] +#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug, Default, serde::Serialize, serde::Deserialize, specta::Type)] pub enum PathOverlayMode { AllHandles = 0, + #[default] SelectedPointHandles = 1, FrontierHandles = 2, } @@ -129,21 +123,6 @@ impl ToolMetadata for PathTool { } } -fn create_path_overlay_mode_widget(path_overlay_mode: PathOverlayMode) -> WidgetHolder { - let entries = vec![ - RadioEntryData::new("1") - .label("1") - .on_update(move |_| PathToolMessage::UpdateOptions(PathOptionsUpdate::OverlayModeType(PathOverlayMode::AllHandles)).into()), - RadioEntryData::new("2") - .label("2") - .on_update(move |_| PathToolMessage::UpdateOptions(PathOptionsUpdate::OverlayModeType(PathOverlayMode::SelectedPointHandles)).into()), - RadioEntryData::new("3") - .label("3") - .on_update(move |_| PathToolMessage::UpdateOptions(PathOptionsUpdate::OverlayModeType(PathOverlayMode::FrontierHandles)).into()), - ]; - RadioInput::new(entries).selected_index(Some(path_overlay_mode as u32)).widget_holder() -} - impl LayoutHolder for PathTool { fn layout(&self) -> Layout { let coordinates = self.tool_data.selection_status.as_one().as_ref().map(|point| point.coordinates); @@ -211,6 +190,20 @@ impl LayoutHolder for PathTool { .tooltip(colinear_handles_tooltip) .widget_holder(); + let path_overlay_mode_widget = RadioInput::new(vec![ + RadioEntryData::new("1") + .label("1") + .on_update(move |_| PathToolMessage::UpdateOptions(PathOptionsUpdate::OverlayModeType(PathOverlayMode::AllHandles)).into()), + RadioEntryData::new("2") + .label("2") + .on_update(move |_| PathToolMessage::UpdateOptions(PathOptionsUpdate::OverlayModeType(PathOverlayMode::SelectedPointHandles)).into()), + RadioEntryData::new("3") + .label("3") + .on_update(move |_| PathToolMessage::UpdateOptions(PathOptionsUpdate::OverlayModeType(PathOverlayMode::FrontierHandles)).into()), + ]) + .selected_index(Some(self.options.path_overlay_mode as u32)) + .widget_holder(); + Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets: vec![ x_location, @@ -220,8 +213,8 @@ impl LayoutHolder for PathTool { colinear_handle_checkbox, related_seperator, colinear_handles_label, - unrelated_seperator.clone(), - create_path_overlay_mode_widget(self.options.path_overlay_mode), + unrelated_seperator, + path_overlay_mode_widget, ], }])) } @@ -481,7 +474,7 @@ impl PathToolData { self.drag_start_pos = input.mouse.position; - let old_selection: Vec = shape_editor.selected_points().cloned().collect(); + let old_selection = shape_editor.selected_points().cloned().collect::>(); // Select the first point within the threshold (in pixels) if let Some(selected_points) = shape_editor.change_point_selection(&document.network_interface, input.mouse.position, SELECTION_THRESHOLD, extend_selection) { @@ -490,7 +483,7 @@ impl PathToolData { if let Some(selected_points) = selected_points { self.drag_start_pos = input.mouse.position; - //If selected points contain only handles and there was some selection before then it stores it and restore on release + // If selected points contain only handles and there was some selection before, then it is stored and becomes restored upon release let mut dragging_only_handles = true; for point in &selected_points.points { if matches!(point.point_id, ManipulatorPointId::Anchor(_)) { @@ -498,7 +491,7 @@ impl PathToolData { break; } } - if dragging_only_handles && !self.handle_drag_toggle && (old_selection.len() > 0) { + if dragging_only_handles && !self.handle_drag_toggle && !old_selection.is_empty() { self.saved_points_before_handle_drag = old_selection; } @@ -770,47 +763,48 @@ impl Fsm for PathToolFsmState { self } (_, PathToolMessage::Overlays(mut overlay_context)) => { - //TODO: find the segment ids of which the selected points are a part of + // TODO: find the segment ids of which the selected points are a part of match tool_options.path_overlay_mode { PathOverlayMode::AllHandles => { - path_overlays(document, shape_editor, &mut overlay_context, DrawHandles::All); + path_overlays(document, DrawHandles::All, shape_editor, &mut overlay_context); } - PathOverlayMode::SelectedPointHandles => { - let selected_segments = get_selected_segments(document, shape_editor); - path_overlays(document, shape_editor, &mut overlay_context, DrawHandles::SelectedAnchors(selected_segments)); - } + let selected_segments = selected_segments(document, shape_editor); + path_overlays(document, DrawHandles::SelectedAnchors(selected_segments), shape_editor, &mut overlay_context); + } PathOverlayMode::FrontierHandles => { - let selected_segments = get_selected_segments(document, shape_editor); - //Behaviour like Selectedpointhandles when only one point is selected + let selected_segments = selected_segments(document, shape_editor); + + // Match the behavior of `PathOverlayMode::SelectedPointHandles` when only one point is selected if shape_editor.selected_points().count() == 1 { - path_overlays(document, shape_editor, &mut overlay_context, DrawHandles::SelectedAnchors(selected_segments)); + path_overlays(document, DrawHandles::SelectedAnchors(selected_segments), shape_editor, &mut overlay_context); } else { let mut segment_endpoints: HashMap> = HashMap::new(); for layer in document.network_interface.selected_nodes(&[]).unwrap().selected_layers(document.metadata()) { - let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { - continue; - }; + let Some(vector_data) = document.network_interface.compute_modified_vector(layer) else { continue }; - //The points which are part of only one segment will be rendered + // The points which are part of only one segment will be rendered let mut selected_segments_by_point: HashMap> = HashMap::new(); + for (segment_id, _bezier, start, end) in vector_data.segment_bezier_iter() { if selected_segments.contains(&segment_id) { - selected_segments_by_point.entry(start).or_insert_with(Vec::new).push(segment_id); - selected_segments_by_point.entry(end).or_insert_with(Vec::new).push(segment_id); + selected_segments_by_point.entry(start).or_default().push(segment_id); + selected_segments_by_point.entry(end).or_default().push(segment_id); } } + for (point, attached_segments) in selected_segments_by_point { if attached_segments.len() == 1 { - segment_endpoints.entry(attached_segments[0]).or_insert_with(Vec::new).push(point); + segment_endpoints.entry(attached_segments[0]).or_default().push(point); } } } - //Now frontier anchors can be sent for rendering overlays - path_overlays(document, shape_editor, &mut overlay_context, DrawHandles::FrontierHandles(segment_endpoints)); + + // Now frontier anchors can be sent for rendering overlays + path_overlays(document, DrawHandles::FrontierHandles(segment_endpoints), shape_editor, &mut overlay_context); } } } @@ -959,7 +953,7 @@ impl Fsm for PathToolFsmState { } } - if (tool_data.saved_points_before_handle_drag.len() > 0) && (tool_data.drag_start_pos.distance(input.mouse.position) > DRAG_THRESHOLD) && (selected_only_handles) { + if !tool_data.saved_points_before_handle_drag.is_empty() && (tool_data.drag_start_pos.distance(input.mouse.position) > DRAG_THRESHOLD) && (selected_only_handles) { tool_data.handle_drag_toggle = true; } @@ -1151,9 +1145,10 @@ impl Fsm for PathToolFsmState { PathToolFsmState::Ready } (_, PathToolMessage::DragStop { extend_selection, .. }) => { - if tool_data.handle_drag_toggle && !(tool_data.drag_start_pos.distance(input.mouse.position) <= DRAG_THRESHOLD) { + if tool_data.handle_drag_toggle && tool_data.drag_start_pos.distance(input.mouse.position) > DRAG_THRESHOLD { shape_editor.deselect_all_points(); shape_editor.select_points_by_manipulator_id(&tool_data.saved_points_before_handle_drag); + tool_data.saved_points_before_handle_drag.clear(); tool_data.handle_drag_toggle = false; } diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index fa1f56c7ae..d59af4ff25 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -116,18 +116,6 @@ fn create_weight_widget(line_weight: f64) -> WidgetHolder { .widget_holder() } -fn create_path_overlay_mode_widget(path_overlay_mode: PenOverlayMode) -> WidgetHolder { - let entries = vec![ - RadioEntryData::new("1") - .label("1") - .on_update(move |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::OverlayModeType(PenOverlayMode::AllHandles)).into()), - RadioEntryData::new("2") - .label("2") - .on_update(move |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::OverlayModeType(PenOverlayMode::FrontierHandles)).into()), - ]; - RadioInput::new(entries).selected_index(Some(path_overlay_mode as u32)).widget_holder() -} - impl LayoutHolder for PenTool { fn layout(&self) -> Layout { let mut widgets = self.options.fill.create_widgets( @@ -147,10 +135,25 @@ impl LayoutHolder for PenTool { |color_type: ToolColorType| WidgetCallback::new(move |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::StrokeColorType(color_type.clone())).into()), |color: &ColorInput| PenToolMessage::UpdateOptions(PenOptionsUpdate::StrokeColor(color.value.as_solid())).into(), )); + widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); + widgets.push(create_weight_widget(self.options.line_weight)); + widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder()); - widgets.push(create_path_overlay_mode_widget(self.options.pen_overlay_mode)); + + widgets.push( + RadioInput::new(vec![ + RadioEntryData::new("1") + .label("1") + .on_update(move |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::OverlayModeType(PenOverlayMode::AllHandles)).into()), + RadioEntryData::new("2") + .label("2") + .on_update(move |_| PenToolMessage::UpdateOptions(PenOptionsUpdate::OverlayModeType(PenOverlayMode::FrontierHandles)).into()), + ]) + .selected_index(Some(self.options.pen_overlay_mode as u32)) + .widget_holder(), + ); Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row { widgets }])) } @@ -822,7 +825,7 @@ impl Fsm for PenToolFsmState { self } (PenToolFsmState::Ready, PenToolMessage::Overlays(mut overlay_context)) => { - path_overlays(document, shape_editor, &mut overlay_context, DrawHandles::All); + path_overlays(document, DrawHandles::All, shape_editor, &mut overlay_context); tool_data.snap_manager.draw_overlays(SnapData::new(document, input), &mut overlay_context); self } @@ -868,14 +871,14 @@ impl Fsm for PenToolFsmState { match tool_options.pen_overlay_mode { PenOverlayMode::AllHandles => { - path_overlays(document, shape_editor, &mut overlay_context, DrawHandles::All); + path_overlays(document, DrawHandles::All, shape_editor, &mut overlay_context); } PenOverlayMode::FrontierHandles => { - //Find the last segment id to be drawn handles of - if let Some(latest_segment) = tool_data.latest_point().unwrap().in_segment { - path_overlays(document, shape_editor, &mut overlay_context, DrawHandles::SelectedAnchors(vec![latest_segment])); + // Find the last segment ID to have its handles drawn + if let Some(latest_segment) = tool_data.latest_point().and_then(|point| point.in_segment) { + path_overlays(document, DrawHandles::SelectedAnchors(vec![latest_segment]), shape_editor, &mut overlay_context); } else { - path_overlays(document, shape_editor, &mut overlay_context, DrawHandles::None); + path_overlays(document, DrawHandles::None, shape_editor, &mut overlay_context); }; } } @@ -891,7 +894,7 @@ impl Fsm for PenToolFsmState { } } else { // Draw the whole path and its manipulators when the user is clicking-and-dragging out from the most recently placed anchor to set its outgoing handle, during which it would otherwise not have its overlays drawn - path_overlays(document, shape_editor, &mut overlay_context, DrawHandles::All); + path_overlays(document, DrawHandles::All, shape_editor, &mut overlay_context); } if self == PenToolFsmState::DraggingHandle(tool_data.handle_mode) && valid(next_anchor, next_handle_start) { diff --git a/node-graph/gcore/src/vector/vector_data.rs b/node-graph/gcore/src/vector/vector_data.rs index 6543e1d581..8502b7178b 100644 --- a/node-graph/gcore/src/vector/vector_data.rs +++ b/node-graph/gcore/src/vector/vector_data.rs @@ -294,7 +294,7 @@ impl VectorData { } } - pub fn get_adjacent_segment(&self, manipulator_id: &ManipulatorPointId) -> Option<(PointId, SegmentId)> { + pub fn adjacent_segment(&self, manipulator_id: &ManipulatorPointId) -> Option<(PointId, SegmentId)> { match manipulator_id { ManipulatorPointId::PrimaryHandle(segment_id) => { // For start handle, find segments ending at our start point