Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
use acadrust::entities::{RasterImage, Wipeout};
|
|
|
|
|
|
|
|
|
|
|
|
use crate::command::EntityTransform;
|
refactor(grip): square-only marker set + oriented stretch handles
Phase 1 of bringing the grip vocabulary in line with the standard
CAD convention: drop the per-position-type shape encoding (Diamond
for translate, Circle for parameter) and use a plain square for
every endpoint / vertex / centre grip. The behavioural midpoint vs
vertex distinction stays — it lives on `GripDef::is_midpoint` and
drives `Translate` vs `Absolute` in the grip-edit dispatcher — only
the marker shape collapses.
- `GripShape` keeps `Square`, `Rectangle`, `Triangle`. Diamond /
Circle are gone.
- `GripDef` gains `dir: Option<[f32; 2]>` — a world-XY direction
vector consumed by `Rectangle` to orient the box along its
segment.
- `entities::common` exposes `square_grip`, `center_grip` (same
square marker, flagged as translate), `rectangle_grip(id, world,
dir)` for oriented mid-segment handles, and a kept-for-Phase-2
`triangle_grip`.
- `overlay::GripMarker` / `grips_to_screen[_paper]` thread `dir`
through to the canvas painter; the Rectangle path rotates the
box around the grip centre using the world-XY direction (flipping
the sin for screen-Y).
Every existing `diamond_grip(id, w)` call becomes `center_grip(id,
w)` — the visual change is square-replacing-diamond at line
midpoints / arc midpoints / circle centres / ellipse centres /
viewport / hatch loop centroids / dimension grips / image corners /
multileader / ray / underlay / ole2frame / solid3d.
`LwPolyline` grows a stretch handle on every segment (straight or
arc), drawn as the new oriented rectangle. The grip-edit path
translates both segment endpoints for straight segments and
adjusts the arc bulge from the new midpoint for arc segments.
2026-05-29 02:07:34 +03:00
|
|
|
|
use crate::entities::common::{center_grip, edit_prop as edit, ro_prop as ro, square_grip};
|
2026-07-18 19:32:14 +03:00
|
|
|
|
use crate::entities::text_support::{resolve_text_style, text_local_bounds};
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
2026-07-18 19:32:14 +03:00
|
|
|
|
use crate::scene::convert::acad_to_truck::{GlyphRun, TextStroke, TruckEntity, TruckObject};
|
2026-06-16 11:33:46 +03:00
|
|
|
|
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
2026-07-18 19:32:14 +03:00
|
|
|
|
use crate::scene::text::lff;
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
|
|
|
|
|
|
// ── Shared geometry helpers ───────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
/// Compute the four world-space corners of an image/wipeout from its
|
|
|
|
|
|
/// insertion_point, u_vector, v_vector and pixel size.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Returns (p0, p1, p2, p3) in counter-clockwise order:
|
|
|
|
|
|
/// p0 = origin
|
|
|
|
|
|
/// p1 = origin + U*W
|
|
|
|
|
|
/// p2 = origin + U*W + V*H
|
|
|
|
|
|
/// p3 = origin + V*H
|
|
|
|
|
|
fn image_corners(
|
|
|
|
|
|
origin: &acadrust::types::Vector3,
|
|
|
|
|
|
u: &acadrust::types::Vector3,
|
|
|
|
|
|
v: &acadrust::types::Vector3,
|
|
|
|
|
|
w: f64,
|
|
|
|
|
|
h: f64,
|
2026-05-12 23:47:40 +03:00
|
|
|
|
) -> [[f64; 3]; 4] {
|
|
|
|
|
|
let ox = origin.x;
|
|
|
|
|
|
let oy = origin.y;
|
|
|
|
|
|
let oz = origin.z;
|
|
|
|
|
|
let ux = u.x * w;
|
|
|
|
|
|
let uy = u.y * w;
|
|
|
|
|
|
let uz = u.z * w;
|
|
|
|
|
|
let vx = v.x * h;
|
|
|
|
|
|
let vy = v.y * h;
|
|
|
|
|
|
let vz = v.z * h;
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
|
|
|
|
|
|
[
|
|
|
|
|
|
[ox, oy, oz],
|
|
|
|
|
|
[ox + ux, oy + uy, oz + uz],
|
|
|
|
|
|
[ox + ux + vx, oy + uy + vy, oz + uz + vz],
|
|
|
|
|
|
[ox + vx, oy + vy, oz + vz],
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Rectangle border + X diagonals — used as a placeholder for images.
|
2026-05-12 23:47:40 +03:00
|
|
|
|
fn image_wire(corners: [[f64; 3]; 4], with_x: bool) -> Vec<[f64; 3]> {
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
let [p0, p1, p2, p3] = corners;
|
|
|
|
|
|
let mut pts = vec![p0, p1, p2, p3, p0];
|
|
|
|
|
|
if with_x {
|
2026-05-12 23:47:40 +03:00
|
|
|
|
pts.push([f64::NAN; 3]);
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
pts.push(p0);
|
|
|
|
|
|
pts.push(p2);
|
2026-05-12 23:47:40 +03:00
|
|
|
|
pts.push([f64::NAN; 3]);
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
pts.push(p1);
|
|
|
|
|
|
pts.push(p3);
|
|
|
|
|
|
}
|
|
|
|
|
|
pts
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 10:36:15 +03:00
|
|
|
|
fn reflect_vec3(vx: &mut f64, vy: &mut f64, ax: f64, ay: f64, len2: f64) {
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
let dot = *vx * ax + *vy * ay;
|
|
|
|
|
|
*vx = 2.0 * dot * ax / len2 - *vx;
|
|
|
|
|
|
*vy = 2.0 * dot * ay / len2 - *vy;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── RasterImage ───────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
impl TruckConvertible for RasterImage {
|
2026-07-18 19:32:14 +03:00
|
|
|
|
fn to_truck(&self, document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
let corners = image_corners(
|
|
|
|
|
|
&self.insertion_point,
|
|
|
|
|
|
&self.u_vector,
|
|
|
|
|
|
&self.v_vector,
|
|
|
|
|
|
self.size.x,
|
|
|
|
|
|
self.size.y,
|
|
|
|
|
|
);
|
2026-05-02 20:01:21 +03:00
|
|
|
|
|
|
|
|
|
|
// Helper: pixel-space → world-space point.
|
2026-05-12 23:47:40 +03:00
|
|
|
|
let ox = self.insertion_point.x;
|
|
|
|
|
|
let oy = self.insertion_point.y;
|
|
|
|
|
|
let oz = self.insertion_point.z;
|
|
|
|
|
|
let px_to_world = |px: f64, py: f64| -> [f64; 3] {
|
2026-05-02 20:01:21 +03:00
|
|
|
|
[
|
2026-05-12 23:47:40 +03:00
|
|
|
|
ox + self.u_vector.x * px + self.v_vector.x * py,
|
|
|
|
|
|
oy + self.u_vector.y * px + self.v_vector.y * py,
|
|
|
|
|
|
oz + self.u_vector.z * px + self.v_vector.z * py,
|
2026-05-02 20:01:21 +03:00
|
|
|
|
]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let pts = if self.clipping_enabled {
|
|
|
|
|
|
let cb = &self.clip_boundary;
|
|
|
|
|
|
match cb.clip_type {
|
|
|
|
|
|
acadrust::entities::ClipType::Polygonal if cb.vertices.len() >= 3 => {
|
2026-05-12 23:47:40 +03:00
|
|
|
|
let mut poly: Vec<[f64; 3]> =
|
2026-05-12 10:36:15 +03:00
|
|
|
|
cb.vertices.iter().map(|v| px_to_world(v.x, v.y)).collect();
|
2026-05-02 20:01:21 +03:00
|
|
|
|
if let Some(&first) = poly.first() {
|
|
|
|
|
|
poly.push(first);
|
|
|
|
|
|
}
|
|
|
|
|
|
poly
|
|
|
|
|
|
}
|
|
|
|
|
|
acadrust::entities::ClipType::Rectangular if cb.vertices.len() >= 2 => {
|
|
|
|
|
|
let v0 = &cb.vertices[0];
|
|
|
|
|
|
let v1 = &cb.vertices[1];
|
|
|
|
|
|
let (xa, xb) = (v0.x.min(v1.x), v0.x.max(v1.x));
|
|
|
|
|
|
let (ya, yb) = (v0.y.min(v1.y), v0.y.max(v1.y));
|
|
|
|
|
|
let c0 = px_to_world(xa, ya);
|
|
|
|
|
|
let c1 = px_to_world(xb, ya);
|
|
|
|
|
|
let c2 = px_to_world(xb, yb);
|
|
|
|
|
|
let c3 = px_to_world(xa, yb);
|
|
|
|
|
|
vec![c0, c1, c2, c3, c0]
|
|
|
|
|
|
}
|
|
|
|
|
|
_ => image_wire(corners, true),
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
image_wire(corners, true)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-18 19:32:14 +03:00
|
|
|
|
// A raster that OCS can actually open renders its pixels (built
|
|
|
|
|
|
// separately) inside this frame — just draw the frame/clip outline.
|
|
|
|
|
|
// A reference OCS cannot resolve (a URL, or a missing/renamed file)
|
|
|
|
|
|
// gets AutoCAD's broken-reference treatment: the frame plus the saved
|
|
|
|
|
|
// path drawn as text, so the user sees WHICH reference is unresolved
|
|
|
|
|
|
// instead of an empty box. OCS never fetches a remote path.
|
|
|
|
|
|
let path = self.file_path.trim();
|
|
|
|
|
|
let resolvable = path.is_empty() || std::path::Path::new(path).is_file();
|
|
|
|
|
|
if resolvable {
|
|
|
|
|
|
return Some(TruckEntity {
|
|
|
|
|
|
pick_tris: Vec::new(),
|
|
|
|
|
|
object: TruckObject::Lines(pts),
|
|
|
|
|
|
snap_pts: vec![],
|
|
|
|
|
|
tangent_geoms: vec![],
|
|
|
|
|
|
key_vertices: corners.to_vec(),
|
|
|
|
|
|
fill_tris: vec![],
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── Unresolved reference: frame outline + path text, image colour ──
|
|
|
|
|
|
let ins = [self.insertion_point.x, self.insertion_point.y];
|
|
|
|
|
|
// Boundary → run-less stroke groups (local to `ins`), split on the
|
|
|
|
|
|
// NaN gaps the wire uses to separate disjoint segments.
|
|
|
|
|
|
let mut boundary: Vec<Vec<[f32; 2]>> = Vec::new();
|
|
|
|
|
|
let mut seg: Vec<[f32; 2]> = Vec::new();
|
|
|
|
|
|
for p in &pts {
|
|
|
|
|
|
if p[0].is_nan() {
|
|
|
|
|
|
if seg.len() >= 2 {
|
|
|
|
|
|
boundary.push(std::mem::take(&mut seg));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
seg.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
seg.push([(p[0] - ins[0]) as f32, (p[1] - ins[1]) as f32]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if seg.len() >= 2 {
|
|
|
|
|
|
boundary.push(seg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let mut groups: Vec<TextStroke> = vec![TextStroke {
|
|
|
|
|
|
strokes: boundary,
|
|
|
|
|
|
origin: ins,
|
|
|
|
|
|
color: None,
|
|
|
|
|
|
fill_tris: vec![],
|
|
|
|
|
|
run: None,
|
|
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
// Place the path text centred in the frame, sized to span ~90% of the
|
|
|
|
|
|
// frame width (capped so it also fits vertically).
|
|
|
|
|
|
let c0 = corners[0];
|
|
|
|
|
|
let c2 = corners[2];
|
|
|
|
|
|
let uw = [corners[1][0] - c0[0], corners[1][1] - c0[1]];
|
|
|
|
|
|
let vh = [corners[3][0] - c0[0], corners[3][1] - c0[1]];
|
|
|
|
|
|
let frame_w = (uw[0] * uw[0] + uw[1] * uw[1]).sqrt();
|
|
|
|
|
|
let frame_h = (vh[0] * vh[0] + vh[1] * vh[1]).sqrt();
|
|
|
|
|
|
if frame_w > 1e-9 && frame_h > 1e-9 {
|
|
|
|
|
|
let u_hat = [uw[0] / frame_w, uw[1] / frame_w];
|
|
|
|
|
|
let v_hat = [vh[0] / frame_h, vh[1] / frame_h];
|
|
|
|
|
|
let rotation = (u_hat[1] as f32).atan2(u_hat[0] as f32);
|
|
|
|
|
|
let font = resolve_text_style("", document).font_name;
|
|
|
|
|
|
// advance at height 1.0 → width per unit height.
|
|
|
|
|
|
let adv = text_local_bounds(&font, path, 1.0, 1.0, 0.0)
|
|
|
|
|
|
.map(|b| b.advance)
|
|
|
|
|
|
.filter(|a| *a > 1e-3)
|
|
|
|
|
|
.unwrap_or(0.6 * path.chars().count().max(1) as f32);
|
|
|
|
|
|
let height = ((frame_w as f32 * 0.9) / adv)
|
|
|
|
|
|
.min(frame_h as f32 * 0.5)
|
|
|
|
|
|
.max(frame_h as f32 * 0.02);
|
|
|
|
|
|
let text_w = (adv * height) as f64;
|
|
|
|
|
|
let center = [(c0[0] + c2[0]) * 0.5, (c0[1] + c2[1]) * 0.5];
|
|
|
|
|
|
// Shift the baseline-left origin so the run is centred both ways.
|
|
|
|
|
|
let origin = [
|
|
|
|
|
|
center[0] - u_hat[0] * text_w * 0.5 - v_hat[0] * height as f64 * 0.35,
|
|
|
|
|
|
center[1] - u_hat[1] * text_w * 0.5 - v_hat[1] * height as f64 * 0.35,
|
|
|
|
|
|
];
|
|
|
|
|
|
let (strokes, fill_tris) =
|
|
|
|
|
|
lff::tessellate_text_ex([0.0, 0.0], height, rotation, 1.0, 0.0, &font, path);
|
|
|
|
|
|
groups.push(TextStroke {
|
|
|
|
|
|
strokes,
|
|
|
|
|
|
origin,
|
|
|
|
|
|
color: None,
|
|
|
|
|
|
fill_tris,
|
|
|
|
|
|
run: Some(GlyphRun {
|
|
|
|
|
|
text: path.to_string(),
|
|
|
|
|
|
font,
|
|
|
|
|
|
height,
|
|
|
|
|
|
rotation,
|
|
|
|
|
|
width_factor: 1.0,
|
|
|
|
|
|
oblique: 0.0,
|
|
|
|
|
|
tracking: 1.0,
|
|
|
|
|
|
bold: false,
|
|
|
|
|
|
}),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
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(),
|
2026-07-18 19:32:14 +03:00
|
|
|
|
object: TruckObject::Text(groups),
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
snap_pts: vec![],
|
|
|
|
|
|
tangent_geoms: vec![],
|
|
|
|
|
|
key_vertices: corners.to_vec(),
|
2026-05-06 23:24:26 +03:00
|
|
|
|
fill_tris: vec![],
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Grippable for RasterImage {
|
|
|
|
|
|
fn grips(&self) -> Vec<GripDef> {
|
|
|
|
|
|
let corners = image_corners(
|
|
|
|
|
|
&self.insertion_point,
|
|
|
|
|
|
&self.u_vector,
|
|
|
|
|
|
&self.v_vector,
|
|
|
|
|
|
self.size.x,
|
|
|
|
|
|
self.size.y,
|
|
|
|
|
|
);
|
|
|
|
|
|
vec![
|
2026-06-11 00:04:37 +03:00
|
|
|
|
square_grip(0, glam::DVec3::from(corners[0])),
|
|
|
|
|
|
center_grip(1, glam::DVec3::from(corners[1])),
|
|
|
|
|
|
center_grip(2, glam::DVec3::from(corners[2])),
|
|
|
|
|
|
center_grip(3, glam::DVec3::from(corners[3])),
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
|
|
|
|
|
|
if grip_id == 0 {
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// Corner grips 1-3 are display-only (resizing changes u/v vectors,
|
|
|
|
|
|
// which requires careful normalization — deferred).
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl PropertyEditable for RasterImage {
|
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
|
|
|
|
let rotation_deg = self.u_vector.y.atan2(self.u_vector.x).to_degrees();
|
|
|
|
|
|
let scale = self.u_vector.length();
|
|
|
|
|
|
let show_image = self.flags.contains(acadrust::entities::ImageDisplayFlags::SHOW_IMAGE);
|
|
|
|
|
|
let show_clipped = self
|
|
|
|
|
|
.flags
|
|
|
|
|
|
.contains(acadrust::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY);
|
|
|
|
|
|
let clip_inverted = self.clip_boundary.clip_mode == acadrust::entities::ClipMode::Inside;
|
|
|
|
|
|
let transparency = format!("{:.0}%", self.common.transparency.as_percent() * 100.0);
|
|
|
|
|
|
vec![
|
|
|
|
|
|
PropSection {
|
|
|
|
|
|
title: "Geometry".into(),
|
|
|
|
|
|
props: vec![
|
|
|
|
|
|
edit("Position X", "ri_ox", self.insertion_point.x),
|
|
|
|
|
|
edit("Position Y", "ri_oy", self.insertion_point.y),
|
|
|
|
|
|
edit("Position Z", "ri_oz", self.insertion_point.z),
|
|
|
|
|
|
ro("Rotation", "ri_rotation", format!("{:.4}", rotation_deg)),
|
|
|
|
|
|
ro("Width", "ri_width", format!("{:.4}", self.width())),
|
|
|
|
|
|
ro("Height", "ri_height", format!("{:.4}", self.height())),
|
|
|
|
|
|
ro("Scale", "ri_scale", format!("{:.4}", scale)),
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
PropSection {
|
|
|
|
|
|
title: "Misc".into(),
|
|
|
|
|
|
props: vec![
|
|
|
|
|
|
ro("Name", "ri_name", self.file_name().to_string()),
|
|
|
|
|
|
edit("Brightness", "ri_bright", self.brightness as f64),
|
|
|
|
|
|
edit("Contrast", "ri_contrast", self.contrast as f64),
|
|
|
|
|
|
edit("Fade", "ri_fade", self.fade as f64),
|
|
|
|
|
|
ro("Transparency", "ri_transparency", transparency),
|
|
|
|
|
|
Property {
|
|
|
|
|
|
label: "Show image".into(),
|
|
|
|
|
|
field: "ri_show_image",
|
|
|
|
|
|
value: PropValue::BoolToggle {
|
|
|
|
|
|
field: "ri_show_image",
|
|
|
|
|
|
value: show_image,
|
|
|
|
|
|
},
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +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
|
|
|
|
Property {
|
|
|
|
|
|
label: "Show clipped".into(),
|
|
|
|
|
|
field: "ri_show_clipped",
|
|
|
|
|
|
value: PropValue::BoolToggle {
|
|
|
|
|
|
field: "ri_show_clipped",
|
|
|
|
|
|
value: show_clipped,
|
|
|
|
|
|
},
|
feat(entities): surface remaining 2D + Region fields in properties
Closes out the 2D-entity audit (and the Region partner that ships next
to Solid3D / Body). Round-trip-only metadata fields plus a few editable
ones gain Properties-panel rows so the values the parser populates are
visible and don't get silently dropped on save:
- Hatch: seed_points count, pixel_size, normal
- Polyline2D: smooth_surface, default_start_width, default_end_width,
thickness, normal (with editors for the widths/thickness)
- Region: uid, silhouettes (shared file with Solid3D / Body)
- Underlay: clip_inverted
- RasterImage: class_version, definition_handle, definition_reactor_handle
- Wipeout: class_version, clip_mode, definition_handle,
definition_reactor_handle
- Leader: annotation_handle, override_color
- Tolerance: dimension_style_name, dimension_style_handle, dimension_gap,
text_height (editable), direction, normal
- MLine: style_handle, style_element_count, justification picker
- Ole2Frame: version, source_application, binary_data size, dwg_mode,
dwg_trailing_byte, is_paper_space
- Viewport: snap_base/spacing/angle, twist_angle, front/back clip Z,
circle_sides, grid_flags, grid_major, base_ucs_handle, ucs_ortho_type,
background_handle, shade_plot_handle, visual_style_handle,
default_lighting, default_lighting_type, ambient_color (with editors
for the snap / clip / circle_sides values)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 21:28:16 +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
|
|
|
|
Property {
|
|
|
|
|
|
label: "Clip inverted".into(),
|
|
|
|
|
|
field: "ri_clip_inverted",
|
|
|
|
|
|
value: PropValue::BoolToggle {
|
|
|
|
|
|
field: "ri_clip_inverted",
|
|
|
|
|
|
value: clip_inverted,
|
|
|
|
|
|
},
|
feat(entities): surface remaining 2D + Region fields in properties
Closes out the 2D-entity audit (and the Region partner that ships next
to Solid3D / Body). Round-trip-only metadata fields plus a few editable
ones gain Properties-panel rows so the values the parser populates are
visible and don't get silently dropped on save:
- Hatch: seed_points count, pixel_size, normal
- Polyline2D: smooth_surface, default_start_width, default_end_width,
thickness, normal (with editors for the widths/thickness)
- Region: uid, silhouettes (shared file with Solid3D / Body)
- Underlay: clip_inverted
- RasterImage: class_version, definition_handle, definition_reactor_handle
- Wipeout: class_version, clip_mode, definition_handle,
definition_reactor_handle
- Leader: annotation_handle, override_color
- Tolerance: dimension_style_name, dimension_style_handle, dimension_gap,
text_height (editable), direction, normal
- MLine: style_handle, style_element_count, justification picker
- Ole2Frame: version, source_application, binary_data size, dwg_mode,
dwg_trailing_byte, is_paper_space
- Viewport: snap_base/spacing/angle, twist_angle, front/back clip Z,
circle_sides, grid_flags, grid_major, base_ucs_handle, ucs_ortho_type,
background_handle, shade_plot_handle, visual_style_handle,
default_lighting, default_lighting_type, ambient_color (with editors
for the snap / clip / circle_sides values)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 21:28:16 +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
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn apply_geom_prop(&mut self, field: &str, value: &str) {
|
|
|
|
|
|
match field {
|
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
|
|
|
|
"ri_show_image" => {
|
|
|
|
|
|
let on = if value == "toggle" {
|
|
|
|
|
|
!self.flags.contains(acadrust::entities::ImageDisplayFlags::SHOW_IMAGE)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
value == "true"
|
|
|
|
|
|
};
|
|
|
|
|
|
self.set_visible(on);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
"ri_show_clipped" => {
|
|
|
|
|
|
let on = if value == "toggle" {
|
|
|
|
|
|
!self
|
|
|
|
|
|
.flags
|
|
|
|
|
|
.contains(acadrust::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
value == "true"
|
|
|
|
|
|
};
|
|
|
|
|
|
if on {
|
|
|
|
|
|
self.flags |= acadrust::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
self.flags &= !acadrust::entities::ImageDisplayFlags::USE_CLIPPING_BOUNDARY;
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
"ri_clip_inverted" => {
|
|
|
|
|
|
let on = if value == "toggle" {
|
|
|
|
|
|
self.clip_boundary.clip_mode != acadrust::entities::ClipMode::Inside
|
2026-05-12 10:36:15 +03:00
|
|
|
|
} else {
|
|
|
|
|
|
value == "true"
|
|
|
|
|
|
};
|
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
|
|
|
|
self.clip_boundary.clip_mode = if on {
|
|
|
|
|
|
acadrust::entities::ClipMode::Inside
|
|
|
|
|
|
} else {
|
|
|
|
|
|
acadrust::entities::ClipMode::Outside
|
|
|
|
|
|
};
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
_ => {}
|
|
|
|
|
|
}
|
2026-05-12 10:36:15 +03:00
|
|
|
|
let Ok(v) = value.trim().parse::<f64>() else {
|
|
|
|
|
|
return;
|
|
|
|
|
|
};
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
match field {
|
|
|
|
|
|
"ri_ox" => self.insertion_point.x = v,
|
|
|
|
|
|
"ri_oy" => self.insertion_point.y = v,
|
|
|
|
|
|
"ri_oz" => self.insertion_point.z = v,
|
|
|
|
|
|
"ri_bright" => self.brightness = v.clamp(0.0, 100.0) as u8,
|
|
|
|
|
|
"ri_contrast" => self.contrast = v.clamp(0.0, 100.0) as u8,
|
|
|
|
|
|
"ri_fade" => self.fade = v.clamp(0.0, 100.0) as u8,
|
|
|
|
|
|
_ => {}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Transformable for RasterImage {
|
|
|
|
|
|
fn apply_transform(&mut self, t: &EntityTransform) {
|
2026-06-16 11:33:46 +03:00
|
|
|
|
crate::scene::view::transform::apply_standard_entity_transform(self, t, |entity, p1, p2| {
|
|
|
|
|
|
crate::scene::view::transform::reflect_xy_point(
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
&mut entity.insertion_point.x,
|
|
|
|
|
|
&mut entity.insertion_point.y,
|
|
|
|
|
|
p1,
|
|
|
|
|
|
p2,
|
|
|
|
|
|
);
|
|
|
|
|
|
let ax = (p2.x - p1.x) as f64;
|
|
|
|
|
|
let ay = (p2.y - p1.y) as f64;
|
|
|
|
|
|
let len2 = ax * ax + ay * ay;
|
|
|
|
|
|
if len2 > 1e-12 {
|
|
|
|
|
|
reflect_vec3(&mut entity.u_vector.x, &mut entity.u_vector.y, ax, ay, len2);
|
|
|
|
|
|
reflect_vec3(&mut entity.v_vector.x, &mut entity.v_vector.y, ax, ay, len2);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ── Wipeout ───────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
impl TruckConvertible for Wipeout {
|
|
|
|
|
|
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
|
|
|
|
|
let corners = image_corners(
|
|
|
|
|
|
&self.insertion_point,
|
|
|
|
|
|
&self.u_vector,
|
|
|
|
|
|
&self.v_vector,
|
|
|
|
|
|
self.size.x,
|
|
|
|
|
|
self.size.y,
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// If clipping is enabled and there's a polygon boundary, show that.
|
|
|
|
|
|
let pts = if self.clipping_enabled
|
|
|
|
|
|
&& self.clip_boundary_vertices.len() >= 3
|
|
|
|
|
|
&& matches!(
|
|
|
|
|
|
self.clip_type,
|
|
|
|
|
|
acadrust::entities::WipeoutClipType::Polygonal
|
2026-05-12 10:36:15 +03:00
|
|
|
|
) {
|
2026-05-22 14:14:22 +03:00
|
|
|
|
// Clip vertices are stored in image-pixel space, centred on the
|
|
|
|
|
|
// image (range ±size/2). The image's bottom-left corner sits at
|
|
|
|
|
|
// `insertion_point`, the image-Y axis points DOWN (per DXF
|
|
|
|
|
|
// "v_vector points down the image"), so map:
|
|
|
|
|
|
// x_off = (clip.x + size.x/2) × u_vector
|
|
|
|
|
|
// y_off = (size.y/2 − clip.y) × v_vector ← y flipped
|
2026-05-12 23:47:40 +03:00
|
|
|
|
let ox = self.insertion_point.x;
|
|
|
|
|
|
let oy = self.insertion_point.y;
|
|
|
|
|
|
let oz = self.insertion_point.z;
|
|
|
|
|
|
let mut poly: Vec<[f64; 3]> = self
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
.clip_boundary_vertices
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
.map(|v| {
|
2026-05-22 14:14:22 +03:00
|
|
|
|
let cx = v.x + self.size.x * 0.5;
|
|
|
|
|
|
let cy = self.size.y * 0.5 - v.y;
|
|
|
|
|
|
let wx = self.u_vector.x * cx + self.v_vector.x * cy;
|
|
|
|
|
|
let wy = self.u_vector.y * cx + self.v_vector.y * cy;
|
|
|
|
|
|
let wz = self.u_vector.z * cx + self.v_vector.z * cy;
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
[ox + wx, oy + wy, oz + wz]
|
|
|
|
|
|
})
|
|
|
|
|
|
.collect();
|
|
|
|
|
|
// Close the polygon.
|
|
|
|
|
|
if let Some(&first) = poly.first() {
|
|
|
|
|
|
poly.push(first);
|
|
|
|
|
|
}
|
|
|
|
|
|
poly
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Rectangular boundary — just the border, no diagonals (mask area).
|
|
|
|
|
|
image_wire(corners, false)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
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: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
object: TruckObject::Lines(pts),
|
|
|
|
|
|
snap_pts: vec![],
|
|
|
|
|
|
tangent_geoms: vec![],
|
|
|
|
|
|
key_vertices: corners.to_vec(),
|
2026-05-06 23:24:26 +03:00
|
|
|
|
fill_tris: vec![],
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Grippable for Wipeout {
|
|
|
|
|
|
fn grips(&self) -> Vec<GripDef> {
|
Feat: ROADMAP Phase 1-5 batch — trim/extend, plot scale, viewport UX, mline caps, table alignment
- TRIM/EXTEND: Ray and XLine entities supported as cutting boundaries and trim targets;
trim results in Ray→Line/Ray, XLine→Ray/Ray or Line; hover preview added
- Plot scale override: Fit/1:1/1:2/1:5/1:10/1:20/1:50/1:100/2:1 buttons added to Page Setup
panel; PageSetupCommit applies scale to PlotSettings
- Viewport UX: locked viewport gets orange border; selected viewport gets white border
- Named view → viewport assignment: Choice dropdown in properties panel copies
view_target/direction/height to the viewport entity
- MLine caps: perpendicular start/end cap lines added for open (non-closed) MLines
- Wipeout polygon grips: boundary vertices become editable grips when clipping_enabled+Polygonal;
world→pixel back-projection on drag
- Table cell alignment: CellStyle.alignment (1-9) drives left/center/right + top/middle/bottom
text positioning; cxf::measure_text() helper added
- New commands/features: DIMCONTINUE (DCO), DIMBASELINE (DBA), TOLERANCE (TOL), TABLE,
ATTDEF, ATTEDIT, ATTDISP, BREAKATPOINT (BAP), PLOTWINDOW (PW), MLINE (ML);
DIMSTYLE/DIMCURRENT/CLAYER/LTSCALE/CELTSCALE/SCALETEXT/XDATA/UCSICON/REGEN/DRAWORDER extended
- PLINE arc mode: A/L/CLOSE text input, bulge computation, arc preview
- Warning cleanup: removed unused imports and unreachable patterns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:31:05 +03:00
|
|
|
|
// If polygonal clipping is active, expose individual polygon vertices as grips.
|
|
|
|
|
|
let is_polygon = self.clipping_enabled
|
|
|
|
|
|
&& self.clip_boundary_vertices.len() >= 3
|
|
|
|
|
|
&& matches!(
|
|
|
|
|
|
self.clip_type,
|
|
|
|
|
|
acadrust::entities::WipeoutClipType::Polygonal
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if is_polygon {
|
2026-06-11 00:04:37 +03:00
|
|
|
|
let ox = self.insertion_point.x;
|
|
|
|
|
|
let oy = self.insertion_point.y;
|
|
|
|
|
|
let oz = self.insertion_point.z;
|
2026-05-22 14:14:22 +03:00
|
|
|
|
// Same image-pixel-space → WCS mapping as `to_truck` so grips
|
|
|
|
|
|
// sit exactly on the rendered polygon vertices.
|
Feat: ROADMAP Phase 1-5 batch — trim/extend, plot scale, viewport UX, mline caps, table alignment
- TRIM/EXTEND: Ray and XLine entities supported as cutting boundaries and trim targets;
trim results in Ray→Line/Ray, XLine→Ray/Ray or Line; hover preview added
- Plot scale override: Fit/1:1/1:2/1:5/1:10/1:20/1:50/1:100/2:1 buttons added to Page Setup
panel; PageSetupCommit applies scale to PlotSettings
- Viewport UX: locked viewport gets orange border; selected viewport gets white border
- Named view → viewport assignment: Choice dropdown in properties panel copies
view_target/direction/height to the viewport entity
- MLine caps: perpendicular start/end cap lines added for open (non-closed) MLines
- Wipeout polygon grips: boundary vertices become editable grips when clipping_enabled+Polygonal;
world→pixel back-projection on drag
- Table cell alignment: CellStyle.alignment (1-9) drives left/center/right + top/middle/bottom
text positioning; cxf::measure_text() helper added
- New commands/features: DIMCONTINUE (DCO), DIMBASELINE (DBA), TOLERANCE (TOL), TABLE,
ATTDEF, ATTEDIT, ATTDISP, BREAKATPOINT (BAP), PLOTWINDOW (PW), MLINE (ML);
DIMSTYLE/DIMCURRENT/CLAYER/LTSCALE/CELTSCALE/SCALETEXT/XDATA/UCSICON/REGEN/DRAWORDER extended
- PLINE arc mode: A/L/CLOSE text input, bulge computation, arc preview
- Warning cleanup: removed unused imports and unreachable patterns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:31:05 +03:00
|
|
|
|
self.clip_boundary_vertices
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
.enumerate()
|
|
|
|
|
|
.map(|(i, v)| {
|
2026-05-22 14:14:22 +03:00
|
|
|
|
let cx = v.x + self.size.x * 0.5;
|
|
|
|
|
|
let cy = self.size.y * 0.5 - v.y;
|
2026-06-11 00:04:37 +03:00
|
|
|
|
let wx = self.u_vector.x * cx + self.v_vector.x * cy;
|
|
|
|
|
|
let wy = self.u_vector.y * cx + self.v_vector.y * cy;
|
|
|
|
|
|
let wz = self.u_vector.z * cx + self.v_vector.z * cy;
|
Feat: ROADMAP Phase 1-5 batch — trim/extend, plot scale, viewport UX, mline caps, table alignment
- TRIM/EXTEND: Ray and XLine entities supported as cutting boundaries and trim targets;
trim results in Ray→Line/Ray, XLine→Ray/Ray or Line; hover preview added
- Plot scale override: Fit/1:1/1:2/1:5/1:10/1:20/1:50/1:100/2:1 buttons added to Page Setup
panel; PageSetupCommit applies scale to PlotSettings
- Viewport UX: locked viewport gets orange border; selected viewport gets white border
- Named view → viewport assignment: Choice dropdown in properties panel copies
view_target/direction/height to the viewport entity
- MLine caps: perpendicular start/end cap lines added for open (non-closed) MLines
- Wipeout polygon grips: boundary vertices become editable grips when clipping_enabled+Polygonal;
world→pixel back-projection on drag
- Table cell alignment: CellStyle.alignment (1-9) drives left/center/right + top/middle/bottom
text positioning; cxf::measure_text() helper added
- New commands/features: DIMCONTINUE (DCO), DIMBASELINE (DBA), TOLERANCE (TOL), TABLE,
ATTDEF, ATTEDIT, ATTDISP, BREAKATPOINT (BAP), PLOTWINDOW (PW), MLINE (ML);
DIMSTYLE/DIMCURRENT/CLAYER/LTSCALE/CELTSCALE/SCALETEXT/XDATA/UCSICON/REGEN/DRAWORDER extended
- PLINE arc mode: A/L/CLOSE text input, bulge computation, arc preview
- Warning cleanup: removed unused imports and unreachable patterns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:31:05 +03:00
|
|
|
|
if i == 0 {
|
2026-06-11 00:04:37 +03:00
|
|
|
|
square_grip(i, glam::DVec3::new(ox + wx, oy + wy, oz + wz))
|
Feat: ROADMAP Phase 1-5 batch — trim/extend, plot scale, viewport UX, mline caps, table alignment
- TRIM/EXTEND: Ray and XLine entities supported as cutting boundaries and trim targets;
trim results in Ray→Line/Ray, XLine→Ray/Ray or Line; hover preview added
- Plot scale override: Fit/1:1/1:2/1:5/1:10/1:20/1:50/1:100/2:1 buttons added to Page Setup
panel; PageSetupCommit applies scale to PlotSettings
- Viewport UX: locked viewport gets orange border; selected viewport gets white border
- Named view → viewport assignment: Choice dropdown in properties panel copies
view_target/direction/height to the viewport entity
- MLine caps: perpendicular start/end cap lines added for open (non-closed) MLines
- Wipeout polygon grips: boundary vertices become editable grips when clipping_enabled+Polygonal;
world→pixel back-projection on drag
- Table cell alignment: CellStyle.alignment (1-9) drives left/center/right + top/middle/bottom
text positioning; cxf::measure_text() helper added
- New commands/features: DIMCONTINUE (DCO), DIMBASELINE (DBA), TOLERANCE (TOL), TABLE,
ATTDEF, ATTEDIT, ATTDISP, BREAKATPOINT (BAP), PLOTWINDOW (PW), MLINE (ML);
DIMSTYLE/DIMCURRENT/CLAYER/LTSCALE/CELTSCALE/SCALETEXT/XDATA/UCSICON/REGEN/DRAWORDER extended
- PLINE arc mode: A/L/CLOSE text input, bulge computation, arc preview
- Warning cleanup: removed unused imports and unreachable patterns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:31:05 +03:00
|
|
|
|
} else {
|
2026-06-11 00:04:37 +03:00
|
|
|
|
center_grip(i, glam::DVec3::new(ox + wx, oy + wy, oz + wz))
|
Feat: ROADMAP Phase 1-5 batch — trim/extend, plot scale, viewport UX, mline caps, table alignment
- TRIM/EXTEND: Ray and XLine entities supported as cutting boundaries and trim targets;
trim results in Ray→Line/Ray, XLine→Ray/Ray or Line; hover preview added
- Plot scale override: Fit/1:1/1:2/1:5/1:10/1:20/1:50/1:100/2:1 buttons added to Page Setup
panel; PageSetupCommit applies scale to PlotSettings
- Viewport UX: locked viewport gets orange border; selected viewport gets white border
- Named view → viewport assignment: Choice dropdown in properties panel copies
view_target/direction/height to the viewport entity
- MLine caps: perpendicular start/end cap lines added for open (non-closed) MLines
- Wipeout polygon grips: boundary vertices become editable grips when clipping_enabled+Polygonal;
world→pixel back-projection on drag
- Table cell alignment: CellStyle.alignment (1-9) drives left/center/right + top/middle/bottom
text positioning; cxf::measure_text() helper added
- New commands/features: DIMCONTINUE (DCO), DIMBASELINE (DBA), TOLERANCE (TOL), TABLE,
ATTDEF, ATTEDIT, ATTDISP, BREAKATPOINT (BAP), PLOTWINDOW (PW), MLINE (ML);
DIMSTYLE/DIMCURRENT/CLAYER/LTSCALE/CELTSCALE/SCALETEXT/XDATA/UCSICON/REGEN/DRAWORDER extended
- PLINE arc mode: A/L/CLOSE text input, bulge computation, arc preview
- Warning cleanup: removed unused imports and unreachable patterns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:31:05 +03:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.collect()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
let corners = image_corners(
|
|
|
|
|
|
&self.insertion_point,
|
|
|
|
|
|
&self.u_vector,
|
|
|
|
|
|
&self.v_vector,
|
|
|
|
|
|
self.size.x,
|
|
|
|
|
|
self.size.y,
|
|
|
|
|
|
);
|
|
|
|
|
|
vec![
|
2026-06-11 00:04:37 +03:00
|
|
|
|
square_grip(0, glam::DVec3::from(corners[0])),
|
|
|
|
|
|
center_grip(1, glam::DVec3::from(corners[1])),
|
|
|
|
|
|
center_grip(2, glam::DVec3::from(corners[2])),
|
|
|
|
|
|
center_grip(3, glam::DVec3::from(corners[3])),
|
Feat: ROADMAP Phase 1-5 batch — trim/extend, plot scale, viewport UX, mline caps, table alignment
- TRIM/EXTEND: Ray and XLine entities supported as cutting boundaries and trim targets;
trim results in Ray→Line/Ray, XLine→Ray/Ray or Line; hover preview added
- Plot scale override: Fit/1:1/1:2/1:5/1:10/1:20/1:50/1:100/2:1 buttons added to Page Setup
panel; PageSetupCommit applies scale to PlotSettings
- Viewport UX: locked viewport gets orange border; selected viewport gets white border
- Named view → viewport assignment: Choice dropdown in properties panel copies
view_target/direction/height to the viewport entity
- MLine caps: perpendicular start/end cap lines added for open (non-closed) MLines
- Wipeout polygon grips: boundary vertices become editable grips when clipping_enabled+Polygonal;
world→pixel back-projection on drag
- Table cell alignment: CellStyle.alignment (1-9) drives left/center/right + top/middle/bottom
text positioning; cxf::measure_text() helper added
- New commands/features: DIMCONTINUE (DCO), DIMBASELINE (DBA), TOLERANCE (TOL), TABLE,
ATTDEF, ATTEDIT, ATTDISP, BREAKATPOINT (BAP), PLOTWINDOW (PW), MLINE (ML);
DIMSTYLE/DIMCURRENT/CLAYER/LTSCALE/CELTSCALE/SCALETEXT/XDATA/UCSICON/REGEN/DRAWORDER extended
- PLINE arc mode: A/L/CLOSE text input, bulge computation, arc preview
- Warning cleanup: removed unused imports and unreachable patterns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:31:05 +03:00
|
|
|
|
]
|
|
|
|
|
|
}
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
|
Feat: ROADMAP Phase 1-5 batch — trim/extend, plot scale, viewport UX, mline caps, table alignment
- TRIM/EXTEND: Ray and XLine entities supported as cutting boundaries and trim targets;
trim results in Ray→Line/Ray, XLine→Ray/Ray or Line; hover preview added
- Plot scale override: Fit/1:1/1:2/1:5/1:10/1:20/1:50/1:100/2:1 buttons added to Page Setup
panel; PageSetupCommit applies scale to PlotSettings
- Viewport UX: locked viewport gets orange border; selected viewport gets white border
- Named view → viewport assignment: Choice dropdown in properties panel copies
view_target/direction/height to the viewport entity
- MLine caps: perpendicular start/end cap lines added for open (non-closed) MLines
- Wipeout polygon grips: boundary vertices become editable grips when clipping_enabled+Polygonal;
world→pixel back-projection on drag
- Table cell alignment: CellStyle.alignment (1-9) drives left/center/right + top/middle/bottom
text positioning; cxf::measure_text() helper added
- New commands/features: DIMCONTINUE (DCO), DIMBASELINE (DBA), TOLERANCE (TOL), TABLE,
ATTDEF, ATTEDIT, ATTDISP, BREAKATPOINT (BAP), PLOTWINDOW (PW), MLINE (ML);
DIMSTYLE/DIMCURRENT/CLAYER/LTSCALE/CELTSCALE/SCALETEXT/XDATA/UCSICON/REGEN/DRAWORDER extended
- PLINE arc mode: A/L/CLOSE text input, bulge computation, arc preview
- Warning cleanup: removed unused imports and unreachable patterns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:31:05 +03:00
|
|
|
|
let is_polygon = self.clipping_enabled
|
|
|
|
|
|
&& self.clip_boundary_vertices.len() >= 3
|
|
|
|
|
|
&& matches!(
|
|
|
|
|
|
self.clip_type,
|
|
|
|
|
|
acadrust::entities::WipeoutClipType::Polygonal
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if is_polygon {
|
|
|
|
|
|
// Move the clicked polygon vertex in world space → back-project to pixel space.
|
|
|
|
|
|
if let Some(v) = self.clip_boundary_vertices.get_mut(grip_id) {
|
|
|
|
|
|
// Compute current world position of this vertex.
|
|
|
|
|
|
let ox = self.insertion_point.x;
|
|
|
|
|
|
let oy = self.insertion_point.y;
|
|
|
|
|
|
let oz = self.insertion_point.z;
|
2026-05-12 10:36:15 +03:00
|
|
|
|
let cur_wx =
|
|
|
|
|
|
ox + self.u_vector.x * v.x * self.size.x + self.v_vector.x * v.y * self.size.y;
|
|
|
|
|
|
let cur_wy =
|
|
|
|
|
|
oy + self.u_vector.y * v.x * self.size.x + self.v_vector.y * v.y * self.size.y;
|
|
|
|
|
|
let cur_wz =
|
|
|
|
|
|
oz + self.u_vector.z * v.x * self.size.x + self.v_vector.z * v.y * self.size.y;
|
Feat: ROADMAP Phase 1-5 batch — trim/extend, plot scale, viewport UX, mline caps, table alignment
- TRIM/EXTEND: Ray and XLine entities supported as cutting boundaries and trim targets;
trim results in Ray→Line/Ray, XLine→Ray/Ray or Line; hover preview added
- Plot scale override: Fit/1:1/1:2/1:5/1:10/1:20/1:50/1:100/2:1 buttons added to Page Setup
panel; PageSetupCommit applies scale to PlotSettings
- Viewport UX: locked viewport gets orange border; selected viewport gets white border
- Named view → viewport assignment: Choice dropdown in properties panel copies
view_target/direction/height to the viewport entity
- MLine caps: perpendicular start/end cap lines added for open (non-closed) MLines
- Wipeout polygon grips: boundary vertices become editable grips when clipping_enabled+Polygonal;
world→pixel back-projection on drag
- Table cell alignment: CellStyle.alignment (1-9) drives left/center/right + top/middle/bottom
text positioning; cxf::measure_text() helper added
- New commands/features: DIMCONTINUE (DCO), DIMBASELINE (DBA), TOLERANCE (TOL), TABLE,
ATTDEF, ATTEDIT, ATTDISP, BREAKATPOINT (BAP), PLOTWINDOW (PW), MLINE (ML);
DIMSTYLE/DIMCURRENT/CLAYER/LTSCALE/CELTSCALE/SCALETEXT/XDATA/UCSICON/REGEN/DRAWORDER extended
- PLINE arc mode: A/L/CLOSE text input, bulge computation, arc preview
- Warning cleanup: removed unused imports and unreachable patterns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:31:05 +03:00
|
|
|
|
let new_w = match apply {
|
2026-05-12 10:36:15 +03:00
|
|
|
|
GripApply::Translate(d) => [
|
|
|
|
|
|
cur_wx + d.x as f64,
|
|
|
|
|
|
cur_wy + d.y as f64,
|
|
|
|
|
|
cur_wz + d.z as f64,
|
|
|
|
|
|
],
|
Feat: ROADMAP Phase 1-5 batch — trim/extend, plot scale, viewport UX, mline caps, table alignment
- TRIM/EXTEND: Ray and XLine entities supported as cutting boundaries and trim targets;
trim results in Ray→Line/Ray, XLine→Ray/Ray or Line; hover preview added
- Plot scale override: Fit/1:1/1:2/1:5/1:10/1:20/1:50/1:100/2:1 buttons added to Page Setup
panel; PageSetupCommit applies scale to PlotSettings
- Viewport UX: locked viewport gets orange border; selected viewport gets white border
- Named view → viewport assignment: Choice dropdown in properties panel copies
view_target/direction/height to the viewport entity
- MLine caps: perpendicular start/end cap lines added for open (non-closed) MLines
- Wipeout polygon grips: boundary vertices become editable grips when clipping_enabled+Polygonal;
world→pixel back-projection on drag
- Table cell alignment: CellStyle.alignment (1-9) drives left/center/right + top/middle/bottom
text positioning; cxf::measure_text() helper added
- New commands/features: DIMCONTINUE (DCO), DIMBASELINE (DBA), TOLERANCE (TOL), TABLE,
ATTDEF, ATTEDIT, ATTDISP, BREAKATPOINT (BAP), PLOTWINDOW (PW), MLINE (ML);
DIMSTYLE/DIMCURRENT/CLAYER/LTSCALE/CELTSCALE/SCALETEXT/XDATA/UCSICON/REGEN/DRAWORDER extended
- PLINE arc mode: A/L/CLOSE text input, bulge computation, arc preview
- Warning cleanup: removed unused imports and unreachable patterns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 15:31:05 +03:00
|
|
|
|
GripApply::Absolute(p) => [p.x as f64, p.y as f64, p.z as f64],
|
|
|
|
|
|
};
|
|
|
|
|
|
// Back-project: solve for pixel coords using u_vector and v_vector.
|
|
|
|
|
|
// In 2D (XY plane): new_w - insertion_point = u_vec * vx * sx + v_vec * vy * sy
|
|
|
|
|
|
let dx = new_w[0] - self.insertion_point.x;
|
|
|
|
|
|
let dy = new_w[1] - self.insertion_point.y;
|
|
|
|
|
|
let ux = self.u_vector.x * self.size.x;
|
|
|
|
|
|
let uy = self.u_vector.y * self.size.x;
|
|
|
|
|
|
let vx = self.v_vector.x * self.size.y;
|
|
|
|
|
|
let vy = self.v_vector.y * self.size.y;
|
|
|
|
|
|
let det = ux * vy - uy * vx;
|
|
|
|
|
|
if det.abs() > 1e-12 {
|
|
|
|
|
|
v.x = (dx * vy - dy * vx) / det;
|
|
|
|
|
|
v.y = (ux * dy - uy * dx) / det;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if grip_id == 0 {
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl PropertyEditable for Wipeout {
|
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
|
|
|
|
let show_image = self.flags.contains(acadrust::entities::WipeoutDisplayFlags::SHOW_IMAGE);
|
|
|
|
|
|
let show_clipped = self
|
|
|
|
|
|
.flags
|
|
|
|
|
|
.contains(acadrust::entities::WipeoutDisplayFlags::USE_CLIPPING_BOUNDARY);
|
|
|
|
|
|
let bg_transparency = self
|
|
|
|
|
|
.flags
|
|
|
|
|
|
.contains(acadrust::entities::WipeoutDisplayFlags::TRANSPARENCY_ON);
|
|
|
|
|
|
vec![
|
|
|
|
|
|
PropSection {
|
|
|
|
|
|
title: "Geometry".into(),
|
|
|
|
|
|
props: vec![
|
|
|
|
|
|
edit("Position X", "wo_ox", self.insertion_point.x),
|
|
|
|
|
|
edit("Position Y", "wo_oy", self.insertion_point.y),
|
|
|
|
|
|
edit("Position Z", "wo_oz", self.insertion_point.z),
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
PropSection {
|
|
|
|
|
|
title: "Misc".into(),
|
|
|
|
|
|
props: vec![
|
|
|
|
|
|
Property {
|
|
|
|
|
|
label: "Show image".into(),
|
|
|
|
|
|
field: "wo_show_image",
|
|
|
|
|
|
value: PropValue::BoolToggle {
|
|
|
|
|
|
field: "wo_show_image",
|
|
|
|
|
|
value: show_image,
|
|
|
|
|
|
},
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +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
|
|
|
|
Property {
|
|
|
|
|
|
label: "Show clipped".into(),
|
|
|
|
|
|
field: "wo_show_clipped",
|
|
|
|
|
|
value: PropValue::BoolToggle {
|
|
|
|
|
|
field: "wo_show_clipped",
|
|
|
|
|
|
value: show_clipped,
|
|
|
|
|
|
},
|
feat(entities): surface remaining 2D + Region fields in properties
Closes out the 2D-entity audit (and the Region partner that ships next
to Solid3D / Body). Round-trip-only metadata fields plus a few editable
ones gain Properties-panel rows so the values the parser populates are
visible and don't get silently dropped on save:
- Hatch: seed_points count, pixel_size, normal
- Polyline2D: smooth_surface, default_start_width, default_end_width,
thickness, normal (with editors for the widths/thickness)
- Region: uid, silhouettes (shared file with Solid3D / Body)
- Underlay: clip_inverted
- RasterImage: class_version, definition_handle, definition_reactor_handle
- Wipeout: class_version, clip_mode, definition_handle,
definition_reactor_handle
- Leader: annotation_handle, override_color
- Tolerance: dimension_style_name, dimension_style_handle, dimension_gap,
text_height (editable), direction, normal
- MLine: style_handle, style_element_count, justification picker
- Ole2Frame: version, source_application, binary_data size, dwg_mode,
dwg_trailing_byte, is_paper_space
- Viewport: snap_base/spacing/angle, twist_angle, front/back clip Z,
circle_sides, grid_flags, grid_major, base_ucs_handle, ucs_ortho_type,
background_handle, shade_plot_handle, visual_style_handle,
default_lighting, default_lighting_type, ambient_color (with editors
for the snap / clip / circle_sides values)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 21:28:16 +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
|
|
|
|
Property {
|
|
|
|
|
|
label: "Background transparency".into(),
|
|
|
|
|
|
field: "wo_bg_transparency",
|
|
|
|
|
|
value: PropValue::BoolToggle {
|
|
|
|
|
|
field: "wo_bg_transparency",
|
|
|
|
|
|
value: bg_transparency,
|
|
|
|
|
|
},
|
feat(entities): surface remaining 2D + Region fields in properties
Closes out the 2D-entity audit (and the Region partner that ships next
to Solid3D / Body). Round-trip-only metadata fields plus a few editable
ones gain Properties-panel rows so the values the parser populates are
visible and don't get silently dropped on save:
- Hatch: seed_points count, pixel_size, normal
- Polyline2D: smooth_surface, default_start_width, default_end_width,
thickness, normal (with editors for the widths/thickness)
- Region: uid, silhouettes (shared file with Solid3D / Body)
- Underlay: clip_inverted
- RasterImage: class_version, definition_handle, definition_reactor_handle
- Wipeout: class_version, clip_mode, definition_handle,
definition_reactor_handle
- Leader: annotation_handle, override_color
- Tolerance: dimension_style_name, dimension_style_handle, dimension_gap,
text_height (editable), direction, normal
- MLine: style_handle, style_element_count, justification picker
- Ole2Frame: version, source_application, binary_data size, dwg_mode,
dwg_trailing_byte, is_paper_space
- Viewport: snap_base/spacing/angle, twist_angle, front/back clip Z,
circle_sides, grid_flags, grid_major, base_ucs_handle, ucs_ortho_type,
background_handle, shade_plot_handle, visual_style_handle,
default_lighting, default_lighting_type, ambient_color (with editors
for the snap / clip / circle_sides values)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 21:28:16 +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
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn apply_geom_prop(&mut self, field: &str, value: &str) {
|
|
|
|
|
|
match field {
|
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
|
|
|
|
"wo_show_image" => {
|
|
|
|
|
|
let on = if value == "toggle" {
|
|
|
|
|
|
!self.flags.contains(acadrust::entities::WipeoutDisplayFlags::SHOW_IMAGE)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
value == "true"
|
|
|
|
|
|
};
|
|
|
|
|
|
self.set_frame_visible(on);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
"wo_show_clipped" => {
|
|
|
|
|
|
let on = if value == "toggle" {
|
|
|
|
|
|
!self
|
|
|
|
|
|
.flags
|
|
|
|
|
|
.contains(acadrust::entities::WipeoutDisplayFlags::USE_CLIPPING_BOUNDARY)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
value == "true"
|
|
|
|
|
|
};
|
|
|
|
|
|
if on {
|
|
|
|
|
|
self.flags |= acadrust::entities::WipeoutDisplayFlags::USE_CLIPPING_BOUNDARY;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
self.flags -= acadrust::entities::WipeoutDisplayFlags::USE_CLIPPING_BOUNDARY;
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
"wo_bg_transparency" => {
|
|
|
|
|
|
let on = if value == "toggle" {
|
|
|
|
|
|
!self.flags.contains(acadrust::entities::WipeoutDisplayFlags::TRANSPARENCY_ON)
|
2026-05-12 10:36:15 +03:00
|
|
|
|
} else {
|
|
|
|
|
|
value == "true"
|
|
|
|
|
|
};
|
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
|
|
|
|
if on {
|
|
|
|
|
|
self.flags |= acadrust::entities::WipeoutDisplayFlags::TRANSPARENCY_ON;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
self.flags -= acadrust::entities::WipeoutDisplayFlags::TRANSPARENCY_ON;
|
|
|
|
|
|
}
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
_ => {}
|
|
|
|
|
|
}
|
2026-05-12 10:36:15 +03:00
|
|
|
|
let Ok(v) = value.trim().parse::<f64>() else {
|
|
|
|
|
|
return;
|
|
|
|
|
|
};
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
match field {
|
|
|
|
|
|
"wo_ox" => self.insertion_point.x = v,
|
|
|
|
|
|
"wo_oy" => self.insertion_point.y = v,
|
|
|
|
|
|
"wo_oz" => self.insertion_point.z = v,
|
|
|
|
|
|
_ => {}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Transformable for Wipeout {
|
|
|
|
|
|
fn apply_transform(&mut self, t: &EntityTransform) {
|
2026-06-16 11:33:46 +03:00
|
|
|
|
crate::scene::view::transform::apply_standard_entity_transform(self, t, |entity, p1, p2| {
|
|
|
|
|
|
crate::scene::view::transform::reflect_xy_point(
|
Feat: Phase 4.3/4.4/4.5 — RasterImage, Wipeout, AttributeDefinition, AttributeEntity
- raster_image.rs: RasterImage renders as border rectangle + X diagonals
(pixel placeholder); Wipeout renders border or polygon clip boundary;
both support insertion_point grip, brightness/contrast/fade properties,
clipping toggle, and mirror transform (u/v vectors reflected)
- attribute.rs: AttributeDefinition renders default_value (or [TAG] if
empty) as font-tessellated text; AttributeEntity renders the live value;
both support insertion grip, position/height/rotation properties,
and transform operations
- mod.rs + traits.rs: wire up all four new entity types through the full
dispatch chain (to_truck, grips, geometry_properties, apply_geom_prop,
apply_grip, apply_transform)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:00:15 +03:00
|
|
|
|
&mut entity.insertion_point.x,
|
|
|
|
|
|
&mut entity.insertion_point.y,
|
|
|
|
|
|
p1,
|
|
|
|
|
|
p2,
|
|
|
|
|
|
);
|
|
|
|
|
|
let ax = (p2.x - p1.x) as f64;
|
|
|
|
|
|
let ay = (p2.y - p1.y) as f64;
|
|
|
|
|
|
let len2 = ax * ax + ay * ay;
|
|
|
|
|
|
if len2 > 1e-12 {
|
|
|
|
|
|
reflect_vec3(&mut entity.u_vector.x, &mut entity.u_vector.y, ax, ay, len2);
|
|
|
|
|
|
reflect_vec3(&mut entity.v_vector.x, &mut entity.v_vector.y, ax, ay, len2);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|