Browse / github.com/storytold/cadcraft / patch
PLINE: Undo returns to the last segment's mode, and PLINEWID is the width
PLINE: Undo returns to the last segment's mode, and PLINEWID is the width ## What was wrong I checked PLINE against AutoCAD 2024 as a black box: 76 typed inputs (every arc option, widths, Close, Length, Undo, PLINEWID) run in `accoreconsole` and read back with `entget` and GETVAR. On `main`, 72 match; with this PR, all 76 do. 1. **Undo after an arc segment stayed in arc mode.** In AutoCAD, `_U` returns to the mode of the segment that is now last. After `… point _A point _U`, the next prompt is line mode's "Specify next point or [Arc/Close/Halfwidth/Length/Undo/Width]", so `_L` is **Length**. In CADCraft, `_L` was arc mode's **Line**, and the next point became a pl
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- 2ez4gcx (imported from pull request #2205, open)
- Base
d864a08b013353143086bd8bb568c26cb6256796- Size
- +52 −0 in 2 files
- Review
- pending
- Shared
- 2026-10-28
- Id
40b15c54f53a9158f70b87f8
How it went
No other operator has reported using it yet.
Diff
raw · crates/engine/src/cmd/draw/line_pline.rs crates/engine/src/tests.rs
@@ -256,6 +256,12 @@ impl Interactive for PlineM { fn name(&self) -> &'static str { "PLINE" }+ /// Segments start at PLINEWID, the width the last Width or Halfwidth answer left.+ fn begin(&mut self, s: &mut Session) -> Result<Step> {+ let w = s.doc()?.header.f64("PLINEWID", 0.0);+ (self.start_w, self.end_w) = if w.is_finite() && w > 0.0 { (w, w) } else { (0.0, 0.0) };+ Ok(Step::Continue)+ } fn prompt(&self, s: &Session) -> Prompt { if self.asking_width > 0 { let unit = if self.half { "half-width" } else { "width" };@@ -302,6 +308,11 @@ impl Interactive for PlineM { self.end_w = self.start_w; } self.asking_width = if self.asking_width == 1 { 2 } else { 0 };+ if self.asking_width == 0 {+ // The ending width becomes PLINEWID, the next polyline's width (AutoCAD:+ // Halfwidth 0.5 0.5 leaves PLINEWID 1).+ s.doc_mut()?.header.set_f64("PLINEWID", self.end_w);+ } return Ok(Step::Continue); } if let (Some(a), Some(st)) = (self.ask, self.verts.last().map(|v| v.p)) {@@ -365,6 +376,10 @@ impl Interactive for PlineM { l.bulge = 0.0; (l.start_width, l.end_width) = (0.0, 0.0); }+ // Back to the mode of the segment now last (AutoCAD: `_A` point `_U` returns+ // to "Specify next point", where `_L` is Length, not arc mode's Line).+ let n = self.verts.len();+ self.arc_mode = n >= 2 && self.verts.get(n - 2).is_some_and(|v| v.bulge != 0.0); self.sync(s, false)?; Ok(Step::Continue) }@@ -1226,6 +1226,43 @@ fn pline_width_answers_taper_the_next_segment() { assert_eq!(widths(&p), (0.0, vec![(0.0, 0.0), (0.0, 0.0)])); } +/// PLINE against what AutoCAD 2024 stores for the same typed input (black-box: synthetic input+/// in accoreconsole, read back with `entget` and GETVAR).+#[test]+fn pline_undo_mode_and_plinewid_match_autocad() {+ // Undo after an arc segment returns to line mode, where `_L` is Length (a point gives the+ // length, along the last segment).+ let p = typed_pline(+ "pline -0.702422643378533,-28.46727901968281 -27.912058384977463,-34.74188138168937 -22.546524604415925,32.44142803067136 _U \+ 25.831317263304115,13.510616645626207 _A -33.2372517304228,12.083585785350365 _U _L -22.546524604415925,32.44142803067136",+ );+ let want = [+ (-0.7024226433785329, -28.4672790196828),+ (-27.91205838497746, -34.74188138168937),+ (25.83131726330411, 13.5106166456262),+ (64.48701958199356, 48.21692560701169),+ ];+ assert_eq!(p.vertices.len(), want.len(), "{p:?}");+ for (v, (x, y)) in p.vertices.iter().zip(want) {+ assert!(v.p.near(Vec2::new(x, y), 1e-9 * x.abs().max(y.abs())) && v.bulge == 0.0, "{p:?}");+ }+ // PLINEWID is the width a new polyline starts with…+ let mut s = Session::new();+ s.cmdline("(setvar \"PLINEWID\" 0.75)").unwrap();+ s.cmdline("pline -21.06802233135781,9.943678105070298 -29.261665218975015,-28.460093326613574 7.898763272534772,6.73634194079888").unwrap();+ s.cmdline("").unwrap();+ assert!(matches!(&s.doc().unwrap().model.last().unwrap().kind, EntityKind::LwPolyline(p) if p.const_width == 0.75));+ // …and the ending width of the last Width or Halfwidth answer (half-width 0.5: PLINEWID 1).+ let mut s = Session::new();+ s.cmdline(+ "pline -9.151085154682761,12.9438035725412 _W 0.0934460985004879 1.547654372298795 19.161590651864245,38.23079339857958 \+ 26.720225103092986,-9.028145532375504 _H 0.5 0.5 -24.7035288980598,-14.309723714209586",+ )+ .unwrap();+ s.cmdline("").unwrap();+ assert_eq!(s.doc().unwrap().header.f64("PLINEWID", 0.0), 1.0);+}+ #[test] fn press_and_drag_selection_window() { let mut s = Session::new();