feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
// Underlay entity — PDF/DWF/DGN reference.
|
|
|
|
|
|
//
|
|
|
|
|
|
// Render: clip boundary polygon (or cross at insertion if no boundary).
|
|
|
|
|
|
// Grips: insertion point + clip boundary vertices.
|
|
|
|
|
|
// Props: position, scales, rotation, contrast, fade, flags.
|
|
|
|
|
|
|
|
|
|
|
|
use acadrust::entities::{Underlay, UnderlayDisplayFlags};
|
|
|
|
|
|
|
|
|
|
|
|
use crate::command::EntityTransform;
|
fix(props): angle rows format via AUNITS, not LUNITS (#297)
Every angle row went through the linear formatter, so switching LUNITS
to Architectural showed a block's Rotation as feet-and-inches — and the
string wouldn't parse back, wedging the field until it was cleared and
retyped. Only the decimal/fractional LUNITS survived by accident.
New edit_angle row helper formats angles with format_angle
(AUNITS/AUPREC: decimal degrees, DMS, grads or radians), applied to all
17 angle rows (rotations, obliquing, arc start/end, hatch pattern
angle, multileader text rotation). parse_angle_deg converts every
AUNITS display form back to degrees ("30°"/"30d", DMS 30°15'20",
33.33g, 0.52r) and parse_f64 falls back to it, so the displayed value
round-trips through an edit.
Closes #297
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 16:42:14 +03:00
|
|
|
|
use crate::entities::common::{center_grip, edit_angle_prop as edit_angle, edit_prop as edit, ro_prop as ro, square_grip};
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
2026-06-16 11:33:46 +03:00
|
|
|
|
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
2026-07-03 08:06:00 +03:00
|
|
|
|
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
2026-06-16 11:33:46 +03:00
|
|
|
|
use crate::scene::model::wire_model::SnapHint;
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
|
|
|
|
|
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
2026-05-12 23:47:40 +03:00
|
|
|
|
fn v3(v: &acadrust::types::Vector3) -> [f64; 3] {
|
|
|
|
|
|
[v.x, v.y, v.z]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn v3f32(v: &acadrust::types::Vector3) -> [f32; 3] {
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
[v.x as f32, v.y as f32, v.z as f32]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Small cross marker at the insertion point (used when no clip boundary).
|
2026-05-12 23:47:40 +03:00
|
|
|
|
fn cross_wire(origin: [f64; 3], size: f64) -> Vec<[f64; 3]> {
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
let [ox, oy, oz] = origin;
|
|
|
|
|
|
vec![
|
|
|
|
|
|
[ox - size, oy, oz],
|
|
|
|
|
|
[ox + size, oy, oz],
|
2026-05-12 23:47:40 +03:00
|
|
|
|
[f64::NAN; 3],
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
[ox, oy - size, oz],
|
|
|
|
|
|
[ox, oy + size, oz],
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── TruckConvertible ──────────────────────────────────────────────────────────
|
|
|
|
|
|
|
feat(underlay): render PDF underlays end-to-end
PDF underlays only drew their clip outline / insertion cross; the page
itself never appeared. The chain now runs: the definition's file path
resolves with the raster-image fallbacks (as stored, relative to the
drawing, basename next to the drawing — attach-time relative paths go
stale), the page rasterises through the system pdftoppm (poppler) at
150 dpi — no new crate; missing tool degrades to the outline — cached
per (path, page) including negative results, and the pixels feed the
existing image pipeline as an ImageModel: 1 underlay unit = 1 PDF inch
(px/dpi × entity scale), rotated about the insertion, fade as opacity,
the clip polygon (non-inverted) as the textured region. Draw-order,
layer visibility and per-viewport freezes ride the generic image path;
in-place edits rebuild through the shared image seed.
When the page renders, the wire path draws its frame with an interior
pick surface instead of the lone cross, so selection covers the visible
page. wasm keeps the outline placeholder (no external process).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 03:41:41 +03:00
|
|
|
|
/// The underlay's page rectangle in world space (CCW from the insertion),
|
|
|
|
|
|
/// when its definition resolves and the page rasterises: page inches × the
|
|
|
|
|
|
/// entity scale, rotated about the insertion. `None` keeps the cross
|
|
|
|
|
|
/// placeholder.
|
|
|
|
|
|
fn page_quad(
|
|
|
|
|
|
u: &Underlay,
|
|
|
|
|
|
document: &acadrust::CadDocument,
|
|
|
|
|
|
) -> Option<[[f64; 3]; 4]> {
|
|
|
|
|
|
let def = match document.objects.get(&u.definition_handle) {
|
|
|
|
|
|
Some(acadrust::objects::ObjectType::UnderlayDefinition(d)) => d,
|
|
|
|
|
|
_ => return None,
|
|
|
|
|
|
};
|
|
|
|
|
|
let page = if def.page_name.trim().is_empty() {
|
|
|
|
|
|
"1"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
def.page_name.trim()
|
|
|
|
|
|
};
|
|
|
|
|
|
let raster = crate::scene::model::pdf_raster::rasterize_page(&def.file_path, page)?;
|
|
|
|
|
|
let w = raster.width as f64 / raster.dpi as f64 * u.x_scale;
|
|
|
|
|
|
let h = raster.height as f64 / raster.dpi as f64 * u.y_scale;
|
|
|
|
|
|
let (c, s) = (u.rotation.cos(), u.rotation.sin());
|
|
|
|
|
|
let o = &u.insertion_point;
|
|
|
|
|
|
let ux = (c * w, s * w);
|
|
|
|
|
|
let vx = (-s * h, c * h);
|
|
|
|
|
|
Some([
|
|
|
|
|
|
[o.x, o.y, o.z],
|
|
|
|
|
|
[o.x + ux.0, o.y + ux.1, o.z],
|
|
|
|
|
|
[o.x + ux.0 + vx.0, o.y + ux.1 + vx.1, o.z],
|
|
|
|
|
|
[o.x + vx.0, o.y + vx.1, o.z],
|
|
|
|
|
|
])
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
impl TruckConvertible for Underlay {
|
|
|
|
|
|
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
|
|
|
|
|
let origin = v3(&self.insertion_point);
|
refactor(snap): producers emit f64 snap points (world_offset removal P3)
TruckEntity.snap_pts is now DVec3 and every entity producer builds snap
candidates straight from the acadrust f64 coordinates instead of casting
to f32 first (text, mtext, arc, circle, ellipse, point, shape, solid,
mline, mtext, attribute, tolerance, table, underlay, ole2frame, mesh,
multileader, dimension, block-cache). offset_snap_pts stays f64
throughout. Still offset-relative (inert) — but snap precision is no
longer capped at ~0.5 m by an early f32 cast, which fixes a latent
UTM-scale snap error and sets up the absolute-coordinate switch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 22:10:29 +03:00
|
|
|
|
let _origin_f32 = v3f32(&self.insertion_point);
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
|
|
|
|
|
|
if !self.clip_boundary_vertices.is_empty() {
|
|
|
|
|
|
// Draw clip boundary polygon + close it.
|
|
|
|
|
|
let world_verts = self.world_clip_boundary();
|
2026-06-11 00:04:37 +03:00
|
|
|
|
let mut pts: Vec<[f64; 3]> = world_verts.iter().map(|v| [v.x, v.y, v.z]).collect();
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
// Close polygon.
|
|
|
|
|
|
if let Some(&first) = pts.first() {
|
|
|
|
|
|
pts.push(first);
|
|
|
|
|
|
}
|
|
|
|
|
|
// Insertion grip.
|
2026-05-12 23:47:40 +03:00
|
|
|
|
let key: Vec<[f64; 3]> = pts.clone();
|
2026-07-21 09:28:07 +03:00
|
|
|
|
// Interior pick surface over the clip polygon so the underlay
|
|
|
|
|
|
// selects on a click anywhere inside, not just on its outline.
|
|
|
|
|
|
let ring: Vec<[f64; 3]> = world_verts.iter().map(|v| [v.x, v.y, v.z]).collect();
|
|
|
|
|
|
let pick_tris = crate::entities::mesh::triangulate_planar(&ring);
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
Some(TruckEntity {
|
2026-07-21 09:28:07 +03:00
|
|
|
|
pick_tris,
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
object: TruckObject::Lines(pts),
|
refactor(snap): producers emit f64 snap points (world_offset removal P3)
TruckEntity.snap_pts is now DVec3 and every entity producer builds snap
candidates straight from the acadrust f64 coordinates instead of casting
to f32 first (text, mtext, arc, circle, ellipse, point, shape, solid,
mline, mtext, attribute, tolerance, table, underlay, ole2frame, mesh,
multileader, dimension, block-cache). offset_snap_pts stays f64
throughout. Still offset-relative (inert) — but snap precision is no
longer capped at ~0.5 m by an early f32 cast, which fixes a latent
UTM-scale snap error and sets up the absolute-coordinate switch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 22:10:29 +03:00
|
|
|
|
snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Node)],
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
tangent_geoms: vec![],
|
|
|
|
|
|
key_vertices: key,
|
2026-05-06 23:24:26 +03:00
|
|
|
|
fill_tris: vec![],
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
})
|
feat(underlay): render PDF underlays end-to-end
PDF underlays only drew their clip outline / insertion cross; the page
itself never appeared. The chain now runs: the definition's file path
resolves with the raster-image fallbacks (as stored, relative to the
drawing, basename next to the drawing — attach-time relative paths go
stale), the page rasterises through the system pdftoppm (poppler) at
150 dpi — no new crate; missing tool degrades to the outline — cached
per (path, page) including negative results, and the pixels feed the
existing image pipeline as an ImageModel: 1 underlay unit = 1 PDF inch
(px/dpi × entity scale), rotated about the insertion, fade as opacity,
the clip polygon (non-inverted) as the textured region. Draw-order,
layer visibility and per-viewport freezes ride the generic image path;
in-place edits rebuild through the shared image seed.
When the page renders, the wire path draws its frame with an interior
pick surface instead of the lone cross, so selection covers the visible
page. wasm keeps the outline placeholder (no external process).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 03:41:41 +03:00
|
|
|
|
} else if let Some(q) = page_quad(self, _document) {
|
|
|
|
|
|
// Rendered page: draw its frame so selection/pick cover the
|
|
|
|
|
|
// visible extent instead of a lone cross under the raster.
|
|
|
|
|
|
let pts = vec![q[0], q[1], q[2], q[3], q[0]];
|
|
|
|
|
|
let pick_tris = crate::entities::mesh::triangulate_planar(&q.to_vec());
|
|
|
|
|
|
Some(TruckEntity {
|
|
|
|
|
|
pick_tris,
|
|
|
|
|
|
object: TruckObject::Lines(pts),
|
|
|
|
|
|
snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Node)],
|
|
|
|
|
|
tangent_geoms: vec![],
|
|
|
|
|
|
key_vertices: q.to_vec(),
|
|
|
|
|
|
fill_tris: vec![],
|
|
|
|
|
|
})
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
} else {
|
|
|
|
|
|
// No clip boundary: draw a cross at insertion point.
|
|
|
|
|
|
let pts = cross_wire(origin, 1.0);
|
|
|
|
|
|
Some(TruckEntity {
|
fix(pick): hit-test lineweight width and thickness walls
Selection tested a flat 8 px radius around each wire's centreline and
nothing else, so two things the user can see were not pickable.
A wire renders as a band `line_weight_px` wide, so pick now widens to that
rendered half-width via `pick_tolerance_px`, mirroring the wire shader's
`select(0.5, half_width, lwdisplay_enable)`. Behaviour is unchanged for
every standard weight (the widest, 2.11 mm, renders 7.97 px half-width —
just under the 8 px threshold); this keeps the two sides from drifting
apart if the display boost in `lineweight_to_px` ever changes.
Entities extruded by a DXF thickness draw their wall as four edges with
nothing in between, so the interior was a hole the cursor fell through.
WireModel gains `pick_tris`: triangles hit-testing treats as solid and the
renderer never uploads. Kept apart from `fill_tris` because that channel
reaches the GPU, and a wall that rendered shaded would change how every
thickness drawing looks. Ranked below `fill_tris` — those are drawn, these
are not, so where they overlap the drawn face is what the user means.
Walls are dropped when a wire is projected into a floating viewport:
`points` are reprojected and clipped into paper coords there, so cloned
model-space triangles would hit-test at a model-scale offset. Extruded
entities stay selectable by their edges, which do get projected.
The wall loop runs on every hover that misses everything else, so it
rejects on the wire's AABB first — an extruded circle is ~128 triangles
and a drawing full of thickness would otherwise project every wall on
each mouse move.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 14:58:55 +03:00
|
|
|
|
pick_tris: Vec::new(),
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
object: TruckObject::Lines(pts),
|
refactor(snap): producers emit f64 snap points (world_offset removal P3)
TruckEntity.snap_pts is now DVec3 and every entity producer builds snap
candidates straight from the acadrust f64 coordinates instead of casting
to f32 first (text, mtext, arc, circle, ellipse, point, shape, solid,
mline, mtext, attribute, tolerance, table, underlay, ole2frame, mesh,
multileader, dimension, block-cache). offset_snap_pts stays f64
throughout. Still offset-relative (inert) — but snap precision is no
longer capped at ~0.5 m by an early f32 cast, which fixes a latent
UTM-scale snap error and sets up the absolute-coordinate switch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 22:10:29 +03:00
|
|
|
|
snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Node)],
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
tangent_geoms: vec![],
|
|
|
|
|
|
key_vertices: vec![origin],
|
2026-05-06 23:24:26 +03:00
|
|
|
|
fill_tris: vec![],
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── Grippable ─────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
impl Grippable for Underlay {
|
|
|
|
|
|
fn grips(&self) -> Vec<GripDef> {
|
2026-06-11 00:04:37 +03:00
|
|
|
|
let origin = glam::DVec3::new(
|
|
|
|
|
|
self.insertion_point.x,
|
|
|
|
|
|
self.insertion_point.y,
|
|
|
|
|
|
self.insertion_point.z,
|
|
|
|
|
|
);
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
let mut grips = vec![square_grip(0, origin)];
|
|
|
|
|
|
|
|
|
|
|
|
if !self.clip_boundary_vertices.is_empty() {
|
|
|
|
|
|
let world_verts = self.world_clip_boundary();
|
|
|
|
|
|
for (i, v) in world_verts.iter().enumerate() {
|
2026-06-11 00:04:37 +03:00
|
|
|
|
grips.push(center_grip(i + 1, glam::DVec3::new(v.x, v.y, v.z)));
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
grips
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
|
|
|
|
|
|
if grip_id == 0 {
|
|
|
|
|
|
// Insertion point grip.
|
|
|
|
|
|
match apply {
|
|
|
|
|
|
GripApply::Translate(d) => {
|
|
|
|
|
|
self.insertion_point.x += d.x as f64;
|
|
|
|
|
|
self.insertion_point.y += d.y as f64;
|
|
|
|
|
|
self.insertion_point.z += d.z as f64;
|
|
|
|
|
|
}
|
|
|
|
|
|
GripApply::Absolute(p) => {
|
|
|
|
|
|
self.insertion_point.x = p.x as f64;
|
|
|
|
|
|
self.insertion_point.y = p.y as f64;
|
|
|
|
|
|
self.insertion_point.z = p.z as f64;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Clip boundary vertex grip (grip_id = vertex_index + 1).
|
|
|
|
|
|
let idx = grip_id - 1;
|
|
|
|
|
|
if idx >= self.clip_boundary_vertices.len() {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// Clip boundary vertices are in local (underlay) space.
|
|
|
|
|
|
// We need to invert the world transform to apply the grip.
|
|
|
|
|
|
let cos_r = self.rotation.cos();
|
|
|
|
|
|
let sin_r = self.rotation.sin();
|
|
|
|
|
|
let new_world = match apply {
|
|
|
|
|
|
GripApply::Absolute(p) => {
|
|
|
|
|
|
// world → local: translate, un-rotate, un-scale
|
|
|
|
|
|
let wx = p.x as f64 - self.insertion_point.x;
|
|
|
|
|
|
let wy = p.y as f64 - self.insertion_point.y;
|
|
|
|
|
|
let lx = (wx * cos_r + wy * sin_r) / self.x_scale.max(1e-10);
|
|
|
|
|
|
let ly = (-wx * sin_r + wy * cos_r) / self.y_scale.max(1e-10);
|
|
|
|
|
|
(lx, ly)
|
|
|
|
|
|
}
|
|
|
|
|
|
GripApply::Translate(d) => {
|
|
|
|
|
|
let v = &self.clip_boundary_vertices[idx];
|
|
|
|
|
|
let wx = d.x as f64 / self.x_scale.max(1e-10);
|
|
|
|
|
|
let wy = d.y as f64 / self.y_scale.max(1e-10);
|
|
|
|
|
|
let lx = wx * cos_r + wy * sin_r;
|
|
|
|
|
|
let ly = -wx * sin_r + wy * cos_r;
|
|
|
|
|
|
(v.x + lx, v.y + ly)
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
self.clip_boundary_vertices[idx].x = new_world.0;
|
|
|
|
|
|
self.clip_boundary_vertices[idx].y = new_world.1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── PropertyEditable ──────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
impl PropertyEditable for Underlay {
|
2026-07-02 22:46:19 +03:00
|
|
|
|
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
|
feat(properties): conform entity property groups to PROPERTIES.md
Rewrite each entity's property builder to the per-entity group/row spec:
the correct sections (Geometry, Misc, Text, Pattern, Lines & Arrows, Leaders,
Block, …) with the spec's rows and real computed values — Diameter,
Circumference, Area, Delta X/Y/Z, Angle, Total angle, Arc length, Radius ratio,
etc. — plus apply routing for the editable rows.
Covers ~26 entities (Line, Circle, Arc, Point, Ellipse, Spline, polylines,
Ray/XLine, Insert, Text, MText, Hatch, Leader, MultiLeader, Tolerance, Solid,
Solid3D/Region/Body, meshes, MLine, Raster/Wipeout, Underlay, Table, Viewport,
Attribute, OLE). The 3D Visualization/Material group and the full Dimension
spec are deferred (they need document access for material/dimstyle name
resolution). Rows whose data is not in the pinned acadrust revision are shown
as empty placeholders, to be filled when the dependency is bumped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 23:03:18 +03:00
|
|
|
|
// Width / Height derived from the world-space clip boundary bounds
|
|
|
|
|
|
// (the only in-entity source of the placed footprint size).
|
|
|
|
|
|
let (width, height) = if self.clip_boundary_vertices.is_empty() {
|
|
|
|
|
|
(0.0_f64, 0.0_f64)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
let verts = self.world_clip_boundary();
|
|
|
|
|
|
let mut min_x = f64::INFINITY;
|
|
|
|
|
|
let mut min_y = f64::INFINITY;
|
|
|
|
|
|
let mut max_x = f64::NEG_INFINITY;
|
|
|
|
|
|
let mut max_y = f64::NEG_INFINITY;
|
|
|
|
|
|
for v in &verts {
|
|
|
|
|
|
min_x = min_x.min(v.x);
|
|
|
|
|
|
min_y = min_y.min(v.y);
|
|
|
|
|
|
max_x = max_x.max(v.x);
|
|
|
|
|
|
max_y = max_y.max(v.y);
|
|
|
|
|
|
}
|
|
|
|
|
|
(max_x - min_x, max_y - min_y)
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
};
|
feat(properties): conform entity property groups to PROPERTIES.md
Rewrite each entity's property builder to the per-entity group/row spec:
the correct sections (Geometry, Misc, Text, Pattern, Lines & Arrows, Leaders,
Block, …) with the spec's rows and real computed values — Diameter,
Circumference, Area, Delta X/Y/Z, Angle, Total angle, Arc length, Radius ratio,
etc. — plus apply routing for the editable rows.
Covers ~26 entities (Line, Circle, Arc, Point, Ellipse, Spline, polylines,
Ray/XLine, Insert, Text, MText, Hatch, Leader, MultiLeader, Tolerance, Solid,
Solid3D/Region/Body, meshes, MLine, Raster/Wipeout, Underlay, Table, Viewport,
Attribute, OLE). The 3D Visualization/Material group and the full Dimension
spec are deferred (they need document access for material/dimstyle name
resolution). Rows whose data is not in the pinned acadrust revision are shown
as empty placeholders, to be filled when the dependency is bumped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 23:03:18 +03:00
|
|
|
|
|
|
|
|
|
|
let show = self.flags.contains(UnderlayDisplayFlags::ON);
|
|
|
|
|
|
let clipping = self.flags.contains(UnderlayDisplayFlags::CLIPPING);
|
|
|
|
|
|
let monochrome = self.flags.contains(UnderlayDisplayFlags::MONOCHROME);
|
|
|
|
|
|
let adjust_bg = self.flags.contains(UnderlayDisplayFlags::ADJUST_FOR_BACKGROUND);
|
|
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
|
PropSection {
|
|
|
|
|
|
title: "Geometry".into(),
|
|
|
|
|
|
props: vec![
|
|
|
|
|
|
edit("Position X", "ul_ix", self.insertion_point.x),
|
|
|
|
|
|
edit("Position Y", "ul_iy", self.insertion_point.y),
|
|
|
|
|
|
edit("Position Z", "ul_iz", self.insertion_point.z),
|
|
|
|
|
|
edit("Scale X", "ul_sx", self.x_scale),
|
|
|
|
|
|
edit("Scale Y", "ul_sy", self.y_scale),
|
|
|
|
|
|
edit("Scale Z", "ul_sz", self.z_scale),
|
|
|
|
|
|
ro("Width", "ul_width", format!("{:.4}", width)),
|
|
|
|
|
|
ro("Height", "ul_height", format!("{:.4}", height)),
|
fix(props): angle rows format via AUNITS, not LUNITS (#297)
Every angle row went through the linear formatter, so switching LUNITS
to Architectural showed a block's Rotation as feet-and-inches — and the
string wouldn't parse back, wedging the field until it was cleared and
retyped. Only the decimal/fractional LUNITS survived by accident.
New edit_angle row helper formats angles with format_angle
(AUNITS/AUPREC: decimal degrees, DMS, grads or radians), applied to all
17 angle rows (rotations, obliquing, arc start/end, hatch pattern
angle, multileader text rotation). parse_angle_deg converts every
AUNITS display form back to degrees ("30°"/"30d", DMS 30°15'20",
33.33g, 0.52r) and parse_f64 falls back to it, so the displayed value
round-trips through an edit.
Closes #297
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 16:42:14 +03:00
|
|
|
|
edit_angle("Rotation", "ul_rot", self.rotation.to_degrees()),
|
feat(properties): conform entity property groups to PROPERTIES.md
Rewrite each entity's property builder to the per-entity group/row spec:
the correct sections (Geometry, Misc, Text, Pattern, Lines & Arrows, Leaders,
Block, …) with the spec's rows and real computed values — Diameter,
Circumference, Area, Delta X/Y/Z, Angle, Total angle, Arc length, Radius ratio,
etc. — plus apply routing for the editable rows.
Covers ~26 entities (Line, Circle, Arc, Point, Ellipse, Spline, polylines,
Ray/XLine, Insert, Text, MText, Hatch, Leader, MultiLeader, Tolerance, Solid,
Solid3D/Region/Body, meshes, MLine, Raster/Wipeout, Underlay, Table, Viewport,
Attribute, OLE). The 3D Visualization/Material group and the full Dimension
spec are deferred (they need document access for material/dimstyle name
resolution). Rows whose data is not in the pinned acadrust revision are shown
as empty placeholders, to be filled when the dependency is bumped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 23:03:18 +03:00
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
PropSection {
|
|
|
|
|
|
title: "Underlay Adjust".into(),
|
|
|
|
|
|
props: vec![
|
|
|
|
|
|
edit("Contrast", "ul_contrast", self.contrast as f64),
|
|
|
|
|
|
edit("Fade", "ul_fade", self.fade as f64),
|
2026-07-03 08:06:00 +03:00
|
|
|
|
Property {
|
|
|
|
|
|
label: "Monochrome".into(),
|
|
|
|
|
|
field: "ul_mono",
|
|
|
|
|
|
value: PropValue::BoolToggle {
|
|
|
|
|
|
field: "ul_mono",
|
|
|
|
|
|
value: monochrome,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
Property {
|
|
|
|
|
|
label: "Adjust Colors for Background".into(),
|
|
|
|
|
|
field: "ul_adjust_bg",
|
|
|
|
|
|
value: PropValue::BoolToggle {
|
|
|
|
|
|
field: "ul_adjust_bg",
|
|
|
|
|
|
value: adjust_bg,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
feat(properties): conform entity property groups to PROPERTIES.md
Rewrite each entity's property builder to the per-entity group/row spec:
the correct sections (Geometry, Misc, Text, Pattern, Lines & Arrows, Leaders,
Block, …) with the spec's rows and real computed values — Diameter,
Circumference, Area, Delta X/Y/Z, Angle, Total angle, Arc length, Radius ratio,
etc. — plus apply routing for the editable rows.
Covers ~26 entities (Line, Circle, Arc, Point, Ellipse, Spline, polylines,
Ray/XLine, Insert, Text, MText, Hatch, Leader, MultiLeader, Tolerance, Solid,
Solid3D/Region/Body, meshes, MLine, Raster/Wipeout, Underlay, Table, Viewport,
Attribute, OLE). The 3D Visualization/Material group and the full Dimension
spec are deferred (they need document access for material/dimstyle name
resolution). Rows whose data is not in the pinned acadrust revision are shown
as empty placeholders, to be filled when the dependency is bumped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 23:03:18 +03:00
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
PropSection {
|
|
|
|
|
|
title: "Misc".into(),
|
|
|
|
|
|
props: vec![
|
|
|
|
|
|
// Underlay name/path/layers live on the separate
|
|
|
|
|
|
// UnderlayDefinition object, not reachable from the entity.
|
|
|
|
|
|
ro("Underlay name", "ul_name", String::new()),
|
|
|
|
|
|
ro("Underlay path", "ul_path", String::new()),
|
2026-07-03 08:06:00 +03:00
|
|
|
|
Property {
|
|
|
|
|
|
label: "Show underlay".into(),
|
|
|
|
|
|
field: "ul_on",
|
|
|
|
|
|
value: PropValue::BoolToggle {
|
|
|
|
|
|
field: "ul_on",
|
|
|
|
|
|
value: show,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
Property {
|
|
|
|
|
|
label: "Clipping".into(),
|
|
|
|
|
|
field: "ul_clip",
|
|
|
|
|
|
value: PropValue::BoolToggle {
|
|
|
|
|
|
field: "ul_clip",
|
|
|
|
|
|
value: clipping,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
Property {
|
|
|
|
|
|
label: "Show clipped".into(),
|
|
|
|
|
|
field: "ul_clip_inverted",
|
|
|
|
|
|
value: PropValue::BoolToggle {
|
|
|
|
|
|
field: "ul_clip_inverted",
|
|
|
|
|
|
value: self.clip_inverted,
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
feat(properties): conform entity property groups to PROPERTIES.md
Rewrite each entity's property builder to the per-entity group/row spec:
the correct sections (Geometry, Misc, Text, Pattern, Lines & Arrows, Leaders,
Block, …) with the spec's rows and real computed values — Diameter,
Circumference, Area, Delta X/Y/Z, Angle, Total angle, Arc length, Radius ratio,
etc. — plus apply routing for the editable rows.
Covers ~26 entities (Line, Circle, Arc, Point, Ellipse, Spline, polylines,
Ray/XLine, Insert, Text, MText, Hatch, Leader, MultiLeader, Tolerance, Solid,
Solid3D/Region/Body, meshes, MLine, Raster/Wipeout, Underlay, Table, Viewport,
Attribute, OLE). The 3D Visualization/Material group and the full Dimension
spec are deferred (they need document access for material/dimstyle name
resolution). Rows whose data is not in the pinned acadrust revision are shown
as empty placeholders, to be filled when the dependency is bumped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 23:03:18 +03:00
|
|
|
|
ro("Underlay layers", "ul_layers", String::new()),
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn apply_geom_prop(&mut self, field: &str, value: &str) {
|
2026-07-03 08:06:00 +03:00
|
|
|
|
match field {
|
|
|
|
|
|
"ul_mono" => {
|
|
|
|
|
|
let on = if value == "toggle" {
|
|
|
|
|
|
!self.flags.contains(UnderlayDisplayFlags::MONOCHROME)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
value == "true"
|
|
|
|
|
|
};
|
|
|
|
|
|
self.set_monochrome(on);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
"ul_adjust_bg" => {
|
|
|
|
|
|
let on = if value == "toggle" {
|
|
|
|
|
|
!self.flags.contains(UnderlayDisplayFlags::ADJUST_FOR_BACKGROUND)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
value == "true"
|
|
|
|
|
|
};
|
|
|
|
|
|
if on {
|
|
|
|
|
|
self.flags |= UnderlayDisplayFlags::ADJUST_FOR_BACKGROUND;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
self.flags -= UnderlayDisplayFlags::ADJUST_FOR_BACKGROUND;
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
"ul_on" => {
|
|
|
|
|
|
let on = if value == "toggle" {
|
|
|
|
|
|
!self.flags.contains(UnderlayDisplayFlags::ON)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
value == "true"
|
|
|
|
|
|
};
|
|
|
|
|
|
self.set_on(on);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
"ul_clip" => {
|
|
|
|
|
|
let on = if value == "toggle" {
|
|
|
|
|
|
!self.flags.contains(UnderlayDisplayFlags::CLIPPING)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
value == "true"
|
|
|
|
|
|
};
|
|
|
|
|
|
if on {
|
|
|
|
|
|
self.flags |= UnderlayDisplayFlags::CLIPPING;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
self.flags -= UnderlayDisplayFlags::CLIPPING;
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
"ul_clip_inverted" => {
|
|
|
|
|
|
let on = if value == "toggle" {
|
|
|
|
|
|
!self.clip_inverted
|
|
|
|
|
|
} else {
|
|
|
|
|
|
value == "true"
|
|
|
|
|
|
};
|
|
|
|
|
|
self.clip_inverted = on;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
_ => {}
|
|
|
|
|
|
}
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
if let Ok(v) = value.trim().parse::<f64>() {
|
|
|
|
|
|
match field {
|
|
|
|
|
|
"ul_ix" => self.insertion_point.x = v,
|
|
|
|
|
|
"ul_iy" => self.insertion_point.y = v,
|
|
|
|
|
|
"ul_iz" => self.insertion_point.z = v,
|
|
|
|
|
|
"ul_sx" => self.x_scale = v,
|
|
|
|
|
|
"ul_sy" => self.y_scale = v,
|
|
|
|
|
|
"ul_sz" => self.z_scale = v,
|
|
|
|
|
|
"ul_rot" => self.rotation = v.to_radians(),
|
|
|
|
|
|
"ul_contrast" => self.set_contrast(v.clamp(0.0, 100.0) as u8),
|
|
|
|
|
|
"ul_fade" => self.set_fade(v.clamp(0.0, 80.0) as u8),
|
|
|
|
|
|
_ => {}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── Transformable ─────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
impl Transformable for Underlay {
|
|
|
|
|
|
fn apply_transform(&mut self, t: &EntityTransform) {
|
2026-06-16 11:33:46 +03:00
|
|
|
|
use crate::scene::view::transform::reflect_xy_point;
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
match t {
|
|
|
|
|
|
EntityTransform::Translate(d) => {
|
|
|
|
|
|
self.insertion_point.x += d.x as f64;
|
|
|
|
|
|
self.insertion_point.y += d.y as f64;
|
|
|
|
|
|
self.insertion_point.z += d.z as f64;
|
|
|
|
|
|
}
|
|
|
|
|
|
EntityTransform::Mirror { p1, p2 } => {
|
|
|
|
|
|
reflect_xy_point(
|
|
|
|
|
|
&mut self.insertion_point.x,
|
|
|
|
|
|
&mut self.insertion_point.y,
|
|
|
|
|
|
*p1,
|
|
|
|
|
|
*p2,
|
|
|
|
|
|
);
|
|
|
|
|
|
// Reflect rotation angle.
|
|
|
|
|
|
let dx = (p2.x - p1.x) as f64;
|
|
|
|
|
|
let dy = (p2.y - p1.y) as f64;
|
|
|
|
|
|
let axis_angle = dy.atan2(dx);
|
|
|
|
|
|
self.rotation = 2.0 * axis_angle - self.rotation;
|
|
|
|
|
|
}
|
|
|
|
|
|
EntityTransform::Scale { center, factor } => {
|
|
|
|
|
|
let bx = center.x as f64;
|
|
|
|
|
|
let by = center.y as f64;
|
|
|
|
|
|
let bz = center.z as f64;
|
|
|
|
|
|
let f = *factor as f64;
|
|
|
|
|
|
self.insertion_point.x = bx + (self.insertion_point.x - bx) * f;
|
|
|
|
|
|
self.insertion_point.y = by + (self.insertion_point.y - by) * f;
|
|
|
|
|
|
self.insertion_point.z = bz + (self.insertion_point.z - bz) * f;
|
|
|
|
|
|
self.x_scale *= f;
|
|
|
|
|
|
self.y_scale *= f;
|
|
|
|
|
|
self.z_scale *= f;
|
|
|
|
|
|
}
|
|
|
|
|
|
EntityTransform::Rotate { center, angle_rad } => {
|
|
|
|
|
|
let bx = center.x as f64;
|
|
|
|
|
|
let by = center.y as f64;
|
|
|
|
|
|
let a = *angle_rad as f64;
|
|
|
|
|
|
let cos_a = a.cos();
|
|
|
|
|
|
let sin_a = a.sin();
|
|
|
|
|
|
let dx = self.insertion_point.x - bx;
|
|
|
|
|
|
let dy = self.insertion_point.y - by;
|
|
|
|
|
|
self.insertion_point.x = bx + dx * cos_a - dy * sin_a;
|
|
|
|
|
|
self.insertion_point.y = by + dx * sin_a + dy * cos_a;
|
|
|
|
|
|
self.rotation += a;
|
|
|
|
|
|
}
|
2026-07-30 19:50:33 +03:00
|
|
|
|
EntityTransform::Affine(transform) => {
|
|
|
|
|
|
acadrust::Entity::apply_transform(self, transform);
|
|
|
|
|
|
}
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|