diff --git a/src/scene/block_actions/stretch.rs b/src/scene/block_actions/stretch.rs index f5818a7c6..4c47cca45 100644 --- a/src/scene/block_actions/stretch.rs +++ b/src/scene/block_actions/stretch.rs @@ -78,7 +78,10 @@ pub(crate) fn bind_existing( crossing }; let mut bindings = vec![]; - for &handle in targets { + let mut unique = targets.to_vec(); + unique.sort(); + unique.dedup(); + for handle in unique { let points = control_points( doc.get_entity(handle) .ok_or("A Stretch target is unavailable.")?, diff --git a/src/scene/block_actions/tests.rs b/src/scene/block_actions/tests.rs index b41ccf1dc..708d4d3da 100644 --- a/src/scene/block_actions/tests.rs +++ b/src/scene/block_actions/tests.rs @@ -1054,3 +1054,28 @@ fn block_actions_retarget_stretch_can_remove_stale_binding_or_replace_it() { }; assert_eq!(action.handles[0].indexes, vec![1]); } + +#[test] +fn block_actions_stretch_duplicate_target_picks_create_one_binding() { + let (mut doc, def, targets, p, _) = stretch_fixture(); + let a = create_with_frame( + &mut doc, + def, + Kind::Stretch, + p, + &[targets[0], targets[0]], + DVec3::ZERO, + Some([DVec3::new(9., -1., 0.), DVec3::new(11., 4., 0.)]), + ) + .unwrap(); + let ObjectType::DynamicBlock(o) = &doc.objects[&a] else { + panic!() + }; + let DynamicBlockData::StretchAction(action) = &o.data else { + panic!() + }; + assert_eq!(action.action.dependencies, vec![targets[0]]); + assert_eq!(action.handles.len(), 1); + let baseline = doc.clone(); + assert!(evaluate(&mut doc, &baseline, def, p, DVec3::new(12., 0., 0.)).unwrap()); +}