feat(props): make dim-line colour editable for leaders and dimensions

The "Dim line color" row on Leader and Dimension entities was
read-only: an earlier attempt wired it to Leader.override_color, which
acadrust never serialises, so the pick was lost on save. Store it
instead as a standard ACAD_DSTYLE per-object dimension-style override
(DXF code 176, an ACI index) through the existing dim_override codec,
so it round-trips through both DWG and DXF like the other dim
overrides. RGB picks collapse to the nearest ACI, matching the rest of
the dim-colour stack (dimension styles are index-only through the file
layer). The renderer prefers the override over the style's DIMCLRD.

The write branch is guarded to leaders and dimensions so a mixed
selection cannot stamp the override onto other entity types.

Bumps acadrust to c9fe982, which carries parsed XDATA onto dimensions
on DXF read (it was dropping common.extended_data), so the dimension
override persists on DXF save as well as DWG.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-07-13 17:31:09 +03:00
1 parent 04bd49c715
commit d005cc4ab1
8 files changed
+241 -29

No files matched your search

+9
View File
@@ -6,6 +6,7 @@
//! renderer and the properties panel prefer an override over the style default,
//! so editing one of these rows writes here and the change round-trips to file.
use acadrust::types::Color;
use acadrust::xdata::{ExtendedData, XDataValue};
use acadrust::{CadDocument, Handle};
@@ -13,6 +14,7 @@ use acadrust::{CadDocument, Handle};
pub const DIMSCALE: i16 = 40; // overall scale (real)
pub const DIMASZ: i16 = 41; // arrow size (real)
pub const DIMTAD: i16 = 77; // text vertical pos (int16)
pub const DIMCLRD: i16 = 176; // dim line colour (int16 = ACI index)
pub const DIMGAP: i16 = 147; // text offset / gap (real)
pub const DIMLWD: i16 = 371; // dim line lineweight (int16)
pub const DIMLDRBLK: i16 = 341; // leader arrow block (handle)
@@ -58,6 +60,13 @@ pub fn int(xd: &ExtendedData, code: i16) -> Option<i16> {
})
}
/// The colour override for `code`, if present. Dim-colour overrides are stored
/// as an ACI index (the same `int16` slot the dimension style uses), so this
/// decodes it back into a `Color` (0 = ByBlock, 256 = ByLayer, else indexed).
pub fn color(xd: &ExtendedData, code: i16) -> Option<Color> {
int(xd, code).map(Color::from_index)
}
/// The handle-valued override for `code`, if present.
pub fn handle(xd: &ExtendedData, code: i16) -> Option<Handle> {
pairs(xd)
+9 -2
View File
@@ -1290,11 +1290,18 @@ fn tessellate_dimension_inner(
);
// Per-spec colours: DIMCLRD (dim/arrows), DIMCLRE (ext), DIMCLRT (text).
// 0=ByBlock and 256=ByLayer fall through to entity_color.
// 0=ByBlock and 256=ByLayer fall through to entity_color. DIMCLRD also
// honours a per-object ACAD_DSTYLE override (code 176) so an edited
// dim-line colour renders even without touching the style.
let dim_color = if selected {
WireModel::SELECTED
} else {
resolve_dim_color(style.map(|s| s.dimclrd).unwrap_or(0), entity_color)
let dim_clr = crate::entities::dim_override::int(
&dim.base().common.extended_data,
crate::entities::dim_override::DIMCLRD,
)
.unwrap_or_else(|| style.map(|s| s.dimclrd).unwrap_or(0));
resolve_dim_color(dim_clr, entity_color)
};
let ext_color = if selected {
WireModel::SELECTED
+20 -1
View File
@@ -547,10 +547,29 @@ impl LeaderTess for Leader {
use crate::entities::dim_override as dov;
use crate::scene::model::wire_model::WireModel;
let xd = &self.common.extended_data;
// Dim-line colour: a per-object ACAD_DSTYLE override (code 176, an ACI
// index) wins over the assigned dim style's DIMCLRD; ByLayer / ByBlock
// (0 / 256) and no setting fall through to the entity colour.
let color = if selected {
WireModel::SELECTED
} else {
entity_color
let dim_clr = dov::int(xd, dov::DIMCLRD).or_else(|| {
document
.dim_styles
.iter()
.find(|s| {
s.name.eq_ignore_ascii_case(&self.dimension_style)
|| (self.dimension_style.trim().is_empty()
&& s.name.eq_ignore_ascii_case("Standard"))
})
.map(|s| s.dimclrd)
});
match dim_clr {
Some(idx) if idx != 0 && idx != 256 => crate::scene::convert::tess_util::aci_to_rgba(
&acadrust::types::Color::from_index(idx),
),
_ => entity_color,
}
};
// A concrete DIMLWD override sets the leader line's weight; ByLayer /
// ByBlock / Default and no override keep the resolved weight passed in.