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};
|
2026-08-02 22:09:25 +03:00
|
|
|
|
use crate::t;
|
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::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};
|
refactor: drop truck, and evaluate every curve through the kernel
The last four truck crates are gone from the manifest. What they were doing
falls into three parts, and each now has one answer instead of two.
NURBS evaluation. truck was carrying B-spline curves and surfaces for the
SPLINE entity, hatch boundaries, BLEND's endpoint frames, the spline preview
and ACIS spline-surface faces. The kernel now has both, over one de Boor
written across however many coordinates a control point holds — so a plane
curve and a space curve cannot drift apart, and a surface is the same
algorithm applied twice. The rational and the polynomial cases stop being
separate types: weights absent means polynomial.
The entity conversion. Every LINE, ARC, ELLIPSE, SPLINE and polyline was
built into truck topology purely so it could be sampled back into points.
They are sampled through `entities::curve` now, which is where each one's
geometry is already defined once and what EXTRUDE and REVOLVE read — so a
circle drawn on screen and a circle handed to the Model tab come from the
same definition. That retires four of TruckObject's variants and the module
is renamed for what it does.
SWEEP and LOFT. Both only ever produced a mesh, so both are built from point
lists: a band of quads per span, and a lid where a profile closes. Lofting
profiles of different densities resamples them by distance rather than by
index, so a circle lofted to a square no longer twists.
Two things worth noting for anyone reading the old comments. The tolerance
globals that lived in the tessellation module were never about truck at all —
they are the per-frame chord height, and they move to `curve_tol`. And the
rule that a profile handed over as `Lines` silently broke EXTRUDE and REVOLVE
no longer holds: those read the curve directly and never look at this channel.
The two `automation` test failures are unchanged from before this and are not
caused by it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:08:50 +03:00
|
|
|
|
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, RenderConvertible};
|
|
|
|
|
|
use crate::scene::convert::acad_to_render::{GlyphRun, TextStroke, RenderEntity, RenderObject};
|
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 ───────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
refactor: drop truck, and evaluate every curve through the kernel
The last four truck crates are gone from the manifest. What they were doing
falls into three parts, and each now has one answer instead of two.
NURBS evaluation. truck was carrying B-spline curves and surfaces for the
SPLINE entity, hatch boundaries, BLEND's endpoint frames, the spline preview
and ACIS spline-surface faces. The kernel now has both, over one de Boor
written across however many coordinates a control point holds — so a plane
curve and a space curve cannot drift apart, and a surface is the same
algorithm applied twice. The rational and the polynomial cases stop being
separate types: weights absent means polynomial.
The entity conversion. Every LINE, ARC, ELLIPSE, SPLINE and polyline was
built into truck topology purely so it could be sampled back into points.
They are sampled through `entities::curve` now, which is where each one's
geometry is already defined once and what EXTRUDE and REVOLVE read — so a
circle drawn on screen and a circle handed to the Model tab come from the
same definition. That retires four of TruckObject's variants and the module
is renamed for what it does.
SWEEP and LOFT. Both only ever produced a mesh, so both are built from point
lists: a band of quads per span, and a lid where a profile closes. Lofting
profiles of different densities resamples them by distance rather than by
index, so a circle lofted to a square no longer twists.
Two things worth noting for anyone reading the old comments. The tolerance
globals that lived in the tessellation module were never about truck at all —
they are the per-frame chord height, and they move to `curve_tol`. And the
rule that a profile handed over as `Lines` silently broke EXTRUDE and REVOLVE
no longer holds: those read the curve directly and never look at this channel.
The two `automation` test failures are unchanged from before this and are not
caused by it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:08:50 +03:00
|
|
|
|
impl RenderConvertible for RasterImage {
|
|
|
|
|
|
fn to_render(&self, document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
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
|
|
|
|
]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-18 20:11:29 +03:00
|
|
|
|
// Clip-boundary Y is in image raster space (row 0 = top, Y down); the
|
|
|
|
|
|
// image's v-vector points up, so flip each vertex's Y (`ih - y`) to
|
|
|
|
|
|
// place the boundary where AutoCAD draws it. Must match the raster's
|
|
|
|
|
|
// own clip triangulation in `ImageModel` so outline and pixels align.
|
|
|
|
|
|
let ih = self.size.y;
|
2026-07-23 03:41:52 +03:00
|
|
|
|
// Diagonals are the BROKEN-reference placeholder; a resolvable image
|
|
|
|
|
|
// draws its pixels inside the frame, so the X would scribble over it.
|
|
|
|
|
|
let path_probe = self.file_path.trim();
|
|
|
|
|
|
let resolvable = path_probe.is_empty()
|
|
|
|
|
|
|| crate::scene::model::image_model::resolve_image(path_probe).is_some();
|
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-07-18 20:11:29 +03:00
|
|
|
|
cb.vertices.iter().map(|v| px_to_world(v.x, ih - 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));
|
2026-07-18 20:11:29 +03:00
|
|
|
|
let (y0, y1) = (ih - v0.y, ih - v1.y);
|
|
|
|
|
|
let (ya, yb) = (y0.min(y1), y0.max(y1));
|
2026-05-02 20:01:21 +03:00
|
|
|
|
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]
|
|
|
|
|
|
}
|
2026-07-23 03:41:52 +03:00
|
|
|
|
_ => image_wire(corners, !resolvable),
|
2026-05-02 20:01:21 +03:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2026-07-23 03:41:52 +03:00
|
|
|
|
image_wire(corners, !resolvable)
|
2026-05-02 20:01:21 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-18 20:11:29 +03:00
|
|
|
|
// A raster OCS can display renders its pixels (built separately) inside
|
|
|
|
|
|
// this frame — just draw the frame/clip outline. A reference it cannot
|
|
|
|
|
|
// resolve (an offline/broken URL, a missing or 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. `resolve_image` is memoised and shared with the
|
|
|
|
|
|
// raster loader, so a URL that fetches online is treated as resolvable
|
|
|
|
|
|
// (no placeholder — the image shows) while an offline one falls back to
|
|
|
|
|
|
// the path text, and neither is fetched twice.
|
2026-07-18 19:32:14 +03:00
|
|
|
|
let path = self.file_path.trim();
|
2026-07-18 20:11:29 +03:00
|
|
|
|
let resolvable =
|
|
|
|
|
|
path.is_empty() || crate::scene::model::image_model::resolve_image(path).is_some();
|
2026-07-18 19:32:14 +03:00
|
|
|
|
if resolvable {
|
refactor: drop truck, and evaluate every curve through the kernel
The last four truck crates are gone from the manifest. What they were doing
falls into three parts, and each now has one answer instead of two.
NURBS evaluation. truck was carrying B-spline curves and surfaces for the
SPLINE entity, hatch boundaries, BLEND's endpoint frames, the spline preview
and ACIS spline-surface faces. The kernel now has both, over one de Boor
written across however many coordinates a control point holds — so a plane
curve and a space curve cannot drift apart, and a surface is the same
algorithm applied twice. The rational and the polynomial cases stop being
separate types: weights absent means polynomial.
The entity conversion. Every LINE, ARC, ELLIPSE, SPLINE and polyline was
built into truck topology purely so it could be sampled back into points.
They are sampled through `entities::curve` now, which is where each one's
geometry is already defined once and what EXTRUDE and REVOLVE read — so a
circle drawn on screen and a circle handed to the Model tab come from the
same definition. That retires four of TruckObject's variants and the module
is renamed for what it does.
SWEEP and LOFT. Both only ever produced a mesh, so both are built from point
lists: a band of quads per span, and a lid where a profile closes. Lofting
profiles of different densities resamples them by distance rather than by
index, so a circle lofted to a square no longer twists.
Two things worth noting for anyone reading the old comments. The tolerance
globals that lived in the tessellation module were never about truck at all —
they are the per-frame chord height, and they move to `curve_tol`. And the
rule that a profile handed over as `Lines` silently broke EXTRUDE and REVOLVE
no longer holds: those read the curve directly and never look at this channel.
The two `automation` test failures are unchanged from before this and are not
caused by it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:08:50 +03:00
|
|
|
|
return Some(RenderEntity {
|
2026-07-21 09:28:07 +03:00
|
|
|
|
// Interior pick surface: the image selects on a click anywhere
|
|
|
|
|
|
// inside its frame, not just on the border.
|
|
|
|
|
|
pick_tris: crate::entities::common::quad_pick_tris(&corners),
|
refactor: drop truck, and evaluate every curve through the kernel
The last four truck crates are gone from the manifest. What they were doing
falls into three parts, and each now has one answer instead of two.
NURBS evaluation. truck was carrying B-spline curves and surfaces for the
SPLINE entity, hatch boundaries, BLEND's endpoint frames, the spline preview
and ACIS spline-surface faces. The kernel now has both, over one de Boor
written across however many coordinates a control point holds — so a plane
curve and a space curve cannot drift apart, and a surface is the same
algorithm applied twice. The rational and the polynomial cases stop being
separate types: weights absent means polynomial.
The entity conversion. Every LINE, ARC, ELLIPSE, SPLINE and polyline was
built into truck topology purely so it could be sampled back into points.
They are sampled through `entities::curve` now, which is where each one's
geometry is already defined once and what EXTRUDE and REVOLVE read — so a
circle drawn on screen and a circle handed to the Model tab come from the
same definition. That retires four of TruckObject's variants and the module
is renamed for what it does.
SWEEP and LOFT. Both only ever produced a mesh, so both are built from point
lists: a band of quads per span, and a lid where a profile closes. Lofting
profiles of different densities resamples them by distance rather than by
index, so a circle lofted to a square no longer twists.
Two things worth noting for anyone reading the old comments. The tolerance
globals that lived in the tessellation module were never about truck at all —
they are the per-frame chord height, and they move to `curve_tol`. And the
rule that a profile handed over as `Lines` silently broke EXTRUDE and REVOLVE
no longer holds: those read the curve directly and never look at this channel.
The two `automation` test failures are unchanged from before this and are not
caused by it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:08:50 +03:00
|
|
|
|
object: RenderObject::Lines(pts),
|
2026-07-18 19:32:14 +03:00
|
|
|
|
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,
|
|
|
|
|
|
}),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
refactor: drop truck, and evaluate every curve through the kernel
The last four truck crates are gone from the manifest. What they were doing
falls into three parts, and each now has one answer instead of two.
NURBS evaluation. truck was carrying B-spline curves and surfaces for the
SPLINE entity, hatch boundaries, BLEND's endpoint frames, the spline preview
and ACIS spline-surface faces. The kernel now has both, over one de Boor
written across however many coordinates a control point holds — so a plane
curve and a space curve cannot drift apart, and a surface is the same
algorithm applied twice. The rational and the polynomial cases stop being
separate types: weights absent means polynomial.
The entity conversion. Every LINE, ARC, ELLIPSE, SPLINE and polyline was
built into truck topology purely so it could be sampled back into points.
They are sampled through `entities::curve` now, which is where each one's
geometry is already defined once and what EXTRUDE and REVOLVE read — so a
circle drawn on screen and a circle handed to the Model tab come from the
same definition. That retires four of TruckObject's variants and the module
is renamed for what it does.
SWEEP and LOFT. Both only ever produced a mesh, so both are built from point
lists: a band of quads per span, and a lid where a profile closes. Lofting
profiles of different densities resamples them by distance rather than by
index, so a circle lofted to a square no longer twists.
Two things worth noting for anyone reading the old comments. The tolerance
globals that lived in the tessellation module were never about truck at all —
they are the per-frame chord height, and they move to `curve_tol`. And the
rule that a profile handed over as `Lines` silently broke EXTRUDE and REVOLVE
no longer holds: those read the curve directly and never look at this channel.
The two `automation` test failures are unchanged from before this and are not
caused by it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:08:50 +03:00
|
|
|
|
Some(RenderEntity {
|
2026-07-21 09:28:07 +03:00
|
|
|
|
pick_tris: crate::entities::common::quad_pick_tris(&corners),
|
refactor: drop truck, and evaluate every curve through the kernel
The last four truck crates are gone from the manifest. What they were doing
falls into three parts, and each now has one answer instead of two.
NURBS evaluation. truck was carrying B-spline curves and surfaces for the
SPLINE entity, hatch boundaries, BLEND's endpoint frames, the spline preview
and ACIS spline-surface faces. The kernel now has both, over one de Boor
written across however many coordinates a control point holds — so a plane
curve and a space curve cannot drift apart, and a surface is the same
algorithm applied twice. The rational and the polynomial cases stop being
separate types: weights absent means polynomial.
The entity conversion. Every LINE, ARC, ELLIPSE, SPLINE and polyline was
built into truck topology purely so it could be sampled back into points.
They are sampled through `entities::curve` now, which is where each one's
geometry is already defined once and what EXTRUDE and REVOLVE read — so a
circle drawn on screen and a circle handed to the Model tab come from the
same definition. That retires four of TruckObject's variants and the module
is renamed for what it does.
SWEEP and LOFT. Both only ever produced a mesh, so both are built from point
lists: a band of quads per span, and a lid where a profile closes. Lofting
profiles of different densities resamples them by distance rather than by
index, so a circle lofted to a square no longer twists.
Two things worth noting for anyone reading the old comments. The tolerance
globals that lived in the tessellation module were never about truck at all —
they are the per-frame chord height, and they move to `curve_tol`. And the
rule that a profile handed over as `Lines` silently broke EXTRUDE and REVOLVE
no longer holds: those read the curve directly and never look at this channel.
The two `automation` test failures are unchanged from before this and are not
caused by it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:08:50 +03:00
|
|
|
|
object: RenderObject::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 {
|
2026-08-02 22:09:25 +03:00
|
|
|
|
title: t!("Geometry").into_owned(),
|
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
|
|
|
|
props: vec![
|
2026-08-02 22:09:25 +03:00
|
|
|
|
edit(t!("Position X").as_ref(), "ri_ox", self.insertion_point.x),
|
|
|
|
|
|
edit(t!("Position Y").as_ref(), "ri_oy", self.insertion_point.y),
|
|
|
|
|
|
edit(t!("Position Z").as_ref(), "ri_oz", self.insertion_point.z),
|
|
|
|
|
|
ro(t!("Rotation").as_ref(), "ri_rotation", format!("{:.4}", rotation_deg)),
|
|
|
|
|
|
ro(t!("Width").as_ref(), "ri_width", format!("{:.4}", self.width())),
|
|
|
|
|
|
ro(t!("Height").as_ref(), "ri_height", format!("{:.4}", self.height())),
|
|
|
|
|
|
ro(t!("Scale").as_ref(), "ri_scale", format!("{:.4}", scale)),
|
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 {
|
2026-08-02 22:09:25 +03:00
|
|
|
|
title: t!("Misc").into_owned(),
|
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
|
|
|
|
props: vec![
|
2026-08-02 22:09:25 +03:00
|
|
|
|
ro(t!("Name").as_ref(), "ri_name", self.file_name().to_string()),
|
|
|
|
|
|
edit(t!("Brightness").as_ref(), "ri_bright", self.brightness as f64),
|
|
|
|
|
|
edit(t!("Contrast").as_ref(), "ri_contrast", self.contrast as f64),
|
|
|
|
|
|
edit(t!("Fade").as_ref(), "ri_fade", self.fade as f64),
|
|
|
|
|
|
ro(t!("Transparency").as_ref(), "ri_transparency", transparency),
|
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 {
|
2026-08-02 22:09:25 +03:00
|
|
|
|
label: t!("Show image").into_owned(),
|
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
|
|
|
|
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 {
|
2026-08-02 22:09:25 +03:00
|
|
|
|
label: t!("Show clipped").into_owned(),
|
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
|
|
|
|
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 {
|
2026-08-02 22:09:25 +03:00
|
|
|
|
label: t!("Clip inverted").into_owned(),
|
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
|
|
|
|
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 ───────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
refactor: drop truck, and evaluate every curve through the kernel
The last four truck crates are gone from the manifest. What they were doing
falls into three parts, and each now has one answer instead of two.
NURBS evaluation. truck was carrying B-spline curves and surfaces for the
SPLINE entity, hatch boundaries, BLEND's endpoint frames, the spline preview
and ACIS spline-surface faces. The kernel now has both, over one de Boor
written across however many coordinates a control point holds — so a plane
curve and a space curve cannot drift apart, and a surface is the same
algorithm applied twice. The rational and the polynomial cases stop being
separate types: weights absent means polynomial.
The entity conversion. Every LINE, ARC, ELLIPSE, SPLINE and polyline was
built into truck topology purely so it could be sampled back into points.
They are sampled through `entities::curve` now, which is where each one's
geometry is already defined once and what EXTRUDE and REVOLVE read — so a
circle drawn on screen and a circle handed to the Model tab come from the
same definition. That retires four of TruckObject's variants and the module
is renamed for what it does.
SWEEP and LOFT. Both only ever produced a mesh, so both are built from point
lists: a band of quads per span, and a lid where a profile closes. Lofting
profiles of different densities resamples them by distance rather than by
index, so a circle lofted to a square no longer twists.
Two things worth noting for anyone reading the old comments. The tolerance
globals that lived in the tessellation module were never about truck at all —
they are the per-frame chord height, and they move to `curve_tol`. And the
rule that a profile handed over as `Lines` silently broke EXTRUDE and REVOLVE
no longer holds: those read the curve directly and never look at this channel.
The two `automation` test failures are unchanged from before this and are not
caused by it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:08:50 +03:00
|
|
|
|
impl RenderConvertible for Wipeout {
|
|
|
|
|
|
fn to_render(&self, _document: &acadrust::CadDocument) -> Option<RenderEntity> {
|
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,
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
refactor: drop truck, and evaluate every curve through the kernel
The last four truck crates are gone from the manifest. What they were doing
falls into three parts, and each now has one answer instead of two.
NURBS evaluation. truck was carrying B-spline curves and surfaces for the
SPLINE entity, hatch boundaries, BLEND's endpoint frames, the spline preview
and ACIS spline-surface faces. The kernel now has both, over one de Boor
written across however many coordinates a control point holds — so a plane
curve and a space curve cannot drift apart, and a surface is the same
algorithm applied twice. The rational and the polynomial cases stop being
separate types: weights absent means polynomial.
The entity conversion. Every LINE, ARC, ELLIPSE, SPLINE and polyline was
built into truck topology purely so it could be sampled back into points.
They are sampled through `entities::curve` now, which is where each one's
geometry is already defined once and what EXTRUDE and REVOLVE read — so a
circle drawn on screen and a circle handed to the Model tab come from the
same definition. That retires four of TruckObject's variants and the module
is renamed for what it does.
SWEEP and LOFT. Both only ever produced a mesh, so both are built from point
lists: a band of quads per span, and a lid where a profile closes. Lofting
profiles of different densities resamples them by distance rather than by
index, so a circle lofted to a square no longer twists.
Two things worth noting for anyone reading the old comments. The tolerance
globals that lived in the tessellation module were never about truck at all —
they are the per-frame chord height, and they move to `curve_tol`. And the
rule that a profile handed over as `Lines` silently broke EXTRUDE and REVOLVE
no longer holds: those read the curve directly and never look at this channel.
The two `automation` test failures are unchanged from before this and are not
caused by it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:08:50 +03:00
|
|
|
|
Some(RenderEntity {
|
2026-07-21 09:28:07 +03:00
|
|
|
|
// Interior pick surface — a wipeout reads as a solid patch, so a
|
|
|
|
|
|
// click anywhere on it should select it.
|
|
|
|
|
|
pick_tris: crate::entities::common::quad_pick_tris(&corners),
|
refactor: drop truck, and evaluate every curve through the kernel
The last four truck crates are gone from the manifest. What they were doing
falls into three parts, and each now has one answer instead of two.
NURBS evaluation. truck was carrying B-spline curves and surfaces for the
SPLINE entity, hatch boundaries, BLEND's endpoint frames, the spline preview
and ACIS spline-surface faces. The kernel now has both, over one de Boor
written across however many coordinates a control point holds — so a plane
curve and a space curve cannot drift apart, and a surface is the same
algorithm applied twice. The rational and the polynomial cases stop being
separate types: weights absent means polynomial.
The entity conversion. Every LINE, ARC, ELLIPSE, SPLINE and polyline was
built into truck topology purely so it could be sampled back into points.
They are sampled through `entities::curve` now, which is where each one's
geometry is already defined once and what EXTRUDE and REVOLVE read — so a
circle drawn on screen and a circle handed to the Model tab come from the
same definition. That retires four of TruckObject's variants and the module
is renamed for what it does.
SWEEP and LOFT. Both only ever produced a mesh, so both are built from point
lists: a band of quads per span, and a lid where a profile closes. Lofting
profiles of different densities resamples them by distance rather than by
index, so a circle lofted to a square no longer twists.
Two things worth noting for anyone reading the old comments. The tolerance
globals that lived in the tessellation module were never about truck at all —
they are the per-frame chord height, and they move to `curve_tol`. And the
rule that a profile handed over as `Lines` silently broke EXTRUDE and REVOLVE
no longer holds: those read the curve directly and never look at this channel.
The two `automation` test failures are unchanged from before this and are not
caused by it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:08:50 +03:00
|
|
|
|
object: RenderObject::Lines(pts),
|
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 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;
|
refactor: drop truck, and evaluate every curve through the kernel
The last four truck crates are gone from the manifest. What they were doing
falls into three parts, and each now has one answer instead of two.
NURBS evaluation. truck was carrying B-spline curves and surfaces for the
SPLINE entity, hatch boundaries, BLEND's endpoint frames, the spline preview
and ACIS spline-surface faces. The kernel now has both, over one de Boor
written across however many coordinates a control point holds — so a plane
curve and a space curve cannot drift apart, and a surface is the same
algorithm applied twice. The rational and the polynomial cases stop being
separate types: weights absent means polynomial.
The entity conversion. Every LINE, ARC, ELLIPSE, SPLINE and polyline was
built into truck topology purely so it could be sampled back into points.
They are sampled through `entities::curve` now, which is where each one's
geometry is already defined once and what EXTRUDE and REVOLVE read — so a
circle drawn on screen and a circle handed to the Model tab come from the
same definition. That retires four of TruckObject's variants and the module
is renamed for what it does.
SWEEP and LOFT. Both only ever produced a mesh, so both are built from point
lists: a band of quads per span, and a lid where a profile closes. Lofting
profiles of different densities resamples them by distance rather than by
index, so a circle lofted to a square no longer twists.
Two things worth noting for anyone reading the old comments. The tolerance
globals that lived in the tessellation module were never about truck at all —
they are the per-frame chord height, and they move to `curve_tol`. And the
rule that a profile handed over as `Lines` silently broke EXTRUDE and REVOLVE
no longer holds: those read the curve directly and never look at this channel.
The two `automation` test failures are unchanged from before this and are not
caused by it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:08:50 +03:00
|
|
|
|
// Same image-pixel-space → WCS mapping as `to_render` so grips
|
2026-05-22 14:14:22 +03:00
|
|
|
|
// 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 {
|
2026-08-02 22:09:25 +03:00
|
|
|
|
title: t!("Geometry").into_owned(),
|
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
|
|
|
|
props: vec![
|
2026-08-02 22:09:25 +03:00
|
|
|
|
edit(t!("Position X").as_ref(), "wo_ox", self.insertion_point.x),
|
|
|
|
|
|
edit(t!("Position Y").as_ref(), "wo_oy", self.insertion_point.y),
|
|
|
|
|
|
edit(t!("Position Z").as_ref(), "wo_oz", self.insertion_point.z),
|
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 {
|
2026-08-02 22:09:25 +03:00
|
|
|
|
title: t!("Misc").into_owned(),
|
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
|
|
|
|
props: vec![
|
|
|
|
|
|
Property {
|
2026-08-02 22:09:25 +03:00
|
|
|
|
label: t!("Show image").into_owned(),
|
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
|
|
|
|
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 {
|
2026-08-02 22:09:25 +03:00
|
|
|
|
label: t!("Show clipped").into_owned(),
|
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
|
|
|
|
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 {
|
2026-08-02 22:09:25 +03:00
|
|
|
|
label: t!("Background transparency").into_owned(),
|
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
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|