Symbols: Reset Transformation's enabled check does not measure the symbol's art

This commit is contained in:
dotCooCoo
2026-11-08 12:21:14 +07:00
committed by bflatastic
parent 1cd607f596
commit 283d46c1cc
4 changed files with 24 additions and 15 deletions
+3 -3
View File
@@ -722,9 +722,9 @@ pub use pathops::shape_count;
/// The gaps View › Show Live Paint Gaps shows on a Live Paint group.
pub use buildcmds::live_paint_gaps;
/// The transform Reset Transformation gives a symbol instance (the Symbols panel menu and the
/// Control bar enable it when there is one).
pub use brushsym::reset_transformation;
/// Whether Reset Transformation changes a symbol instance (the Symbols panel menu and the
/// Control bar enable it when it changes one).
pub use brushsym::reset_transformation_changes;
/// Command ids kept only so older scripts keep working: `(alias, the command it duplicates)`.
/// They run as before but the command palette leaves them out (it lists the command once).
+2 -2
View File
@@ -24,8 +24,8 @@ use super::{
};
use crate::EngineError;
/// The transform Reset Transformation gives a symbol instance.
pub use symbols::reset_transformation;
/// Whether Reset Transformation changes a symbol instance.
pub use symbols::reset_transformation_changes;
mod brushes;
mod dynamic;
+18 -8
View File
@@ -702,22 +702,32 @@ const RESET_TOLERANCE: f64 = 1e-9;
/// The transform Reset Transformation gives instance `n` of the document of `boxes`: its symbol's
/// own scale, without rotation, shear or reflection, with the center of its art's bounding box
/// where it is. `None` when `n` is not an instance of a symbol the document holds, is in
/// perspective, or already has that transform.
pub fn reset_transformation(boxes: &vectorcraft_doc::SymbolBoxes, n: &Node) -> Option<Affine> {
/// where it is. `None` when [`reset_transformation_changes`] is false for `n`.
fn reset_transformation(boxes: &vectorcraft_doc::SymbolBoxes, n: &Node) -> Option<Affine> {
let d = boxes.document();
let NodeKind::SymbolInstance { symbol, xf } = &n.kind else { return None };
if n.extras().perspective.is_some() || !d.symbols.iter().any(|s| s.name == *symbol) {
if !reset_transformation_changes(d, n) {
return None;
}
// The symbol's stored natural size, or the art unscaled when that size is not positive and finite.
let NodeKind::SymbolInstance { symbol, xf } = &n.kind else { return None };
let scale = d.symbol_natural_xf(symbol);
// The art's box in symbol space (the ±HALF square when the art cannot be measured): its
// center keeps its place on the page.
let art = boxes.art_bounds(symbol).unwrap_or_else(|| vectorcraft_geom::Rect::new(-HALF, -HALF, HALF, HALF));
let center = xf.transform_rect_bbox(art).center();
let new = Affine::translate(center - scale * art.center()) * scale;
xf.as_coeffs().iter().zip(new.as_coeffs()).any(|(a, b)| (a - b).abs() > RESET_TOLERANCE).then_some(new)
Some(Affine::translate(center - scale * art.center()) * scale)
}
/// Does Reset Transformation change `n`? True for an instance of a symbol `d` holds, not in
/// perspective, whose scale, rotation, shear or reflection differs from the symbol's own scale
/// (its stored natural size, or the art unscaled when that size is not positive and finite).
/// It does not measure the art.
pub fn reset_transformation_changes(d: &Document, n: &Node) -> bool {
let NodeKind::SymbolInstance { symbol, xf } = &n.kind else { return false };
if n.extras().perspective.is_some() || !d.symbols.iter().any(|s| s.name == *symbol) {
return false;
}
let natural = d.symbol_natural_xf(symbol).as_coeffs();
xf.as_coeffs()[..4].iter().zip(&natural[..4]).any(|(a, b)| (a - b).abs() > RESET_TOLERANCE)
}
pub(super) fn symbol_instance_reset_transform(s: &mut Session, p: &Value) -> Result<Value> {
+1 -2
View File
@@ -164,8 +164,7 @@ pub(crate) fn changed_instances_selected(app: &VectorcraftApp) -> bool {
/// symbol's, which Reset Transformation restores?
fn transformed_instances_selected(app: &VectorcraftApp) -> bool {
let Some(doc) = app.session.active().map(|st| st.doc.clone()) else { return false };
let boxes = doc.symbol_boxes();
instance_selected(app, |c| vectorcraft_engine::cmd::reset_transformation(&boxes, c).is_some())
instance_selected(app, |c| vectorcraft_engine::cmd::reset_transformation_changes(&doc, c))
}
/// The symbols of the selected objects when every one is a symbol instance; `None` otherwise.