feat(props): uniform-scale checkbox for block references

A selected INSERT's Geometry section gains a "Uniform scale" box
(#427): while the three factors are equal it is checked and the panel
shows a single Scale row that writes all three axes; unchecking
expands the familiar Scale X/Y/Z rows without touching the values
(remembered per entity), and re-checking collapses Y/Z onto X as an
undoable CHPROP step.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-07-21 10:27:50 +03:00
commit 8821bb7131
4 changed files with 82 additions and 0 deletions

View file

@ -250,6 +250,10 @@ pub(super) struct OpenCADStudio {
video_thumbs: std::collections::HashMap<String, iced::widget::image::Handle>,
/// True while the boot-time playlist fetch is still in flight.
videos_loading: bool,
/// Block references whose properties panel shows per-axis Scale X/Y/Z even
/// though the three factors are currently equal — the user unchecked the
/// "Uniform scale" box for them (#427). Keyed by entity handle.
props_asym_scale: std::collections::HashSet<u64>,
/// Which Start-page section is shown when the page is too narrow for all
/// three side by side and falls back to a tab bar.
start_section: StartSection,
@ -2201,6 +2205,7 @@ impl OpenCADStudio {
videos: Vec::new(),
video_thumbs: std::collections::HashMap::new(),
videos_loading: false,
props_asym_scale: std::collections::HashSet::new(),
start_section: StartSection::default(),
props_expanded: false,
history_content: iced::widget::text_editor::Content::new(),

View file

@ -139,6 +139,51 @@ impl OpenCADStudio {
}
}
// Uniform-scale checkbox for block references (#427):
// while the three scale factors are equal (and the user
// hasn't opted into per-axis editing) the panel shows one
// Scale row plus a checked "Uniform scale" box; unchecking
// expands the familiar Scale X/Y/Z rows.
if let acadrust::EntityType::Insert(ins) = entity {
let eq = (ins.x_scale() - ins.y_scale()).abs() < 1e-12
&& (ins.x_scale() - ins.z_scale()).abs() < 1e-12;
let uniform =
eq && !self.props_asym_scale.contains(&handle.value());
for section in sections.iter_mut() {
let Some(xi) =
section.props.iter().position(|p| p.field == "x_scale")
else {
continue;
};
let toggle = crate::scene::model::object::Property {
label: "Uniform scale".into(),
field: "ins_uniform",
value: crate::scene::model::object::PropValue::BoolToggle {
field: "ins_uniform",
value: uniform,
},
};
if uniform {
section
.props
.retain(|p| p.field != "y_scale" && p.field != "z_scale");
let xi = section
.props
.iter()
.position(|p| p.field == "x_scale")
.unwrap_or(xi.min(section.props.len()));
section.props[xi] = crate::entities::common::edit_prop(
"Scale",
"u_scale",
ins.x_scale(),
);
section.props.insert(xi, toggle);
} else {
section.props.insert(xi, toggle);
}
}
}
// In named plot-style mode (PSTYLEMODE=1) the Plot style row
// picks a named style from the drawing's plot style table. In
// the color-dependent mode it stays read-only (the object's

View file

@ -2622,6 +2622,32 @@ impl OpenCADStudio {
crate::scene::view::dispatch::toggle_invisible(entity);
}
}
// Uniform-scale checkbox on a block reference
// (#427): checking collapses Y/Z onto X; unchecking
// only switches the panel to per-axis rows.
"ins_uniform" => {
let scales = match self.tabs[i].scene.document.get_entity(handle) {
Some(acadrust::EntityType::Insert(ins)) => {
Some((ins.x_scale(), ins.y_scale(), ins.z_scale()))
}
_ => None,
};
let Some((sx, sy, sz)) = scales else { continue };
let eq = (sx - sy).abs() < 1e-12 && (sx - sz).abs() < 1e-12;
let checked =
eq && !self.props_asym_scale.contains(&handle.value());
if checked {
self.props_asym_scale.insert(handle.value());
} else {
self.props_asym_scale.remove(&handle.value());
if let Some(acadrust::EntityType::Insert(ins)) =
self.tabs[i].scene.document.get_entity_mut(handle)
{
ins.set_y_scale(sx);
ins.set_z_scale(sx);
}
}
}
_ => {
if let Some(entity) =
self.tabs[i].scene.document.get_entity_mut(handle)

View file

@ -94,6 +94,12 @@ fn apply_geom_prop(ins: &mut Insert, field: &str, value: &str) {
acadrust::Entity::translate(att, delta);
}
}
// Single Scale row shown while "Uniform scale" is checked (#427).
"u_scale" => {
ins.set_x_scale(v);
ins.set_y_scale(v);
ins.set_z_scale(v);
}
"x_scale" => ins.set_x_scale(v),
"y_scale" => ins.set_y_scale(v),
"z_scale" => ins.set_z_scale(v),