Enable in-place editing of inherited properties in the Properties panel:
- Transparency: Switch to PropValue::EditChoice with ByLayer and ByBlock presets to allow direct typing of any numeric percentage value (0..90%) without combo_box autocomplete interference.
- Select-all-on-click: Integrate EditChoice text inputs into build_field_key_map with dedicated widget IDs, preserving click-to-select-all across editable fields.
- Material: Provide bounded preset choices (ByLayer, ByBlock, Global, and active custom material) to avoid scanning large drawing dictionaries.
- Plot style: Implement mode-aware behavior with interactive Choice in STB mode and ReadOnlyWithTooltip in CTB mode.
- Read-only tooltips: Introduce PropValue::ReadOnlyWithTooltip to provide contextual explanations for locked fields while preserving mouse text selection and clipboard copying.
- Dropdown alignment & unified borders: Fix EditChoice internal input/caret background clipping so the container's 1px neutral/active border surrounds the entire control identically to Lineweight and text inputs.
- Document defaults & aggregation: Synchronize document header defaults when editing with No selection, and aggregate heterogeneous multi-selections (*VARIES*).
Implement the AutoCAD compatible HATCHTOBACK (HB) command and enhance the interactive DRAWORDER command pipeline with comprehensive verb selection and viewport entity picking.
Key implementations and architectural details:
1. HATCHTOBACK command execution
* Isolates entities belonging to the active layout block record or global space.
* Filters out entities residing on locked layers using an efficient hash set lookup.
* Records targeted delta undo operations on SortEntitiesTable objects (~100 bytes) rather than snapshotting full document structures.
* Performs granular draw depth cache invalidation via Scene::invalidate_draw_depth, preserving existing geometry tessellations and spatial indices.
* Emits localized user notifications when no qualifying hatch entities are found.
2. Interactive DrawOrderCommand state machine
* Supports preselected entities as well as interactive on demand selection gathering.
* Implements subverb selection supporting single character shortcuts (A for Above, U for Under, F for Front, B for Back) and case insensitive keyword parsing.
* Enables interactive reference object picking directly in the viewport via needs_entity_pick and on_entity_pick callbacks.
* Supports hexadecimal handle specification directly from the command line interface.
3. Ecosystem and system integration
* Bumps DEFAULT_ALIASES_VERSION from 2 to 3 to register the HB alias while preserving existing user overrides.
* Integrates HATCHTOBACK and HB into dynamic autocomplete registries.
* Adds localized message strings across all 20 Fluent translation catalogs.
* Corrects hatch boundary serialization flags to ensure outermost boundary rings consistently carry the external attribute.
Persist camera, render state, and solid fallback geometry across saves. Generate previews from a clean live viewport and refresh recent-file thumbnails immediately.
1. post_stl_export_to_host() now opens the CAM page with
window.open(..., '_blank') instead of window.location().set_href() -
the latter navigated the CAD editor's own tab away, which tears down
its WASM/GPU/worker context. Going back afterward doesn't reliably
restore it, and a user who then hit Save on the broken restored state
would silently overwrite the real file with whatever that broken state
held. A new tab leaves the original completely untouched. (User report:
CAM froze on load, then going back and saving "blanked" the file.)
2. save_with_default_format(): a plain Save (not Save As) on an
already-loaded document used to ALWAYS serialize using the hardcoded
default format (DWG 2018), ignoring what the document actually was -
confirmed live via a real corrupted attachment (a .dxf that, after one
Save, contained binary DWG bytes under its original .dxf name and
filename, size dropped ~11.6MB -> 1.5MB). This is a pre-existing
upstream gap, not something the CMMS patches introduced - native builds
never hit it because on_save_file()'s native branch has an early-return
for "just re-save to the known path" that preserves the current
version; web has no equivalent and always fell through to this
function's unconditional default. Extended the same format-preservation
logic recovery-saves already use to also apply whenever the document
has a known current_path (i.e. it's not actually a fresh, never-saved
drawing).
Previously the CMMS's STL-export-and-navigate flow was only reachable by
typing STLOUT/EXPORTSTL into the command line, with no visible button and
no way to choose the filename. Adds a proper UI entry point:
- Ribbon: a new quick-access button next to Save As (same style/position,
GEAR icon - no dedicated CAM/CNC icon asset exists), command EXPORTCAM.
- A filename dialog (ModalKind::CamExportDialog, cam_export_filename
field) mirrors the existing Save-As dialog's shape minus the format
picker (always STL) - defaults to "<drawing name>.stl", editable before
confirming.
- STLOUT/EXPORTSTL commands are unchanged (still instant-export using the
drawing's own name, no popup) - this is a second, separate entry point,
not a replacement.
Wires Message::StlExport's existing STLOUT command to the CMMS when
embedded, instead of the native save-dialog flow (which was already
non-functional on the web build regardless - handle_path() has no real
filesystem to write to there, a pre-existing upstream gap, not something
this touches).
- Cargo.toml: add the Location web-sys feature (needed for
window.location().set_href()).
- src/sys.rs: post_stl_export_to_host() - POSTs STL bytes as a new
attachment (cad_export_stl action, not cad_save/cad_save_new - STL isn't
in CAD_EDITABLE_EXT, it needs its own allowlist), then navigates the
browser straight to the CMMS's Kiri:Moto CAM page for the attachment it
just created. Splits cfg.job_id's "type:id" owner token apart to build
cam-edit.php's entity_type=/entity_id= params.
- src/app/mod.rs + update/mod.rs: CmmsStlExportResult message/handler -
only ever surfaces a failure (a success already navigated away).
- src/app/update/mod.rs: Message::StlExport gains a wasm32+embedded branch
that skips the file-picker entirely and calls the above directly.
cad-edit.php?new=1 launches the editor with no attachment_id/load_url yet -
CmmsConfig's load_url/attachment_id/original_name become Optional (only
save_url/job_id/csrf_token are always required). load_from_cmms_web() and
boot_web()'s auto-load task both skip cleanly when load_url is absent (no
error, just the normal blank Start tab). post_bytes_to_host() now takes the
filename and picks cad_save (update, has attachment_id) vs cad_save_new
(create); on a successful create it writes the new id/loadUrl/originalName
back into window.CAD_EDITOR_CONFIG in place, so the tab's *next* save
updates that row instead of creating a duplicate each time.
Additive only - standalone/opencadstudio.com use is unaffected since every
new path is gated on window.CAD_EDITOR_CONFIG being present (set by the
CMMS's cad-edit.php host page, absent everywhere else).
- src/sys.rs: cmms_config() reads window.CAD_EDITOR_CONFIG; post_bytes_to_host()
POSTs saved bytes back via FormData instead of triggering a download.
- src/io/mod.rs: load_from_cmms_web() fetches bytes from the host-provided
loadUrl and feeds them through the existing load_web_bytes parse path.
- src/app/mod.rs: boot_web() auto-loads via load_from_cmms_web() when
embedded; CmmsSaveResult message variant carries the save outcome.
- src/app/update/mod.rs: CmmsSaveResult handler surfaces success/failure
in the command line.
- src/app/update/file.rs: web save branch calls post_bytes_to_host() instead
of download_bytes() when embedded.
- Cargo.toml: add Request/RequestInit/FormData to the web-sys feature list.