Fix live hinge animation and Drive Joint slider previews (#835)
Joint previews keep showing finished poses while the slider moves, and the latest value is still computed.
This commit is contained in:
1 parent
152418b624
commit
b702f0efde
3 files changed
+194
-7
No files matched your search
@@ -264,6 +264,69 @@ fn drive_value_takes_the_keyboard() {
|
||||
assert!(app.dialog.is_none());
|
||||
}
|
||||
|
||||
/// A real slider drag updates the requested pose while the pointer is still down.
|
||||
/// Previewing and cancelling must leave the saved joint and occurrence positions alone.
|
||||
#[test]
|
||||
fn drive_slider_previews_intermediate_positions_before_release() {
|
||||
let mut h = crate::scenario::Harness::new();
|
||||
h.app = two_boxes();
|
||||
h.app.viewport.no_pixels = true;
|
||||
let (a, b) = (occ(&h.app, "A"), occ(&h.app, "B"));
|
||||
h.app
|
||||
.run(
|
||||
"joint.create",
|
||||
json!({"type": "revolute", "a": {"occurrence": a, "face": [10, 10, 10]},
|
||||
"b": {"occurrence": b, "face": [40, 10, 0]}, "limits": [[-90, 90]]}),
|
||||
)
|
||||
.unwrap();
|
||||
let before = h.app.session.doc.clone();
|
||||
h.app.start("joint.drive");
|
||||
h.frames(4);
|
||||
let bounds = h
|
||||
.output
|
||||
.accesskit_update
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.nodes
|
||||
.iter()
|
||||
.find_map(|(_, n)| (n.role() == egui::accesskit::Role::Slider).then(|| n.bounds()).flatten())
|
||||
.expect("drive slider");
|
||||
let at = |fraction: f64| egui::pos2((bounds.x0 + fraction * (bounds.x1 - bounds.x0)) as f32, ((bounds.y0 + bounds.y1) / 2.0) as f32);
|
||||
let start = at(0.25);
|
||||
h.app.synthetic.extend([
|
||||
egui::Event::PointerMoved(start),
|
||||
egui::Event::PointerButton { pos: start, button: egui::PointerButton::Primary, pressed: true, modifiers: Default::default() },
|
||||
]);
|
||||
h.frames(3);
|
||||
let first = preview_commands(&h.app, h.app.dialog.as_ref().unwrap()).unwrap();
|
||||
h.app.synthetic.push(egui::Event::PointerMoved(at(0.75)));
|
||||
h.frames(3);
|
||||
let second = preview_commands(&h.app, h.app.dialog.as_ref().unwrap()).unwrap();
|
||||
assert_ne!(first, second, "the held slider requests a new pose before release");
|
||||
assert!(h.ctx.input(|i| i.pointer.primary_down()));
|
||||
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(10);
|
||||
while h.app.preview.busy {
|
||||
assert!(std::time::Instant::now() < deadline, "held-slider preview did not finish");
|
||||
std::thread::sleep(std::time::Duration::from_millis(1));
|
||||
h.frame();
|
||||
}
|
||||
assert!(h.app.preview.active, "the viewport shows the pose before release");
|
||||
assert!(h.app.preview.error.is_none());
|
||||
assert_eq!(h.app.preview.replaced, ["Body2"]);
|
||||
assert_eq!(h.app.session.doc, before);
|
||||
h.app.synthetic.push(egui::Event::PointerButton {
|
||||
pos: at(0.75),
|
||||
button: egui::PointerButton::Primary,
|
||||
pressed: false,
|
||||
modifiers: Default::default(),
|
||||
});
|
||||
h.frames(3);
|
||||
h.step(&json!({"key": "Escape"})).unwrap();
|
||||
assert!(h.app.dialog.is_none());
|
||||
assert!(!h.app.preview.active);
|
||||
assert_eq!(h.app.session.doc, before, "cancel leaves the joint at its original angle");
|
||||
}
|
||||
|
||||
/// Named joint origins are drawn where their component is: a drive of the occurrence, or a free
|
||||
/// move not captured yet, carries them along.
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user