mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-25 19:36:49 -06:00
sonar-fix/enforce-https
593
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d87950afe8 |
Press-and-drag selection windows (PICKDRAG = 2) (#63)
Selection windows only worked click-then-click: the canvas reacts to clicks, and a press that moves before release is a drag, not a click, so a drag was ignored entirely. Now, while objects are being selected (no command running, or a command asking for objects), a drag opens the window where the button went down and letting go closes it, as with AutoCAD's default PICKDRAG = 2. Dragging right is a window, dragging left a crossing window, Shift still removes, and click-click works as before. Drags that start on a grip or while a command asks for a point are left alone. Session::begin_window opens the window at the drag's start, even over an object (a click there would pick the object instead), with an engine test. Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1dfa3660a7 |
Write Wipeout entities to DXF so saving keeps them (#79) (#147)
* Write Wipeout entities to DXF so saving keeps them (#79) * Wipeout: clip vertices are in image pixel space (origin top-left, y down) Write and read the boundary with y flipped, so other programs show the same shape and wipeouts from other programs are no longer mirrored vertically. Tested with an asymmetric boundary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Wipeout: collapse nested if (clippy) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
f0d6f248f7 |
DXF/DWG: keep hatch gradients through save and reopen (fixes #80) (#162)
* DXF/DWG: keep hatch gradients through save and reopen (fixes #80) The HATCH writer never emitted a gradient and the reader always set `gradient: None`, so a GRADIENT fill reopened as a plain SOLID hatch after any DXF or DWG save. - Writer: native HATCH groups per the DXF Reference (450 gradient flag, 451, 452 two-colour, 453 colour count, 460 angle in radians, 461 shift (0 = centered), 462 tint, 463 per-colour records with 63 ACI and 421 true colour, 470 name), plus a `CADCRAFT` `GRADIENT` xdata copy (name cut to 255 bytes, angle, centered, colour names). - Reader: native groups win when present (another program may have edited them); otherwise the xdata copy is used. The xdata is what survives DWG saves: the file is R2000 (AC1015), whose DWG HATCH has no gradient fields, so the DWG bridge drops the native groups. - Hostile values (NaN angles, out-of-range colours, extra colour records, missing groups) fall back to the GRADIENT command's defaults. Tests: gradient_hatch_roundtrips_through_dxf, gradient_hatch_roundtrips_through_dwg, gradient_falls_back_to_xdata_and_native_groups_win, long_gradient_name_is_cut_only_in_xdata, hostile_gradient_groups_never_panic. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * contributors: add vangel76 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Gradient test: expect \U+ escapes now that non-ASCII text is escaped (#169) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com> |
||
|
|
8fceaaff3a |
Fix the arc-length DWG round-trip test build; cargo fmt
The squash for #159 picked up an earlier revision of the #140 test, which called as_bytes() on a Vec<u8>. Also apply rustfmt to code from #120 and #155. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
bd2412f495 |
PLINE: Halfwidth is centre-to-edge, and Width answers taper the next segment (fixes #83, #104) (#121)
* DIMANGULAR: accept polyline segments (fixes #10) Picking a side of a rectangle or a PLINE segment was rejected with "Select a line or an arc." because only LINE and ARC entities were accepted. The picked object is now resolved to the segment under the cursor: straight polyline segments work like lines and arc segments like arcs. * Redraw edits made while a command is still running (fixes #4) LINE and PLINE add geometry on every point, but the canvas only rebuilt its display list when the drawing revision or the document pointer changed. The revision was bumped when a command finished, and the pointer changed only on the first copy-on-write edit, so only the first segment appeared until the command ended. Session::feed now bumps the revision after each input once the running command has changed the drawing. * Fix #14: include DWG in the Open drawing filter * Blocks window: click a block to insert it (#8) Each block name in the Blocks window is now a button. Clicking it starts INSERT with that block already chosen, so the command line asks for the insertion point. * SCALE: Reference option (#17) SCALE > Reference printed "not available yet". It now asks for the reference length (typed, or two points) and the new length (typed, or a point measured from the base point), and scales by new / reference. Zero, negative or non-finite lengths are rejected and asked again. * Print and Ctrl+P ask where to save the PDF (#5) PLOT/EXPORTPDF started from the menu, the toolbar, Ctrl+P or the command line had no path, so the PDF was built in memory and dropped. They now open the save dialog (PDF filter first) and write the file there. JSON calls from scripts, the control channel and MCP still never open a dialog. Ctrl+P was shown in the menu but not bound; it is now. * Scripts: split a line at keyword prompts so POLYGON 6 200,20 I 15 works (#43) * Layer Properties Manager: stop the window growing every frame (fixes #29) The vertical separator between the filter tree and the table takes all the height it is offered, and a resizable window offers its previous height, so the window grew 30px per frame until it filled the screen. Cap the row at the table's fixed height. Regression test runs the dialog headless for 30 frames and checks the height stays put. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ui.render: fit the drawing and return pngBase64 like the headless render (#49, #50) * Linux: default to XWayland for file drag-and-drop on Wayland desktops * Fonts: per-character fallback, FONTALT and .ttc for CJK text in SHX styles (#130) CJK text in a style that uses an SHX font (romans.shx + chineset.shx big font) drew every ideograph as an empty box: the SHX name resolves to our stroke font, which has no CJK glyphs, and the font scan skipped .ttc collections, where most CJK system fonts live. - Per-character fallback: a character the text's font lacks (stroke font or TrueType) is drawn from an installed font that has it, checked by cmap. Wide-coverage fonts go first (Noto Sans CJK, Source Han, WenQuanYi, Droid Sans Fallback, PingFang, Microsoft JhengHei/YaHei, MS Gothic, ...), regular weights before others. Fallback glyphs are sized like TrueType text (cap height = text height). Lookups are cached; the search is bounded (24 files, 160 MiB, 256 faces per character, files over 96 MiB never read) and skips spaces, controls and private-use code points. No fallback: the box as before. - FONTALT (sysvar, seeded from CADCRAFT_FONTALT): font used for a style font that can't be found (an SHX file, a missing TTF). Empty = our stroke font. - FONTFALLBACK (sysvar, seeded from CADCRAFT_FONTFALLBACK): fonts tried first for missing characters, e.g. "Noto Sans CJK TC". - .ttc/.otc are scanned; TextFont::Outline carries a ttf::Face (bytes + face index). Fonts are also found by family name among files with a similar stem, so "Noto Sans CJK TC" picks face 3 of NotoSansCJK-Regular.ttc. - Cap height falls back to the height of "H" when OS/2 has none (DejaVu Sans), which fixes ttf_tests::system_font_outlines_when_available and render's truetype_text_is_filled_or_outlined on machines without Arial. - README: a Fonts section for the two settings; ROADMAP M4 note. Native SHX / big-font rendering stays on the roadmap (M4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fonts: cap the total bytes of system font files loaded from disk A drawing naming many text styles could otherwise load every installed font into memory through family-name lookups. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pan with a two-finger trackpad swipe; keep wheel and pinch zoom Trackpad two-finger swipes arrive as scroll events, and the canvas turned every scroll into a zoom, so trackpad users had no realtime pan (middle-drag needs a middle button). Scroll now follows the device: precise point deltas (trackpad, Magic Mouse) pan the view by x and y; notched line deltas (mouse wheel) zoom about the cursor as before. Pinch and Cmd+scroll still zoom through zoom_delta, and middle-drag still pans. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr * Add Tru10 to contributors/people.toml Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr * Trackpad pan: only on macOS, where point deltas mean a trackpad Browsers and Wayland smooth-scroll mice report ordinary wheels in points too, so the wheel keeps zooming there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep arc-length dimensions as arc-length through DXF save and reopen (#100) * PLINE: Halfwidth is centre-to-edge, and Width answers taper the next segment (fixes #83, #104) Interactive PLINE kept one width value: Halfwidth answers were stored as the total width, and the ending-width answer overwrote the starting one, so a taper became a constant width. The next segment's starting and ending widths are now tracked separately, Halfwidth answers are doubled, and each new segment (including the closing one) gets its widths on its first vertex; later segments are uniform at the ending width, as in AutoCAD. Uniform polylines are still stored as const_width, so their DXF output is unchanged. Fixes #83. Fixes #104. * Arc-length dimensions: write a standard aligned record plus CADCraft xdata DXF has no arc-length DIMENSION type, so write type 1 and mark the kind and arc centre in CADCRAFT xdata (like ASSOC). Other programs read an aligned dimension; CADCraft restores the arc length, through DXF and DWG. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Desktop: write log records to standard error and a rotating log file The desktop app installed no logger, so every log::warn!/log::error!/ log::info! in the workspace was discarded: a broken app icon, the GPU canvas set-up, the engine's command-line echo at debug level. A launch from a desktop menu has no terminal either, so there was nothing to attach to a bug report. apps/cadcraft/src/logging.rs (no new dependency): - standard error plus <settings dir>/logs/cadcraft.log; each launch rotates the previous log to cadcraft.1.log and .2.log, so the log of a run that crashed survives the next start; the file is capped at 16 MiB - records logged before the settings directory is known are buffered (bounded) and written once the file is attached - default levels: info for cadcraft*, warn for everything else; RUST_LOG replaces them with env_logger-style directives - never panics: an unusable directory or a failed write leaves standard error as the only sink; a poisoned lock is tolerated CADCraft had no per-user directory yet. config_dir in main.rs adds one: CADCRAFT_CONFIG_DIR, else $XDG_CONFIG_HOME/cadcraft or ~/.config/cadcraft (Linux, BSDs), ~/Library/Application Support/CADCraft (macOS), %APPDATA%\CADCraft (Windows). The logger is installed first in main and the file is opened after argument parsing (--version leaves no file). The control server's eprintln!s now go through the logger. A --control or CADCRAFT_CONTROL_PORT value that is not a port is now logged instead of silently leaving the control channel off. Documented in README.md (Quick start > Logs). --------- Co-authored-by: DWAA1660 <dwatnip123@gmail.com> Co-authored-by: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Co-authored-by: lloyd <34131158+LloydNicholson@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com> Co-authored-by: vangel76 <vangel1976@googlemail.com> Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Tru10 <133776756+Tru10@users.noreply.github.com> Co-authored-by: Gert Pellin <gert@pellin.be> |
||
|
|
a82f6ff306 |
Keep arc-length dimensions as arc-length through DXF save and reopen (#100) (#140)
* DIMANGULAR: accept polyline segments (fixes #10) Picking a side of a rectangle or a PLINE segment was rejected with "Select a line or an arc." because only LINE and ARC entities were accepted. The picked object is now resolved to the segment under the cursor: straight polyline segments work like lines and arc segments like arcs. * Redraw edits made while a command is still running (fixes #4) LINE and PLINE add geometry on every point, but the canvas only rebuilt its display list when the drawing revision or the document pointer changed. The revision was bumped when a command finished, and the pointer changed only on the first copy-on-write edit, so only the first segment appeared until the command ended. Session::feed now bumps the revision after each input once the running command has changed the drawing. * Fix #14: include DWG in the Open drawing filter * Blocks window: click a block to insert it (#8) Each block name in the Blocks window is now a button. Clicking it starts INSERT with that block already chosen, so the command line asks for the insertion point. * SCALE: Reference option (#17) SCALE > Reference printed "not available yet". It now asks for the reference length (typed, or two points) and the new length (typed, or a point measured from the base point), and scales by new / reference. Zero, negative or non-finite lengths are rejected and asked again. * Print and Ctrl+P ask where to save the PDF (#5) PLOT/EXPORTPDF started from the menu, the toolbar, Ctrl+P or the command line had no path, so the PDF was built in memory and dropped. They now open the save dialog (PDF filter first) and write the file there. JSON calls from scripts, the control channel and MCP still never open a dialog. Ctrl+P was shown in the menu but not bound; it is now. * Scripts: split a line at keyword prompts so POLYGON 6 200,20 I 15 works (#43) * Layer Properties Manager: stop the window growing every frame (fixes #29) The vertical separator between the filter tree and the table takes all the height it is offered, and a resizable window offers its previous height, so the window grew 30px per frame until it filled the screen. Cap the row at the table's fixed height. Regression test runs the dialog headless for 30 frames and checks the height stays put. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ui.render: fit the drawing and return pngBase64 like the headless render (#49, #50) * Linux: default to XWayland for file drag-and-drop on Wayland desktops * Fonts: per-character fallback, FONTALT and .ttc for CJK text in SHX styles (#130) CJK text in a style that uses an SHX font (romans.shx + chineset.shx big font) drew every ideograph as an empty box: the SHX name resolves to our stroke font, which has no CJK glyphs, and the font scan skipped .ttc collections, where most CJK system fonts live. - Per-character fallback: a character the text's font lacks (stroke font or TrueType) is drawn from an installed font that has it, checked by cmap. Wide-coverage fonts go first (Noto Sans CJK, Source Han, WenQuanYi, Droid Sans Fallback, PingFang, Microsoft JhengHei/YaHei, MS Gothic, ...), regular weights before others. Fallback glyphs are sized like TrueType text (cap height = text height). Lookups are cached; the search is bounded (24 files, 160 MiB, 256 faces per character, files over 96 MiB never read) and skips spaces, controls and private-use code points. No fallback: the box as before. - FONTALT (sysvar, seeded from CADCRAFT_FONTALT): font used for a style font that can't be found (an SHX file, a missing TTF). Empty = our stroke font. - FONTFALLBACK (sysvar, seeded from CADCRAFT_FONTFALLBACK): fonts tried first for missing characters, e.g. "Noto Sans CJK TC". - .ttc/.otc are scanned; TextFont::Outline carries a ttf::Face (bytes + face index). Fonts are also found by family name among files with a similar stem, so "Noto Sans CJK TC" picks face 3 of NotoSansCJK-Regular.ttc. - Cap height falls back to the height of "H" when OS/2 has none (DejaVu Sans), which fixes ttf_tests::system_font_outlines_when_available and render's truetype_text_is_filled_or_outlined on machines without Arial. - README: a Fonts section for the two settings; ROADMAP M4 note. Native SHX / big-font rendering stays on the roadmap (M4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fonts: cap the total bytes of system font files loaded from disk A drawing naming many text styles could otherwise load every installed font into memory through family-name lookups. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pan with a two-finger trackpad swipe; keep wheel and pinch zoom Trackpad two-finger swipes arrive as scroll events, and the canvas turned every scroll into a zoom, so trackpad users had no realtime pan (middle-drag needs a middle button). Scroll now follows the device: precise point deltas (trackpad, Magic Mouse) pan the view by x and y; notched line deltas (mouse wheel) zoom about the cursor as before. Pinch and Cmd+scroll still zoom through zoom_delta, and middle-drag still pans. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr * Add Tru10 to contributors/people.toml Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr * Trackpad pan: only on macOS, where point deltas mean a trackpad Browsers and Wayland smooth-scroll mice report ordinary wheels in points too, so the wheel keeps zooming there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep arc-length dimensions as arc-length through DXF save and reopen (#100) * PLINE: Halfwidth is centre-to-edge, and Width answers taper the next segment (fixes #83, #104) Interactive PLINE kept one width value: Halfwidth answers were stored as the total width, and the ending-width answer overwrote the starting one, so a taper became a constant width. The next segment's starting and ending widths are now tracked separately, Halfwidth answers are doubled, and each new segment (including the closing one) gets its widths on its first vertex; later segments are uniform at the ending width, as in AutoCAD. Uniform polylines are still stored as const_width, so their DXF output is unchanged. Fixes #83. Fixes #104. * Arc-length dimensions: write a standard aligned record plus CADCraft xdata DXF has no arc-length DIMENSION type, so write type 1 and mark the kind and arc centre in CADCRAFT xdata (like ASSOC). Other programs read an aligned dimension; CADCraft restores the arc length, through DXF and DWG. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Desktop: write log records to standard error and a rotating log file The desktop app installed no logger, so every log::warn!/log::error!/ log::info! in the workspace was discarded: a broken app icon, the GPU canvas set-up, the engine's command-line echo at debug level. A launch from a desktop menu has no terminal either, so there was nothing to attach to a bug report. apps/cadcraft/src/logging.rs (no new dependency): - standard error plus <settings dir>/logs/cadcraft.log; each launch rotates the previous log to cadcraft.1.log and .2.log, so the log of a run that crashed survives the next start; the file is capped at 16 MiB - records logged before the settings directory is known are buffered (bounded) and written once the file is attached - default levels: info for cadcraft*, warn for everything else; RUST_LOG replaces them with env_logger-style directives - never panics: an unusable directory or a failed write leaves standard error as the only sink; a poisoned lock is tolerated CADCraft had no per-user directory yet. config_dir in main.rs adds one: CADCRAFT_CONFIG_DIR, else $XDG_CONFIG_HOME/cadcraft or ~/.config/cadcraft (Linux, BSDs), ~/Library/Application Support/CADCraft (macOS), %APPDATA%\CADCraft (Windows). The logger is installed first in main and the file is opened after argument parsing (--version leaves no file). The control server's eprintln!s now go through the logger. A --control or CADCRAFT_CONTROL_PORT value that is not a port is now logged instead of silently leaving the control channel off. Documented in README.md (Quick start > Logs). --------- Co-authored-by: SBaksa <sabaksa11@gmail.com> Co-authored-by: DWAA1660 <dwatnip123@gmail.com> Co-authored-by: lloyd <34131158+LloydNicholson@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com> Co-authored-by: vangel76 <vangel1976@googlemail.com> Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Tru10 <133776756+Tru10@users.noreply.github.com> Co-authored-by: Gert Pellin <gert@pellin.be> |
||
|
|
35521ad957 |
Trackpad pan (#58)
* DIMANGULAR: accept polyline segments (fixes #10) Picking a side of a rectangle or a PLINE segment was rejected with "Select a line or an arc." because only LINE and ARC entities were accepted. The picked object is now resolved to the segment under the cursor: straight polyline segments work like lines and arc segments like arcs. * Redraw edits made while a command is still running (fixes #4) LINE and PLINE add geometry on every point, but the canvas only rebuilt its display list when the drawing revision or the document pointer changed. The revision was bumped when a command finished, and the pointer changed only on the first copy-on-write edit, so only the first segment appeared until the command ended. Session::feed now bumps the revision after each input once the running command has changed the drawing. * Fix #14: include DWG in the Open drawing filter * Blocks window: click a block to insert it (#8) Each block name in the Blocks window is now a button. Clicking it starts INSERT with that block already chosen, so the command line asks for the insertion point. * SCALE: Reference option (#17) SCALE > Reference printed "not available yet". It now asks for the reference length (typed, or two points) and the new length (typed, or a point measured from the base point), and scales by new / reference. Zero, negative or non-finite lengths are rejected and asked again. * Print and Ctrl+P ask where to save the PDF (#5) PLOT/EXPORTPDF started from the menu, the toolbar, Ctrl+P or the command line had no path, so the PDF was built in memory and dropped. They now open the save dialog (PDF filter first) and write the file there. JSON calls from scripts, the control channel and MCP still never open a dialog. Ctrl+P was shown in the menu but not bound; it is now. * Scripts: split a line at keyword prompts so POLYGON 6 200,20 I 15 works (#43) * Layer Properties Manager: stop the window growing every frame (fixes #29) The vertical separator between the filter tree and the table takes all the height it is offered, and a resizable window offers its previous height, so the window grew 30px per frame until it filled the screen. Cap the row at the table's fixed height. Regression test runs the dialog headless for 30 frames and checks the height stays put. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ui.render: fit the drawing and return pngBase64 like the headless render (#49, #50) * Linux: default to XWayland for file drag-and-drop on Wayland desktops * Fonts: per-character fallback, FONTALT and .ttc for CJK text in SHX styles (#130) CJK text in a style that uses an SHX font (romans.shx + chineset.shx big font) drew every ideograph as an empty box: the SHX name resolves to our stroke font, which has no CJK glyphs, and the font scan skipped .ttc collections, where most CJK system fonts live. - Per-character fallback: a character the text's font lacks (stroke font or TrueType) is drawn from an installed font that has it, checked by cmap. Wide-coverage fonts go first (Noto Sans CJK, Source Han, WenQuanYi, Droid Sans Fallback, PingFang, Microsoft JhengHei/YaHei, MS Gothic, ...), regular weights before others. Fallback glyphs are sized like TrueType text (cap height = text height). Lookups are cached; the search is bounded (24 files, 160 MiB, 256 faces per character, files over 96 MiB never read) and skips spaces, controls and private-use code points. No fallback: the box as before. - FONTALT (sysvar, seeded from CADCRAFT_FONTALT): font used for a style font that can't be found (an SHX file, a missing TTF). Empty = our stroke font. - FONTFALLBACK (sysvar, seeded from CADCRAFT_FONTFALLBACK): fonts tried first for missing characters, e.g. "Noto Sans CJK TC". - .ttc/.otc are scanned; TextFont::Outline carries a ttf::Face (bytes + face index). Fonts are also found by family name among files with a similar stem, so "Noto Sans CJK TC" picks face 3 of NotoSansCJK-Regular.ttc. - Cap height falls back to the height of "H" when OS/2 has none (DejaVu Sans), which fixes ttf_tests::system_font_outlines_when_available and render's truetype_text_is_filled_or_outlined on machines without Arial. - README: a Fonts section for the two settings; ROADMAP M4 note. Native SHX / big-font rendering stays on the roadmap (M4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fonts: cap the total bytes of system font files loaded from disk A drawing naming many text styles could otherwise load every installed font into memory through family-name lookups. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pan with a two-finger trackpad swipe; keep wheel and pinch zoom Trackpad two-finger swipes arrive as scroll events, and the canvas turned every scroll into a zoom, so trackpad users had no realtime pan (middle-drag needs a middle button). Scroll now follows the device: precise point deltas (trackpad, Magic Mouse) pan the view by x and y; notched line deltas (mouse wheel) zoom about the cursor as before. Pinch and Cmd+scroll still zoom through zoom_delta, and middle-drag still pans. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr * Add Tru10 to contributors/people.toml Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr * Trackpad pan: only on macOS, where point deltas mean a trackpad Browsers and Wayland smooth-scroll mice report ordinary wheels in points too, so the wheel keeps zooming there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep arc-length dimensions as arc-length through DXF save and reopen (#100) * PLINE: Halfwidth is centre-to-edge, and Width answers taper the next segment (fixes #83, #104) Interactive PLINE kept one width value: Halfwidth answers were stored as the total width, and the ending-width answer overwrote the starting one, so a taper became a constant width. The next segment's starting and ending widths are now tracked separately, Halfwidth answers are doubled, and each new segment (including the closing one) gets its widths on its first vertex; later segments are uniform at the ending width, as in AutoCAD. Uniform polylines are still stored as const_width, so their DXF output is unchanged. Fixes #83. Fixes #104. * Arc-length dimensions: write a standard aligned record plus CADCraft xdata DXF has no arc-length DIMENSION type, so write type 1 and mark the kind and arc centre in CADCRAFT xdata (like ASSOC). Other programs read an aligned dimension; CADCraft restores the arc length, through DXF and DWG. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Desktop: write log records to standard error and a rotating log file The desktop app installed no logger, so every log::warn!/log::error!/ log::info! in the workspace was discarded: a broken app icon, the GPU canvas set-up, the engine's command-line echo at debug level. A launch from a desktop menu has no terminal either, so there was nothing to attach to a bug report. apps/cadcraft/src/logging.rs (no new dependency): - standard error plus <settings dir>/logs/cadcraft.log; each launch rotates the previous log to cadcraft.1.log and .2.log, so the log of a run that crashed survives the next start; the file is capped at 16 MiB - records logged before the settings directory is known are buffered (bounded) and written once the file is attached - default levels: info for cadcraft*, warn for everything else; RUST_LOG replaces them with env_logger-style directives - never panics: an unusable directory or a failed write leaves standard error as the only sink; a poisoned lock is tolerated CADCraft had no per-user directory yet. config_dir in main.rs adds one: CADCRAFT_CONFIG_DIR, else $XDG_CONFIG_HOME/cadcraft or ~/.config/cadcraft (Linux, BSDs), ~/Library/Application Support/CADCraft (macOS), %APPDATA%\CADCraft (Windows). The logger is installed first in main and the file is opened after argument parsing (--version leaves no file). The control server's eprintln!s now go through the logger. A --control or CADCRAFT_CONTROL_PORT value that is not a port is now logged instead of silently leaving the control channel off. Documented in README.md (Quick start > Logs). --------- Co-authored-by: SBaksa <sabaksa11@gmail.com> Co-authored-by: DWAA1660 <dwatnip123@gmail.com> Co-authored-by: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Co-authored-by: lloyd <34131158+LloydNicholson@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com> Co-authored-by: vangel76 <vangel1976@googlemail.com> Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Gert Pellin <gert@pellin.be> |
||
|
|
b731a395df |
Fonts: per-character fallback, FONTALT and .ttc support for CJK text in SHX styles (#173)
* DIMANGULAR: accept polyline segments (fixes #10) Picking a side of a rectangle or a PLINE segment was rejected with "Select a line or an arc." because only LINE and ARC entities were accepted. The picked object is now resolved to the segment under the cursor: straight polyline segments work like lines and arc segments like arcs. * Redraw edits made while a command is still running (fixes #4) LINE and PLINE add geometry on every point, but the canvas only rebuilt its display list when the drawing revision or the document pointer changed. The revision was bumped when a command finished, and the pointer changed only on the first copy-on-write edit, so only the first segment appeared until the command ended. Session::feed now bumps the revision after each input once the running command has changed the drawing. * Fix #14: include DWG in the Open drawing filter * Blocks window: click a block to insert it (#8) Each block name in the Blocks window is now a button. Clicking it starts INSERT with that block already chosen, so the command line asks for the insertion point. * SCALE: Reference option (#17) SCALE > Reference printed "not available yet". It now asks for the reference length (typed, or two points) and the new length (typed, or a point measured from the base point), and scales by new / reference. Zero, negative or non-finite lengths are rejected and asked again. * Print and Ctrl+P ask where to save the PDF (#5) PLOT/EXPORTPDF started from the menu, the toolbar, Ctrl+P or the command line had no path, so the PDF was built in memory and dropped. They now open the save dialog (PDF filter first) and write the file there. JSON calls from scripts, the control channel and MCP still never open a dialog. Ctrl+P was shown in the menu but not bound; it is now. * Scripts: split a line at keyword prompts so POLYGON 6 200,20 I 15 works (#43) * Layer Properties Manager: stop the window growing every frame (fixes #29) The vertical separator between the filter tree and the table takes all the height it is offered, and a resizable window offers its previous height, so the window grew 30px per frame until it filled the screen. Cap the row at the table's fixed height. Regression test runs the dialog headless for 30 frames and checks the height stays put. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ui.render: fit the drawing and return pngBase64 like the headless render (#49, #50) * Linux: default to XWayland for file drag-and-drop on Wayland desktops * Fonts: per-character fallback, FONTALT and .ttc for CJK text in SHX styles (#130) CJK text in a style that uses an SHX font (romans.shx + chineset.shx big font) drew every ideograph as an empty box: the SHX name resolves to our stroke font, which has no CJK glyphs, and the font scan skipped .ttc collections, where most CJK system fonts live. - Per-character fallback: a character the text's font lacks (stroke font or TrueType) is drawn from an installed font that has it, checked by cmap. Wide-coverage fonts go first (Noto Sans CJK, Source Han, WenQuanYi, Droid Sans Fallback, PingFang, Microsoft JhengHei/YaHei, MS Gothic, ...), regular weights before others. Fallback glyphs are sized like TrueType text (cap height = text height). Lookups are cached; the search is bounded (24 files, 160 MiB, 256 faces per character, files over 96 MiB never read) and skips spaces, controls and private-use code points. No fallback: the box as before. - FONTALT (sysvar, seeded from CADCRAFT_FONTALT): font used for a style font that can't be found (an SHX file, a missing TTF). Empty = our stroke font. - FONTFALLBACK (sysvar, seeded from CADCRAFT_FONTFALLBACK): fonts tried first for missing characters, e.g. "Noto Sans CJK TC". - .ttc/.otc are scanned; TextFont::Outline carries a ttf::Face (bytes + face index). Fonts are also found by family name among files with a similar stem, so "Noto Sans CJK TC" picks face 3 of NotoSansCJK-Regular.ttc. - Cap height falls back to the height of "H" when OS/2 has none (DejaVu Sans), which fixes ttf_tests::system_font_outlines_when_available and render's truetype_text_is_filled_or_outlined on machines without Arial. - README: a Fonts section for the two settings; ROADMAP M4 note. Native SHX / big-font rendering stays on the roadmap (M4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fonts: cap the total bytes of system font files loaded from disk A drawing naming many text styles could otherwise load every installed font into memory through family-name lookups. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pan with a two-finger trackpad swipe; keep wheel and pinch zoom Trackpad two-finger swipes arrive as scroll events, and the canvas turned every scroll into a zoom, so trackpad users had no realtime pan (middle-drag needs a middle button). Scroll now follows the device: precise point deltas (trackpad, Magic Mouse) pan the view by x and y; notched line deltas (mouse wheel) zoom about the cursor as before. Pinch and Cmd+scroll still zoom through zoom_delta, and middle-drag still pans. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr * Add Tru10 to contributors/people.toml Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr * Trackpad pan: only on macOS, where point deltas mean a trackpad Browsers and Wayland smooth-scroll mice report ordinary wheels in points too, so the wheel keeps zooming there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep arc-length dimensions as arc-length through DXF save and reopen (#100) * PLINE: Halfwidth is centre-to-edge, and Width answers taper the next segment (fixes #83, #104) Interactive PLINE kept one width value: Halfwidth answers were stored as the total width, and the ending-width answer overwrote the starting one, so a taper became a constant width. The next segment's starting and ending widths are now tracked separately, Halfwidth answers are doubled, and each new segment (including the closing one) gets its widths on its first vertex; later segments are uniform at the ending width, as in AutoCAD. Uniform polylines are still stored as const_width, so their DXF output is unchanged. Fixes #83. Fixes #104. * Arc-length dimensions: write a standard aligned record plus CADCraft xdata DXF has no arc-length DIMENSION type, so write type 1 and mark the kind and arc centre in CADCRAFT xdata (like ASSOC). Other programs read an aligned dimension; CADCraft restores the arc length, through DXF and DWG. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Desktop: write log records to standard error and a rotating log file The desktop app installed no logger, so every log::warn!/log::error!/ log::info! in the workspace was discarded: a broken app icon, the GPU canvas set-up, the engine's command-line echo at debug level. A launch from a desktop menu has no terminal either, so there was nothing to attach to a bug report. apps/cadcraft/src/logging.rs (no new dependency): - standard error plus <settings dir>/logs/cadcraft.log; each launch rotates the previous log to cadcraft.1.log and .2.log, so the log of a run that crashed survives the next start; the file is capped at 16 MiB - records logged before the settings directory is known are buffered (bounded) and written once the file is attached - default levels: info for cadcraft*, warn for everything else; RUST_LOG replaces them with env_logger-style directives - never panics: an unusable directory or a failed write leaves standard error as the only sink; a poisoned lock is tolerated CADCraft had no per-user directory yet. config_dir in main.rs adds one: CADCRAFT_CONFIG_DIR, else $XDG_CONFIG_HOME/cadcraft or ~/.config/cadcraft (Linux, BSDs), ~/Library/Application Support/CADCraft (macOS), %APPDATA%\CADCraft (Windows). The logger is installed first in main and the file is opened after argument parsing (--version leaves no file). The control server's eprintln!s now go through the logger. A --control or CADCRAFT_CONTROL_PORT value that is not a port is now logged instead of silently leaving the control channel off. Documented in README.md (Quick start > Logs). --------- Co-authored-by: SBaksa <sabaksa11@gmail.com> Co-authored-by: DWAA1660 <dwatnip123@gmail.com> Co-authored-by: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Co-authored-by: lloyd <34131158+LloydNicholson@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com> Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Tru10 <133776756+Tru10@users.noreply.github.com> Co-authored-by: Gert Pellin <gert@pellin.be> |
||
|
|
3e7e0bdf2a |
Linux: default to XWayland for file drag-and-drop on Wayland desktops (#159)
* DIMANGULAR: accept polyline segments (fixes #10) Picking a side of a rectangle or a PLINE segment was rejected with "Select a line or an arc." because only LINE and ARC entities were accepted. The picked object is now resolved to the segment under the cursor: straight polyline segments work like lines and arc segments like arcs. * Redraw edits made while a command is still running (fixes #4) LINE and PLINE add geometry on every point, but the canvas only rebuilt its display list when the drawing revision or the document pointer changed. The revision was bumped when a command finished, and the pointer changed only on the first copy-on-write edit, so only the first segment appeared until the command ended. Session::feed now bumps the revision after each input once the running command has changed the drawing. * Fix #14: include DWG in the Open drawing filter * Blocks window: click a block to insert it (#8) Each block name in the Blocks window is now a button. Clicking it starts INSERT with that block already chosen, so the command line asks for the insertion point. * SCALE: Reference option (#17) SCALE > Reference printed "not available yet". It now asks for the reference length (typed, or two points) and the new length (typed, or a point measured from the base point), and scales by new / reference. Zero, negative or non-finite lengths are rejected and asked again. * Print and Ctrl+P ask where to save the PDF (#5) PLOT/EXPORTPDF started from the menu, the toolbar, Ctrl+P or the command line had no path, so the PDF was built in memory and dropped. They now open the save dialog (PDF filter first) and write the file there. JSON calls from scripts, the control channel and MCP still never open a dialog. Ctrl+P was shown in the menu but not bound; it is now. * Scripts: split a line at keyword prompts so POLYGON 6 200,20 I 15 works (#43) * Layer Properties Manager: stop the window growing every frame (fixes #29) The vertical separator between the filter tree and the table takes all the height it is offered, and a resizable window offers its previous height, so the window grew 30px per frame until it filled the screen. Cap the row at the table's fixed height. Regression test runs the dialog headless for 30 frames and checks the height stays put. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ui.render: fit the drawing and return pngBase64 like the headless render (#49, #50) * Linux: default to XWayland for file drag-and-drop on Wayland desktops * Fonts: per-character fallback, FONTALT and .ttc for CJK text in SHX styles (#130) CJK text in a style that uses an SHX font (romans.shx + chineset.shx big font) drew every ideograph as an empty box: the SHX name resolves to our stroke font, which has no CJK glyphs, and the font scan skipped .ttc collections, where most CJK system fonts live. - Per-character fallback: a character the text's font lacks (stroke font or TrueType) is drawn from an installed font that has it, checked by cmap. Wide-coverage fonts go first (Noto Sans CJK, Source Han, WenQuanYi, Droid Sans Fallback, PingFang, Microsoft JhengHei/YaHei, MS Gothic, ...), regular weights before others. Fallback glyphs are sized like TrueType text (cap height = text height). Lookups are cached; the search is bounded (24 files, 160 MiB, 256 faces per character, files over 96 MiB never read) and skips spaces, controls and private-use code points. No fallback: the box as before. - FONTALT (sysvar, seeded from CADCRAFT_FONTALT): font used for a style font that can't be found (an SHX file, a missing TTF). Empty = our stroke font. - FONTFALLBACK (sysvar, seeded from CADCRAFT_FONTFALLBACK): fonts tried first for missing characters, e.g. "Noto Sans CJK TC". - .ttc/.otc are scanned; TextFont::Outline carries a ttf::Face (bytes + face index). Fonts are also found by family name among files with a similar stem, so "Noto Sans CJK TC" picks face 3 of NotoSansCJK-Regular.ttc. - Cap height falls back to the height of "H" when OS/2 has none (DejaVu Sans), which fixes ttf_tests::system_font_outlines_when_available and render's truetype_text_is_filled_or_outlined on machines without Arial. - README: a Fonts section for the two settings; ROADMAP M4 note. Native SHX / big-font rendering stays on the roadmap (M4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fonts: cap the total bytes of system font files loaded from disk A drawing naming many text styles could otherwise load every installed font into memory through family-name lookups. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pan with a two-finger trackpad swipe; keep wheel and pinch zoom Trackpad two-finger swipes arrive as scroll events, and the canvas turned every scroll into a zoom, so trackpad users had no realtime pan (middle-drag needs a middle button). Scroll now follows the device: precise point deltas (trackpad, Magic Mouse) pan the view by x and y; notched line deltas (mouse wheel) zoom about the cursor as before. Pinch and Cmd+scroll still zoom through zoom_delta, and middle-drag still pans. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr * Add Tru10 to contributors/people.toml Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr * Trackpad pan: only on macOS, where point deltas mean a trackpad Browsers and Wayland smooth-scroll mice report ordinary wheels in points too, so the wheel keeps zooming there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep arc-length dimensions as arc-length through DXF save and reopen (#100) * PLINE: Halfwidth is centre-to-edge, and Width answers taper the next segment (fixes #83, #104) Interactive PLINE kept one width value: Halfwidth answers were stored as the total width, and the ending-width answer overwrote the starting one, so a taper became a constant width. The next segment's starting and ending widths are now tracked separately, Halfwidth answers are doubled, and each new segment (including the closing one) gets its widths on its first vertex; later segments are uniform at the ending width, as in AutoCAD. Uniform polylines are still stored as const_width, so their DXF output is unchanged. Fixes #83. Fixes #104. * Arc-length dimensions: write a standard aligned record plus CADCraft xdata DXF has no arc-length DIMENSION type, so write type 1 and mark the kind and arc centre in CADCRAFT xdata (like ASSOC). Other programs read an aligned dimension; CADCraft restores the arc length, through DXF and DWG. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Desktop: write log records to standard error and a rotating log file The desktop app installed no logger, so every log::warn!/log::error!/ log::info! in the workspace was discarded: a broken app icon, the GPU canvas set-up, the engine's command-line echo at debug level. A launch from a desktop menu has no terminal either, so there was nothing to attach to a bug report. apps/cadcraft/src/logging.rs (no new dependency): - standard error plus <settings dir>/logs/cadcraft.log; each launch rotates the previous log to cadcraft.1.log and .2.log, so the log of a run that crashed survives the next start; the file is capped at 16 MiB - records logged before the settings directory is known are buffered (bounded) and written once the file is attached - default levels: info for cadcraft*, warn for everything else; RUST_LOG replaces them with env_logger-style directives - never panics: an unusable directory or a failed write leaves standard error as the only sink; a poisoned lock is tolerated CADCraft had no per-user directory yet. config_dir in main.rs adds one: CADCRAFT_CONFIG_DIR, else $XDG_CONFIG_HOME/cadcraft or ~/.config/cadcraft (Linux, BSDs), ~/Library/Application Support/CADCraft (macOS), %APPDATA%\CADCraft (Windows). The logger is installed first in main and the file is opened after argument parsing (--version leaves no file). The control server's eprintln!s now go through the logger. A --control or CADCRAFT_CONTROL_PORT value that is not a port is now logged instead of silently leaving the control channel off. Documented in README.md (Quick start > Logs). --------- Co-authored-by: SBaksa <sabaksa11@gmail.com> Co-authored-by: DWAA1660 <dwatnip123@gmail.com> Co-authored-by: MarekSpodBiedry <73122968+MarekSpodBiedry@users.noreply.github.com> Co-authored-by: lloyd <34131158+LloydNicholson@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: vangel76 <vangel1976@googlemail.com> Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Tru10 <133776756+Tru10@users.noreply.github.com> Co-authored-by: Gert Pellin <gert@pellin.be> |
||
|
|
3886add967 | ui.render: fit the drawing and return pngBase64 like the headless render (#49, #50) (#52) | ||
|
|
5cbc4f078e |
Layer Properties Manager: stop the window growing every frame (fixes #29) (#46)
The vertical separator between the filter tree and the table takes all the height it is offered, and a resizable window offers its previous height, so the window grew 30px per frame until it filled the screen. Cap the row at the table's fixed height. Regression test runs the dialog headless for 30 frames and checks the height stays put. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
415da86d39 | Scripts: split a line at keyword prompts so POLYGON 6 200,20 I 15 works (#43) (#45) | ||
|
|
8995fb9174 |
Blocks window: click a block to insert it (#8) (#28)
Each block name in the Blocks window is now a button. Clicking it starts INSERT with that block already chosen, so the command line asks for the insertion point. |
||
|
|
a1df2f2c8c |
SCALE: Reference option (#17) (#27)
SCALE > Reference printed "not available yet". It now asks for the reference length (typed, or two points) and the new length (typed, or a point measured from the base point), and scales by new / reference. Zero, negative or non-finite lengths are rejected and asked again. |
||
|
|
986307f764 |
Print and Ctrl+P ask where to save the PDF (#5) (#26)
PLOT/EXPORTPDF started from the menu, the toolbar, Ctrl+P or the command line had no path, so the PDF was built in memory and dropped. They now open the save dialog (PDF filter first) and write the file there. JSON calls from scripts, the control channel and MCP still never open a dialog. Ctrl+P was shown in the menu but not bound; it is now. |
||
|
|
3278c58942 | Fix #14: include DWG in the Open drawing filter (#21) | ||
|
|
093c87d08a |
DIMANGULAR: accept polyline segments (fixes #10) (#15)
Picking a side of a rectangle or a PLINE segment was rejected with "Select a line or an arc." because only LINE and ARC entities were accepted. The picked object is now resolved to the segment under the cursor: straight polyline segments work like lines and arc segments like arcs. |
||
|
|
698f2c8c36 |
Redraw edits made while a command is still running (fixes #4) (#22)
LINE and PLINE add geometry on every point, but the canvas only rebuilt its display list when the drawing revision or the document pointer changed. The revision was bumped when a command finished, and the pointer changed only on the first copy-on-write edit, so only the first segment appeared until the command ended. Session::feed now bumps the revision after each input once the running command has changed the drawing. |
||
|
|
8be4b9b01c |
Default Windows startup to DirectX 12 (#31)
eframe's default wgpu instance enables PRIMARY | GL on Windows. Creating the OpenGL backend can crash inside AMD's atio6axx.dll before the window appears, so the app exits silently at launch. When WGPU_BACKEND is not set, the Windows instance now enables only DirectX 12; an explicit WGPU_BACKEND is still honoured. macOS, Linux and web are unchanged. Same fix as storytold/designcraft#168 and storytold/filmcraft#179. Claude-Session: https://claude.ai/code/session_01LyVbT6Vv4BwWZ4hY8973qD Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
f3c1e121d2 |
macOS: the delete key erases the selection, guarded against typing (#64)
The key labelled "delete" on a Mac sends Backspace, and only forward Delete (fn+delete) erased the selection, so the obvious key did nothing. On macOS (native, and the web build via egui's user-agent detection), Backspace now erases selected objects, but only when it can't be meant for the command line: - a fresh press, never an auto-repeat, so holding delete to clear typing can't run on into the drawing; - a plain press: Option/Cmd+delete delete a word or line of text on macOS; - no command running and the command line empty; - nothing typed at the command line since the selection was made (typing, then clearing it, leaves delete editing text until the selection changes). Windows and Linux are unchanged: Backspace only edits the command line there. The decision is a small pure function with unit tests. Claude-Session: https://claude.ai/code/session_019uMCkRAB8DMd8MEmoY9Vyr Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
8b13fa3b17 | fix(cadcraft-cli): reject unknown options (#120) | ||
|
|
348d3b6724 |
Extents: a wide polyline's bounds follow its drawn band (fixes #90) (#127)
Polyline extents were the centre line padded by const_width / 2, so per-segment start/end widths never counted: a band built from vertex widths, a taper, or segments of different widths reported the zero-height bounds of the centre line. The bounds now enclose the filled band of every segment as it is drawn: the exact corners of straight segments (tapers included), and both edges of arc segments, sampled along the arc with the width interpolated and widened by the sampling tolerance so they are never too small. The constant width still wins over vertex widths, the end vertex of an open polyline starts no segment, and non-finite or negative widths count as zero. Thin polylines take the same path as before. Fixes #90. |
||
|
|
3c577968f6 |
ARC: refuse zero-radius arcs instead of adding them (fixes #85) (#123)
The `arc` command checked its three-point form for collinear points but added the arcs built by its start/center/end and center/radius forms unchecked, so radius 0 (or a start point on the center) added a degenerate Arc, dirtied the drawing and recorded an undo step. Every form now goes through the existing finite_arc check and fails with the same "these values do not define an arc" error the arc.* variants and the interactive ARC already use, leaving the drawing unchanged. Fixes #85. |
||
|
|
882c4d67a6 | Keep dimension text rotation when saving DXF (#78) (#153) | ||
|
|
3e0de7e4eb | Keep a free measured origin in place when its source moves (#109) (#152) | ||
|
|
083a3f095d | Use macOS-margin runtime app icon on macOS (#128) | ||
|
|
8fe9baddb5 |
Menu commands open their dialogs; JSON calls never open file pickers (fixes #65, fixes #101) (#125)
* Render tests: drop the always-true assert in degenerate_input `assert!(... || true)` trips clippy's overly_complex_bool_expr on current stable (1.96), which fails `cargo xtask ci` at the clippy step. The check only proves that NaN input does not panic, so call the function and discard the result instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Menu commands open their dialogs; JSON calls never open pickers (#65, #101) Tools > Drafting Settings... (DSETTINGS, DS, SE) ran the JSON form with no parameters, which changed nothing, so the menu item looked dead; only the status-bar gear opened the dialog. Typed or menu-invoked DSETTINGS now opens the Drafting Settings dialog, and PROPERTIES (PR, CH) shows the Properties palette. The engine's OPEN, SAVEAS and QSAVE opened a native file picker whenever their parameters had no path, so `engine.execute` and the bridged MCP `execute` tool could block on a desktop dialog. They now ask for a file only when typed or chosen from a menu; JSON calls get the command's own missing-path error. The ui.open / ui.saveas commands (Cmd+O, Cmd+Shift+S) still open the pickers. Typing the `cmd {json}` form at the command line (e.g. `layer {}`) no longer opens the command's dialog or picker; the engine runs it with those parameters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
1fdee1a1a4 |
Ask Save / Don't Save / Cancel before closing a dirty drawing (#124) (#172)
File > Close, a file tab's x and File > Close All ran the engine's
close/closeall directly, which drop the drawing. Nothing checked for
unsaved changes on any platform; the web report just made it visible.
- New ui-egui `closing` module: close requests from the UI go through a
queue of drawings (by DocState uid). A dirty drawing is shown and asked
about in an in-app egui modal ("Save changes to X?" Save / Don't Save /
Cancel, Escape = Cancel), the same on desktop and web.
- Save routes to the existing qsave path (picker for untitled drawings)
and closes only if the drawing is really clean afterwards; otherwise it
stays open with its edits and a status message.
- Close All asks per dirty drawing in tab order; Cancel stops it.
- Menu, typed CLOSE/CLOSEALL (null params) and the tab x use the prompt;
JSON calls (engine.execute, control, MCP, scripts) keep discarding
without asking.
- Shortcuts are paused while the prompt is open; ui.inspect reports
`closePrompt`.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|
|
3dd97cad56 |
Linux: present without a vsync queue so the crosshair follows the mouse (#25) (#183)
* Linux: present without a vsync queue so the crosshair follows the mouse (#25) The canvas hides the OS pointer and draws its own crosshair, so every frame the swapchain holds back shows as cursor lag. Under vsync (FIFO) wgpu asks for one queued frame, but Vulkan clamps it to the driver's minimum swapchain size: three images on X11 (Linux Mint's Cinnamon session), i.e. two frames queued behind the one on screen. Windows DX12 honours one. The canvas also requested a repaint on every frame while hovered, which kept that queue full. - gpu::surface_config: AutoNoVsync (Immediate, then Mailbox, then FIFO; valid on every surface) on Linux/BSD, frame latency 1. CADCRAFT_VSYNC=1 restores vsync, CADCRAFT_VSYNC=0 selects low latency elsewhere. - gpu::FrameCap (240 fps) when presenting without vsync: nothing else paces frames on X11, and a 1000 Hz input stream rendered ~900 frames per second. - No continuous repaint while hovering the canvas; input repaints by itself. The status-bar message schedules its own repaint to clear on time. - Hover/selection highlight looks up primitives in a per-list sorted index instead of scanning the whole display list every frame (~2.5 ms per frame on a 270k-entity drawing). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Move frame-cap and status-repaint hunks away from other PRs' to avoid merge conflicts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
a349e4925f |
Command line, ViewCube and UCS icon take the pointer; history window (F2) (#181)
Clicks on the command line's history, the UCS icon and the ViewCube ring fell through to the drawing (picking objects or starting a selection window, or entering a point during a command), the chevron did nothing, and the wheel over the overlays zoomed the drawing. The ViewCube's Top face was a click-only widget, so the canvas still counted as hovered underneath it (crosshair, wheel). - Every overlay now registers a widget that senses clicks and drags, so egui hands the pointer to the overlay instead of the canvas. - Command line: a click on the history lines or the chevron (now pointing up) opens a scrollable history window with the whole log; F2 and TEXTSCR open it too (`ui.toggle.history`, Window > Command History). Dragging the history's top edge sets how many lines show (`ui.cmdline.lines`, 0-12). - ViewCube (new viewcube.rs): Top face and a Home button run `zoom.extents`; hover highlights; right-click menu (Home, Hide ViewCube). The compass ring says that the 2D plan view can't rotate (no view twist yet) instead of doing nothing. - UCS icon and the WCS pill open the coordinate-system menu (World, Hide UCS Icon). - Control channel: `ui.drag` (real press, move, release) and `cmdline.state` -> `historyExpanded`. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
24a3954b39 |
Light and System interface themes (System follows the OS appearance live) (#179)
* Light and System interface themes (System follows the OS appearance live)
CADCraft had one hard-coded dark interface: Tokens::get() always returned
Tokens::DARK and Visuals::dark() was installed once at startup.
- theme.rs: Tokens::LIGHT (light grey chrome, dark text) beside the unchanged
Tokens::DARK; Tokens::get() returns the palette of the theme in use (a
UI-thread thread-local set once per frame). Both egui styles are built from
the tokens and egui is switched to the shown theme, so standard widgets,
menus and popups follow too. The drawing area (canvas, grid, axes,
selection, grips, ViewCube, UCS icon) keeps its model-space colours in both
themes: drawing colours are not part of the interface theme.
- ThemePref { System, Light, Dark } in UiState (`theme`), resolved every
frame against ctx.system_theme(), so System follows the OS (winit, or the
browser's prefers-color-scheme) live without touching the saved choice.
No reported appearance: System shows Dark (SYSTEM_FALLBACK). Default stays
Dark (today's look).
- View > Interface Theme > Use System Setting / Light / Dark (ui.theme.system,
ui.theme.light, ui.theme.dark) and ui.theme {theme} for scripts and the
control channel; ui.inspect reports the theme shown.
- Hard-coded colours on the command line (history, border, keywords,
AutoComplete list), the status-bar message and the layer status icon go
through tokens; overlays drawn on the canvas use a new canvas_ink token.
- Desktop app: the choice persists via eframe storage (`persistence`
feature, key cadcraft.prefs); window geometry and egui memory are not
persisted, as before.
Fixes #59.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Document the theme field away from other PRs' edits to avoid merge conflicts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|
|
b7be0a5fda |
Windows installer: offer a desktop shortcut (#32) (#184)
The MSI gets a setup wizard (WixUI dialogs, no licence or folder page) with a Shortcuts page: the Start Menu shortcut as before, plus an opt-in "Create a desktop shortcut" checkbox bound to DESKTOPSHORTCUT. Silent installs take DESKTOPSHORTCUT=1. The shortcut goes on the all-users desktop (per-machine install) in its own component with an HKCU key path (ICE38/43/57), so uninstall removes it; upgrades read that value back and keep the previous choice unless DESKTOPSHORTCUT is given. The build now needs WixToolset.UI.wixext 5.0.2 (release workflow and package.ps1 updated). Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
14cffbcbe6 |
MCP plate test: finish TEXT before undo and check the centre line survives (#171)
The scripted TEXT ended with a single newline, so TEXT was still asking for the next line when the test ran undo. Undo then reverted to before the centre line (taking the uncommitted text with it), and the only post-undo check, "no Text", passed anyway. The script now ends TEXT with a blank line (Enter), as an AutoCAD script would, and the test asserts no command is running afterwards. After undo it checks that exactly the text was undone and that the four circles, the outline and the Center-layer line are still there. Fixes #51. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
396b098d9a |
CLI: image exports honour the current view and take --window/--view (fixes #165) (#170)
`convert` and `run --export` always fitted the model-space extents, so `zoom`, `pan` or `view.set` in a run had no effect on the image and there was no way to export a region. - io: `write_framed(d, name, window)` frames PNG, SVG and PDF on a model-space rectangle (fitted without margin, centred, no distortion); `write` is unchanged and still fits the extents. `check_window` rejects non-finite, inverted, zero-size and out-of-range (±1e12) windows. - CLI: `run --export` shows the current view when the commands changed it, otherwise the extents as before. `--window x0,y0,x1,y1` and `--view extents|current` on `convert` and `run` choose the framing explicitly. The usage text and README say how images are framed. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
bcbbc5e8a4 |
cadcraft-cli mcp: --connect without HOST:PORT is an error, not a headless session (fixes #103) (#167)
* cadcraft-cli mcp: --connect without HOST:PORT is an error, not a headless session (#103) `mcp --connect` with no address (or an empty or flag-like one) fell through to the headless backend, so a client meant for the app got successful edits in a separate drawing. The mcp arguments now go through parse_mcp_args: --connect must be followed by a non-empty value that doesn't start with `-`, unknown arguments and a repeated --connect are rejected, and every error exits non-zero before any MCP request is served. Plain `mcp` is still headless; a real address still connects, and an unreachable one still fails. - Unit tests for the parser; integration tests (tests/mcp_connect.rs) run the binary: missing/empty/flag-like address, headless control, loopback endpoint routing, closed port. - docs/mcp.md says what happens without an address. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Move tests away from other PRs' hunks to avoid merge conflicts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
6c145ed733 |
Menu items open their missing dialogs; COUNT shows its result; New Layout asks for a name (#126, part 1) (#180)
* Menu items open their missing dialogs; COUNT shows its result; New Layout asks for a name (#126) Eight menu items ran their JSON form with no parameters and changed nothing. Typed or chosen from a menu they now do what the menu promises; JSON calls still run the command and never open a dialog. - New crates/ui-egui/src/managers.rs: Linetype Manager (load from the library, set current, global scale, pattern preview), Point Style (PDMODE tiles drawn in code, size relative/absolute), Table Style and Multileader Style (list, set current, new, edit properties), Page Setup Manager (per layout: paper, orientation, plot area, fit/scale, center, lineweights) and Constraint Settings (infer, bars, transparency, dynamic constraints, AutoConstrain types and tolerances). All changes go through their commands (app.run), so they are undoable and scriptable. - menus::run_ui_command routes LINETYPE/LT, DDPTYPE, TABLESTYLE/TS, MLEADERSTYLE/MLS, PAGESETUP and CONSTRAINTSETTINGS/CSETTINGS without parameters to the dialogs; dialogs::show dispatches them. - COUNT returns a `message` (per-block counts and total) that the command line shows; Session::start echoes multi-line messages line by line. - LAYOUT.NEW from the menu or command line prompts "Enter name of new layout <LayoutN>:"; Enter takes the default, a taken or invalid name is reported and asked again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Move COUNT test away from other PRs' hunks to avoid merge conflicts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
8d71f7de4a |
Properties palette: every control acts or is visibly unavailable (#182)
* Properties palette: every control acts or is visibly unavailable (#6) Several Properties palette controls looked clickable but did nothing: most current-property rows with nothing selected (linetype, lineweight, thickness, text/dimension/multileader/table style), the selection-type drop-down, a circle's circumference and area, a line's length and angle, a dimension's style, and the All/My switch. - Nothing selected: Linetype runs `linetype {current}`, Lineweight `lweight`, Thickness `setvar THICKNESS`, the style rows `style.current`, `dimstyle.current`, `mleaderstyle` and `tablestyle`. Transparency, Annotation scale and Plot style(s) have no command yet: greyed with a "Not available yet" tooltip. - Header: the type drop-down narrows the selection to one object type (`select {handles}`), plus Toggle PICKADD (`setvar PICKADD`), Select Objects (`select`) and Quick Select buttons, with icons drawn in code. - Geometry: circle circumference/area, line length/angle and dimension style are editable through `properties.set` (new keys `circumference`, `area`, `dimStyle`); computed values (line deltas, polyline length/area, block name) are greyed read-only. - PICKADD now changes clicking with no command running: off, each pick replaces the selection and Shift adds. - Palette text fields keep typed text while the window itself is unfocused (they read focus from egui memory, not `Response::has_focus`). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Move palette tests away from other PRs' hunks to avoid merge conflicts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
306ba991a5 |
Selection commands prompt "Select objects" without a pickfirst selection (#126) (#176)
Edit > Cut / Copy / Copy with Base Point, View > Zoom > Object, Dimension >
Update, Tools > Draw Order > Bring to Front / Send to Back and the Format >
Layer Tools LAYCUR, LAYFRZ, LAYOFF, LAYLCK and LAYULK did nothing when started
from a menu, toolbar or the command line with nothing selected.
- machines::SelectRun: "Select objects:", then run the command's JSON body on
the picked handles. With a pickfirst selection it runs at once, as before.
It replaces the DIMREASSOCIATE/DIMDISASSOCIATE SelectThen in annotate.rs and
calls the command body directly, so the command records one undo step.
- LAYFRZ/LAYOFF/LAYLCK/LAYULK pick one object ("Select an object on the layer
to be frozen" etc.).
- COPYBASE asks for the base point first, then for objects (skipped with a
pickfirst selection).
- Objects picked at the prompt are deselected afterwards.
- JSON/programmatic calls are unchanged and never prompt.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|
|
7666c1cd68 |
LINE: deferred tangent/perpendicular for the first point (fixes #69) (#168)
TAN and PER snaps need the other end of the line, so the first point of a LINE (no base point yet) could never snap tangent: a belt line tangent to two circles was impossible to draw. Now, as in AutoCAD, a point prompt can accept *deferred* snaps: - snap: with no base and the new `deferred` flag, osnap offers "Deferred Tangent" (circles, arcs) and "Deferred Perpendicular" (circles, arcs, lines, xlines, rays) where no other snap wins. The hit carries the curve (`SnapHit::deferred`, `Deferred`, `SnapCurve`). - `resolve_deferred` solves the line once the other end is known: tangent or perpendicular from a point, tangent-to-tangent (common tangents of two circles, new `Circle::common_tangents` in geom) and the perpendicular mixes. Among several solutions the one nearest the picks wins. No solution (point inside the circle, concentric or nested circles, non-finite input) is `None`, never a panic. - prompt: `Prompt::deferred()` opts a prompt in; `Input::Deferred` reaches only such prompts, everywhere else the session turns it into the point it was picked at, so other commands snap as before. - LINE opts in for its first point (and the next one while the first is still deferred). No solution reports and re-prompts; Undo drops the deferred point. The rubber band shows the resolved line, also the tangent-to-tangent one while hovering the second curve (`Session::cursor_deferred`, set by the canvas). - canvas: passes the prompt's flag to osnap and sends a deferred pick as `Input::Deferred`. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
4d61f57eec |
HATCH/GRADIENT/BOUNDARY: islands made of separate lines (fixes #106) (#163)
Point picks found the outer boundary by tracing the planar graph of all curves, but islands only came from single closed objects (circles, closed polylines, full ellipses, closed splines). A square drawn as four LINEs inside a rectangle was ignored: HATCH drew through it, GRADIENT filled it and BOUNDARY created only the outer polyline. - geom::region::boundary_at returns the outer loop plus islands: every connected group of curves inside the face that doesn't touch its boundary and doesn't surround the pick point. Each island is the outline of the group's outside, traced with the same sharpest-turn walk from its leftmost vertex after dangling ends are pruned. Islands report which input curves they came from. Traces are bounded by the group's edge count and islands are capped at MAX_ISLANDS. - loops_at (shared by HATCH, GRADIENT and BOUNDARY) adds those islands when every curve in the group is an open LINE, ARC, elliptical arc, open polyline or open spline. Groups containing a closed object keep the existing per-object islands, so closed-polyline and circle islands are unchanged (bulges kept). - Tests: geom region tests for separate-line islands, dangling ends, open and attached curves, nesting and hostile input; engine tests for HATCH (rendered pattern stays out of the hole), GRADIENT (375 filled, hole clear) and BOUNDARY (two polylines) with four-line and closed-polyline islands. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
61875b1f0c |
DWG open: stop runaway conversions early and name the limit (#57) (#175)
* DWG open: stop runaway conversions early, name the limit (#57) "file too large" was the DXF reader's 50,000,000 group-code cap (MAX_TAGS), not a file-size limit. For a DWG it was only checked at the very end: after acadrust had read the whole file, written all of its DXF text into one Vec, the text had been copied again for decoding, and 50 million tags had been parsed. A real 10 MB DWG is nowhere near the cap (a synthetic 10 MB AC1024 file is 3.7 million group codes and opens in about 2 s). A damaged file, or objects the DWG reader misreads, can be: acadrust caps every count at 100,000 and reads zeros past the end of the data, so one desynchronised object becomes a polyline with 100,000 vertices. A fuzzed 0.25 MB AC1024 file made it write 11 GB of DXF. - cadcraft-dwg: Limits { max_dwg_bytes: 512 MB, max_dxf_bytes: 1 GB }. The DWG size is checked before the reader runs; the DXF is streamed into a writer that fails as soon as it passes the limit, so the conversion stops there instead of filling memory. Both errors give actual and allowed sizes. The input is no longer copied, and the DXF writer also runs under catch_unwind. - cadcraft-dxf: TooLarge { tags, limit } says "drawing too large: N DXF group codes, more than the 50000000 CADCraft reads". For ASCII the count comes from the line count before any decoding or tag allocation. Valid UTF-8 text is borrowed instead of copied. MAX_TAGS is public and unchanged. - cadcraft-io: errors from the DXF converted from a DWG say so. On the fuzzed file: before, 76 s and 13.4 GB, then the process aborted copying the 11 GB text (under a 16 GB memory limit). After, 15 s and 5.3 GB, with "DWG: converting this 0.2 MB file produced more than 1024 MB of drawing data (the limit); ...". What's left is acadrust's reader itself (8 s, 5.3 GB on that file), which this bridge can't bound without patching the crate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Move tests away from other PRs' hunks to avoid merge conflicts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
7497618f76 |
fix(engine): programmatic undo/redo ends a running command first (#178)
* Programmatic undo/redo ends a running command first (#177) `undo` or `redo` run through engine.execute, MCP, the control channel or a script while an interactive command was still running (e.g. TEXT waiting for another line) swapped the drawing under that command. Interactive commands push their undo step only when they end, so `undo` popped the previous command's step instead: it removed the earlier geometry, dropped the running command's entities, and left the command running from a stale state. Both commands now first end the running command the way Esc does, exactly as Session::start already does for Cmd+Z, the menu and the command line. The command's work so far becomes one undo step, and `undo` then removes that step. Regression test: programmatic_undo_during_a_command_ends_it_first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Move test away from other PRs' hunks to avoid merge conflicts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
bacb951059 |
DXF: write non-ASCII text as \U+ escapes so R2000 files read correctly elsewhere (fixes #164) (#169)
* DXF: write non-ASCII text as \U+ escapes so AC1015 files stay valid (#164) The writer declares $ACADVER AC1015 (R2000) and $DWGCODEPAGE ANSI_1252, where text is in the code page, but wrote strings as raw UTF-8. Every other reader decoded those bytes as CP1252 and turned non-ASCII text into mojibake; only CADCraft (which tries UTF-8 first) read its own files back correctly. - cadcraft_dxf::write_ascii now writes pure ASCII: every non-ASCII character in a string group becomes the pre-R2007 \U+XXXX escape (UTF-16 code units, so characters above U+FFFF are a surrogate pair of escapes). This covers TEXT, MTEXT, ATTRIB/ATTDEF, table, block and layer names, xdata and XRECORD strings alike. The header and the R2000 structure are unchanged, so the DWG bridge (acadrust, which decodes the escapes) behaves as before. - The reader combines surrogate-pair escapes, requires four hex digits, keeps malformed escapes and unpaired surrogates as literal text, and now also unescapes strings in binary DXF. - Tests: R2000 save/reopen of CJK, Latin-1 and astral text in TEXT, MTEXT, a layer name, a block name and ATTRIB/ATTDEF; pure-ASCII output with the AC1015/ANSI_1252 header; UTF-8 (AC1032) and code-page (AC1015) input still read; DWG round trip; hostile escapes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Move code and tests away from other PRs' hunks to avoid merge conflicts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
3fe93806b7 |
Entity transparency: set it, report it, round-trip DXF group 440 (#174)
properties.set documented `transparency` but never read it, nothing reported it, and DXF dropped group 440. Fixes #132. - properties.set takes "ByLayer", "ByBlock" or a percentage 0..90 (a number or "50"/"50%"); anything else (out of range, NaN, junk) is an error and leaves the selection unchanged. - properties and drawing.inspect / drawing.entities report it in the same form. - Properties palette: the Transparency row is a menu (ByLayer, ByBlock, a 0..90 percentage) that acts through properties.set. - DXF: entities write 440 unless ByLayer (ByBlock 0x01000000, a percentage its alpha | 0x02000000, the alpha mapping layers use); the reader parses it back, any other value reads as ByLayer. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
0cdde077ef |
DXF: keep layer transparency and description through save and reopen (fixes #96, fixes #97) (#131)
* Render tests: drop the always-true assert in degenerate_input `assert!(... || true)` trips clippy's overly_complex_bool_expr on current stable (1.96), which fails `cargo xtask ci` at the clippy step. The check only proves that NaN input does not panic, so call the function and discard the result instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * DXF: keep layer transparency and description through save and reopen (#96, #97) The LAYER writer omitted both properties and the reader left them at their defaults, so a drawing reopened with every layer opaque and every description empty. Both are xdata on the LAYER record, as AutoCAD writes them: - transparency: AcCmTransparency, 1071 = 0x02000000 | alpha, with alpha = (100 - percent) * 255 / 100 (40 % is alpha 153); values that aren't "by alpha" read as opaque - description: AcAecLayerStandard, two 1000 strings (the layer standard's name, unused, then the description), cut to the 255 bytes a 1000 group may hold Both applications are registered in the APPID table. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b7f83a6687 | Keep viewport frozen-layer lists through DXF save and reopen (#98) (#150) | ||
|
|
576e6f9020 | Write LWPOLYLINE elevation (group 38) to DXF (#77) (#142) | ||
|
|
56c39f1c17 | Keep ATTDEF prompt when saving DXF (#81) (#137) | ||
|
|
df1c074fff | Keep an ordinate dimension's datum fixed when its feature moves (#105) (#157) | ||
|
|
947535158a | Store canonical autoTypes names so accepted spellings take effect (#95) (#156) |