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>
This commit is contained in:
parent
613d6cf99d
commit
0b4facc50d
10 changed files with 361 additions and 1 deletions
|
|
@ -63,6 +63,17 @@ fn properties(h: &Hatch) -> PropSection {
|
|||
if h.is_associative { "Yes" } else { "No" },
|
||||
),
|
||||
edit("Elevation", "elevation", h.elevation),
|
||||
ro("Seed Points", "seed_count", h.seed_points.len().to_string()),
|
||||
ro(
|
||||
"Pixel Size",
|
||||
"pixel_size",
|
||||
format!("{:.6}", h.pixel_size),
|
||||
),
|
||||
ro(
|
||||
"Normal",
|
||||
"normal",
|
||||
format!("{:.3}, {:.3}, {:.3}", h.normal.x, h.normal.y, h.normal.z),
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,6 +227,25 @@ fn properties(leader: &Leader) -> PropSection {
|
|||
// Stats
|
||||
ro("Vertices", "vertex_count", n.to_string()),
|
||||
ro("Length", "length", format!("{:.4}", leader.length())),
|
||||
// Annotation reference + dim-style colour override (read-only —
|
||||
// they are written by the file and survive a round-trip).
|
||||
ro(
|
||||
"Annotation",
|
||||
"annotation_handle",
|
||||
if leader.annotation_handle.is_null() {
|
||||
"(none)".to_string()
|
||||
} else {
|
||||
format!("{:X}", leader.annotation_handle.value())
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Override Color",
|
||||
"override_color",
|
||||
match leader.override_color.rgb() {
|
||||
Some((r, g, b)) => format!("RGB({},{},{})", r, g, b),
|
||||
None => format!("{:?}", leader.override_color),
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
// Arrow point (vertex[0])
|
||||
|
|
|
|||
|
|
@ -156,12 +156,41 @@ impl Grippable for MLine {
|
|||
|
||||
impl PropertyEditable for MLine {
|
||||
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
|
||||
let just_str = match self.justification {
|
||||
acadrust::entities::MLineJustification::Top => "Top",
|
||||
acadrust::entities::MLineJustification::Zero => "Zero",
|
||||
acadrust::entities::MLineJustification::Bottom => "Bottom",
|
||||
};
|
||||
PropSection {
|
||||
title: "Geometry".into(),
|
||||
props: vec![
|
||||
ro("Style", "ml_style", self.style_name.clone()),
|
||||
ro(
|
||||
"Style Handle",
|
||||
"ml_style_handle",
|
||||
match self.style_handle {
|
||||
Some(h) if !h.is_null() => format!("{:X}", h.value()),
|
||||
_ => "(none)".to_string(),
|
||||
},
|
||||
),
|
||||
ro("Vertices", "ml_verts", self.vertices.len().to_string()),
|
||||
ro(
|
||||
"Style Elements",
|
||||
"ml_style_elem_count",
|
||||
self.style_element_count.to_string(),
|
||||
),
|
||||
edit("Scale", "ml_scale", self.scale_factor),
|
||||
Property {
|
||||
label: "Justification".into(),
|
||||
field: "ml_justification",
|
||||
value: PropValue::Choice {
|
||||
selected: just_str.to_string(),
|
||||
options: ["Top", "Zero", "Bottom"]
|
||||
.into_iter()
|
||||
.map(str::to_string)
|
||||
.collect(),
|
||||
},
|
||||
},
|
||||
Property {
|
||||
label: "Closed".into(),
|
||||
field: "ml_closed",
|
||||
|
|
@ -186,6 +215,14 @@ impl PropertyEditable for MLine {
|
|||
.set(acadrust::entities::MLineFlags::CLOSED, closed);
|
||||
return;
|
||||
}
|
||||
"ml_justification" => {
|
||||
self.justification = match value {
|
||||
"Top" => acadrust::entities::MLineJustification::Top,
|
||||
"Bottom" => acadrust::entities::MLineJustification::Bottom,
|
||||
_ => acadrust::entities::MLineJustification::Zero,
|
||||
};
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let Ok(v) = value.trim().parse::<f64>() else {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,32 @@ fn properties(ole: &Ole2Frame) -> PropSection {
|
|||
edit("Upper Left Y", "ole_uly", ole.upper_left_corner.y),
|
||||
edit("Lower Right X", "ole_lrx", ole.lower_right_corner.x),
|
||||
edit("Lower Right Y", "ole_lry", ole.lower_right_corner.y),
|
||||
ro("Version", "ole_version", ole.version.to_string()),
|
||||
ro(
|
||||
"Source App",
|
||||
"ole_source_app",
|
||||
if ole.source_application.is_empty() {
|
||||
"(unknown)".to_string()
|
||||
} else {
|
||||
ole.source_application.clone()
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Data Size",
|
||||
"ole_data_size",
|
||||
format!("{} bytes", ole.binary_data.len()),
|
||||
),
|
||||
ro("DWG Mode", "ole_dwg_mode", ole.dwg_mode.to_string()),
|
||||
ro(
|
||||
"DWG Trailing Byte",
|
||||
"ole_dwg_trailing",
|
||||
format!("{:#04x}", ole.dwg_trailing_byte),
|
||||
),
|
||||
ro(
|
||||
"Paper Space",
|
||||
"ole_paper_space",
|
||||
if ole.is_paper_space { "Yes" } else { "No" },
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -347,11 +347,29 @@ impl Grippable for Polyline2D {
|
|||
|
||||
impl PropertyEditable for Polyline2D {
|
||||
fn geometry_properties(&self, _text_style_names: &[String]) -> PropSection {
|
||||
let smooth = match self.smooth_surface {
|
||||
acadrust::entities::SmoothSurfaceType::None => "None",
|
||||
acadrust::entities::SmoothSurfaceType::QuadraticBSpline => "Quadratic",
|
||||
acadrust::entities::SmoothSurfaceType::CubicBSpline => "Cubic",
|
||||
acadrust::entities::SmoothSurfaceType::Bezier => "Bezier",
|
||||
};
|
||||
PropSection {
|
||||
title: "Geometry".into(),
|
||||
props: vec![
|
||||
ro("Vertices", "vertices", self.vertices.len().to_string()),
|
||||
edit("Elevation", "pl2_elevation", self.elevation),
|
||||
edit("Default Start W", "pl2_start_w", self.start_width),
|
||||
edit("Default End W", "pl2_end_w", self.end_width),
|
||||
edit("Thickness", "pl2_thickness", self.thickness),
|
||||
ro("Smooth Surface", "pl2_smooth", smooth),
|
||||
ro(
|
||||
"Normal",
|
||||
"pl2_normal",
|
||||
format!(
|
||||
"{:.3}, {:.3}, {:.3}",
|
||||
self.normal.x, self.normal.y, self.normal.z
|
||||
),
|
||||
),
|
||||
Property {
|
||||
label: "Closed".into(),
|
||||
field: "pl2_closed",
|
||||
|
|
@ -383,6 +401,25 @@ impl PropertyEditable for Polyline2D {
|
|||
self.elevation = v;
|
||||
}
|
||||
}
|
||||
"pl2_start_w" => {
|
||||
if let Ok(v) = value.trim().parse::<f64>() {
|
||||
if v >= 0.0 {
|
||||
self.start_width = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
"pl2_end_w" => {
|
||||
if let Ok(v) = value.trim().parse::<f64>() {
|
||||
if v >= 0.0 {
|
||||
self.end_width = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
"pl2_thickness" => {
|
||||
if let Ok(v) = value.trim().parse::<f64>() {
|
||||
self.thickness = v;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,6 +186,27 @@ impl PropertyEditable for RasterImage {
|
|||
value: self.clipping_enabled,
|
||||
},
|
||||
},
|
||||
ro(
|
||||
"Class Version",
|
||||
"ri_class_version",
|
||||
self.class_version.to_string(),
|
||||
),
|
||||
ro(
|
||||
"Definition",
|
||||
"ri_def_handle",
|
||||
match self.definition_handle {
|
||||
Some(h) if !h.is_null() => format!("{:X}", h.value()),
|
||||
_ => "(none)".to_string(),
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Def Reactor",
|
||||
"ri_def_reactor_handle",
|
||||
match self.definition_reactor_handle {
|
||||
Some(h) if !h.is_null() => format!("{:X}", h.value()),
|
||||
_ => "(none)".to_string(),
|
||||
},
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
@ -421,6 +442,32 @@ impl PropertyEditable for Wipeout {
|
|||
value: self.clipping_enabled,
|
||||
},
|
||||
},
|
||||
ro(
|
||||
"Class Version",
|
||||
"wo_class_version",
|
||||
self.class_version.to_string(),
|
||||
),
|
||||
ro(
|
||||
"Clip Mode",
|
||||
"wo_clip_mode",
|
||||
format!("{:?}", self.clip_mode),
|
||||
),
|
||||
ro(
|
||||
"Definition",
|
||||
"wo_def_handle",
|
||||
match self.definition_handle {
|
||||
Some(h) if !h.is_null() => format!("{:X}", h.value()),
|
||||
_ => "(none)".to_string(),
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Def Reactor",
|
||||
"wo_def_reactor_handle",
|
||||
match self.definition_reactor_handle {
|
||||
Some(h) if !h.is_null() => format!("{:X}", h.value()),
|
||||
_ => "(none)".to_string(),
|
||||
},
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,28 @@ impl PropertyEditable for Solid3D {
|
|||
format!("{:.4}", self.point_of_reference.z),
|
||||
),
|
||||
ro("ACIS Data", "s3d_acis", size),
|
||||
ro(
|
||||
"UID",
|
||||
"s3d_uid",
|
||||
if self.uid.is_empty() {
|
||||
"(none)".to_string()
|
||||
} else {
|
||||
self.uid.clone()
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Silhouettes",
|
||||
"s3d_silhouettes",
|
||||
self.silhouettes.len().to_string(),
|
||||
),
|
||||
ro(
|
||||
"History",
|
||||
"s3d_history",
|
||||
match self.history_handle {
|
||||
Some(h) if !h.is_null() => format!("{:X}", h.value()),
|
||||
_ => "(none)".to_string(),
|
||||
},
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
@ -141,6 +163,20 @@ impl PropertyEditable for Region {
|
|||
format!("{:.4}", self.point_of_reference.z),
|
||||
),
|
||||
ro("ACIS Data", "rgn_acis", size),
|
||||
ro(
|
||||
"UID",
|
||||
"rgn_uid",
|
||||
if self.uid.is_empty() {
|
||||
"(none)".to_string()
|
||||
} else {
|
||||
self.uid.clone()
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Silhouettes",
|
||||
"rgn_silhouettes",
|
||||
self.silhouettes.len().to_string(),
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
@ -195,6 +231,20 @@ impl PropertyEditable for Body {
|
|||
format!("{:.4}", self.point_of_reference.z),
|
||||
),
|
||||
ro("ACIS Data", "bdy_acis", size),
|
||||
ro(
|
||||
"UID",
|
||||
"bdy_uid",
|
||||
if self.uid.is_empty() {
|
||||
"(none)".to_string()
|
||||
} else {
|
||||
self.uid.clone()
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Silhouettes",
|
||||
"bdy_silhouettes",
|
||||
self.silhouettes.len().to_string(),
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -290,6 +290,41 @@ impl PropertyEditable for Tolerance {
|
|||
edit("Insert X", "tol_ix", self.insertion_point.x),
|
||||
edit("Insert Y", "tol_iy", self.insertion_point.y),
|
||||
edit("Insert Z", "tol_iz", self.insertion_point.z),
|
||||
ro(
|
||||
"Dim Style",
|
||||
"tol_dim_style",
|
||||
if self.dimension_style_name.is_empty() {
|
||||
"(default)".to_string()
|
||||
} else {
|
||||
self.dimension_style_name.clone()
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Dim Style Handle",
|
||||
"tol_dim_style_handle",
|
||||
match self.dimension_style_handle {
|
||||
Some(h) if !h.is_null() => format!("{:X}", h.value()),
|
||||
_ => "(none)".to_string(),
|
||||
},
|
||||
),
|
||||
edit("Text Height", "tol_text_height", self.text_height),
|
||||
edit("Dim Gap", "tol_dim_gap", self.dimension_gap),
|
||||
ro(
|
||||
"Direction",
|
||||
"tol_direction",
|
||||
format!(
|
||||
"{:.3}, {:.3}, {:.3}",
|
||||
self.direction.x, self.direction.y, self.direction.z
|
||||
),
|
||||
),
|
||||
ro(
|
||||
"Normal",
|
||||
"tol_normal",
|
||||
format!(
|
||||
"{:.3}, {:.3}, {:.3}",
|
||||
self.normal.x, self.normal.y, self.normal.z
|
||||
),
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
@ -302,6 +337,8 @@ impl PropertyEditable for Tolerance {
|
|||
"tol_ix" => self.insertion_point.x = v,
|
||||
"tol_iy" => self.insertion_point.y = v,
|
||||
"tol_iz" => self.insertion_point.z = v,
|
||||
"tol_text_height" if v > 0.0 => self.text_height = v,
|
||||
"tol_dim_gap" => self.dimension_gap = v,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,6 +195,11 @@ impl PropertyEditable for Underlay {
|
|||
"No"
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Clip Inverted",
|
||||
"ul_clip_inverted",
|
||||
if self.clip_inverted { "Yes" } else { "No" },
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ use acadrust::entities::{Viewport, ViewportRenderMode};
|
|||
use glam::Vec3;
|
||||
|
||||
use crate::command::EntityTransform;
|
||||
use crate::entities::common::{diamond_grip, edit_prop as edit, parse_f64, square_grip};
|
||||
use crate::entities::common::{
|
||||
diamond_grip, edit_prop as edit, parse_f64, ro_prop as ro, square_grip,
|
||||
};
|
||||
use crate::entities::traits::{Grippable, PropertyEditable, Transformable};
|
||||
use crate::scene::object::{GripApply, GripDef, PropSection, PropValue, Property};
|
||||
|
||||
|
|
@ -230,6 +232,84 @@ fn properties(vp: &Viewport) -> PropSection {
|
|||
edit("UCS Y-Axis X", "vp_ucs_yx", vp.ucs_y_axis.x),
|
||||
edit("UCS Y-Axis Y", "vp_ucs_yy", vp.ucs_y_axis.y),
|
||||
edit("UCS Y-Axis Z", "vp_ucs_yz", vp.ucs_y_axis.z),
|
||||
// Snap / grid metadata (drives the snap-aware UI; not rendered
|
||||
// into the viewport contents directly).
|
||||
edit("Snap Base X", "vp_snap_bx", vp.snap_base.x),
|
||||
edit("Snap Base Y", "vp_snap_by", vp.snap_base.y),
|
||||
edit("Snap Spacing X", "vp_snap_sx", vp.snap_spacing.x),
|
||||
edit("Snap Spacing Y", "vp_snap_sy", vp.snap_spacing.y),
|
||||
edit("Snap Angle", "vp_snap_ang", vp.snap_angle.to_degrees()),
|
||||
edit("Twist Angle", "vp_twist", vp.twist_angle.to_degrees()),
|
||||
edit("Front Clip Z", "vp_front_clip", vp.front_clip_z),
|
||||
edit("Back Clip Z", "vp_back_clip", vp.back_clip_z),
|
||||
edit(
|
||||
"Circle Sides",
|
||||
"vp_circle_sides",
|
||||
vp.circle_sides as f64,
|
||||
),
|
||||
ro(
|
||||
"Grid Flags",
|
||||
"vp_grid_flags",
|
||||
format!("{:#06b}", vp.grid_flags.to_bits()),
|
||||
),
|
||||
ro("Grid Major", "vp_grid_major", vp.grid_major.to_string()),
|
||||
ro(
|
||||
"Base UCS",
|
||||
"vp_base_ucs_handle",
|
||||
if vp.base_ucs_handle.is_null() {
|
||||
"(none)".to_string()
|
||||
} else {
|
||||
format!("{:X}", vp.base_ucs_handle.value())
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"UCS Ortho",
|
||||
"vp_ucs_ortho",
|
||||
vp.ucs_ortho_type.to_string(),
|
||||
),
|
||||
ro(
|
||||
"Background",
|
||||
"vp_background_handle",
|
||||
if vp.background_handle.is_null() {
|
||||
"(none)".to_string()
|
||||
} else {
|
||||
format!("{:X}", vp.background_handle.value())
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Shade Plot",
|
||||
"vp_shade_plot_handle",
|
||||
if vp.shade_plot_handle.is_null() {
|
||||
"(none)".to_string()
|
||||
} else {
|
||||
format!("{:X}", vp.shade_plot_handle.value())
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Visual Style",
|
||||
"vp_visual_style_handle",
|
||||
if vp.visual_style_handle.is_null() {
|
||||
"(none)".to_string()
|
||||
} else {
|
||||
format!("{:X}", vp.visual_style_handle.value())
|
||||
},
|
||||
),
|
||||
// 3D lighting (not yet applied to the viewport mesh path).
|
||||
ro(
|
||||
"Default Lighting",
|
||||
"vp_default_lighting",
|
||||
if vp.default_lighting { "Yes" } else { "No" },
|
||||
),
|
||||
ro(
|
||||
"Lighting Type",
|
||||
"vp_lighting_type",
|
||||
vp.default_lighting_type.to_string(),
|
||||
),
|
||||
ro(
|
||||
"Ambient Color",
|
||||
"vp_ambient_color",
|
||||
format!("{:#010x}", vp.ambient_color as u32),
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
@ -404,6 +484,17 @@ fn apply_geom_prop(vp: &mut Viewport, field: &str, value: &str) {
|
|||
"vp_ucs_yx" => vp.ucs_y_axis.x = v,
|
||||
"vp_ucs_yy" => vp.ucs_y_axis.y = v,
|
||||
"vp_ucs_yz" => vp.ucs_y_axis.z = v,
|
||||
"vp_snap_bx" => vp.snap_base.x = v,
|
||||
"vp_snap_by" => vp.snap_base.y = v,
|
||||
"vp_snap_sx" if v >= 0.0 => vp.snap_spacing.x = v,
|
||||
"vp_snap_sy" if v >= 0.0 => vp.snap_spacing.y = v,
|
||||
"vp_snap_ang" => vp.snap_angle = v.to_radians(),
|
||||
"vp_twist" => vp.twist_angle = v.to_radians(),
|
||||
"vp_front_clip" => vp.front_clip_z = v,
|
||||
"vp_back_clip" => vp.back_clip_z = v,
|
||||
"vp_circle_sides" if v >= 0.0 && v <= i16::MAX as f64 => {
|
||||
vp.circle_sides = v as i16;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue