150 lines
6.5 KiB
Rust
150 lines
6.5 KiB
Rust
//! Completed distances must reach the viewport before a continuously moving pointer stops.
|
|
use super::*;
|
|
use serde_json::json;
|
|
|
|
fn colors() -> Colors {
|
|
Colors { body: [1, 1, 1, 255], added: [2, 2, 2, 255], new_body: [2, 2, 2, 255], removed: [3, 3, 3, 100], edge: [0, 0, 0, 255] }
|
|
}
|
|
|
|
fn fixture() -> Session {
|
|
let mut s = Session::new(solidcraft_engine::doc::Document::new("Preview drag"));
|
|
s.execute("sketch.create", &json!({"plane":"XY", "name":"Profile"})).unwrap();
|
|
s.execute("sketch.rectangle.two_point", &json!({"p0":[0,0], "p1":[10,10]})).unwrap();
|
|
s.execute("sketch.finish", &json!({})).unwrap();
|
|
s
|
|
}
|
|
|
|
fn extrude(distance: i32) -> Vec<(String, Value)> {
|
|
vec![("solid.extrude".into(), json!({"sketch":"Profile", "distance":distance, "operation":"new"}))]
|
|
}
|
|
|
|
fn check_drag(s: &Session, commands: impl Fn(i32) -> Vec<(String, Value)>, base_z: f64) {
|
|
let original = serde_json::to_value(&*s.doc).unwrap();
|
|
let undo = s.undo.len();
|
|
let mut pv = PreviewState::default();
|
|
for (finished, wanted) in [(10, 20), (20, 30), (30, 30)] {
|
|
let old = commands(finished);
|
|
let new = commands(wanted);
|
|
let old_key = job_key(&old, s.revision, colors());
|
|
let key = job_key(&new, s.revision, colors());
|
|
let (tx, rx) = std::sync::mpsc::channel();
|
|
pv.running = Some((old_key, rx));
|
|
pv.running_tool = as_new_body(&old).is_some();
|
|
pv.running_stream_key = stream_key(&old, s.revision, colors());
|
|
let built = compute_tool(s, &old, colors()).unwrap();
|
|
tx.send(Ok(built)).unwrap();
|
|
pv.poll(key, stream_key(&new, s.revision, colors()));
|
|
assert!(pv.active && pv.error.is_none(), "completed geometry must show during the drag: {:?}", pv.error);
|
|
assert!((pv.bounds.max.z - base_z - f64::from(finished)).abs() < 1e-8);
|
|
assert_eq!(pv.shown_key, Some(old_key));
|
|
assert_eq!(pv.shown_key == Some(key), finished == wanted, "only the final distance satisfies the latest request");
|
|
assert!(pv.running.is_none());
|
|
}
|
|
assert_eq!(serde_json::to_value(&*s.doc).unwrap(), original);
|
|
assert_eq!(s.undo.len(), undo);
|
|
}
|
|
|
|
#[test]
|
|
fn new_body_extrude_keeps_moving_during_a_drag() {
|
|
check_drag(&fixture(), extrude, 0.0);
|
|
}
|
|
|
|
#[test]
|
|
fn edited_new_body_extrude_keeps_moving_during_a_drag() {
|
|
let mut s = fixture();
|
|
let feature = s.execute("solid.extrude", &extrude(5)[0].1).unwrap()["feature"].as_u64().unwrap();
|
|
check_drag(
|
|
&s,
|
|
|distance| vec![("timeline.redefine".into(), json!({"feature":feature,"command":"solid.extrude","params":extrude(distance)[0].1}))],
|
|
0.0,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn face_offset_keeps_moving_during_a_drag() {
|
|
let mut s = Session::new(solidcraft_engine::doc::Document::new("Face offset drag"));
|
|
s.execute("solid.box", &json!({"length":10,"width":10,"height":10})).unwrap();
|
|
check_drag(&s, |distance| vec![("solid.offset_face".into(), json!({"faces":[[5,5,10]],"distance":distance}))], 10.0);
|
|
}
|
|
|
|
#[test]
|
|
fn join_tool_keeps_moving_without_waiting_for_its_boolean() {
|
|
let mut s = fixture();
|
|
s.execute("solid.box", &json!({"length":10,"width":10,"height":5})).unwrap();
|
|
check_drag(&s, |distance| vec![("solid.extrude".into(), json!({"sketch":"Profile","distance":distance,"operation":"join"}))], 0.0);
|
|
}
|
|
|
|
#[test]
|
|
fn distance_stream_keeps_feature_selection_and_extent_context() {
|
|
let old = extrude(10);
|
|
let key = stream_key(&old, 7, colors());
|
|
assert!(key.is_some());
|
|
assert_eq!(key, stream_key(&extrude(20), 7, colors()));
|
|
assert_ne!(key, stream_key(&old, 8, colors()));
|
|
let mut recolored = colors();
|
|
recolored.added = [40, 50, 60, 255];
|
|
assert_ne!(key, stream_key(&old, 7, recolored));
|
|
for (field, value) in [
|
|
("sketch", json!("Other")),
|
|
("profiles", json!([1])),
|
|
("face", json!([0, 0, 5])),
|
|
("operation", json!("cut")),
|
|
("direction", json!("negative")),
|
|
("distance2", json!(5)),
|
|
("to", json!([0, 0, 50])),
|
|
("taper", json!(5)),
|
|
("start_offset", json!(3)),
|
|
("participants", json!(["Other"])),
|
|
] {
|
|
let mut changed = old.clone();
|
|
changed[0].1[field] = value;
|
|
assert_ne!(key, stream_key(&changed, 7, colors()), "changed {field} cannot reuse the old result");
|
|
}
|
|
for field in ["distance2", "to_offset"] {
|
|
let mut from = old.clone();
|
|
from[0].1[field] = json!(5);
|
|
let mut to = from.clone();
|
|
to[0].1[field] = json!(9);
|
|
assert_eq!(stream_key(&from, 7, colors()), stream_key(&to, 7, colors()));
|
|
}
|
|
let edit =
|
|
|feature, distance| vec![("timeline.redefine".into(), json!({"feature":feature,"command":"solid.extrude","params":extrude(distance)[0].1}))];
|
|
assert_eq!(stream_key(&edit(2, 10), 7, colors()), stream_key(&edit(2, 20), 7, colors()));
|
|
assert_ne!(stream_key(&edit(2, 10), 7, colors()), stream_key(&edit(3, 20), 7, colors()));
|
|
assert_ne!(key, stream_key(&edit(2, 10), 7, colors()));
|
|
let offset = |distance| vec![("solid.offset_face".into(), json!({"faces":[[5,5,10]],"distance":distance}))];
|
|
assert!(stream_key(&offset(1), 7, colors()).is_some());
|
|
assert_eq!(stream_key(&offset(1), 7, colors()), stream_key(&offset(5), 7, colors()));
|
|
assert!(stream_key(&[], 7, colors()).is_none());
|
|
assert!(stream_key(&[("solid.fillet".into(), json!({"radius":5}))], 7, colors()).is_none());
|
|
let mut mixed = old;
|
|
mixed.push(("select.clear".into(), json!({})));
|
|
assert!(stream_key(&mixed, 7, colors()).is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn distance_results_reject_other_setups_and_obsolete_errors() {
|
|
let s = fixture();
|
|
let old = extrude(10);
|
|
let current = extrude(20);
|
|
for (revision, failed) in [(s.revision + 1, false), (s.revision, true)] {
|
|
let mut built = compute_tool(&s, &old, colors()).unwrap();
|
|
if failed {
|
|
built.error = Some("old distance failed".into());
|
|
}
|
|
let (tx, rx) = std::sync::mpsc::channel();
|
|
let mut pv = PreviewState {
|
|
running: Some((job_key(&old, s.revision, colors()), rx)),
|
|
running_stream_key: stream_key(&old, s.revision, colors()),
|
|
..Default::default()
|
|
};
|
|
tx.send(Ok(built)).unwrap();
|
|
pv.poll(job_key(¤t, revision, colors()), stream_key(¤t, revision, colors()));
|
|
assert!(!pv.active && pv.error.is_none() && pv.shown_key.is_none());
|
|
}
|
|
let mut join = current.clone();
|
|
join[0].1["operation"] = json!("join");
|
|
assert!(as_new_body(&join).is_some());
|
|
assert!(stream_key(&join, s.revision, colors()).is_none(), "tool previews retain their upstream streaming path");
|
|
}
|