feat(text): MTEXT background fill / mask + text frame, editable in Properties
Render the MTEXT background (never drawn before — the flags were only shown read-only in the panel) and make it editable. - Text arm emits an opaque fill_tris rect behind the glyphs: flag 0x01 uses the entity background colour, 0x02 uses the canvas colour (a wipeout-style mask). Box = glyph bounds padded by (background_scale - 1) × text height. - Text frame (flag 0x10) draws a closed rectangle in the text colour around the same box. - Threaded `bg_color` into `tessellate()` (+ all callers and the MultiLeaderTess trait) so the mask can use the drawing-window colour. - Properties: "Background mask" is a Off / Fill / Mask dropdown, "Background color" is its own colour picker (independent of the entity colour — new PropBgColor* messages; picking a colour switches to Fill mode), and "Text frame" is a checkbox toggle. Edits re-tessellate so the change shows live. Renders via the face3d fill path, so the fill shows with FILLMODE on (same as MLEADER background fill); the frame is a stroke and always shows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
110683f419
commit
cd7306f530
10 changed files with 223 additions and 14 deletions
|
|
@ -239,6 +239,7 @@ pub(crate) fn append_insert_attribute_wires(
|
|||
sub_lw_px,
|
||||
anno_scale,
|
||||
None,
|
||||
bg_color,
|
||||
);
|
||||
// Use the INSERT's handle so selection / picking groups attribute
|
||||
// text with the parent insert instead of treating it as a stray text.
|
||||
|
|
|
|||
|
|
@ -204,7 +204,6 @@ fn properties(t: &MText, text_style_names: &[String]) -> Vec<PropSection> {
|
|||
// Absolute line-space distance for single spacing (~1.66 * height) scaled
|
||||
// by the line-spacing factor.
|
||||
let line_space_distance = t.height * 1.666_666_666_666_667 * t.line_spacing_factor;
|
||||
let bg_mask_on = (t.background_fill_flags & 0x03) != 0;
|
||||
let text_frame_on = (t.background_fill_flags & 0x10) != 0;
|
||||
vec![
|
||||
PropSection {
|
||||
|
|
@ -280,18 +279,38 @@ fn properties(t: &MText, text_style_names: &[String]) -> Vec<PropSection> {
|
|||
_ => "At least",
|
||||
},
|
||||
),
|
||||
ro(
|
||||
"Background mask",
|
||||
"background_mask",
|
||||
if bg_mask_on { "On" } else { "Off" },
|
||||
),
|
||||
Property {
|
||||
label: "Background mask".into(),
|
||||
field: "background_mask",
|
||||
value: PropValue::Choice {
|
||||
selected: if t.background_fill_flags & 0x01 != 0 {
|
||||
"Fill".into()
|
||||
} else if t.background_fill_flags & 0x02 != 0 {
|
||||
"Mask".into()
|
||||
} else {
|
||||
"Off".into()
|
||||
},
|
||||
options: ["Off", "Fill", "Mask"]
|
||||
.into_iter()
|
||||
.map(str::to_string)
|
||||
.collect(),
|
||||
},
|
||||
},
|
||||
Property {
|
||||
label: "Background color".into(),
|
||||
field: "background_color",
|
||||
value: PropValue::ColorChoice(t.background_color.clone()),
|
||||
},
|
||||
edit("Defined width", "rect_w", t.rectangle_width),
|
||||
edit("Defined height", "rect_h", t.rectangle_height.unwrap_or(0.0)),
|
||||
ro(
|
||||
"Text frame",
|
||||
"text_frame",
|
||||
if text_frame_on { "On" } else { "Off" },
|
||||
),
|
||||
Property {
|
||||
label: "Text frame".into(),
|
||||
field: "text_frame",
|
||||
value: PropValue::BoolToggle {
|
||||
field: "text_frame",
|
||||
value: text_frame_on,
|
||||
},
|
||||
},
|
||||
ro(
|
||||
"Columns",
|
||||
"columns",
|
||||
|
|
@ -336,6 +355,27 @@ fn apply_geom_prop(t: &mut MText, field: &str, value: &str) {
|
|||
}
|
||||
return;
|
||||
}
|
||||
"background_mask" => {
|
||||
// Clear both fill bits, then set the chosen one. 0x01 = use the
|
||||
// background-fill colour, 0x02 = use the drawing-window colour (mask).
|
||||
t.background_fill_flags &= !0x03;
|
||||
match value {
|
||||
"Fill" => t.background_fill_flags |= 0x01,
|
||||
"Mask" => t.background_fill_flags |= 0x02,
|
||||
_ => {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
"text_frame" => {
|
||||
// Rendered as a checkbox (BoolToggle) → the toggle sends "toggle";
|
||||
// flip the frame bit. Accept explicit "On"/"Off" too for safety.
|
||||
match value {
|
||||
"toggle" => t.background_fill_flags ^= 0x10,
|
||||
"On" => t.background_fill_flags |= 0x10,
|
||||
_ => t.background_fill_flags &= !0x10,
|
||||
}
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let Some(v) = crate::entities::common::parse_f64(value) else {
|
||||
|
|
|
|||
|
|
@ -1071,6 +1071,7 @@ pub trait MultiLeaderTess {
|
|||
line_weight_px: f32,
|
||||
anno_scale: f32,
|
||||
world_per_pixel: Option<f32>,
|
||||
bg_color: [f32; 4],
|
||||
) -> Vec<crate::scene::model::wire_model::WireModel>;
|
||||
}
|
||||
|
||||
|
|
@ -1084,6 +1085,7 @@ impl MultiLeaderTess for MultiLeader {
|
|||
line_weight_px: f32,
|
||||
anno_scale: f32,
|
||||
world_per_pixel: Option<f32>,
|
||||
bg_color: [f32; 4],
|
||||
) -> Vec<crate::scene::model::wire_model::WireModel> {
|
||||
use crate::scene::convert::tessellate::{
|
||||
append_arrow, arrow_from_block, color_or_inherit, tessellate, ArrowKind, DimGeom,
|
||||
|
|
@ -1354,6 +1356,7 @@ impl MultiLeaderTess for MultiLeader {
|
|||
leader_lw_px,
|
||||
1.0,
|
||||
None,
|
||||
bg_color,
|
||||
);
|
||||
for w in &mut sub_wires {
|
||||
w.name = name.clone();
|
||||
|
|
|
|||
Loading…
Reference in a new issue