2026-04-02 19:06:20 +03:00
|
|
|
use acadrust::entities::MLine;
|
|
|
|
|
|
|
|
|
|
use crate::command::EntityTransform;
|
|
|
|
|
use crate::entities::common::{edit_prop as edit, ro_prop as ro, square_grip};
|
|
|
|
|
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
2026-06-16 11:33:46 +03:00
|
|
|
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
|
|
|
|
use crate::scene::model::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
|
|
|
|
use crate::scene::model::wire_model::SnapHint;
|
2026-04-02 19:06:20 +03:00
|
|
|
|
|
|
|
|
impl TruckConvertible for MLine {
|
|
|
|
|
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
|
|
|
|
if self.vertices.is_empty() {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let n = self.vertices.len();
|
|
|
|
|
let closed = self.flags.contains(acadrust::entities::MLineFlags::CLOSED);
|
|
|
|
|
|
|
|
|
|
// Spine: center line connecting all vertex positions.
|
|
|
|
|
// Also attempt to draw parallel offset lines (±scale/2 in miter direction)
|
|
|
|
|
// when scale_factor is non-zero.
|
2026-05-12 23:47:40 +03:00
|
|
|
let scale = self.scale_factor;
|
2026-04-02 19:06:20 +03:00
|
|
|
|
2026-05-12 23:47:40 +03:00
|
|
|
let mut pts: Vec<[f64; 3]> = Vec::new();
|
2026-04-02 19:06:20 +03:00
|
|
|
|
|
|
|
|
// Center spine.
|
|
|
|
|
for v in &self.vertices {
|
2026-05-12 23:47:40 +03:00
|
|
|
pts.push([v.position.x, v.position.y, v.position.z]);
|
2026-04-02 19:06:20 +03:00
|
|
|
}
|
|
|
|
|
if closed && n >= 2 {
|
|
|
|
|
pts.push([
|
2026-05-12 23:47:40 +03:00
|
|
|
self.vertices[0].position.x,
|
|
|
|
|
self.vertices[0].position.y,
|
|
|
|
|
self.vertices[0].position.z,
|
2026-04-02 19:06:20 +03:00
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parallel offset lines — one at +scale/2 and one at -scale/2
|
|
|
|
|
// along each vertex's miter direction.
|
|
|
|
|
if scale.abs() > 1e-6 {
|
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 half = scale * 0.5;
|
2026-05-12 23:47:40 +03:00
|
|
|
for sign in [-1.0_f64, 1.0_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
|
|
|
let offset = half * sign;
|
2026-05-12 23:47:40 +03:00
|
|
|
pts.push([f64::NAN; 3]);
|
2026-04-02 19:06:20 +03:00
|
|
|
for v in &self.vertices {
|
2026-05-12 23:47:40 +03:00
|
|
|
let mx = v.miter.x;
|
|
|
|
|
let my = v.miter.y;
|
|
|
|
|
let mz = v.miter.z;
|
2026-04-02 19:06:20 +03:00
|
|
|
pts.push([
|
2026-05-12 23:47:40 +03:00
|
|
|
v.position.x + mx * offset,
|
|
|
|
|
v.position.y + my * offset,
|
|
|
|
|
v.position.z + mz * offset,
|
2026-04-02 19:06:20 +03:00
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
if closed && n >= 2 {
|
|
|
|
|
let v0 = &self.vertices[0];
|
2026-05-12 23:47:40 +03:00
|
|
|
let mx = v0.miter.x;
|
|
|
|
|
let my = v0.miter.y;
|
|
|
|
|
let mz = v0.miter.z;
|
2026-04-02 19:06:20 +03:00
|
|
|
pts.push([
|
2026-05-12 23:47:40 +03:00
|
|
|
v0.position.x + mx * offset,
|
|
|
|
|
v0.position.y + my * offset,
|
|
|
|
|
v0.position.z + mz * offset,
|
2026-04-02 19:06:20 +03:00
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
}
|
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
|
|
|
|
|
|
|
|
// Start and end caps: perpendicular line connecting the two offset lines
|
|
|
|
|
// at the first and last vertex of an open MLine.
|
|
|
|
|
if !closed {
|
|
|
|
|
let cap_v = |v: &acadrust::entities::MLineVertex| {
|
2026-05-12 23:47:40 +03:00
|
|
|
let mx = v.miter.x;
|
|
|
|
|
let my = v.miter.y;
|
|
|
|
|
let mz = v.miter.z;
|
|
|
|
|
let px = v.position.x;
|
|
|
|
|
let py = v.position.y;
|
|
|
|
|
let pz = v.position.z;
|
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
|
|
|
[
|
2026-05-12 23:47:40 +03:00
|
|
|
[f64::NAN; 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
|
|
|
[px + mx * (-half), py + my * (-half), pz + mz * (-half)],
|
2026-05-12 10:36:15 +03:00
|
|
|
[px + mx * half, py + my * half, pz + mz * half],
|
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
|
|
|
]
|
|
|
|
|
};
|
|
|
|
|
pts.extend_from_slice(&cap_v(&self.vertices[0]));
|
|
|
|
|
pts.extend_from_slice(&cap_v(&self.vertices[n - 1]));
|
|
|
|
|
}
|
2026-04-02 19:06:20 +03:00
|
|
|
}
|
|
|
|
|
|
2026-05-12 23:47:40 +03:00
|
|
|
let key_verts: Vec<[f64; 3]> = self
|
2026-04-02 19:06:20 +03:00
|
|
|
.vertices
|
|
|
|
|
.iter()
|
2026-05-12 23:47:40 +03:00
|
|
|
.map(|v| [v.position.x, v.position.y, v.position.z])
|
2026-04-02 19:06:20 +03:00
|
|
|
.collect();
|
|
|
|
|
|
2026-05-02 19:59:37 +03:00
|
|
|
let snap_pts = self
|
|
|
|
|
.vertices
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|v| {
|
|
|
|
|
(
|
refactor(snap): producers emit f64 snap points (world_offset removal P3)
TruckEntity.snap_pts is now DVec3 and every entity producer builds snap
candidates straight from the acadrust f64 coordinates instead of casting
to f32 first (text, mtext, arc, circle, ellipse, point, shape, solid,
mline, mtext, attribute, tolerance, table, underlay, ole2frame, mesh,
multileader, dimension, block-cache). offset_snap_pts stays f64
throughout. Still offset-relative (inert) — but snap precision is no
longer capped at ~0.5 m by an early f32 cast, which fixes a latent
UTM-scale snap error and sets up the absolute-coordinate switch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 22:10:29 +03:00
|
|
|
glam::DVec3::new(v.position.x, v.position.y, v.position.z),
|
2026-05-02 19:59:37 +03:00
|
|
|
SnapHint::Node,
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
|
2026-04-02 19:06:20 +03:00
|
|
|
Some(TruckEntity {
|
|
|
|
|
object: TruckObject::Lines(pts),
|
2026-05-02 19:59:37 +03:00
|
|
|
snap_pts,
|
2026-04-02 19:06:20 +03:00
|
|
|
tangent_geoms: vec![],
|
|
|
|
|
key_vertices: key_verts,
|
2026-05-06 23:24:26 +03:00
|
|
|
fill_tris: vec![],
|
2026-04-02 19:06:20 +03:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Grippable for MLine {
|
|
|
|
|
fn grips(&self) -> Vec<GripDef> {
|
|
|
|
|
self.vertices
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.map(|(i, v)| {
|
|
|
|
|
square_grip(
|
|
|
|
|
i,
|
2026-06-11 00:04:37 +03:00
|
|
|
glam::DVec3::new(v.position.x, v.position.y, v.position.z),
|
2026-04-02 19:06:20 +03:00
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
|
|
|
|
|
if let Some(v) = self.vertices.get_mut(grip_id) {
|
|
|
|
|
match apply {
|
|
|
|
|
GripApply::Translate(d) => {
|
|
|
|
|
v.position.x += d.x as f64;
|
|
|
|
|
v.position.y += d.y as f64;
|
|
|
|
|
v.position.z += d.z as f64;
|
|
|
|
|
}
|
|
|
|
|
GripApply::Absolute(p) => {
|
|
|
|
|
v.position.x = p.x as f64;
|
|
|
|
|
v.position.y = p.y as f64;
|
|
|
|
|
v.position.z = p.z as f64;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
feat(grip): popup menus for polylines, spline, mline, hatch, leaders, text
Vocabulary added: AddFitPoint, RemoveFitPoint, Refit, RefineVertices,
TangentDirection, MoveWithText, StackText, UnstackText.
Polyline/Polyline2D/Polyline3D: vertex Add/Remove. MLine: same.
Spline: CV Add/Remove plus Refine Vertices (chord-midpoint insertion,
weights kept in sync, knots cleared so to_truck rebuilds uniform vec).
Hatch: centroid Origin/Angle/Scale (Angle and Scale prompt for value).
Leader: vertex Add/Remove (arrow + centroid stay Stretch-only).
MultiLeader: vertex Add/Remove Leader; MText location Move-with-Leader /
Move-Independent (menu live, structural edits stubbed). Text/MText:
Rotate prompts for degrees and sets rotation.
Spline, Leader, MultiLeader switched from impl_entity_basics! to manual
trait impls so grip_menu can be overridden.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 15:14:43 +03:00
|
|
|
|
2026-06-16 11:33:46 +03:00
|
|
|
fn grip_menu(&self, _grip_id: usize) -> Vec<crate::scene::model::object::GripMenuItem> {
|
|
|
|
|
use crate::scene::model::object::{GripMenuAction, GripMenuItem};
|
feat(grip): popup menus for polylines, spline, mline, hatch, leaders, text
Vocabulary added: AddFitPoint, RemoveFitPoint, Refit, RefineVertices,
TangentDirection, MoveWithText, StackText, UnstackText.
Polyline/Polyline2D/Polyline3D: vertex Add/Remove. MLine: same.
Spline: CV Add/Remove plus Refine Vertices (chord-midpoint insertion,
weights kept in sync, knots cleared so to_truck rebuilds uniform vec).
Hatch: centroid Origin/Angle/Scale (Angle and Scale prompt for value).
Leader: vertex Add/Remove (arrow + centroid stay Stretch-only).
MultiLeader: vertex Add/Remove Leader; MText location Move-with-Leader /
Move-Independent (menu live, structural edits stubbed). Text/MText:
Rotate prompts for degrees and sets rotation.
Spline, Leader, MultiLeader switched from impl_entity_basics! to manual
trait impls so grip_menu can be overridden.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 15:14:43 +03:00
|
|
|
vec![
|
2026-06-11 00:04:37 +03:00
|
|
|
GripMenuItem {
|
|
|
|
|
label: "Stretch",
|
|
|
|
|
action: GripMenuAction::Stretch,
|
|
|
|
|
},
|
|
|
|
|
GripMenuItem {
|
|
|
|
|
label: "Add Vertex",
|
|
|
|
|
action: GripMenuAction::AddVertex,
|
|
|
|
|
},
|
|
|
|
|
GripMenuItem {
|
|
|
|
|
label: "Remove Vertex",
|
|
|
|
|
action: GripMenuAction::RemoveVertex,
|
|
|
|
|
},
|
feat(grip): popup menus for polylines, spline, mline, hatch, leaders, text
Vocabulary added: AddFitPoint, RemoveFitPoint, Refit, RefineVertices,
TangentDirection, MoveWithText, StackText, UnstackText.
Polyline/Polyline2D/Polyline3D: vertex Add/Remove. MLine: same.
Spline: CV Add/Remove plus Refine Vertices (chord-midpoint insertion,
weights kept in sync, knots cleared so to_truck rebuilds uniform vec).
Hatch: centroid Origin/Angle/Scale (Angle and Scale prompt for value).
Leader: vertex Add/Remove (arrow + centroid stay Stretch-only).
MultiLeader: vertex Add/Remove Leader; MText location Move-with-Leader /
Move-Independent (menu live, structural edits stubbed). Text/MText:
Rotate prompts for degrees and sets rotation.
Spline, Leader, MultiLeader switched from impl_entity_basics! to manual
trait impls so grip_menu can be overridden.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 15:14:43 +03:00
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-16 11:33:46 +03:00
|
|
|
fn apply_grip_menu(&mut self, grip_id: usize, action: crate::scene::model::object::GripMenuAction) {
|
|
|
|
|
use crate::scene::model::object::GripMenuAction as A;
|
feat(grip): popup menus for polylines, spline, mline, hatch, leaders, text
Vocabulary added: AddFitPoint, RemoveFitPoint, Refit, RefineVertices,
TangentDirection, MoveWithText, StackText, UnstackText.
Polyline/Polyline2D/Polyline3D: vertex Add/Remove. MLine: same.
Spline: CV Add/Remove plus Refine Vertices (chord-midpoint insertion,
weights kept in sync, knots cleared so to_truck rebuilds uniform vec).
Hatch: centroid Origin/Angle/Scale (Angle and Scale prompt for value).
Leader: vertex Add/Remove (arrow + centroid stay Stretch-only).
MultiLeader: vertex Add/Remove Leader; MText location Move-with-Leader /
Move-Independent (menu live, structural edits stubbed). Text/MText:
Rotate prompts for degrees and sets rotation.
Spline, Leader, MultiLeader switched from impl_entity_basics! to manual
trait impls so grip_menu can be overridden.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 15:14:43 +03:00
|
|
|
let n = self.vertices.len();
|
|
|
|
|
match action {
|
|
|
|
|
A::AddVertex if grip_id < n => {
|
|
|
|
|
let i1 = (grip_id + 1).min(n - 1);
|
|
|
|
|
if i1 == grip_id {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let v0 = &self.vertices[grip_id];
|
|
|
|
|
let v1 = &self.vertices[i1];
|
|
|
|
|
let mut new_v = v0.clone();
|
|
|
|
|
new_v.position.x = (v0.position.x + v1.position.x) * 0.5;
|
|
|
|
|
new_v.position.y = (v0.position.y + v1.position.y) * 0.5;
|
|
|
|
|
new_v.position.z = (v0.position.z + v1.position.z) * 0.5;
|
|
|
|
|
self.vertices.insert(i1, new_v);
|
|
|
|
|
}
|
|
|
|
|
A::RemoveVertex if grip_id < n && n > 2 => {
|
|
|
|
|
self.vertices.remove(grip_id);
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-02 19:06:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PropertyEditable for MLine {
|
2026-07-02 22:46:19 +03:00
|
|
|
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
|
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
|
|
|
let just_str = match self.justification {
|
|
|
|
|
acadrust::entities::MLineJustification::Top => "Top",
|
|
|
|
|
acadrust::entities::MLineJustification::Zero => "Zero",
|
|
|
|
|
acadrust::entities::MLineJustification::Bottom => "Bottom",
|
|
|
|
|
};
|
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 cur = self.vertices.first();
|
|
|
|
|
let cur_x = cur.map(|v| v.position.x).unwrap_or(0.0);
|
|
|
|
|
let cur_y = cur.map(|v| v.position.y).unwrap_or(0.0);
|
|
|
|
|
let cur_z = cur.map(|v| v.position.z).unwrap_or(0.0);
|
|
|
|
|
vec![
|
|
|
|
|
PropSection {
|
|
|
|
|
title: "Geometry".into(),
|
|
|
|
|
props: vec![
|
|
|
|
|
ro("Vertex", "ml_vertex", if self.vertices.is_empty() { String::new() } else { "1".to_string() }),
|
|
|
|
|
edit("Vertex X", "ml_vertex_x", cur_x),
|
|
|
|
|
edit("Vertex Y", "ml_vertex_y", cur_y),
|
|
|
|
|
edit("Vertex Z", "ml_vertex_z", cur_z),
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
PropSection {
|
|
|
|
|
title: "Misc".into(),
|
|
|
|
|
props: vec![
|
2026-07-03 08:06:00 +03:00
|
|
|
Property {
|
|
|
|
|
label: "Style".into(),
|
|
|
|
|
field: "ml_style",
|
|
|
|
|
value: PropValue::EditText(self.style_name.clone()),
|
|
|
|
|
},
|
feat(properties): conform entity property groups to PROPERTIES.md
Rewrite each entity's property builder to the per-entity group/row spec:
the correct sections (Geometry, Misc, Text, Pattern, Lines & Arrows, Leaders,
Block, …) with the spec's rows and real computed values — Diameter,
Circumference, Area, Delta X/Y/Z, Angle, Total angle, Arc length, Radius ratio,
etc. — plus apply routing for the editable rows.
Covers ~26 entities (Line, Circle, Arc, Point, Ellipse, Spline, polylines,
Ray/XLine, Insert, Text, MText, Hatch, Leader, MultiLeader, Tolerance, Solid,
Solid3D/Region/Body, meshes, MLine, Raster/Wipeout, Underlay, Table, Viewport,
Attribute, OLE). The 3D Visualization/Material group and the full Dimension
spec are deferred (they need document access for material/dimstyle name
resolution). Rows whose data is not in the pinned acadrust revision are shown
as empty placeholders, to be filled when the dependency is bumped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 23:03:18 +03:00
|
|
|
Property {
|
|
|
|
|
label: "Style justification".into(),
|
|
|
|
|
field: "ml_justification",
|
|
|
|
|
value: PropValue::Choice {
|
|
|
|
|
selected: just_str.to_string(),
|
|
|
|
|
options: ["Top", "Zero", "Bottom"]
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(str::to_string)
|
|
|
|
|
.collect(),
|
|
|
|
|
},
|
2026-04-02 19:06:20 +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
|
|
|
edit("Style scale", "ml_scale", self.scale_factor),
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
]
|
2026-04-02 19:06:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn apply_geom_prop(&mut self, field: &str, value: &str) {
|
|
|
|
|
match field {
|
|
|
|
|
"ml_closed" => {
|
|
|
|
|
let closed = if value == "toggle" {
|
|
|
|
|
!self.flags.contains(acadrust::entities::MLineFlags::CLOSED)
|
|
|
|
|
} else {
|
|
|
|
|
value == "true"
|
|
|
|
|
};
|
2026-05-12 10:36:15 +03:00
|
|
|
self.flags
|
|
|
|
|
.set(acadrust::entities::MLineFlags::CLOSED, closed);
|
2026-04-02 19:06:20 +03:00
|
|
|
return;
|
|
|
|
|
}
|
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
|
|
|
"ml_justification" => {
|
|
|
|
|
self.justification = match value {
|
|
|
|
|
"Top" => acadrust::entities::MLineJustification::Top,
|
|
|
|
|
"Bottom" => acadrust::entities::MLineJustification::Bottom,
|
|
|
|
|
_ => acadrust::entities::MLineJustification::Zero,
|
|
|
|
|
};
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-07-03 08:06:00 +03:00
|
|
|
"ml_style" => {
|
|
|
|
|
self.style_name = value.to_string();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-04-02 19:06:20 +03:00
|
|
|
_ => {}
|
|
|
|
|
}
|
2026-05-12 10:36:15 +03:00
|
|
|
let Ok(v) = value.trim().parse::<f64>() else {
|
|
|
|
|
return;
|
|
|
|
|
};
|
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
|
|
|
match field {
|
|
|
|
|
"ml_scale" if v != 0.0 => self.scale_factor = v,
|
|
|
|
|
"ml_vertex_x" => {
|
|
|
|
|
if let Some(vx) = self.vertices.first_mut() {
|
|
|
|
|
vx.position.x = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"ml_vertex_y" => {
|
|
|
|
|
if let Some(vx) = self.vertices.first_mut() {
|
|
|
|
|
vx.position.y = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"ml_vertex_z" => {
|
|
|
|
|
if let Some(vx) = self.vertices.first_mut() {
|
|
|
|
|
vx.position.z = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
2026-04-02 19:06:20 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Transformable for MLine {
|
|
|
|
|
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| {
|
2026-04-02 19:06:20 +03:00
|
|
|
for v in &mut entity.vertices {
|
2026-06-16 11:33:46 +03:00
|
|
|
crate::scene::view::transform::reflect_xy_point(
|
2026-04-02 19:06:20 +03:00
|
|
|
&mut v.position.x,
|
|
|
|
|
&mut v.position.y,
|
|
|
|
|
p1,
|
|
|
|
|
p2,
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-06-16 11:33:46 +03:00
|
|
|
crate::scene::view::transform::reflect_xy_point(
|
2026-04-02 19:06:20 +03:00
|
|
|
&mut entity.start_point.x,
|
|
|
|
|
&mut entity.start_point.y,
|
|
|
|
|
p1,
|
|
|
|
|
p2,
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|