Ortho and polar drawing constraints snapped to world X/Y; under an active
UCS they now snap to the UCS axes, routed through the shared UcsXform
(identity = unchanged world-XY behaviour). Applied at all three input
sites (grip drag, command point, command preview). Typed coordinates
already flow through the converter via ucs_to_wcs / ucs_rotate_vec.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce one bridge between WCS (how geometry and the file are stored)
and the active UCS (the coordinate system the user works in), so every
UCS-aware system routes through it instead of re-deriving axis math.
- UcsXform (app/helpers.rs): the converter — to_wcs/to_ucs (points),
vec_to_wcs/vec_to_ucs (directions), axes(), is_identity(). Orthonormal
axes, so the inverse is the transpose. The old ucs_to_wcs / ucs_rotate_vec
free fns now delegate to it (one implementation).
- DocumentTab::ucs_xform() builds it from the tab's active_ucs (None = WCS).
- DocumentTab::adopt_active_ucs_from_header() loads the document's saved
current UCS (header model-space UCS) into active_ucs on open, so the file's
coordinate system is live immediately; called from both load paths.
- Status-bar coordinate readout reports the cursor in the active UCS.
- UCS icon tripod projects the active UCS axes, so it rotates to the UCS
instead of always showing world X/Y/Z.
First slice of routing the app's coordinate systems through the converter;
input/picking, grid, ViewCube, and the remaining readouts follow.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Gate target-specific code so neither build warns about the other's items:
native-only helpers (view, window icon, file dialogs, file association, plugin
host/guard/registry, self-update) are cfg'd to non-wasm; the wasm-only font
fallback (script_of / cjk_lang / request) is cfg'd to wasm. Drop an unused mut,
allow the few genuinely-conditional dead items (mesh_click_hit, GPU layout
helpers, parity stubs), and gate the embedded PlotSettings-unrelated dead
constants. Both targets now build clean (only the unavoidable nom/quick-xml
future-incompat dependency notice remains).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Turn the ribbon Clipboard "Paste" button into a dropdown:
- Paste — existing pick-a-point paste.
- Paste to Original Coordinates — drops the clipboard at its source
coordinates with no prompt.
- Paste as Block — wraps the clipboard contents in a new block definition
and starts an interactive insert (prompts for the drop point, with the
geometry rubber-banding under the cursor).
Also fixes two bugs the new commands exposed:
- entities_centroid summed the NaN separator points wire models carry,
so the paste base point came out NaN; non-finite points are now
skipped. A NaN base previously froze block tessellation outright.
- PASTEORIG added clipboard entities with their original handles
(duplicates on same-document paste); it now goes through
add_entity_clone and merges referenced records like the other pastes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ACAD_SURFACE entities now load and render. Their NURBS faces are
tessellated by building a truck BSplineSurface from the ACIS `spline-surface`
control net and knot vectors, then sampling its parametric grid — reusing the
same NURBS kernel the Model tab already builds on. Analytic faces
(plane/cone/sphere/torus) continue through the existing tessellator.
- New spline_tess.rs: parse the ACIS `nubs` block (degrees, knots with the
clamped end-multiplicity fix, control grid) into a truck BSplineSurface and
mesh it.
- tessellate_surface + Surface wired through the mesh-build, fallback-wire,
and entity-classification paths.
- Bump acadrust to the commit that adds the Surface entity.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
POLAR locked the cursor to the nearest angle everywhere, so it could
never point between angles. Snap only when the cursor is within the snap
aperture (in screen pixels) of a polar ray; otherwise leave it free, so
POLAR behaves as if off when pointing away from every angle. The polar
guide line now shows only while actually snapped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 4.1. Handle / u64 keys dominate the hot maps (block_defn,
hatch / image / mesh caches, draw-depth map, viewport wire caches);
the default SipHash is wasted work on integer keys. Alias the std
types to rustc_hash::FxHashMap / FxHashSet crate-wide so every map and
set — including the cross-module draw-depth map shared between scene
and the GPU pipelines — uses the faster hasher consistently.
Mechanical: no behavioural change. Constructors moved from ::new() to
::default() (Fx variants carry no RandomState). Build + 13 tests green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Koordinat girişi artık göreli/mutlak ayrımını destekliyor:
- `@x,y[,z]` → son girilen noktaya göreli (UCS eksenlerinde döndürülür)
- `#x,y[,z]` → her zaman mutlak (DYN durumundan bağımsız)
- ön ek yok → DYN açıksa göreli, kapalıysa mutlak
İlk noktada referans olmadığından göreli giriş mutlağa düşer. Çözülen
WCS noktası last_point olarak saklanıyor, böylece ardışık göreli
girişler zincirleniyor.
parse_coord artık (Vec3, CoordKind) döndürüyor; relative offset için
ucs_rotate_vec eklendi (origin translation olmadan UCS rotasyonu).
UCS ORIGIN komutu prefix'i yok sayıp mutlak kalıyor.
Ayrıca ViewCube snap refactor'undan kalan kullanılmayan kod temizlendi:
angle_close, active_viewport_yaw_pitch, CubeRegion::snap_angles.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two near-identical match-on-EntityType tables lived far apart:
scene/properties.rs::entity_type_name returned mixed-case UI labels;
app/commands.rs::entity_type_name returned uppercase DXF record names.
Both enumerated ~30 variants; adding a new entity meant remembering to
touch two files in two crates' worth of source layout.
Move both into a single entities/names.rs as `ui_name()` and
`dxf_name()`. Adjacent so a new variant gets both labels added at once;
function names make the intended audience explicit at the callsite.
scene/properties.rs and app/commands.rs each lose their local match
plus one re-export, gaining a `crate::entities::names::*` call.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Joining the OpenAEC Foundation (open-aec.com). Crate/struct become
OpenCADStudio, user-facing strings use the spaced "Open CAD Studio"
form, repo URLs point to HakanSeven12/open-cad-studio. Logo (window
icon + assets/logo.svg) redrawn with OCS initials. Drop examples/
binaries — unused.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* helpers::wcs_to_ucs — UCS inverse transform with zero call sites.
* scene::Scene::compute_and_set_world_offset — never called; the load
path uses the free function `compute_world_offset` directly.
* tessellate::tessellate_mesh — never called; mesh tessellation goes
through `solid3d_tess`, not the truck Shell/Solid path.
* truck_tess::tess_to_mesh_model — orphaned with tessellate_mesh's
removal.
* MeshModel::WHITE / MeshModel::SELECTED — only used by the removed
tessellate_mesh.
* xattach::Step::FilePath variant — never constructed; XATTACH always
enters through `with_path` after the file picker. Replaced the Step
enum + prefilled_path field with flat `path` / `block_name` fields
and dropped the unreachable text-input flow.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Make scene::properties::entity_type_name the single source of truth.
entity_type_label in helpers.rs now delegates to it instead of
maintaining a separate match list.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Properties panel header was still showing "Entity" for unrecognized
types because helpers.rs had its own incomplete match. Both functions now
enumerate every acadrust EntityType variant explicitly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add `active_ucs: Option<Ucs>` per-tab state to DocumentTab
- Add `ucs_to_wcs`, `wcs_to_ucs`, `ucs_z_axis`, `ucs_rotated_z` helpers
- Add `Camera::pick_on_plane` for ray–plane intersection against any plane
- Mouse picks project onto the active UCS XY plane instead of world XY
- Typed coordinates are converted from UCS space to WCS before dispatch
- UCS command now really activates/deactivates a UCS:
- `UCS W` resets to WCS (clears active_ucs)
- `UCS <name>` activates a named UCS
- `UCS SAVE <name>` saves the current active UCS
- `UCS ORIGIN x,y,z` shifts origin (in current UCS space)
- `UCS X/Y/Z <angle>` rotates the UCS around its own axes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>