diff --git a/Cargo.lock b/Cargo.lock index 940c1a5..6d477b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1563,7 +1563,7 @@ dependencies = [ [[package]] name = "glifrenderer" version = "0.1.2" -source = "git+https://github.com/MFEK/glifrenderer.rlib#1e4243bb78f1f1252cafa92558b4be1afc132f54" +source = "git+https://github.com/MFEK/glifrenderer.rlib#7fd9b9ee48227673d7fb242c90b8883f010f017d" dependencies = [ "MFEKmath", "derive_more", @@ -2607,9 +2607,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "roots" diff --git a/src/tool_behaviors/move_handle.rs b/src/tool_behaviors/move_handle.rs index 7021135..8c6cee9 100644 --- a/src/tool_behaviors/move_handle.rs +++ b/src/tool_behaviors/move_handle.rs @@ -4,6 +4,7 @@ pub use crate::user_interface::follow::Follow; use glifparser::PointData; use glifparser::glif::contour::MFEKContourCommon; use glifparser::glif::point::MFEKPointCommon; +use MFEKmath::polar::PolarCoordinates; #[derive(Clone, Debug)] pub struct MoveHandle { @@ -54,12 +55,21 @@ impl MoveHandle { // Difference in x, difference in y let (dx, dy) = (cx - x, cy - y); - let follow = if self.creating { + let mut follow = if self.creating { Follow::Mirror } else { Follow::from(self.mouse_info) }; + if point.get_smooth() == Some(true) { + // Follow::Mirror breaks smoothness + follow = Follow::ForceLine; + } + + if point.get_handle(self.wh.opposite()).unwrap() == Handle::Colocated && follow == Follow::ForceLine { + // If the opposite handle is colocated, force line crashes due to unwrapping a None value. + follow = Follow::No; + } match self.wh { WhichHandle::A | WhichHandle::B => { point.set_handle(self.wh, Handle::At(x, y)); @@ -94,21 +104,13 @@ impl MoveHandle { } } - fn force_line(&mut self, _point: &mut dyn MFEKPointCommon) { - // TODO: Fix this? I have zero clue why this errors. It's forcing point to `static. - /*let (r, _) = point.polar(self.wh.opposite()); + fn force_line(&self, mut point: &mut dyn MFEKPointCommon) { + let (r, _) = point.polar(self.wh.opposite()); let (_, theta) = point.polar(self.wh); match point.get_handle(self.wh.opposite()).unwrap() { Handle::At(..) => point.set_polar(self.wh.opposite(), (r, theta.to_degrees())), - Handle::Colocated => { - if !self.warned_force_line { - log::warn!( - "Makes no sense to force line when opposite handle is colocated, ignoring" - ); - } - self.warned_force_line = true; - } - }*/ + Handle::Colocated => unreachable!("Force line is nonsensical when the opposite handle is colocated") + } } } diff --git a/src/user_interface/gui/windows/inspection_window.rs b/src/user_interface/gui/windows/inspection_window.rs index 8bbe3ff..b291b63 100644 --- a/src/user_interface/gui/windows/inspection_window.rs +++ b/src/user_interface/gui/windows/inspection_window.rs @@ -8,9 +8,10 @@ use crate::{ use egui::Context; use glifparser::{ glif::{contour::MFEKContourCommon, inner::MFEKContourInnerType, point::MFEKPointCommon}, - Handle, PointData, WhichHandle, + Contour, Handle, MFEKPointData, PointData, WhichHandle, }; use MFEKmath::mfek::ResolveCubic; +use MFEKmath::polar::PolarCoordinates; use super::egui_parsed_textfield; @@ -50,7 +51,7 @@ impl GlifWindow for InspectionWindow { .show(ctx, |ui| { if let Some((ci, pi)) = v.selected_point() { let mut contour = v.get_active_layer_ref().outline[ci].clone(); - let point = contour + let mut point = contour .get_point_mut(pi) .expect("Editor should have valid selection!"); // do contour stuff @@ -114,7 +115,34 @@ impl GlifWindow for InspectionWindow { egui_parsed_textfield(ui, "px", point.x(), &mut self.edit_buf), egui_parsed_textfield(ui, "py", point.y(), &mut self.edit_buf), ); - + if let Some(smooth) = point.get_smooth() { + let mut checked = smooth; + let smooth_can_be_enabled = point.get_handle(WhichHandle::A).unwrap() + != Handle::Colocated + && point.get_handle(WhichHandle::B).unwrap() != Handle::Colocated; + ui.add_enabled_ui(smooth_can_be_enabled, |ui| { + ui.checkbox(&mut checked, "Smooth"). + on_disabled_hover_text("Cannot enable smoothness if one of the off curve handles is colocated with the point") + }); + if smooth != checked { + point.set_smooth(checked); + // If smooth was enabled just now, we need to ensure the curve is actually smooth. + if checked { + // Force curve points into a line to make the curve smooth + let wh = WhichHandle::A; + let (r, _) = point.polar(wh.opposite()); + let (_, theta) = point.polar(wh); + match point.get_handle(wh.opposite()).expect("Both handles should exist") { + Handle::At(..) => point.set_polar(wh.opposite(), (r, theta.to_degrees())), + Handle::Colocated => unreachable!("Handles not being colocated is required to reach this clause") + } + } + } + // If either handle is colocated, smooth *must* be disabled + if !smooth_can_be_enabled { + point.set_smooth(false); + } + } ui.collapsing("Handles", |ui| { if point.has_handle(WhichHandle::A) { ui.label("Handle A:"); @@ -222,6 +250,10 @@ impl GlifWindow for InspectionWindow { mutated_point.set_name(name); } + if let Some(smooth) = point.get_smooth() { + mutated_point.set_smooth(smooth); + } + v.end_modification(); } }); @@ -240,6 +272,7 @@ fn point_equivalent( && a.get_position() == b.get_position() && a.get_handle_position(WhichHandle::A) == b.get_handle_position(WhichHandle::A) && a.get_handle_position(WhichHandle::B) == b.get_handle_position(WhichHandle::B) + && a.get_smooth() == b.get_smooth() } /*